From c8405214a891ea9d623a6ca318be58b62a6b853d Mon Sep 17 00:00:00 2001 From: Armando Graterol Date: Wed, 6 Mar 2024 17:09:05 -0300 Subject: [PATCH] Updated cleave.js to cleave-zen --- package-lock.json | 37 +-- package.json | 3 +- .../partials/BalanceModal/BalanceModal.tsx | 1 - .../partials/MintTokensDescription.tsx | 2 +- .../partials/SimplePaymentDescription.tsx | 2 +- .../partials/TransferFundsDescription.tsx | 2 +- .../partials/AmountField/AmountField.tsx | 230 +++++++++--------- .../partials/AmountField/hooks.ts | 36 ++- .../partials/AmountField/types.ts | 5 - .../partials/AmountRow/AmountRow.tsx | 8 +- .../ActionSidebar/partials/AmountRow/types.ts | 2 +- .../partials/StakingForm/StakingForm.tsx | 2 - .../TransactionTable/TransactionTable.tsx | 7 +- .../partials/TransactionTable/hooks.tsx | 4 +- .../forms/MintTokenForm/MintTokenForm.tsx | 6 - .../partials/forms/MintTokenForm/consts.ts | 13 +- .../partials/forms/MintTokenForm/hooks.ts | 4 +- .../partials/forms/MintTokenForm/utils.tsx | 14 +- .../SimplePaymentForm/SimplePaymentForm.tsx | 2 +- .../partials/forms/SimplePaymentForm/hooks.ts | 75 +++--- .../forms/SimplePaymentForm/utils.tsx | 9 +- .../partials/forms/TransferFundsForm/hooks.ts | 50 ++-- .../forms/TransferFundsForm/utils.tsx | 7 +- .../Fields/InputBase/FormFormattedInput.tsx | 7 +- .../Fields/InputBase/FormattedInput.tsx | 20 +- .../v5/common/Fields/InputBase/hooks.ts | 44 +--- .../v5/common/Fields/InputBase/types.ts | 7 +- .../v5/common/TokensModal/TokensModal.tsx | 2 - src/constants/extensions.ts | 9 - src/types/extensions.ts | 4 +- 30 files changed, 223 insertions(+), 391 deletions(-) diff --git a/package-lock.json b/package-lock.json index 854d055d700..30f2a43f623 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,7 +52,7 @@ "bn.js": "^5.1.1", "camelcase": "^6.0.0", "classnames": "^2.2.6", - "cleave.js": "1.4.10", + "cleave-zen": "^0.0.17", "clsx": "^1.2.1", "constants-browserify": "^1.0.0", "copy-to-clipboard": "^3.0.8", @@ -138,7 +138,6 @@ "@storybook/testing-library": "^0.0.14-next.2", "@svgr/webpack": "^5.4.0", "@testing-library/cypress": "^8.0.2", - "@types/cleave.js": "^1.4.7", "@types/dompurify": "^3.0.5", "@types/enzyme": "^3.10.3", "@types/jest": "^26.0.0", @@ -10853,15 +10852,6 @@ "@types/node": "*" } }, - "node_modules/@types/cleave.js": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/@types/cleave.js/-/cleave.js-1.4.7.tgz", - "integrity": "sha512-0MatQhFMEsOWOjfY06z7Ez+84dWJFXWsqGRsZn+dxcZ8FqZbHftP4g4NIdpZmPm5I7RWmjDmrF5wtg99TVCgQA==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -17484,10 +17474,10 @@ "webpack": ">=4.0.0 <6.0.0" } }, - "node_modules/cleave.js": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/cleave.js/-/cleave.js-1.4.10.tgz", - "integrity": "sha512-7AWnh+6pgQbbRT+e7WnK/yc+U50zhtQZklvEcKDiFDpfcu3kb300BdV7FMYtGOIsAzD5TKy7KH38ZwgyWyFE2Q==" + "node_modules/cleave-zen": { + "version": "0.0.17", + "resolved": "https://registry.npmjs.org/cleave-zen/-/cleave-zen-0.0.17.tgz", + "integrity": "sha512-SLuad6RaACsONu3Fr4F3sE9YXxMlMv6AiaZ8qkwfdV9Ex+TJ+ip3rLFsdrqvnp0YGlslfzAfw8q8MwQJW3yHdg==" }, "node_modules/cli-boxes": { "version": "2.2.1", @@ -67771,15 +67761,6 @@ "@types/node": "*" } }, - "@types/cleave.js": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/@types/cleave.js/-/cleave.js-1.4.7.tgz", - "integrity": "sha512-0MatQhFMEsOWOjfY06z7Ez+84dWJFXWsqGRsZn+dxcZ8FqZbHftP4g4NIdpZmPm5I7RWmjDmrF5wtg99TVCgQA==", - "dev": true, - "requires": { - "@types/react": "*" - } - }, "@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -72707,10 +72688,10 @@ "del": "^4.1.1" } }, - "cleave.js": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/cleave.js/-/cleave.js-1.4.10.tgz", - "integrity": "sha512-7AWnh+6pgQbbRT+e7WnK/yc+U50zhtQZklvEcKDiFDpfcu3kb300BdV7FMYtGOIsAzD5TKy7KH38ZwgyWyFE2Q==" + "cleave-zen": { + "version": "0.0.17", + "resolved": "https://registry.npmjs.org/cleave-zen/-/cleave-zen-0.0.17.tgz", + "integrity": "sha512-SLuad6RaACsONu3Fr4F3sE9YXxMlMv6AiaZ8qkwfdV9Ex+TJ+ip3rLFsdrqvnp0YGlslfzAfw8q8MwQJW3yHdg==" }, "cli-boxes": { "version": "2.2.1", diff --git a/package.json b/package.json index 91872c1ae50..f7519d8fce6 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,6 @@ "@storybook/testing-library": "^0.0.14-next.2", "@svgr/webpack": "^5.4.0", "@testing-library/cypress": "^8.0.2", - "@types/cleave.js": "^1.4.7", "@types/dompurify": "^3.0.5", "@types/enzyme": "^3.10.3", "@types/jest": "^26.0.0", @@ -202,7 +201,7 @@ "bn.js": "^5.1.1", "camelcase": "^6.0.0", "classnames": "^2.2.6", - "cleave.js": "1.4.10", + "cleave-zen": "^0.0.17", "clsx": "^1.2.1", "constants-browserify": "^1.0.0", "copy-to-clipboard": "^3.0.8", diff --git a/src/components/frame/v5/pages/BalancePage/partials/BalanceModal/BalanceModal.tsx b/src/components/frame/v5/pages/BalancePage/partials/BalanceModal/BalanceModal.tsx index 9f8487f3b8c..15490eae6d7 100644 --- a/src/components/frame/v5/pages/BalancePage/partials/BalanceModal/BalanceModal.tsx +++ b/src/components/frame/v5/pages/BalancePage/partials/BalanceModal/BalanceModal.tsx @@ -40,7 +40,6 @@ const BalanceModal: FC> = ({ name="amount" placeholder="0" options={{ - numeral: true, numeralDecimalScale: undefined, numeralPositiveOnly: true, rawValueTrimPrefix: true, diff --git a/src/components/v5/common/ActionSidebar/partials/ActionSidebarDescription/partials/MintTokensDescription.tsx b/src/components/v5/common/ActionSidebar/partials/ActionSidebarDescription/partials/MintTokensDescription.tsx index 7185178a673..6f97fe34533 100644 --- a/src/components/v5/common/ActionSidebar/partials/ActionSidebarDescription/partials/MintTokensDescription.tsx +++ b/src/components/v5/common/ActionSidebar/partials/ActionSidebarDescription/partials/MintTokensDescription.tsx @@ -18,7 +18,7 @@ const displayName = export const MintTokensDescription = () => { const formValues = useFormContext().getValues(); - const { amount: { amount } = {} } = formValues; + const { amount } = formValues; const { colony: { nativeToken }, } = useColonyContext(); diff --git a/src/components/v5/common/ActionSidebar/partials/ActionSidebarDescription/partials/SimplePaymentDescription.tsx b/src/components/v5/common/ActionSidebar/partials/ActionSidebarDescription/partials/SimplePaymentDescription.tsx index 954c4001d16..40d0a6683a2 100644 --- a/src/components/v5/common/ActionSidebar/partials/ActionSidebarDescription/partials/SimplePaymentDescription.tsx +++ b/src/components/v5/common/ActionSidebar/partials/ActionSidebarDescription/partials/SimplePaymentDescription.tsx @@ -20,7 +20,7 @@ const displayName = export const SimplePaymentDescription = () => { const formValues = useFormContext().getValues(); const { colony } = useColonyContext(); - const { amount: { amount, tokenAddress } = {}, recipient } = formValues; + const { amount, tokenAddress, recipient } = formValues; const { nativeToken } = colony; const matchingColonyToken = colony.tokens?.items.find( diff --git a/src/components/v5/common/ActionSidebar/partials/ActionSidebarDescription/partials/TransferFundsDescription.tsx b/src/components/v5/common/ActionSidebar/partials/ActionSidebarDescription/partials/TransferFundsDescription.tsx index f5f68472b2f..529d424b970 100644 --- a/src/components/v5/common/ActionSidebar/partials/ActionSidebarDescription/partials/TransferFundsDescription.tsx +++ b/src/components/v5/common/ActionSidebar/partials/ActionSidebarDescription/partials/TransferFundsDescription.tsx @@ -22,7 +22,7 @@ export const TransferFundsDescription = () => { } = useColonyContext(); const formValues = useFormContext().getValues(); - const { amount: { amount, tokenAddress } = {}, from, to } = formValues; + const { amount, tokenAddress, from, to } = formValues; const fromDomain = domains?.items.find((domain) => domain?.nativeId === from); const toDomain = domains?.items.find((domain) => domain?.nativeId === to); diff --git a/src/components/v5/common/ActionSidebar/partials/AmountField/AmountField.tsx b/src/components/v5/common/ActionSidebar/partials/AmountField/AmountField.tsx index 5601ebb4e96..e0c25223d36 100644 --- a/src/components/v5/common/ActionSidebar/partials/AmountField/AmountField.tsx +++ b/src/components/v5/common/ActionSidebar/partials/AmountField/AmountField.tsx @@ -1,7 +1,7 @@ import { Id } from '@colony/colony-js'; -import Cleave from 'cleave.js/react'; +import { formatNumeral, unformatNumeral } from 'cleave-zen'; import clsx from 'clsx'; -import React, { type FC } from 'react'; +import React, { useState, type ChangeEvent, type FC, useEffect } from 'react'; import { useController } from 'react-hook-form'; import { useAdditionalFormOptionsContext } from '~context/AdditionalFormOptionsContext/AdditionalFormOptionsContext.tsx'; @@ -20,13 +20,12 @@ import MenuContainer from '~v5/shared/MenuContainer/index.ts'; import Portal from '~v5/shared/Portal/index.ts'; import { useAmountField } from './hooks.ts'; -import { type AmountFieldProps, type CleaveChangeEvent } from './types.ts'; +import { type AmountFieldProps } from './types.ts'; const displayName = 'v5.common.ActionsContent.partials.AmountField'; const AmountField: FC = ({ name, - tokenAddress, maxWidth, domainId, isDisabled, @@ -35,14 +34,15 @@ const AmountField: FC = ({ field, fieldState: { error }, } = useController({ - name: `${name}.amount`, + name, }); const { field: tokenAddressController, fieldState: { error: tokenAddressError }, } = useController({ - name: `${name}.tokenAddress`, + name: 'tokenAddress', }); + const [value, setValue] = useState(''); const isError = !!error || !!tokenAddressError; const { colony } = useColonyContext(); const [ @@ -53,22 +53,24 @@ const AmountField: FC = ({ const { colonyTokens, - dynamicCleaveOptionKey, formattingOptions, selectedToken, inputRef, adjustInputWidth, - } = useAmountField( - tokenAddress || tokenAddressController.value, - name, - maxWidth, - ); + } = useAmountField(tokenAddressController.value, maxWidth); - const handleCleaveChange = (e: CleaveChangeEvent) => { - field.onChange(e.target.rawValue); + const handleFieldChange = (e: ChangeEvent) => { + setValue(formatNumeral(e.target.value, formattingOptions)); adjustInputWidth(); }; + useEffect(() => { + const unformattedValue = unformatNumeral(value); + if (field.value !== unformattedValue) { + field.onChange(unformatNumeral(value)); + } + }, [value, field]); + const { portalElementRef, relativeElementRef } = useRelativePortalElement< HTMLButtonElement, HTMLDivElement @@ -94,15 +96,13 @@ const AmountField: FC = ({ className="flex items-center gap-3 w-full text-md" ref={registerContainerRef} > - { - inputRef.current = ref; + { + inputRef.current = ref || undefined; adjustInputWidth(); }} readOnly={readonly || isDisabled} name={name} - key={dynamicCleaveOptionKey} - options={formattingOptions} className={clsx('flex-shrink text-gray-900 outline-0 outline-none', { 'placeholder:text-gray-400': !isError || isDisabled, 'text-negative-400 placeholder:text-negative-400': @@ -111,107 +111,103 @@ const AmountField: FC = ({ placeholder={formatText({ id: 'actionSidebar.enterAmount', })} - value={field.value} + value={value} autoComplete="off" - onChange={handleCleaveChange} + onChange={handleFieldChange} /> - {tokenAddress ? ( -
{selectedTokenContent}
- ) : ( -
- - {isTokenSelectVisible && ( - - { - registerContainerRef(ref); - portalElementRef.current = ref; - }} - > -
- {formatText({ id: 'actionSidebar.availableTokens' })} -
-
    - {colonyTokens.map((colonyToken) => { - const tokenBalance = getBalanceForTokenAndDomain( - colony.balances, - colonyToken.tokenAddress, - domainId ?? Id.RootDomain, - ); - - return ( -
  • - - - -
  • - ); - })} -
-
-
+
+ + {isTokenSelectVisible && ( + + { + registerContainerRef(ref); + portalElementRef.current = ref; + }} + > +
+ {formatText({ id: 'actionSidebar.availableTokens' })} +
+
    + {colonyTokens.map((colonyToken) => { + const tokenBalance = getBalanceForTokenAndDomain( + colony.balances, + colonyToken.tokenAddress, + domainId ?? Id.RootDomain, + ); + + return ( +
  • + + + +
  • + ); + })} +
+
+
+ )} +
); }; diff --git a/src/components/v5/common/ActionSidebar/partials/AmountField/hooks.ts b/src/components/v5/common/ActionSidebar/partials/AmountField/hooks.ts index 9d0330749c1..59b654f5eac 100644 --- a/src/components/v5/common/ActionSidebar/partials/AmountField/hooks.ts +++ b/src/components/v5/common/ActionSidebar/partials/AmountField/hooks.ts @@ -1,4 +1,5 @@ -import { useMemo, useRef } from 'react'; +import { type FormatNumeralOptions } from 'cleave-zen'; +import { useRef } from 'react'; import { useColonyContext } from '~context/ColonyContext.tsx'; import { notNull } from '~utils/arrays/index.ts'; @@ -9,33 +10,31 @@ import { } from '~utils/tokens.ts'; export const useAmountField = ( - selectedTokenAddress: string, - name: string, + selectedTokenAddress: string | undefined, maxWidth: number | undefined, ) => { const inputRef = useRef(); - const { colony } = useColonyContext(); + const { + colony, + colony: { nativeToken }, + } = useColonyContext(); const colonyTokens = colony.tokens?.items .filter(notNull) .map((colonyToken) => colonyToken.token) || []; - const selectedToken = getSelectedToken(colony, selectedTokenAddress); - - const formattingOptions = useMemo( - () => ({ - name, - delimiter: ',', - numeral: true, - numeralPositiveOnly: true, - numeralDecimalScale: getTokenDecimalsWithFallback( - selectedToken?.decimals, - ), - }), - [selectedToken, name], + const selectedToken = getSelectedToken( + colony, + selectedTokenAddress || nativeToken.tokenAddress, ); + const formattingOptions: FormatNumeralOptions = { + delimiter: ',', + numeralPositiveOnly: true, + numeralDecimalScale: getTokenDecimalsWithFallback(selectedToken?.decimals), + }; + const adjustInputWidth = () => { if (!inputRef.current) { return; @@ -47,13 +46,10 @@ export const useAmountField = ( )}px`; }; - const dynamicCleaveOptionKey = JSON.stringify(formattingOptions); - return { inputRef, colonyTokens, adjustInputWidth, - dynamicCleaveOptionKey, formattingOptions, selectedToken, }; diff --git a/src/components/v5/common/ActionSidebar/partials/AmountField/types.ts b/src/components/v5/common/ActionSidebar/partials/AmountField/types.ts index 9aaa942a8f4..2055bfb7b84 100644 --- a/src/components/v5/common/ActionSidebar/partials/AmountField/types.ts +++ b/src/components/v5/common/ActionSidebar/partials/AmountField/types.ts @@ -1,12 +1,7 @@ -export type CleaveChangeEvent = React.ChangeEvent< - HTMLInputElement & { rawValue: string } ->; - export interface AmountFieldProps { name: string; amount?: string; defaultToken?: string; - tokenAddress?: string; maxWidth?: number; domainId?: number; isDisabled?: boolean; diff --git a/src/components/v5/common/ActionSidebar/partials/AmountRow/AmountRow.tsx b/src/components/v5/common/ActionSidebar/partials/AmountRow/AmountRow.tsx index b28be768e10..a1d3f0ccfc1 100644 --- a/src/components/v5/common/ActionSidebar/partials/AmountRow/AmountRow.tsx +++ b/src/components/v5/common/ActionSidebar/partials/AmountRow/AmountRow.tsx @@ -11,12 +11,7 @@ import { type AmountRowProps } from './types.ts'; const displayName = 'v5.common.ActionSidebar.partials.AmountRow'; -const AmountRow = ({ - tokenAddress, - domainId, - title, - tooltips, -}: AmountRowProps) => { +const AmountRow = ({ domainId, title, tooltips }: AmountRowProps) => { const hasNoDecisionMethods = useHasNoDecisionMethods(); return ( @@ -30,7 +25,6 @@ const AmountRow = ({ diff --git a/src/components/v5/common/ActionSidebar/partials/AmountRow/types.ts b/src/components/v5/common/ActionSidebar/partials/AmountRow/types.ts index b6a71298fb0..05c1f7427f0 100644 --- a/src/components/v5/common/ActionSidebar/partials/AmountRow/types.ts +++ b/src/components/v5/common/ActionSidebar/partials/AmountRow/types.ts @@ -3,7 +3,7 @@ import { type ActionFormRowProps } from '~v5/common/ActionFormRow/types.ts'; import { type AmountFieldProps } from '../AmountField/types.ts'; export interface AmountRowProps - extends Pick, + extends Pick, Pick { title?: React.ReactNode; } diff --git a/src/components/v5/common/ActionSidebar/partials/Motions/steps/StakingStep/partials/StakingForm/StakingForm.tsx b/src/components/v5/common/ActionSidebar/partials/Motions/steps/StakingStep/partials/StakingForm/StakingForm.tsx index f5732e4e639..58687ef5e8d 100644 --- a/src/components/v5/common/ActionSidebar/partials/Motions/steps/StakingStep/partials/StakingForm/StakingForm.tsx +++ b/src/components/v5/common/ActionSidebar/partials/Motions/steps/StakingStep/partials/StakingForm/StakingForm.tsx @@ -181,11 +181,9 @@ const StakingForm: FC = ({ name="amount" placeholder="0" options={{ - numeral: true, numeralDecimalScale: getTokenDecimalsWithFallback(tokenDecimals), numeralPositiveOnly: true, - rawValueTrimPrefix: true, tailPrefix: true, }} buttonProps={{ diff --git a/src/components/v5/common/ActionSidebar/partials/TransactionTable/TransactionTable.tsx b/src/components/v5/common/ActionSidebar/partials/TransactionTable/TransactionTable.tsx index 5e72e54bec0..872ab41b48b 100644 --- a/src/components/v5/common/ActionSidebar/partials/TransactionTable/TransactionTable.tsx +++ b/src/components/v5/common/ActionSidebar/partials/TransactionTable/TransactionTable.tsx @@ -18,10 +18,7 @@ import { const displayName = 'v5.common.ActionsContent.partials.TransactionTable'; -const TransactionTable: FC = ({ - name, - tokenAddress, -}) => { +const TransactionTable: FC = ({ name }) => { const fieldArrayMethods = useFieldArray({ name, }); @@ -31,7 +28,7 @@ const TransactionTable: FC = ({ }), ); const { readonly } = useAdditionalFormOptionsContext(); - const columns = useTransactionTableColumns(name, tokenAddress); + const columns = useTransactionTableColumns(name); const isMobile = useMobile(); const value = useWatch({ name }); const getMenuProps = ({ index }) => diff --git a/src/components/v5/common/ActionSidebar/partials/TransactionTable/hooks.tsx b/src/components/v5/common/ActionSidebar/partials/TransactionTable/hooks.tsx index e84004d8234..d6b74e569f7 100644 --- a/src/components/v5/common/ActionSidebar/partials/TransactionTable/hooks.tsx +++ b/src/components/v5/common/ActionSidebar/partials/TransactionTable/hooks.tsx @@ -11,7 +11,6 @@ import { type TransactionTableModel } from './types.ts'; export const useTransactionTableColumns = ( name: string, - tokenAddress?: string, ): ColumnDef[] => { const { watch } = useFormContext(); const selectedTeam = watch('from'); @@ -37,13 +36,12 @@ export const useTransactionTableColumns = ( ), }), ], - [columnHelper, name, selectedTeam, tokenAddress], + [columnHelper, name, selectedTeam], ); return columns; diff --git a/src/components/v5/common/ActionSidebar/partials/forms/MintTokenForm/MintTokenForm.tsx b/src/components/v5/common/ActionSidebar/partials/forms/MintTokenForm/MintTokenForm.tsx index 8471ccd9036..8ad2ff17624 100644 --- a/src/components/v5/common/ActionSidebar/partials/forms/MintTokenForm/MintTokenForm.tsx +++ b/src/components/v5/common/ActionSidebar/partials/forms/MintTokenForm/MintTokenForm.tsx @@ -1,6 +1,5 @@ import React, { type FC } from 'react'; -import { useColonyContext } from '~context/ColonyContext.tsx'; import { formatText } from '~utils/intl.ts'; import { type ActionFormBaseProps } from '../../../types.ts'; @@ -14,16 +13,11 @@ import { useMintToken } from './hooks.ts'; const displayName = 'v5.common.ActionSidebar.partials.MintTokenForm'; const MintTokenForm: FC = ({ getFormOptions }) => { - const { - colony: { nativeToken }, - } = useColonyContext(); - useMintToken(getFormOptions); return ( <> 'required field') - .transform((value) => toFinite(value)) - .moreThan(0, () => 'Amount must be greater than zero.'), - }) - .required(), + amount: number() + .required(() => 'required field') + .transform((value) => toFinite(value)) + .moreThan(0, () => 'Amount must be greater than zero.'), + tokenAddress: string().address().required(), decisionMethod: string().defined(), }) .defined() diff --git a/src/components/v5/common/ActionSidebar/partials/forms/MintTokenForm/hooks.ts b/src/components/v5/common/ActionSidebar/partials/forms/MintTokenForm/hooks.ts index 874749ab5fc..ed794363cd7 100644 --- a/src/components/v5/common/ActionSidebar/partials/forms/MintTokenForm/hooks.ts +++ b/src/components/v5/common/ActionSidebar/partials/forms/MintTokenForm/hooks.ts @@ -28,9 +28,9 @@ export const useMintToken = ( defaultValues: useMemo>( () => ({ createdIn: Id.RootDomain, - amount: {}, + tokenAddress: colony.nativeToken.tokenAddress, }), - [], + [colony], ), actionType: decisionMethod === DecisionMethod.Permissions diff --git a/src/components/v5/common/ActionSidebar/partials/forms/MintTokenForm/utils.tsx b/src/components/v5/common/ActionSidebar/partials/forms/MintTokenForm/utils.tsx index 0c1b62dd7bd..89b30919195 100644 --- a/src/components/v5/common/ActionSidebar/partials/forms/MintTokenForm/utils.tsx +++ b/src/components/v5/common/ActionSidebar/partials/forms/MintTokenForm/utils.tsx @@ -12,15 +12,11 @@ export const getMintTokenPayload = ( colony: Colony, values: MintTokenFormValues, ) => { - const { - amount: { amount: inputAmount }, - description: annotationMessage, - title, - } = values; + const { amount, description: annotationMessage, title } = values; - const amount = BigNumber.from( + const WEIAmount = BigNumber.from( moveDecimal( - inputAmount, + amount, getTokenDecimalsWithFallback(colony?.nativeToken?.decimals), ), ); @@ -30,8 +26,8 @@ export const getMintTokenPayload = ( colonyAddress: colony.colonyAddress, colonyName: colony.name, nativeTokenAddress: colony.nativeToken.tokenAddress, - motionParams: [amount], - amount, + motionParams: [WEIAmount], + amount: WEIAmount, annotationMessage: annotationMessage ? sanitizeHTML(annotationMessage) : undefined, diff --git a/src/components/v5/common/ActionSidebar/partials/forms/SimplePaymentForm/SimplePaymentForm.tsx b/src/components/v5/common/ActionSidebar/partials/forms/SimplePaymentForm/SimplePaymentForm.tsx index 2d7d785c373..2d38c3f2adc 100644 --- a/src/components/v5/common/ActionSidebar/partials/forms/SimplePaymentForm/SimplePaymentForm.tsx +++ b/src/components/v5/common/ActionSidebar/partials/forms/SimplePaymentForm/SimplePaymentForm.tsx @@ -72,7 +72,7 @@ const SimplePaymentForm: FC = ({ getFormOptions }) => { {/* Disabled for now */} - {/* */} + {/* */} ); }; diff --git a/src/components/v5/common/ActionSidebar/partials/forms/SimplePaymentForm/hooks.ts b/src/components/v5/common/ActionSidebar/partials/forms/SimplePaymentForm/hooks.ts index 9297b9048df..9ea6731df79 100644 --- a/src/components/v5/common/ActionSidebar/partials/forms/SimplePaymentForm/hooks.ts +++ b/src/components/v5/common/ActionSidebar/partials/forms/SimplePaymentForm/hooks.ts @@ -32,29 +32,19 @@ export const useValidationSchema = () => { () => object() .shape({ - amount: object() - .shape({ - amount: number() - .required(() => formatText({ id: 'errors.amount' })) - .transform((value) => toFinite(value)) - .moreThan(0, () => - formatText({ id: 'errors.amount.greaterThanZero' }), - ) - .test( - 'enough-tokens', - formatText({ id: 'errors.amount.notEnoughTokens' }) || '', - (value, context) => - hasEnoughFundsValidation( - value, - context, - selectedTeam, - colony, - ), - ), - tokenAddress: string().address().required(), - }) - .required() - .defined(), + amount: number() + .required(() => formatText({ id: 'errors.amount' })) + .transform((value) => toFinite(value)) + .moreThan(0, () => + formatText({ id: 'errors.amount.greaterThanZero' }), + ) + .test( + 'enough-tokens', + formatText({ id: 'errors.amount.notEnoughTokens' }) || '', + (value, context) => + hasEnoughFundsValidation(value, context, selectedTeam, colony), + ), + tokenAddress: string().address().required(), createdIn: number().defined(), recipient: string().address().required(), from: number().required(), @@ -64,25 +54,21 @@ export const useValidationSchema = () => { object() .shape({ recipient: string().required(), - amount: object() - .shape({ - amount: number() - .required(() => formatText({ id: 'errors.amount' })) - .transform((value) => toFinite(value)) - .moreThan(0, ({ path }) => { - const index = getLastIndexFromPath(path); + amount: number() + .required(() => formatText({ id: 'errors.amount' })) + .transform((value) => toFinite(value)) + .moreThan(0, ({ path }) => { + const index = getLastIndexFromPath(path); - if (index === undefined) { - return formatText({ id: 'errors.amount' }); - } + if (index === undefined) { + return formatText({ id: 'errors.amount' }); + } - return formatText( - { id: 'errors.payments.amount' }, - { paymentIndex: index + 1 }, - ); - }), - }) - .required(), + return formatText( + { id: 'errors.payments.amount' }, + { paymentIndex: index + 1 }, + ); + }), }) .required(), ) @@ -108,9 +94,6 @@ export const useSimplePayment = ( const decisionMethod: DecisionMethod | undefined = useWatch({ name: DECISION_METHOD_FIELD_NAME, }); - const selectedTokenAddress: string = useWatch({ - name: 'amount.tokenAddress', - }); const validationSchema = useValidationSchema(); useActionFormBaseHook({ @@ -119,11 +102,9 @@ export const useSimplePayment = ( () => ({ createdIn: Id.RootDomain, payments: [], - amount: { - tokenAddress: selectedTokenAddress ?? colony.nativeToken.tokenAddress, - }, + tokenAddress: colony.nativeToken.tokenAddress, }), - [selectedTokenAddress, colony.nativeToken.tokenAddress], + [colony.nativeToken.tokenAddress], ), actionType: decisionMethod === DecisionMethod.Permissions diff --git a/src/components/v5/common/ActionSidebar/partials/forms/SimplePaymentForm/utils.tsx b/src/components/v5/common/ActionSidebar/partials/forms/SimplePaymentForm/utils.tsx index d0c02fc0393..f12b7955d8b 100644 --- a/src/components/v5/common/ActionSidebar/partials/forms/SimplePaymentForm/utils.tsx +++ b/src/components/v5/common/ActionSidebar/partials/forms/SimplePaymentForm/utils.tsx @@ -52,6 +52,7 @@ export const getSimplePaymentPayload = ( createdIn, title, amount, + tokenAddress, recipient: recipientAddress, payments, } = values; @@ -66,16 +67,16 @@ export const getSimplePaymentPayload = ( getPaymentPayload({ colony, recipientAddress, - amount: amount.amount.toString(), - tokenAddress: amount.tokenAddress, + amount: amount.toString(), + tokenAddress, networkInverseFee, }), ...payments.map(({ recipient, amount: paymentAmount }) => getPaymentPayload({ colony, recipientAddress: recipient, - amount: paymentAmount.amount.toString(), - tokenAddress: amount.tokenAddress, + amount: paymentAmount.toString(), + tokenAddress, networkInverseFee, }), ), diff --git a/src/components/v5/common/ActionSidebar/partials/forms/TransferFundsForm/hooks.ts b/src/components/v5/common/ActionSidebar/partials/forms/TransferFundsForm/hooks.ts index 4634eaf23dd..caf589164c2 100644 --- a/src/components/v5/common/ActionSidebar/partials/forms/TransferFundsForm/hooks.ts +++ b/src/components/v5/common/ActionSidebar/partials/forms/TransferFundsForm/hooks.ts @@ -30,29 +30,19 @@ export const useValidationSchema = () => { () => object() .shape({ - amount: object() - .shape({ - amount: number() - .required(() => formatText({ id: 'errors.amount' })) - .transform((value) => toFinite(value)) - .moreThan(0, () => - formatText({ id: 'errors.amount.greaterThanZero' }), - ) - .test( - 'enough-tokens', - formatText({ id: 'errors.amount.notEnoughTokens' }) || '', - (value, context) => - hasEnoughFundsValidation( - value, - context, - selectedTeam, - colony, - ), - ), - tokenAddress: string().address().required(), - }) - .required() - .defined(), + amount: number() + .required(() => formatText({ id: 'errors.amount' })) + .transform((value) => toFinite(value)) + .moreThan(0, () => + formatText({ id: 'errors.amount.greaterThanZero' }), + ) + .test( + 'enough-tokens', + formatText({ id: 'errors.amount.notEnoughTokens' }) || '', + (value, context) => + hasEnoughFundsValidation(value, context, selectedTeam, colony), + ), + tokenAddress: string().address().required(), createdIn: number().defined(), from: number().required(), to: number() @@ -81,17 +71,11 @@ export const useTransferFunds = ( getFormOptions: ActionFormBaseProps['getFormOptions'], ) => { const { colony } = useColonyContext(); - const { - [DECISION_METHOD_FIELD_NAME]: decisionMethod, - from, - amount, - } = useWatch<{ + const { [DECISION_METHOD_FIELD_NAME]: decisionMethod, from } = useWatch<{ decisionMethod: DecisionMethod; from: TransferFundsFormValues['from']; - amount: TransferFundsFormValues['amount']; }>(); - const selectedTokenAddress = amount?.tokenAddress; const validationSchema = useValidationSchema(); useActionFormBaseHook({ @@ -100,11 +84,9 @@ export const useTransferFunds = ( () => ({ createdIn: from || Id.RootDomain, from: Id.RootDomain, - amount: { - tokenAddress: selectedTokenAddress ?? colony.nativeToken.tokenAddress, - }, + tokenAddress: colony.nativeToken.tokenAddress, }), - [from, selectedTokenAddress, colony.nativeToken.tokenAddress], + [from, colony.nativeToken.tokenAddress], ), actionType: decisionMethod === DecisionMethod.Permissions diff --git a/src/components/v5/common/ActionSidebar/partials/forms/TransferFundsForm/utils.tsx b/src/components/v5/common/ActionSidebar/partials/forms/TransferFundsForm/utils.tsx index 6c05db227de..bd7572a7dc1 100644 --- a/src/components/v5/common/ActionSidebar/partials/forms/TransferFundsForm/utils.tsx +++ b/src/components/v5/common/ActionSidebar/partials/forms/TransferFundsForm/utils.tsx @@ -11,7 +11,8 @@ import { type TransferFundsFormValues } from './hooks.ts'; export const getTransferFundsPayload = ( colony: Colony, { - amount: { amount: transferAmount, tokenAddress }, + amount, + tokenAddress, from: fromDomainId, to: toDomainId, description: annotationMessage, @@ -25,7 +26,7 @@ export const getTransferFundsPayload = ( const decimals = getTokenDecimalsWithFallback(selectedToken?.token.decimals); // Convert amount string with decimals to BigInt (eth to wei) - const amount = BigNumber.from(moveDecimal(transferAmount, decimals)); + const transferAmount = BigNumber.from(moveDecimal(amount, decimals)); const fromDomain = findDomainByNativeId(Number(fromDomainId), colony); const toDomain = findDomainByNativeId(Number(toDomainId), colony); @@ -36,7 +37,7 @@ export const getTransferFundsPayload = ( tokenAddress, fromDomain, toDomain, - amount, + amount: transferAmount, annotationMessage: annotationMessage ? sanitizeHTML(annotationMessage) : undefined, diff --git a/src/components/v5/common/Fields/InputBase/FormFormattedInput.tsx b/src/components/v5/common/Fields/InputBase/FormFormattedInput.tsx index 2673164916a..84d7c227dbe 100644 --- a/src/components/v5/common/Fields/InputBase/FormFormattedInput.tsx +++ b/src/components/v5/common/Fields/InputBase/FormFormattedInput.tsx @@ -14,7 +14,7 @@ const FormFormattedInput: FC = ({ ...rest }) => { const { - field: { onChange, value }, + field: { value }, fieldState: { invalid, error }, } = useController({ name, @@ -26,11 +26,6 @@ const FormFormattedInput: FC = ({ {...rest} type={type} value={value} - onChange={(event) => { - const { rawValue } = event.target; - - onChange(rawValue); - }} state={invalid ? FieldState.Error : undefined} /> ); diff --git a/src/components/v5/common/Fields/InputBase/FormattedInput.tsx b/src/components/v5/common/Fields/InputBase/FormattedInput.tsx index 20428c1ed20..333c2b21139 100644 --- a/src/components/v5/common/Fields/InputBase/FormattedInput.tsx +++ b/src/components/v5/common/Fields/InputBase/FormattedInput.tsx @@ -1,4 +1,3 @@ -import Cleave from 'cleave.js/react'; import clsx from 'clsx'; import React, { type FC } from 'react'; @@ -11,10 +10,8 @@ import { type FormattedInputProps } from './types.ts'; const displayName = 'v5.common.Fields.FormattedInput'; const FormattedInput: FC = ({ - options, onChange, disabled, - value, placeholder, className, state, @@ -27,13 +24,7 @@ const FormattedInput: FC = ({ message, ...rest }) => { - const { - dynamicCleaveOptionKey, - setCleave, - buttonRef, - wrapperRef, - customPrefixRef, - } = useFormattedInput(value, options); + const { buttonRef, wrapperRef, customPrefixRef } = useFormattedInput(); const stateClassNames = useStateClassNames( { @@ -86,17 +77,10 @@ const FormattedInput: FC = ({ {customPrefix} )} - setCleave(cleaveInstance)} onChange={onChange} className={clsx( className, diff --git a/src/components/v5/common/Fields/InputBase/hooks.ts b/src/components/v5/common/Fields/InputBase/hooks.ts index a80d3f0d65e..0f700675017 100644 --- a/src/components/v5/common/Fields/InputBase/hooks.ts +++ b/src/components/v5/common/Fields/InputBase/hooks.ts @@ -1,16 +1,8 @@ -import { type ReactInstanceWithCleave } from 'cleave.js/react/props'; import noop from 'lodash/noop'; -import { - useEffect, - useLayoutEffect, - useRef, - useState, - useImperativeHandle, -} from 'react'; +import { useEffect, useLayoutEffect, useRef, useImperativeHandle } from 'react'; import { getInputTextWidth } from '~utils/elements.ts'; -import { type FormattedInputProps } from './types.ts'; import { addWidthProperty } from './utils.ts'; export const useAdjustInputWidth = ( @@ -49,33 +41,11 @@ export const useAdjustInputWidth = ( return inputRef; }; -export const useFormattedInput = ( - value: FormattedInputProps['value'], - options?: FormattedInputProps['options'], -) => { - const [cleave, setCleave] = useState(null); +export const useFormattedInput = () => { const wrapperRef = useRef(null); const buttonRef = useRef(null); const customPrefixRef = useRef(null); - const { prefix, tailPrefix } = options || {}; - - /** - * Sync the cleave raw value with value prop - * This is necessary for correctly setting the initial value - */ - useEffect(() => { - if (typeof value !== 'string') { - return; - } - - cleave?.setRawValue( - `${prefix && !tailPrefix ? prefix : ''}${value}${ - prefix && tailPrefix ? ` ${prefix}` : '' - }`, - ); - }, [cleave, prefix, tailPrefix, value]); - useEffect(() => { addWidthProperty(buttonRef.current, wrapperRef.current, 'button'); addWidthProperty( @@ -85,17 +55,7 @@ export const useFormattedInput = ( ); }, []); - // /* - // * @NOTE Coerce cleave into handling dynamically changing options - // * See here for why this isn't yet supported "officially": - // * https://github.com/nosir/cleave.js/issues/352#issuecomment-447640572 - // */ - - const dynamicCleaveOptionKey = JSON.stringify(options); - return { - dynamicCleaveOptionKey, - setCleave, wrapperRef, buttonRef, customPrefixRef, diff --git a/src/components/v5/common/Fields/InputBase/types.ts b/src/components/v5/common/Fields/InputBase/types.ts index bd90ede8ef2..d62a6bfeedf 100644 --- a/src/components/v5/common/Fields/InputBase/types.ts +++ b/src/components/v5/common/Fields/InputBase/types.ts @@ -1,4 +1,4 @@ -import { type Props as CleaveProps } from 'cleave.js/react/props'; +import { type FormatNumeralOptions } from 'cleave-zen'; import { type InputHTMLAttributes } from 'react'; import { type BaseFieldProps } from '../types.ts'; @@ -21,9 +21,8 @@ export interface FormInputBaseProps name: string; } -export interface FormattedInputProps - extends Omit, - CleaveProps { +export interface FormattedInputProps extends Omit { + options: FormatNumeralOptions; buttonProps?: React.HTMLAttributes & { label: string; }; diff --git a/src/components/v5/common/TokensModal/TokensModal.tsx b/src/components/v5/common/TokensModal/TokensModal.tsx index 3a2257dd795..dbeda04a1eb 100644 --- a/src/components/v5/common/TokensModal/TokensModal.tsx +++ b/src/components/v5/common/TokensModal/TokensModal.tsx @@ -83,10 +83,8 @@ const TokensModal: FC = ({ type, onClose, ...props }) => { ) : undefined } options={{ - numeral: true, numeralDecimalScale: tokenDecimals, numeralPositiveOnly: true, - rawValueTrimPrefix: true, tailPrefix: true, }} buttonProps={{ diff --git a/src/constants/extensions.ts b/src/constants/extensions.ts index 2e4a716aee0..c7b47f4a4f8 100644 --- a/src/constants/extensions.ts +++ b/src/constants/extensions.ts @@ -352,7 +352,6 @@ export const supportedExtensionsConfig: ExtensionConfig[] = [ type: ExtensionParamType.Input, complementaryLabel: 'percent', formattingOptions: { - numeral: true, numeralPositiveOnly: true, }, transformValue: convertFractionToWei, @@ -370,7 +369,6 @@ export const supportedExtensionsConfig: ExtensionConfig[] = [ type: ExtensionParamType.Input, complementaryLabel: 'percent', formattingOptions: { - numeral: true, numeralPositiveOnly: true, }, transformValue: convertFractionToWei, @@ -388,7 +386,6 @@ export const supportedExtensionsConfig: ExtensionConfig[] = [ type: ExtensionParamType.Input, complementaryLabel: 'percent', formattingOptions: { - numeral: true, numeralPositiveOnly: true, }, transformValue: convertFractionToWei, @@ -406,7 +403,6 @@ export const supportedExtensionsConfig: ExtensionConfig[] = [ type: ExtensionParamType.Input, complementaryLabel: 'percent', formattingOptions: { - numeral: true, numeralPositiveOnly: true, }, transformValue: convertFractionToWei, @@ -424,7 +420,6 @@ export const supportedExtensionsConfig: ExtensionConfig[] = [ type: ExtensionParamType.Input, complementaryLabel: 'hours', formattingOptions: { - numeral: true, numeralPositiveOnly: true, }, transformValue: convertPeriodToSeconds, @@ -442,7 +437,6 @@ export const supportedExtensionsConfig: ExtensionConfig[] = [ type: ExtensionParamType.Input, complementaryLabel: 'hours', formattingOptions: { - numeral: true, numeralPositiveOnly: true, }, transformValue: convertPeriodToSeconds, @@ -460,7 +454,6 @@ export const supportedExtensionsConfig: ExtensionConfig[] = [ type: ExtensionParamType.Input, complementaryLabel: 'hours', formattingOptions: { - numeral: true, numeralPositiveOnly: true, }, transformValue: convertPeriodToSeconds, @@ -484,7 +477,6 @@ export const supportedExtensionsConfig: ExtensionConfig[] = [ type: ExtensionParamType.Input, complementaryLabel: 'hours', formattingOptions: { - numeral: true, numeralPositiveOnly: true, }, transformValue: convertPeriodToSeconds, @@ -523,7 +515,6 @@ export const supportedExtensionsConfig: ExtensionConfig[] = [ // type: ExtensionParamType.Input, // complementaryLabel: 'percent', // formattingOptions: { - // numeral: true, // numeralPositiveOnly: true, // }, // transformValue: convertFractionToWei, diff --git a/src/types/extensions.ts b/src/types/extensions.ts index f07aa0d434d..5b40d5e5a9b 100644 --- a/src/types/extensions.ts +++ b/src/types/extensions.ts @@ -1,6 +1,6 @@ import { type ColonyRole, type Extension } from '@colony/colony-js'; import { type Icon } from '@phosphor-icons/react'; -import { type CleaveOptions } from 'cleave.js/options'; +import { type FormatNumeralOptions } from 'cleave-zen'; import { type BigNumberish } from 'ethers'; import { type MessageDescriptor } from 'react-intl'; import { type Schema } from 'yup'; @@ -28,7 +28,7 @@ export interface ExtensionInitParam { validation: Schema; type: ExtensionParamType; complementaryLabel?: 'hours' | 'periods' | 'percent'; - formattingOptions?: CleaveOptions; + formattingOptions?: FormatNumeralOptions; // Transform function that will be applied to the param value before passing it to the saga transformValue?: (value: string | number) => BigNumberish; }