mirror of
https://github.com/aljazceru/mutiny-web.git
synced 2026-01-31 12:04:23 +01:00
feat: new features for amountEditable
This commit is contained in:
3
src/assets/icons/currency-swap.svg
Normal file
3
src/assets/icons/currency-swap.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="15" height="12" viewBox="0 0 15 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1.5 3.99992L4.16667 1.33325M4.16667 1.33325L6.83333 3.99992M4.16667 1.33325V10.6666M13.5 7.99992L10.8333 10.6666M10.8333 10.6666L8.16667 7.99992M10.8333 10.6666V1.33325" stroke="#A3A3A3" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 372 B |
@@ -53,7 +53,7 @@ function USDShower(props: { amountSats: string; fee?: string }) {
|
||||
<Show when={!(props.amountSats === "0")}>
|
||||
<KeyValue gray key="">
|
||||
<div class="self-end">
|
||||
≈ {amountInUsd()}
|
||||
~{amountInUsd()}
|
||||
<span class="text-sm">USD</span>
|
||||
</div>
|
||||
</KeyValue>
|
||||
|
||||
@@ -4,7 +4,8 @@ import {
|
||||
Show,
|
||||
createResource,
|
||||
createSignal,
|
||||
onMount
|
||||
onMount,
|
||||
onCleanup
|
||||
} from "solid-js";
|
||||
import { Button } from "~/components/layout";
|
||||
import { useMegaStore } from "~/state/megaStore";
|
||||
@@ -12,6 +13,7 @@ import { satsToUsd, usdToSats } from "~/utils/conversions";
|
||||
import { Dialog } from "@kobalte/core";
|
||||
import close from "~/assets/icons/close.svg";
|
||||
import pencil from "~/assets/icons/pencil.svg";
|
||||
import currencySwap from "~/assets/icons/currency-swap.svg";
|
||||
import { InlineAmount } from "./AmountCard";
|
||||
import { DIALOG_CONTENT, DIALOG_POSITIONER } from "~/styles/dialogs";
|
||||
import { InfoBox } from "./InfoBox";
|
||||
@@ -76,8 +78,32 @@ function satsInputSanitizer(input: string): string {
|
||||
function SingleDigitButton(props: {
|
||||
character: string;
|
||||
onClick: (c: string) => void;
|
||||
onClear: () => void;
|
||||
fiat: boolean;
|
||||
}) {
|
||||
let holdTimer: number;
|
||||
const holdThreshold = 500;
|
||||
|
||||
function onHold() {
|
||||
holdTimer = setTimeout(() => {
|
||||
props.onClear();
|
||||
}, holdThreshold);
|
||||
}
|
||||
|
||||
function endHold() {
|
||||
clearTimeout(holdTimer);
|
||||
}
|
||||
|
||||
function onClick() {
|
||||
props.onClick(props.character);
|
||||
|
||||
clearTimeout(holdTimer);
|
||||
}
|
||||
|
||||
onCleanup(() => {
|
||||
clearTimeout(holdTimer);
|
||||
});
|
||||
|
||||
return (
|
||||
// Skip the "." if it's fiat
|
||||
<Show
|
||||
@@ -85,8 +111,11 @@ function SingleDigitButton(props: {
|
||||
fallback={<div />}
|
||||
>
|
||||
<button
|
||||
class="disabled:opacity-50 p-2 rounded-lg md:hover:bg-white/10 active:bg-m-blue text-white text-4xl font-semi font-mono"
|
||||
onClick={() => props.onClick(props.character)}
|
||||
class="disabled:opacity-50 flex justify-center items-center p-2 rounded-lg md:hover:bg-white/10 active:bg-m-blue text-white text-4xl font-semi font-inter"
|
||||
onMouseDown={onHold}
|
||||
onMouseUp={endHold}
|
||||
onMouseLeave={endHold}
|
||||
onClick={onClick}
|
||||
>
|
||||
{props.character}
|
||||
</button>
|
||||
@@ -99,14 +128,14 @@ function BigScalingText(props: { text: string; fiat: boolean }) {
|
||||
|
||||
return (
|
||||
<h1
|
||||
class="font-light text-center transition-transform ease-out duration-300 text-4xl"
|
||||
class="font-light px-2 text-center transition-transform ease-out duration-300 text-4xl"
|
||||
classList={{
|
||||
"scale-90": chars() > 9,
|
||||
"scale-95": chars() > 8,
|
||||
"scale-100": chars() > 7,
|
||||
"scale-105": chars() > 6,
|
||||
"scale-110": chars() > 5,
|
||||
"scale-125": chars() > 4,
|
||||
"scale-90": chars() >= 11,
|
||||
"scale-95": chars() === 10,
|
||||
"scale-100": chars() === 9,
|
||||
"scale-105": chars() === 7,
|
||||
"scale-110": chars() === 6,
|
||||
"scale-125": chars() === 5,
|
||||
"scale-150": chars() <= 4
|
||||
}}
|
||||
>
|
||||
@@ -118,17 +147,38 @@ function BigScalingText(props: { text: string; fiat: boolean }) {
|
||||
|
||||
function SmallSubtleAmount(props: { text: string; fiat: boolean }) {
|
||||
return (
|
||||
<h2 class="text-xl font-light text-neutral-400">
|
||||
≈ {props.text}
|
||||
<span class="text-sm">{props.fiat ? "USD" : "SATS"}</span>
|
||||
<h2 class="flex flex-row items-end text-xl font-light text-neutral-400">
|
||||
~{props.text}
|
||||
<span class="text-base">{props.fiat ? "USD" : "SATS"}</span>
|
||||
<img
|
||||
class={"pl-[4px] pb-[4px] hover:cursor-pointer"}
|
||||
src={currencySwap}
|
||||
height={24}
|
||||
width={24}
|
||||
alt="Swap currencies"
|
||||
/>
|
||||
</h2>
|
||||
);
|
||||
}
|
||||
|
||||
function toDisplayHandleNaN(input: string, _fiat: boolean): string {
|
||||
const parsed = Number(input);
|
||||
|
||||
//handle decimals so the user can always see the accurate amount
|
||||
if (isNaN(parsed)) {
|
||||
return "0";
|
||||
} else if (parsed === Math.trunc(parsed) && input.endsWith(".")) {
|
||||
return parsed.toLocaleString() + ".";
|
||||
} else if (parsed === Math.trunc(parsed) && input.endsWith(".0")) {
|
||||
return parsed.toFixed(1);
|
||||
} else if (parsed === Math.trunc(parsed) && input.endsWith(".00")) {
|
||||
return parsed.toFixed(2);
|
||||
} else if (
|
||||
parsed !== Math.trunc(parsed) &&
|
||||
input.endsWith("0") &&
|
||||
input.includes(".", input.length - 3)
|
||||
) {
|
||||
return parsed.toFixed(2);
|
||||
} else {
|
||||
return parsed.toLocaleString();
|
||||
}
|
||||
@@ -212,7 +262,11 @@ export const AmountEditable: ParentComponent<{
|
||||
let sane;
|
||||
|
||||
if (character === "DEL") {
|
||||
sane = inputSanitizer(localValue().slice(0, -1));
|
||||
if (localValue().length <= 1) {
|
||||
sane = "0";
|
||||
} else {
|
||||
sane = inputSanitizer(localValue().slice(0, -1));
|
||||
}
|
||||
} else {
|
||||
if (localValue() === "0") {
|
||||
sane = inputSanitizer(character);
|
||||
@@ -235,6 +289,21 @@ export const AmountEditable: ParentComponent<{
|
||||
focus();
|
||||
}
|
||||
|
||||
function handleClear() {
|
||||
const isFiatMode = mode() === "fiat";
|
||||
|
||||
if (isFiatMode) {
|
||||
setLocalFiat("0");
|
||||
setLocalSats(usdToSats(state.price, parseFloat("0") || 0, false));
|
||||
} else {
|
||||
setLocalSats("0");
|
||||
setLocalFiat(satsToUsd(state.price, Number("0") || 0, false));
|
||||
}
|
||||
|
||||
// After a button press make sure we re-focus the input
|
||||
focus();
|
||||
}
|
||||
|
||||
function setFixedAmount(amount: string) {
|
||||
if (mode() === "fiat") {
|
||||
setLocalFiat(amount);
|
||||
@@ -265,6 +334,7 @@ export const AmountEditable: ParentComponent<{
|
||||
function handleSubmit(e: SubmitEvent | MouseEvent) {
|
||||
e.preventDefault();
|
||||
props.setAmountSats(BigInt(localSats()));
|
||||
setLocalFiat(satsToUsd(state.price, Number(localSats()) || 0, false));
|
||||
setIsOpen(false);
|
||||
}
|
||||
|
||||
@@ -377,26 +447,28 @@ export const AmountEditable: ParentComponent<{
|
||||
</form>
|
||||
|
||||
<div class="flex flex-col flex-1 justify-around gap-2 max-w-[400px] mx-auto w-full">
|
||||
<div
|
||||
class="p-4 flex flex-col gap-4 items-center justify-center"
|
||||
onClick={toggle}
|
||||
>
|
||||
<BigScalingText
|
||||
text={
|
||||
mode() === "fiat"
|
||||
? displayFiat()
|
||||
: displaySats()
|
||||
}
|
||||
fiat={mode() === "fiat"}
|
||||
/>
|
||||
<SmallSubtleAmount
|
||||
text={
|
||||
mode() === "fiat"
|
||||
? displaySats()
|
||||
: displayFiat()
|
||||
}
|
||||
fiat={mode() !== "fiat"}
|
||||
/>
|
||||
<div class="flex justify-center">
|
||||
<div
|
||||
class="p-4 flex flex-col gap-4 w-max items-center justify-center"
|
||||
onClick={toggle}
|
||||
>
|
||||
<BigScalingText
|
||||
text={
|
||||
mode() === "fiat"
|
||||
? displayFiat()
|
||||
: displaySats()
|
||||
}
|
||||
fiat={mode() === "fiat"}
|
||||
/>
|
||||
<SmallSubtleAmount
|
||||
text={
|
||||
mode() !== "fiat"
|
||||
? displayFiat()
|
||||
: displaySats()
|
||||
}
|
||||
fiat={mode() !== "fiat"}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Show when={warningText() && !props.skipWarnings}>
|
||||
<InfoBox accent="blue">
|
||||
@@ -444,12 +516,13 @@ export const AmountEditable: ParentComponent<{
|
||||
fiat={mode() === "fiat"}
|
||||
character={character}
|
||||
onClick={handleCharacterInput}
|
||||
onClear={handleClear}
|
||||
/>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
<Button
|
||||
intent="blue"
|
||||
intent="green"
|
||||
class="w-full flex-none"
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export const DIALOG_POSITIONER = "fixed inset-0 h-[100dvh] z-50";
|
||||
export const DIALOG_CONTENT =
|
||||
"h-[100dvh] flex flex-col justify-between px-4 pt-4 pb-8 bg-neutral-800/80 backdrop-blur-xl touch-manipulation select-none";
|
||||
"h-[100dvh] flex flex-col justify-between px-4 pt-4 pb-8 bg-m-grey-800 touch-manipulation select-none";
|
||||
|
||||
Reference in New Issue
Block a user