From 40e1a22f3139ad5fd83c8cf405a5fe03c4fd0f68 Mon Sep 17 00:00:00 2001 From: Brandon Fancher Date: Wed, 10 Nov 2021 18:35:13 -0500 Subject: [PATCH] Factor out Asset and Account form input components. --- packages/webapp/src/_app/ui/form.tsx | 128 +++++++++++++++++- .../withdraw-modal-step-form.tsx | 88 ++---------- 2 files changed, 141 insertions(+), 75 deletions(-) diff --git a/packages/webapp/src/_app/ui/form.tsx b/packages/webapp/src/_app/ui/form.tsx index 46009c571..0c60f8eeb 100644 --- a/packages/webapp/src/_app/ui/form.tsx +++ b/packages/webapp/src/_app/ui/form.tsx @@ -1,5 +1,8 @@ import React, { HTMLProps } from "react"; +import { tokenConfig } from "config"; +import { Button } from "_app"; + export const Label: React.FC<{ htmlFor: string; }> = (props) => ( @@ -8,12 +11,17 @@ export const Label: React.FC<{ ); -export const Input: React.FC> = (props) => ( +export const Input: React.FC< + HTMLProps & { + inputRef?: React.Ref | null; + } +> = ({ inputRef, ...props }) => ( ); @@ -99,6 +107,122 @@ export const LabeledSet: React.FC<{ ); }; +export const ChainAccountInput = ( + props: HTMLProps & { id: string } +) => { + const validateAccountField = (e: React.FormEvent) => { + const target = e.target as HTMLInputElement; + if (target.validity.valueMissing) { + target.setCustomValidity("Enter an account name"); + } else { + target.setCustomValidity("Invalid account name"); + } + }; + + const clearErrorMessages = (e: React.FormEvent) => { + (e.target as HTMLInputElement).setCustomValidity(""); + }; + + const onInput = (e: React.FormEvent) => { + clearErrorMessages(e); + props.onInput?.(e); + }; + + const onInvalid = (e: React.FormEvent) => { + validateAccountField(e); + props.onInvalid?.(e); + }; + + return ( + + + + ); +}; + +export const AssetInput = ( + props: HTMLProps & { + label: string; // required + id: string; // required + inputRef?: React.RefObject; + } +) => { + const { label, inputRef, ...inputProps } = props; + + const amountRef = inputRef ?? React.useRef(null); + + const amountInputPreventChangeOnScroll = ( + e: React.WheelEvent + ) => (e.target as HTMLInputElement).blur(); + + const validateAmountField = (e: React.FormEvent) => { + const target = e.target as HTMLInputElement; + if (target.validity.rangeOverflow) { + target.setCustomValidity("Insufficient funds available"); + } else { + target.setCustomValidity("Enter a valid amount"); + } + }; + + const clearErrorMessages = (e: React.FormEvent) => { + (e.target as HTMLInputElement).setCustomValidity(""); + }; + + const setMaxAmount = () => { + amountRef.current?.setCustomValidity(""); + + // ensures this works with uncontrolled instances of this input too + Object.getOwnPropertyDescriptor( + window.HTMLInputElement.prototype, + "value" + )?.set?.call?.(amountRef.current, inputProps.max); + amountRef.current?.dispatchEvent( + new Event("change", { bubbles: true }) + ); + // (adapted from: https://coryrylan.com/blog/trigger-input-updates-with-react-controlled-inputs) + }; + + return ( + +
+
+ +
+

+ {tokenConfig.symbol} +

+
+
+ {inputProps.max ? ( + + ) : null} +
+
+ ); +}; + export const Form = { Label, Input, @@ -107,6 +231,8 @@ export const Form = { LabeledSet, FileInput, Checkbox, + ChainAccountInput, + AssetInput, }; export default Form; diff --git a/packages/webapp/src/members/components/withdraw-funds/withdraw-modal-step-form.tsx b/packages/webapp/src/members/components/withdraw-funds/withdraw-modal-step-form.tsx index b43ce3537..90d1d52da 100644 --- a/packages/webapp/src/members/components/withdraw-funds/withdraw-modal-step-form.tsx +++ b/packages/webapp/src/members/components/withdraw-funds/withdraw-modal-step-form.tsx @@ -27,43 +27,14 @@ export const WithdrawModalStepForm = ({ setFields(e); }; - const validateAccountField = (e: React.FormEvent) => { - const target = e.target as HTMLInputElement; - if (target.validity.valueMissing) { - target.setCustomValidity("Enter an account name"); - } else { - target.setCustomValidity("Invalid account name"); - } - }; - - const validateAmountField = (e: React.FormEvent) => { - const target = e.target as HTMLInputElement; - if (target.validity.rangeOverflow) { - target.setCustomValidity("Insufficient funds available"); - } else { - target.setCustomValidity("Enter a valid withdrawal amount"); - } - }; - - const clearErrorMessages = (e: React.FormEvent) => { - (e.target as HTMLInputElement).setCustomValidity(""); - }; - if (!availableFunds) return null; const maxWithdrawal = Number( assetToString(availableFunds!, availableFunds.precision).split(" ")[0] ); - const setMaxAmount = () => - setFields({ target: { id: "amount", value: maxWithdrawal } }); - const isThirdPartyWithdrawal = ualAccount.accountName !== formState[0].to; - const amountInputPreventChangeOnScroll = ( - e: React.WheelEvent - ) => (e.target as HTMLInputElement).blur(); - return (
Withdraw funds @@ -81,51 +52,20 @@ export const WithdrawModalStepForm = ({
- - - - -
-
- -
-

- {availableFunds?.symbol} -

-
-
- -
-
+ + {isThirdPartyWithdrawal && (