mirror of
https://github.com/getAlby/hub.git
synced 2026-08-13 12:33:39 +02:00
feat: refresh payment QR and status components (#2459)
* feat: refresh payment QR and status components * fix: align payment success button spacing * fix: invert payment QR colors in dark mode * fix: address payment QR review feedback * fix: flatten nested cards in payment review FixedFloat tiles * chore: remove internal payment component review screen Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: keep QR codes dark-on-light in dark mode Inverted QR codes are unreadable by many scanner apps (e.g. Phoenix). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: René Aaron <rene@getalby.com> Co-authored-by: Roland Bewick <roland.bewick@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
5b49783478
commit
417cb16d97
21 changed files with 8864 additions and 127 deletions
|
|
@ -37,12 +37,12 @@
|
|||
"dayjs": "^1.11.20",
|
||||
"embla-carousel-react": "^8.6.0",
|
||||
"lucide-react": "^1.7.0",
|
||||
"qr-code-styling": "^1.9.2",
|
||||
"radix-ui": "^1.4.3",
|
||||
"react": "^19.2.6",
|
||||
"react-day-picker": "^9.14.0",
|
||||
"react-dom": "^19.2.6",
|
||||
"react-lottie": "^1.2.4",
|
||||
"react-qr-code": "^2.0.12",
|
||||
"react-router": "^7.14.2",
|
||||
"sonner": "^2.0.7",
|
||||
"swr": "^2.4.1",
|
||||
|
|
|
|||
8588
frontend/src/assets/lotties/success-check.json
Normal file
8588
frontend/src/assets/lotties/success-check.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -4,12 +4,12 @@ import {
|
|||
ExternalLinkIcon,
|
||||
HandCoinsIcon,
|
||||
} from "lucide-react";
|
||||
import TickSVG from "public/images/illustrations/tick.svg";
|
||||
import { useEffect, useState } from "react";
|
||||
import { FixedFloatButton } from "src/components/FixedFloatButton";
|
||||
import { FormattedBitcoinAmount } from "src/components/FormattedBitcoinAmount";
|
||||
import FormattedFiatAmount from "src/components/FormattedFiatAmount";
|
||||
import LottieLoading from "src/components/LottieLoading";
|
||||
import LottieSuccess from "src/components/LottieSuccess";
|
||||
import { Button } from "src/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
|
|
@ -77,7 +77,7 @@ export function FixedFloatSwapInFlow({
|
|||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-center">Waiting for Payment</CardTitle>
|
||||
<CardTitle className="text-center">Waiting for Payment...</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col items-center gap-6">
|
||||
<LottieLoading size={288} />
|
||||
|
|
@ -91,7 +91,7 @@ export function FixedFloatSwapInFlow({
|
|||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="flex flex-col gap-2 pt-2">
|
||||
<CardFooter className="flex flex-col gap-3 pt-2">
|
||||
<Button
|
||||
type="button"
|
||||
className="w-full"
|
||||
|
|
@ -123,7 +123,7 @@ export function FixedFloatSwapInFlow({
|
|||
<CardTitle className="text-center">Transaction Received!</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col items-center gap-6">
|
||||
<img src={TickSVG} className="w-48" />
|
||||
<LottieSuccess />
|
||||
<div className="flex flex-col gap-1 items-center">
|
||||
<p className="text-2xl font-medium slashed-zero">
|
||||
<FormattedBitcoinAmount amountMsat={transaction.amountMsat} />
|
||||
|
|
@ -134,7 +134,7 @@ export function FixedFloatSwapInFlow({
|
|||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="flex flex-col gap-2 pt-2">
|
||||
<CardFooter className="flex flex-col gap-3 pt-2">
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
|
|
@ -144,11 +144,11 @@ export function FixedFloatSwapInFlow({
|
|||
variant="outline"
|
||||
className="w-full"
|
||||
>
|
||||
<HandCoinsIcon className="w-4 h-4 mr-2" />
|
||||
<HandCoinsIcon className="size-4" />
|
||||
{resetLabel}
|
||||
</Button>
|
||||
<LinkButton to="/wallet" variant="link" className="w-full">
|
||||
<ArrowLeftIcon className="w-4 h-4 mr-2" />
|
||||
<ArrowLeftIcon className="size-4" />
|
||||
Back to Wallet
|
||||
</LinkButton>
|
||||
</CardFooter>
|
||||
|
|
|
|||
21
frontend/src/components/LottieSuccess.tsx
Normal file
21
frontend/src/components/LottieSuccess.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { useMemo } from "react";
|
||||
import Lottie from "react-lottie";
|
||||
import animationData from "src/assets/lotties/success-check.json";
|
||||
|
||||
export default function LottieSuccess({ size = 288 }: { size?: number }) {
|
||||
const options = useMemo(
|
||||
() => ({
|
||||
loop: false,
|
||||
autoplay: true,
|
||||
animationData,
|
||||
rendererSettings: { preserveAspectRatio: "xMidYMid meet" },
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="[&_path[fill='rgb(75,177,0)']]:fill-positive-foreground [&_path[stroke='rgb(75,177,0)']]:stroke-positive-foreground [&_path[stroke='rgb(255,255,255)']]:stroke-card">
|
||||
<Lottie options={options} height={size} width={size} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ import { CopyIcon, ExternalLinkIcon } from "lucide-react";
|
|||
import React from "react";
|
||||
import { FixedFloatButton } from "src/components/FixedFloatButton";
|
||||
import { FormattedBitcoinAmount } from "src/components/FormattedBitcoinAmount";
|
||||
import { LightningIcon } from "src/components/icons/Lightning";
|
||||
import Loading from "src/components/Loading";
|
||||
import QRCode from "src/components/QRCode";
|
||||
import { Button } from "src/components/ui/button";
|
||||
|
|
@ -28,16 +27,13 @@ export function PayLightningInvoice({ invoice }: PayLightningInvoiceProps) {
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="w-96 flex flex-col gap-6 p-6 items-center justify-center">
|
||||
<div className="flex items-center justify-center gap-2 text-muted-foreground">
|
||||
<div className="flex w-full flex-col items-center justify-center gap-6">
|
||||
<div className="flex items-center justify-center gap-2 font-semibold leading-none">
|
||||
<Loading variant="loader" />
|
||||
<p>Waiting for lightning payment...</p>
|
||||
<p>Waiting for Payment...</p>
|
||||
</div>
|
||||
<div className="w-full relative flex items-center justify-center">
|
||||
<QRCode value={invoice} className="w-full" />
|
||||
<div className="bg-white absolute rounded-full p-1">
|
||||
<LightningIcon className="w-12 h-12" />
|
||||
</div>
|
||||
<div className="relative flex w-full items-center justify-center">
|
||||
<QRCode value={invoice} className="w-full" paymentType="lightning" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-lg font-semibold">
|
||||
|
|
@ -50,23 +46,19 @@ export function PayLightningInvoice({ invoice }: PayLightningInvoiceProps) {
|
|||
}).format(fiatAmount)}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 w-full">
|
||||
<Button
|
||||
onClick={copy}
|
||||
variant="outline"
|
||||
className="flex-1 flex gap-2 items-center justify-center"
|
||||
>
|
||||
<div className="flex w-full flex-col gap-3">
|
||||
<Button onClick={copy} variant="secondary" className="w-full">
|
||||
<CopyIcon />
|
||||
Copy Invoice
|
||||
</Button>
|
||||
<FixedFloatButton
|
||||
to="BTCLN"
|
||||
address={invoice}
|
||||
className="flex-1 flex gap-2 items-center justify-center"
|
||||
variant="secondary"
|
||||
className="w-full"
|
||||
variant="outline"
|
||||
>
|
||||
Pay with other Cryptocurrency
|
||||
<ExternalLinkIcon className="size-4" />
|
||||
Pay with Crypto
|
||||
</FixedFloatButton>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,38 +1,116 @@
|
|||
import ReactQRCode from "react-qr-code";
|
||||
import { type ReactNode, useEffect, useMemo, useRef } from "react";
|
||||
import QRCodeStyling, { type Options } from "qr-code-styling";
|
||||
import { BitcoinPaymentIcon } from "src/components/icons/BitcoinPayment";
|
||||
import { LightningIcon } from "src/components/icons/Lightning";
|
||||
import { cn } from "src/lib/utils";
|
||||
|
||||
export type Props = {
|
||||
value: string;
|
||||
size?: number;
|
||||
className?: string;
|
||||
showAvatar?: boolean;
|
||||
frameType?: "lightning" | "onchain";
|
||||
paymentType?: "lightning" | "onchain";
|
||||
centerContent?: ReactNode;
|
||||
|
||||
// set the level to Q if there are overlays
|
||||
// Q will improve error correction (so we can add overlays covering up to 25% of the QR)
|
||||
// at the price of decreased information density (meaning the QR codes "pixels" have to be
|
||||
// smaller to encode the same information).
|
||||
// While that isn't that much of a problem for lightning addresses (because they are usually quite short),
|
||||
// for invoices that contain larger amount of data those QR codes can get "harder" to read.
|
||||
// (meaning you have to aim your phone very precisely and have to wait longer for the reader
|
||||
// to recognize the QR code)
|
||||
// Use Q when an external overlay covers part of the QR code.
|
||||
level?: "Q" | undefined;
|
||||
};
|
||||
|
||||
function QRCode({ value, size, level, className }: Props) {
|
||||
// Do not use dark mode: some apps do not handle it well (e.g. Phoenix)
|
||||
// const { isDarkMode } = useTheme();
|
||||
const fgColor = "#242424"; // isDarkMode ? "#FFFFFF" : "#242424";
|
||||
const bgColor = "#FFFFFF"; // isDarkMode ? "#242424" : "#FFFFFF";
|
||||
function QRCode({
|
||||
value,
|
||||
size = 256,
|
||||
level,
|
||||
className,
|
||||
showAvatar = false,
|
||||
frameType,
|
||||
paymentType,
|
||||
centerContent,
|
||||
}: Props) {
|
||||
const resolvedFrameType = paymentType ?? frameType;
|
||||
const hasCenterContent = Boolean(centerContent);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const options = useMemo<Options>(
|
||||
() => ({
|
||||
type: "svg",
|
||||
width: size,
|
||||
height: size,
|
||||
data: value,
|
||||
image: showAvatar ? "/icon-lightmode.svg" : undefined,
|
||||
margin: 0,
|
||||
qrOptions: {
|
||||
errorCorrectionLevel:
|
||||
level ?? (showAvatar || paymentType || hasCenterContent ? "Q" : "M"),
|
||||
},
|
||||
imageOptions: {
|
||||
crossOrigin: "anonymous",
|
||||
hideBackgroundDots: true,
|
||||
imageSize: 0.15,
|
||||
margin: 4,
|
||||
},
|
||||
dotsOptions: {
|
||||
color: "var(--qr-foreground)",
|
||||
type: "dots",
|
||||
roundSize: false,
|
||||
},
|
||||
cornersSquareOptions: {
|
||||
color: "var(--qr-foreground)",
|
||||
type: "extra-rounded",
|
||||
},
|
||||
cornersDotOptions: {
|
||||
color: "var(--qr-foreground)",
|
||||
type: "dot",
|
||||
},
|
||||
backgroundOptions: {
|
||||
color: "var(--qr-background)",
|
||||
},
|
||||
}),
|
||||
[hasCenterContent, level, paymentType, showAvatar, size, value]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const container = containerRef.current;
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
const qrCode = new QRCodeStyling(options);
|
||||
qrCode.append(container);
|
||||
|
||||
return () => {
|
||||
container.replaceChildren();
|
||||
};
|
||||
}, [options]);
|
||||
|
||||
return (
|
||||
<div className="bg-white p-2 rounded-md">
|
||||
<ReactQRCode
|
||||
value={value}
|
||||
size={size}
|
||||
fgColor={fgColor}
|
||||
bgColor={bgColor}
|
||||
className={cn("rounded", className)}
|
||||
level={level}
|
||||
/>
|
||||
<div
|
||||
className={cn(
|
||||
"relative w-full rounded-[28px] p-2",
|
||||
resolvedFrameType === "lightning"
|
||||
? "bg-payment-lightning"
|
||||
: resolvedFrameType === "onchain"
|
||||
? "bg-payment-onchain"
|
||||
: "bg-primary",
|
||||
className
|
||||
)}
|
||||
style={{ maxWidth: size }}
|
||||
>
|
||||
<div className="rounded-3xl bg-qr-background p-4">
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="aspect-square w-full overflow-hidden [&_svg]:size-full"
|
||||
/>
|
||||
</div>
|
||||
{(paymentType || centerContent) && (
|
||||
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-qr-background p-1 text-qr-background">
|
||||
{centerContent ??
|
||||
(paymentType === "lightning" ? (
|
||||
<LightningIcon className="size-12" />
|
||||
) : (
|
||||
<BitcoinPaymentIcon className="size-12" />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { Link } from "react-router";
|
|||
import FirstChannelJitAlert from "src/components/FirstChannelJitAlert";
|
||||
import Loading from "src/components/Loading";
|
||||
import QRCode from "src/components/QRCode";
|
||||
import UserAvatar from "src/components/UserAvatar";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
|
|
@ -34,7 +35,12 @@ export function ReceiveToLightning() {
|
|||
<FirstChannelJitAlert />
|
||||
<Card>
|
||||
<CardContent className="flex flex-col items-center gap-6">
|
||||
<QRCode value={me.lightning_address} className="w-full h-auto" />
|
||||
<QRCode
|
||||
value={me.lightning_address}
|
||||
className="h-auto w-full"
|
||||
frameType="lightning"
|
||||
centerContent={<UserAvatar className="size-12 rounded-full" />}
|
||||
/>
|
||||
<div className="flex max-w-full items-center justify-center gap-1">
|
||||
<p className="min-w-0 text-center font-medium text-lg break-all">
|
||||
{me.lightning_address}
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ import {
|
|||
HandCoinsIcon,
|
||||
RefreshCwIcon,
|
||||
} from "lucide-react";
|
||||
import TickSVG from "public/images/illustrations/tick.svg";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { FixedFloatButton } from "src/components/FixedFloatButton";
|
||||
import { FormattedBitcoinAmount } from "src/components/FormattedBitcoinAmount";
|
||||
import FormattedFiatAmount from "src/components/FormattedFiatAmount";
|
||||
import Loading from "src/components/Loading";
|
||||
import LottieLoading from "src/components/LottieLoading";
|
||||
import LottieSuccess from "src/components/LottieSuccess";
|
||||
import OnchainAddressDisplay from "src/components/OnchainAddressDisplay";
|
||||
import QRCode from "src/components/QRCode";
|
||||
import { Button } from "src/components/ui/button";
|
||||
|
|
@ -120,13 +120,13 @@ export function ReceiveToOnchain() {
|
|||
target="_blank"
|
||||
className="flex justify-center"
|
||||
>
|
||||
<QRCode value={onchainAddress} />
|
||||
<QRCode value={onchainAddress} paymentType="onchain" />
|
||||
</a>
|
||||
<div className="flex flex-wrap max-w-64 gap-2 items-center justify-center">
|
||||
<OnchainAddressDisplay address={onchainAddress} />
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="flex flex-col gap-2 pt-2">
|
||||
<CardFooter className="flex flex-col gap-3 pt-2">
|
||||
<Button
|
||||
className="w-full"
|
||||
onClick={() => {
|
||||
|
|
@ -150,10 +150,10 @@ export function ReceiveToOnchain() {
|
|||
to="BTC"
|
||||
address={onchainAddress}
|
||||
className="w-full"
|
||||
variant="secondary"
|
||||
variant="outline"
|
||||
>
|
||||
<ExternalLinkIcon className="size-4" />
|
||||
Top up using other Cryptocurrency
|
||||
Top Up with Crypto
|
||||
</FixedFloatButton>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
|
|
@ -174,8 +174,7 @@ function DepositPending({
|
|||
return (
|
||||
<Card className="w-full">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center justify-center gap-2">
|
||||
<Loading className="w-4 h-4" />
|
||||
<CardTitle className="text-center">
|
||||
Waiting for On-chain Confirmation...
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
|
|
@ -190,13 +189,13 @@ function DepositPending({
|
|||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
<CardFooter className="flex flex-col gap-2 pt-2">
|
||||
<CardFooter className="flex flex-col gap-3 pt-2">
|
||||
<ExternalLinkButton
|
||||
to={`${info?.mempoolUrl}/tx/${txId}`}
|
||||
variant="outline"
|
||||
className="w-full"
|
||||
>
|
||||
<ExternalLinkIcon className="w-4 h-4 mr-2" />
|
||||
<ExternalLinkIcon className="size-4" />
|
||||
View on Mempool
|
||||
</ExternalLinkButton>
|
||||
</CardFooter>
|
||||
|
|
@ -221,7 +220,7 @@ function DepositSuccess({
|
|||
<CardTitle className="text-center">Transaction Received!</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col items-center gap-6">
|
||||
<img src={TickSVG} className="w-48" />
|
||||
<LottieSuccess />
|
||||
<div className="flex flex-col gap-1 items-center">
|
||||
<p className="text-2xl font-medium slashed-zero">
|
||||
<FormattedBitcoinAmount amountMsat={amountSat * 1000} />
|
||||
|
|
@ -229,13 +228,13 @@ function DepositSuccess({
|
|||
<FormattedFiatAmount amountSat={amountSat} className="text-xl" />
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="flex flex-col gap-2 pt-2">
|
||||
<CardFooter className="flex flex-col gap-3 pt-2">
|
||||
<ExternalLinkButton
|
||||
to={`${info?.mempoolUrl}/tx/${txId}`}
|
||||
variant="outline"
|
||||
className="w-full"
|
||||
>
|
||||
<ExternalLinkIcon className="w-4 h-4 mr-2" />
|
||||
<ExternalLinkIcon className="size-4" />
|
||||
View on Mempool
|
||||
</ExternalLinkButton>
|
||||
<Button
|
||||
|
|
@ -244,11 +243,11 @@ function DepositSuccess({
|
|||
className="w-full"
|
||||
onClick={onReceiveAnother}
|
||||
>
|
||||
<HandCoinsIcon className="w-4 h-4 mr-2" />
|
||||
<HandCoinsIcon className="size-4" />
|
||||
Receive Another Payment
|
||||
</Button>
|
||||
<LinkButton to="/wallet" variant="link" className="w-full">
|
||||
<ArrowLeftIcon className="w-4 h-4 mr-2" />
|
||||
<ArrowLeftIcon className="size-4" />
|
||||
Back to Wallet
|
||||
</LinkButton>
|
||||
</CardFooter>
|
||||
|
|
|
|||
25
frontend/src/components/icons/BitcoinPayment.tsx
Normal file
25
frontend/src/components/icons/BitcoinPayment.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { SVGAttributes } from "react";
|
||||
|
||||
export function BitcoinPaymentIcon(props: SVGAttributes<SVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M63.0394 39.7416C58.7654 56.8846 41.4024 67.3176 24.2574 63.0426C7.11937 58.7686 -3.31363 41.4046 0.962367 24.2626C5.23437 7.1176 22.5974 -3.3164 39.7374 0.957596C56.8814 5.2316 67.3134 22.5976 63.0394 39.7416Z"
|
||||
fill="#FB923C"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M33.0171 11.2938C34.6304 11.7261 35.5879 13.3844 35.1556 14.9977L34.8575 16.11L36.1559 16.4579L36.4539 15.3456C36.8862 13.7323 38.5445 12.7748 40.1579 13.2071C41.7712 13.6394 42.7286 15.2977 42.2963 16.9111L41.9448 18.2229C45.7919 20.1883 47.8803 24.6345 46.7172 28.9754C46.2003 30.9045 45.1168 32.5306 43.6938 33.7225C45.3314 35.9478 45.9793 38.8701 45.2085 41.7464L45.1384 42.0082C43.831 46.8875 38.8157 49.783 33.9365 48.4757L33.8452 48.4512L33.5472 49.5635C33.1149 51.1768 31.4565 52.1342 29.8432 51.7019C28.2298 51.2696 27.2724 49.6113 27.7047 47.998L28.0027 46.8857L26.7044 46.5378L26.4064 47.6501C25.9741 49.2634 24.3158 50.2209 22.7024 49.7886C21.0891 49.3563 20.1316 47.698 20.5639 46.0846L20.862 44.9723L16.6424 43.8417C15.0291 43.4094 14.0716 41.7511 14.5039 40.1378C14.9362 38.5244 16.5946 37.567 18.2079 37.9993L19.0671 38.2295L24.0892 19.4866L23.2301 19.2563C21.6167 18.824 20.6593 16.5946 21.0916 15.5524C21.5239 13.939 23.1822 12.9816 24.7955 13.4139L29.0151 14.5445L29.3131 13.4322C29.7454 11.8189 31.4037 10.8615 33.0171 11.2938ZM29.9317 21.052L28.2188 27.4445L36.8221 29.7497C38.5873 30.2227 40.4017 29.1752 40.8747 27.4099C41.3477 25.6447 40.3001 23.8303 38.5349 23.3573L29.9317 21.052ZM26.6533 33.287L24.9095 39.795L35.502 42.6332C37.1545 43.076 38.8531 42.0953 39.296 40.4427L39.3661 40.181C39.8476 38.3838 38.7811 36.5366 36.984 36.055L26.6533 33.287Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ export function LightningIcon(props: SVGAttributes<SVGElement>) {
|
|||
/>
|
||||
<path
|
||||
d="M33.3099 12.4881C32.5628 12.3958 31.9053 12.6446 31.3666 13.0015C30.8466 13.346 30.3632 13.8383 29.8999 14.3907C28.9936 15.4713 27.9225 17.0832 26.5847 19.0983L19.0419 30.4596C18.1163 31.8537 17.3375 33.0266 16.8825 33.9955C16.4166 34.9876 16.1007 36.1567 16.7178 37.3017C17.335 38.4468 18.4871 38.8294 19.5742 38.9896C20.6357 39.1461 22.0465 39.146 23.7235 39.146H24.9235C25.8369 39.146 26.4043 39.1481 26.8221 39.197C27.2053 39.2418 27.2901 39.3106 27.3097 39.3265C27.3533 39.3618 27.3937 39.4022 27.4291 39.4457C27.445 39.4652 27.5135 39.549 27.5584 39.9311C27.6074 40.3476 27.6096 40.9132 27.6096 41.8239V41.9194C27.6095 44.3546 27.6095 46.3017 27.7679 47.7093C27.8484 48.4249 27.979 49.1014 28.2219 49.6748C28.4735 50.2688 28.884 50.8381 29.5581 51.1722C29.9135 51.3484 30.2962 51.4633 30.6901 51.5119C31.4372 51.6042 32.0947 51.3554 32.6334 50.9985C33.1534 50.654 33.6368 50.1617 34.1001 49.6093C35.0114 48.5227 36.0894 46.899 37.4375 44.8683L44.9581 33.5404C45.8837 32.1463 46.6625 30.9734 47.1175 30.0045C47.5834 29.0124 47.8993 27.8433 47.2822 26.6983C46.665 25.5532 45.5129 25.1706 44.4258 25.0104C43.3643 24.8539 41.9535 24.854 40.2765 24.854L39.0765 24.854C38.1631 24.854 37.5957 24.8519 37.1779 24.803C36.7947 24.7582 36.7099 24.6894 36.6903 24.6735C36.6467 24.6382 36.6063 24.5978 36.5709 24.5543C36.555 24.5348 36.4865 24.4509 36.4416 24.0689C36.3926 23.6524 36.3904 23.0868 36.3904 22.1761V22.0806C36.3905 19.6454 36.3905 17.6982 36.2321 16.2907C36.1516 15.5751 36.021 14.8986 35.7781 14.3252C35.5265 13.7312 35.116 13.1619 34.4419 12.8278C34.0865 12.6516 33.7038 12.5367 33.3099 12.4881Z"
|
||||
fill="white"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ function PayBitcoinChannelOrderTopup({ order }: { order: NewChannelOrder }) {
|
|||
</DialogHeader>
|
||||
<div className="flex flex-row justify-center p-3">
|
||||
<a href={`bitcoin:${onchainAddress}`} target="_blank">
|
||||
<QRCode value={onchainAddress} />
|
||||
<QRCode value={onchainAddress} paymentType="onchain" />
|
||||
</a>
|
||||
</div>
|
||||
</DialogContent>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { AlertTriangleIcon, CopyIcon, ExternalLinkIcon } from "lucide-react";
|
||||
import React from "react";
|
||||
import { toast } from "sonner";
|
||||
import buzzpay from "src/assets/suggested-apps/buzzpay.png";
|
||||
import { AppDetailConnectedApps } from "src/components/connections/AppDetailConnectedApps";
|
||||
import { AppStoreDetailHeader } from "src/components/connections/AppStoreDetailHeader";
|
||||
import { appStoreApps } from "src/components/connections/SuggestedAppData";
|
||||
|
|
@ -82,20 +81,24 @@ export function BuzzPay() {
|
|||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
<div className="flex flex-col items-center relative">
|
||||
<div className="flex flex-col items-center">
|
||||
<QRCode value={posUrl} />
|
||||
<img
|
||||
src={buzzpay}
|
||||
className="absolute w-12 h-12 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-muted p-1 rounded-xl"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex flex-col gap-3">
|
||||
<Input disabled readOnly type="text" value={posUrl} />
|
||||
<Button onClick={() => copyToClipboard(posUrl)} variant="outline">
|
||||
<Button
|
||||
className="w-full"
|
||||
onClick={() => copyToClipboard(posUrl)}
|
||||
variant="outline"
|
||||
>
|
||||
<CopyIcon />
|
||||
Copy
|
||||
</Button>
|
||||
<Button onClick={() => openLink(posUrl)} variant="outline">
|
||||
<Button
|
||||
className="w-full"
|
||||
onClick={() => openLink(posUrl)}
|
||||
variant="outline"
|
||||
>
|
||||
<ExternalLinkIcon />
|
||||
Open
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import {
|
||||
CircleCheckIcon,
|
||||
CopyIcon,
|
||||
CreditCardIcon,
|
||||
ExternalLinkIcon,
|
||||
|
|
@ -12,6 +11,7 @@ import { FormattedBitcoinAmount } from "src/components/FormattedBitcoinAmount";
|
|||
import FormattedFiatAmount from "src/components/FormattedFiatAmount";
|
||||
import Loading from "src/components/Loading";
|
||||
import LottieLoading from "src/components/LottieLoading";
|
||||
import LottieSuccess from "src/components/LottieSuccess";
|
||||
import { MempoolAlert } from "src/components/MempoolAlert";
|
||||
import OnchainAddressDisplay from "src/components/OnchainAddressDisplay";
|
||||
import QRCode from "src/components/QRCode";
|
||||
|
|
@ -129,7 +129,7 @@ export default function DepositBitcoin() {
|
|||
target="_blank"
|
||||
className="flex justify-center"
|
||||
>
|
||||
<QRCode value={onchainAddress} />
|
||||
<QRCode value={onchainAddress} paymentType="onchain" />
|
||||
</a>
|
||||
|
||||
<div className="flex flex-wrap gap-2 items-center justify-center">
|
||||
|
|
@ -137,11 +137,11 @@ export default function DepositBitcoin() {
|
|||
</div>
|
||||
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-1 flex-row gap-4 justify-center w-full">
|
||||
<div className="flex w-full flex-col gap-3">
|
||||
<LoadingButton
|
||||
variant="outline"
|
||||
onClick={getNewAddress}
|
||||
className="flex-1"
|
||||
className="w-full"
|
||||
loading={loadingAddress}
|
||||
>
|
||||
{!loadingAddress && <RefreshCwIcon />}
|
||||
|
|
@ -149,7 +149,7 @@ export default function DepositBitcoin() {
|
|||
</LoadingButton>
|
||||
<Button
|
||||
variant="secondary"
|
||||
className="flex-1"
|
||||
className="w-full"
|
||||
onClick={() => {
|
||||
copyToClipboard(onchainAddress);
|
||||
}}
|
||||
|
|
@ -163,10 +163,10 @@ export default function DepositBitcoin() {
|
|||
to="BTC"
|
||||
address={onchainAddress}
|
||||
className="w-full"
|
||||
variant="secondary"
|
||||
variant="outline"
|
||||
>
|
||||
<ExternalLinkIcon className="size-4" />
|
||||
Deposit using other Cryptocurrency
|
||||
Top Up with Crypto
|
||||
</FixedFloatButton>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
|
@ -201,14 +201,14 @@ function DepositPending({
|
|||
<FormattedFiatAmount amountSat={amountSat} />
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<div className="w-full">
|
||||
<ExternalLinkButton
|
||||
to={`${info?.mempoolUrl}/tx/${txId}`}
|
||||
variant="outline"
|
||||
className="flex items-center mt-2"
|
||||
className="mt-2 w-full"
|
||||
>
|
||||
View on Mempool
|
||||
<ExternalLinkIcon className="size-4 ml-2" />
|
||||
<ExternalLinkIcon className="size-4" />
|
||||
</ExternalLinkButton>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
|
@ -232,21 +232,21 @@ function DepositSuccess({
|
|||
<CardTitle className="text-center">Payment Received!</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col items-center gap-4">
|
||||
<CircleCheckIcon className="w-72 h-72 p-2" />
|
||||
<LottieSuccess />
|
||||
<div className="flex flex-col gap-2 items-center">
|
||||
<p className="text-xl font-semibold slashed-zero">
|
||||
<FormattedBitcoinAmount amountMsat={amountSat * 1000} />
|
||||
</p>
|
||||
<FormattedFiatAmount amountSat={amountSat} />
|
||||
</div>
|
||||
<div>
|
||||
<div className="w-full">
|
||||
<ExternalLinkButton
|
||||
to={`${info?.mempoolUrl}/tx/${txId}`}
|
||||
variant="outline"
|
||||
className="flex items-center mt-2"
|
||||
className="mt-2 w-full"
|
||||
>
|
||||
View on Mempool
|
||||
<ExternalLinkIcon className="size-4 ml-2" />
|
||||
<ExternalLinkIcon className="size-4" />
|
||||
</ExternalLinkButton>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import {
|
|||
PlusIcon,
|
||||
ReceiptTextIcon,
|
||||
} from "lucide-react";
|
||||
import TickSVG from "public/images/illustrations/tick.svg";
|
||||
import React from "react";
|
||||
import { Link } from "react-router";
|
||||
import { toast } from "sonner";
|
||||
|
|
@ -16,6 +15,7 @@ import ExternalLink from "src/components/ExternalLink";
|
|||
import { FormattedBitcoinAmount } from "src/components/FormattedBitcoinAmount";
|
||||
import FormattedFiatAmount from "src/components/FormattedFiatAmount";
|
||||
import Loading from "src/components/Loading";
|
||||
import LottieSuccess from "src/components/LottieSuccess";
|
||||
import LowReceivingCapacityAlert from "src/components/LowReceivingCapacityAlert";
|
||||
import QRCode from "src/components/QRCode";
|
||||
import {
|
||||
|
|
@ -198,13 +198,16 @@ export default function ReceiveInvoice() {
|
|||
{!paymentDone ? (
|
||||
<>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex justify-center">
|
||||
<Loading className="size-4 mr-2" />
|
||||
<p>Waiting for payment</p>
|
||||
<CardTitle className="flex items-center justify-center gap-2">
|
||||
<Loading variant="loader" />
|
||||
<p>Waiting for Payment...</p>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col items-center gap-6">
|
||||
<QRCode value={transaction.invoice} />
|
||||
<QRCode
|
||||
value={transaction.invoice}
|
||||
paymentType="lightning"
|
||||
/>
|
||||
<div className="flex flex-col gap-1 items-center">
|
||||
<p className="text-2xl font-medium slashed-zero">
|
||||
<FormattedBitcoinAmount
|
||||
|
|
@ -220,13 +223,13 @@ export default function ReceiveInvoice() {
|
|||
<div className="w-full">{newChannelFeeAlert}</div>
|
||||
)}
|
||||
</CardContent>
|
||||
<CardFooter className="flex flex-col gap-2">
|
||||
<CardFooter className="flex flex-col gap-3">
|
||||
<Button
|
||||
className="w-full"
|
||||
onClick={copy}
|
||||
variant="outline"
|
||||
>
|
||||
<CopyIcon className="w-4 h-4 mr-2" />
|
||||
<CopyIcon className="size-4" />
|
||||
Copy Invoice
|
||||
</Button>
|
||||
</CardFooter>
|
||||
|
|
@ -239,7 +242,7 @@ export default function ReceiveInvoice() {
|
|||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col items-center gap-6">
|
||||
<img src={TickSVG} className="w-48" />
|
||||
<LottieSuccess />
|
||||
<div className="flex flex-col gap-1 items-center">
|
||||
<p className="text-2xl font-medium slashed-zero">
|
||||
<FormattedBitcoinAmount
|
||||
|
|
@ -252,7 +255,7 @@ export default function ReceiveInvoice() {
|
|||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="flex flex-col gap-2 pt-2">
|
||||
<CardFooter className="flex flex-col gap-3 pt-2">
|
||||
<Button
|
||||
onClick={() => {
|
||||
setTransaction(null);
|
||||
|
|
@ -260,7 +263,7 @@ export default function ReceiveInvoice() {
|
|||
variant="outline"
|
||||
className="w-full"
|
||||
>
|
||||
<PlusIcon className="w-4 h-4 mr-2" />
|
||||
<PlusIcon className="size-4" />
|
||||
Create Another Invoice
|
||||
</Button>
|
||||
<LinkButton
|
||||
|
|
@ -268,7 +271,7 @@ export default function ReceiveInvoice() {
|
|||
variant="link"
|
||||
className="w-full"
|
||||
>
|
||||
<ArrowLeftIcon className="w-4 h-4 mr-2" />
|
||||
<ArrowLeftIcon className="size-4" />
|
||||
Back to Wallet
|
||||
</LinkButton>
|
||||
</CardFooter>
|
||||
|
|
|
|||
|
|
@ -91,14 +91,18 @@ export default function ReceiveOffer() {
|
|||
<CardTitle className="text-center">Lightning Offer</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col items-center gap-6">
|
||||
<QRCode value={offer} className="w-full" />
|
||||
<QRCode
|
||||
value={offer}
|
||||
className="w-full"
|
||||
paymentType="lightning"
|
||||
/>
|
||||
{description && (
|
||||
<p className="text-muted-foreground my-2">{description}</p>
|
||||
)}
|
||||
</CardContent>
|
||||
<CardFooter className="flex flex-col gap-2">
|
||||
<CardFooter className="flex flex-col gap-3">
|
||||
<Button className="w-full" onClick={copy} variant="secondary">
|
||||
<CopyIcon className="w-4 h-4 mr-2" />
|
||||
<CopyIcon className="size-4" />
|
||||
Copy Offer
|
||||
</Button>
|
||||
<Button
|
||||
|
|
@ -109,7 +113,7 @@ export default function ReceiveOffer() {
|
|||
setOffer(null);
|
||||
}}
|
||||
>
|
||||
<RefreshCwIcon className="h-4 w-4 shrink-0 mr-2" />
|
||||
<RefreshCwIcon className="size-4 shrink-0" />
|
||||
New Offer
|
||||
</Button>
|
||||
</CardFooter>
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ import {
|
|||
CardTitle,
|
||||
} from "src/components/ui/card";
|
||||
|
||||
import TickSVG from "public/images/illustrations/tick.svg";
|
||||
import AppHeader from "src/components/AppHeader";
|
||||
import Loading from "src/components/Loading";
|
||||
import LottieLoading from "src/components/LottieLoading";
|
||||
import LottieSuccess from "src/components/LottieSuccess";
|
||||
import { ExternalLinkButton } from "src/components/ui/custom/external-link-button";
|
||||
import { LinkButton } from "src/components/ui/custom/link-button";
|
||||
import { useInfo } from "src/hooks/useInfo";
|
||||
|
|
@ -50,7 +50,7 @@ export default function OnchainSuccess() {
|
|||
</CardHeader>
|
||||
<CardContent className="flex flex-col items-center gap-6">
|
||||
{mempoolTx?.status.confirmed ? (
|
||||
<img src={TickSVG} className="w-48" />
|
||||
<LottieSuccess />
|
||||
) : (
|
||||
<LottieLoading size={288} />
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ import {
|
|||
} from "src/components/ui/card";
|
||||
import { copyToClipboard } from "src/lib/clipboard";
|
||||
|
||||
import TickSVG from "public/images/illustrations/tick.svg";
|
||||
import AppHeader from "src/components/AppHeader";
|
||||
import LottieSuccess from "src/components/LottieSuccess";
|
||||
import { LinkButton } from "src/components/ui/custom/link-button";
|
||||
|
||||
export default function PaymentSuccess() {
|
||||
|
|
@ -56,7 +56,7 @@ export default function PaymentSuccess() {
|
|||
<CardTitle className="text-center">Payment Successful</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col items-center gap-6">
|
||||
<img src={TickSVG} className="w-48" />
|
||||
<LottieSuccess />
|
||||
<div className="flex flex-col gap-1 items-center">
|
||||
<p className="text-2xl font-medium slashed-zero">
|
||||
<FormattedBitcoinAmount
|
||||
|
|
@ -82,17 +82,17 @@ export default function PaymentSuccess() {
|
|||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
<CardFooter className="flex flex-col gap-2 pt-2">
|
||||
<CardFooter className="flex flex-col gap-3 pt-2">
|
||||
<Button onClick={copy} variant="outline" className="w-full">
|
||||
<CopyIcon className="w-4 h-4 mr-2" />
|
||||
<CopyIcon className="size-4" />
|
||||
Copy Preimage
|
||||
</Button>
|
||||
<LinkButton to="/wallet/send" variant="outline" className="w-full">
|
||||
<HandCoinsIcon className="w-4 h-4 mr-2" />
|
||||
<HandCoinsIcon className="size-4" />
|
||||
Make Another Payment
|
||||
</LinkButton>
|
||||
<LinkButton to="/wallet" variant="link" className="w-full">
|
||||
<ArrowLeftIcon className="w-4 h-4 mr-2" />
|
||||
<ArrowLeftIcon className="size-4" />
|
||||
Back to Wallet
|
||||
</LinkButton>
|
||||
</CardFooter>
|
||||
|
|
|
|||
|
|
@ -214,9 +214,13 @@ export default function SwapInStatus() {
|
|||
<FormattedFiatAmount amountSat={swap.sendAmountSat} />
|
||||
</div>
|
||||
{!swap.lockupTxId && !isInternalSwap && (
|
||||
<div className="flex justify-center gap-4 flex-wrap">
|
||||
<div className="flex w-full flex-col gap-3">
|
||||
{swap.state !== "FAILED" && (
|
||||
<Button onClick={copyAddress} variant="outline">
|
||||
<Button
|
||||
className="w-full"
|
||||
onClick={copyAddress}
|
||||
variant="outline"
|
||||
>
|
||||
<CopyIcon />
|
||||
Copy Address
|
||||
</Button>
|
||||
|
|
@ -225,6 +229,7 @@ export default function SwapInStatus() {
|
|||
<ExternalLinkButton
|
||||
to={`bitcoin:${swap.lockupAddress}?amount=${swap.sendAmountSat / 100_000_000}`}
|
||||
variant="secondary"
|
||||
className="w-full"
|
||||
>
|
||||
Open in External Wallet
|
||||
<ExternalLinkIcon />
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@
|
|||
--positive-foreground: oklch(0.623 0.169 149.178);
|
||||
--warning: oklch(0.976 0.016 73.092);
|
||||
--warning-foreground: oklch(0.645 0.192 41.712);
|
||||
--payment-lightning: #ffdf6f;
|
||||
--payment-onchain: #fb923c;
|
||||
--qr-foreground: #242424;
|
||||
--qr-background: #ffffff;
|
||||
}
|
||||
|
||||
.dark,
|
||||
|
|
@ -96,4 +100,10 @@
|
|||
--positive-foreground: oklch(0.859 0.14 152.167);
|
||||
--warning: oklch(0.318 0.035 71.647);
|
||||
--warning-foreground: oklch(0.848 0.117 72.544);
|
||||
--payment-lightning: #ffdf6f;
|
||||
--payment-onchain: #fb923c;
|
||||
/* QR codes stay dark-on-light even in dark mode: many scanner apps
|
||||
(e.g. Phoenix) cannot read inverted QR codes */
|
||||
--qr-foreground: #242424;
|
||||
--qr-background: #ffffff;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,10 @@
|
|||
|
||||
--color-warning: var(--warning);
|
||||
--color-warning-foreground: var(--warning-foreground);
|
||||
--color-payment-lightning: var(--payment-lightning);
|
||||
--color-payment-onchain: var(--payment-onchain);
|
||||
--color-qr-foreground: var(--qr-foreground);
|
||||
--color-qr-background: var(--qr-background);
|
||||
|
||||
--shadow-sm: none;
|
||||
|
||||
|
|
|
|||
|
|
@ -5069,7 +5069,7 @@ pretty-bytes@^6.1.1:
|
|||
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-6.1.1.tgz#38cd6bb46f47afbf667c202cfc754bffd2016a3b"
|
||||
integrity sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==
|
||||
|
||||
prop-types@^15.6.1, prop-types@^15.8.1:
|
||||
prop-types@^15.6.1:
|
||||
version "15.8.1"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
|
||||
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
||||
|
|
@ -5091,10 +5091,17 @@ punycode@^2.1.0:
|
|||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
|
||||
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
|
||||
|
||||
qr.js@0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f"
|
||||
integrity sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==
|
||||
qr-code-styling@^1.9.2:
|
||||
version "1.9.2"
|
||||
resolved "https://registry.yarnpkg.com/qr-code-styling/-/qr-code-styling-1.9.2.tgz#071714860a7e59829e8822c9575e989042139d2d"
|
||||
integrity sha512-RgJaZJ1/RrXJ6N0j7a+pdw3zMBmzZU4VN2dtAZf8ZggCfRB5stEQ3IoDNGaNhYY3nnZKYlYSLl5YkfWN5dPutg==
|
||||
dependencies:
|
||||
qrcode-generator "^1.4.4"
|
||||
|
||||
qrcode-generator@^1.4.4:
|
||||
version "1.5.2"
|
||||
resolved "https://registry.yarnpkg.com/qrcode-generator/-/qrcode-generator-1.5.2.tgz#43faea8061a60d2b4ca5e9b0c0c0fb99e2d93e3a"
|
||||
integrity sha512-pItrW0Z9HnDBnFmgiNrY1uxRdri32Uh9EjNYLPVC2zZ3ZRIIEqBoDgm4DkvDwNNDHTK7FNkmr8zAa77BYc9xNw==
|
||||
|
||||
queue-microtask@^1.2.2:
|
||||
version "1.2.3"
|
||||
|
|
@ -5193,14 +5200,6 @@ react-lottie@^1.2.4:
|
|||
lottie-web "^5.12.2"
|
||||
prop-types "^15.6.1"
|
||||
|
||||
react-qr-code@^2.0.12:
|
||||
version "2.0.18"
|
||||
resolved "https://registry.yarnpkg.com/react-qr-code/-/react-qr-code-2.0.18.tgz#237de8fbab537885d6b2b10f4fd5318b371e3b17"
|
||||
integrity sha512-v1Jqz7urLMhkO6jkgJuBYhnqvXagzceg3qJUWayuCK/c6LTIonpWbwxR1f1APGd4xrW/QcQEovNrAojbUz65Tg==
|
||||
dependencies:
|
||||
prop-types "^15.8.1"
|
||||
qr.js "0.0.0"
|
||||
|
||||
react-remove-scroll-bar@^2.3.7:
|
||||
version "2.3.8"
|
||||
resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue