Asset modal rework (min balance with decimals) (#5126)
* Asset modal rework (min balance with decimals) * Language cleanups
This commit is contained in:
parent
957dc068aa
commit
c231b66f6b
@ -2,16 +2,15 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { AssetId } from '@polkadot/types/interfaces';
|
||||
import type { InfoState, MetadataState, TeamState } from './types';
|
||||
import type { InfoState, TeamState } from './types';
|
||||
|
||||
import React, { useMemo, useState } from 'react';
|
||||
|
||||
import { Button, Modal, TxButton } from '@polkadot/react-components';
|
||||
import { useStepper, useTxBatch } from '@polkadot/react-hooks';
|
||||
import { useApi, useStepper, useTxBatch } from '@polkadot/react-hooks';
|
||||
|
||||
import { useTranslation } from '../../translate';
|
||||
import Info from './Info';
|
||||
import Metadata from './Metadata';
|
||||
import Team from './Team';
|
||||
|
||||
interface Props {
|
||||
@ -26,21 +25,43 @@ const BATCH_OPTIONS = {
|
||||
|
||||
function Create ({ assetIds, className, onClose }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const [step, nextStep, prevStep] = useStepper();
|
||||
const [asset, setAsset] = useState<InfoState | null>(null);
|
||||
const [metadata, setMetadata] = useState<MetadataState | null>(null);
|
||||
const [team, setTeam] = useState<TeamState | null>(null);
|
||||
const txs = useMemo(() => asset && metadata && team && (
|
||||
team.teamTx
|
||||
? [asset.createTx, metadata.metadataTx, team.teamTx]
|
||||
: [asset.createTx, metadata.metadataTx]
|
||||
), [asset, metadata, team]);
|
||||
|
||||
const [createTx, metadataTx] = useMemo(
|
||||
() => asset
|
||||
? [
|
||||
api.tx.assets.create(asset.assetId, asset.accountId, asset.minBalance),
|
||||
api.tx.assets.setMetadata(asset.assetId, asset.assetName, asset.assetSymbol, asset.assetDecimals)
|
||||
]
|
||||
: [null, null],
|
||||
[api, asset]
|
||||
);
|
||||
|
||||
const teamTx = useMemo(
|
||||
() => asset && team && (team.adminId !== asset.accountId || team.freezerId !== asset.accountId || team.issuerId !== asset.accountId)
|
||||
? api.tx.assets.setTeam(asset.assetId, team.issuerId, team.adminId, team.freezerId)
|
||||
: null,
|
||||
[api, asset, team]
|
||||
);
|
||||
|
||||
const txs = useMemo(
|
||||
() => createTx && metadataTx && team && (
|
||||
teamTx
|
||||
? [createTx, metadataTx, teamTx]
|
||||
: [createTx, metadataTx]
|
||||
),
|
||||
[createTx, metadataTx, team, teamTx]
|
||||
);
|
||||
|
||||
const extrinsic = useTxBatch(txs, BATCH_OPTIONS);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className={className}
|
||||
header={t<string>('create asset {{step}}/{{steps}}', { replace: { step, steps: 3 } })}
|
||||
header={t<string>('create asset {{step}}/{{steps}}', { replace: { step, steps: 2 } })}
|
||||
size='large'
|
||||
>
|
||||
{step === 1 && (
|
||||
@ -50,17 +71,9 @@ function Create ({ assetIds, className, onClose }: Props): React.ReactElement<Pr
|
||||
onChange={setAsset}
|
||||
/>
|
||||
)}
|
||||
{step === 2 && (
|
||||
<Metadata
|
||||
assetId={asset?.assetId}
|
||||
defaultValue={metadata}
|
||||
onChange={setMetadata}
|
||||
/>
|
||||
)}
|
||||
{step === 3 && (
|
||||
{step === 2 && asset && (
|
||||
<Team
|
||||
accountId={asset?.accountId}
|
||||
assetId={asset?.assetId}
|
||||
accountId={asset.accountId}
|
||||
defaultValue={team}
|
||||
onChange={setTeam}
|
||||
/>
|
||||
@ -75,21 +88,6 @@ function Create ({ assetIds, className, onClose }: Props): React.ReactElement<Pr
|
||||
/>
|
||||
}
|
||||
{step === 2 && (
|
||||
<>
|
||||
<Button
|
||||
icon='step-backward'
|
||||
label={t<string>('Prev')}
|
||||
onClick={prevStep}
|
||||
/>
|
||||
<Button
|
||||
icon='step-forward'
|
||||
isDisabled={!metadata}
|
||||
label={t<string>('Next')}
|
||||
onClick={nextStep}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{step === 3 && (
|
||||
<>
|
||||
<Button
|
||||
icon='step-backward'
|
||||
|
||||
@ -7,7 +7,7 @@ import type { InfoState } from './types';
|
||||
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { InputAddress, InputNumber, Modal } from '@polkadot/react-components';
|
||||
import { Input, InputAddress, InputBalance, InputNumber, Modal } from '@polkadot/react-components';
|
||||
import { useApi } from '@polkadot/react-hooks';
|
||||
import { BN_ONE, BN_ZERO } from '@polkadot/util';
|
||||
|
||||
@ -33,20 +33,45 @@ function Info ({ assetIds, className = '', defaultValue, onChange }: Props): Rea
|
||||
const [initialId] = useState(() => findAvailbleId(assetIds));
|
||||
const [accountId, setAccountId] = useState<string | null>(null);
|
||||
const [assetId, setAssetId] = useState<BN | null>(null);
|
||||
const [assetDecimals, setAssetDecimals] = useState<BN | null>(null);
|
||||
const [assetName, setAssetName] = useState<string | null | undefined>(() => defaultValue?.assetName);
|
||||
const [assetSymbol, setAssetSymbol] = useState<string | null | undefined>(() => defaultValue?.assetSymbol);
|
||||
const [minBalance, setMinBalance] = useState<BN | null>(null);
|
||||
|
||||
const isIdValid = useMemo(
|
||||
const [siDecimals, siSymbol] = useMemo(
|
||||
() => assetDecimals && assetSymbol
|
||||
? [assetDecimals.toNumber(), assetSymbol.toUpperCase()]
|
||||
: [0, 'NONE'],
|
||||
[assetDecimals, assetSymbol]
|
||||
);
|
||||
|
||||
const isValidDecimals = useMemo(
|
||||
() => !!assetDecimals && assetDecimals.lten(20),
|
||||
[assetDecimals]
|
||||
);
|
||||
|
||||
const isValidName = useMemo(
|
||||
() => !!assetName && assetName.length >= 3 && assetName.length <= 32,
|
||||
[assetName]
|
||||
);
|
||||
|
||||
const isValidSymbol = useMemo(
|
||||
() => !!assetSymbol && assetSymbol.length >= 3 && assetSymbol.length <= 7,
|
||||
[assetSymbol]
|
||||
);
|
||||
|
||||
const isValidId = useMemo(
|
||||
() => !!assetId && assetId.gt(BN_ZERO) && !assetIds.some((a) => a.eq(assetId)),
|
||||
[assetId, assetIds]
|
||||
);
|
||||
|
||||
useEffect((): void => {
|
||||
onChange(
|
||||
assetId && accountId && minBalance && isIdValid && !minBalance.isZero()
|
||||
? { accountId, assetId, createTx: api.tx.assets.create(assetId, accountId, minBalance), minBalance }
|
||||
assetId && assetName && assetSymbol && assetDecimals && isValidId && isValidName && isValidSymbol && isValidDecimals && accountId && minBalance && !minBalance.isZero()
|
||||
? { accountId, assetDecimals, assetId, assetName, assetSymbol, minBalance }
|
||||
: null
|
||||
);
|
||||
}, [api, accountId, assetId, assetIds, isIdValid, minBalance, onChange]);
|
||||
}, [api, accountId, assetDecimals, assetId, assetIds, assetName, assetSymbol, isValidId, isValidName, isValidSymbol, isValidDecimals, minBalance, onChange]);
|
||||
|
||||
return (
|
||||
<Modal.Content className={className}>
|
||||
@ -58,22 +83,48 @@ function Info ({ assetIds, className = '', defaultValue, onChange }: Props): Rea
|
||||
type='account'
|
||||
/>
|
||||
</Modal.Columns>
|
||||
<Modal.Columns hint={t<string>('The selected id for the asset. This should not match an already-existing asset id.')}>
|
||||
<InputNumber
|
||||
<Modal.Columns hint={t<string>('The descriptive name for this asset.')}>
|
||||
<Input
|
||||
autoFocus
|
||||
defaultValue={initial?.assetId || initialId}
|
||||
isError={!isIdValid}
|
||||
isZeroable={false}
|
||||
label={t<string>('asset id')}
|
||||
onChange={setAssetId}
|
||||
defaultValue={initial?.assetName}
|
||||
isError={!isValidName}
|
||||
label={t<string>('asset name')}
|
||||
onChange={setAssetName}
|
||||
/>
|
||||
</Modal.Columns>
|
||||
<Modal.Columns hint={t<string>('The minimum balance for the asset.')}>
|
||||
<Modal.Columns hint={t<string>('The symbol that will represent this asset.')}>
|
||||
<Input
|
||||
defaultValue={initial?.assetSymbol}
|
||||
isError={!isValidSymbol}
|
||||
label={t<string>('asset symbol')}
|
||||
onChange={setAssetSymbol}
|
||||
/>
|
||||
</Modal.Columns>
|
||||
<Modal.Columns hint={t<string>('The number of decimals for this token. Max allowed via the UI is set to 20.')}>
|
||||
<InputNumber
|
||||
defaultValue={initial?.minBalance || BN_ONE}
|
||||
defaultValue={initial?.assetDecimals}
|
||||
isError={!isValidDecimals}
|
||||
label={t<string>('asset decimals')}
|
||||
onChange={setAssetDecimals}
|
||||
/>
|
||||
</Modal.Columns>
|
||||
<Modal.Columns hint={t<string>('The minimum balance for the asset. This is specified in the units and decimals as requested.')}>
|
||||
<InputBalance
|
||||
defaultValue={initial?.minBalance}
|
||||
isZeroable={false}
|
||||
label={t<string>('minimum balance')}
|
||||
onChange={setMinBalance}
|
||||
siDecimals={siDecimals}
|
||||
siSymbol={siSymbol}
|
||||
/>
|
||||
</Modal.Columns>
|
||||
<Modal.Columns hint={t<string>('The selected id for the asset. This should not match an already-existing asset id.')}>
|
||||
<InputNumber
|
||||
defaultValue={initial?.assetId || initialId}
|
||||
isError={!isValidId}
|
||||
isZeroable={false}
|
||||
label={t<string>('asset id')}
|
||||
onChange={setAssetId}
|
||||
/>
|
||||
</Modal.Columns>
|
||||
</Modal.Content>
|
||||
|
||||
@ -1,83 +0,0 @@
|
||||
// Copyright 2017-2021 @polkadot/app-assets authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type BN from 'bn.js';
|
||||
import type { MetadataState } from './types';
|
||||
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { Input, InputNumber, Modal } from '@polkadot/react-components';
|
||||
import { useApi } from '@polkadot/react-hooks';
|
||||
|
||||
import { useTranslation } from '../../translate';
|
||||
|
||||
interface Props {
|
||||
assetId?: BN | null;
|
||||
className?: string;
|
||||
defaultValue: MetadataState | null;
|
||||
onChange: (info: MetadataState | null) => void;
|
||||
}
|
||||
|
||||
function Metadata ({ assetId, className = '', defaultValue, onChange }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const [initial] = useState(() => defaultValue);
|
||||
const [assetDecimals, setAssetDecimals] = useState<BN | null>(null);
|
||||
const [assetName, setAssetName] = useState<string | null | undefined>(() => defaultValue?.assetName);
|
||||
const [assetSymbol, setAssetSymbol] = useState<string | null | undefined>(() => defaultValue?.assetSymbol);
|
||||
|
||||
const isValidDecimals = useMemo(
|
||||
() => !!assetDecimals && assetDecimals.lten(20),
|
||||
[assetDecimals]
|
||||
);
|
||||
|
||||
const isValidName = useMemo(
|
||||
() => !!assetName && assetName.length >= 3 && assetName.length <= 32,
|
||||
[assetName]
|
||||
);
|
||||
|
||||
const isValidSymbol = useMemo(
|
||||
() => !!assetSymbol && assetSymbol.length >= 3,
|
||||
[assetSymbol]
|
||||
);
|
||||
|
||||
useEffect((): void => {
|
||||
onChange(
|
||||
assetId && assetName && assetSymbol && assetDecimals && isValidName && isValidSymbol && isValidDecimals
|
||||
? { assetDecimals, assetName, assetSymbol, metadataTx: api.tx.assets.setMetadata(assetId, assetName, assetSymbol, assetDecimals) }
|
||||
: null
|
||||
);
|
||||
}, [api, assetDecimals, assetId, assetName, assetSymbol, isValidName, isValidSymbol, isValidDecimals, onChange]);
|
||||
|
||||
return (
|
||||
<Modal.Content className={className}>
|
||||
<Modal.Columns hint={t<string>('The descriptive name for this asset.')}>
|
||||
<Input
|
||||
autoFocus
|
||||
defaultValue={initial?.assetName}
|
||||
isError={!isValidName}
|
||||
label={t<string>('asset name')}
|
||||
onChange={setAssetName}
|
||||
/>
|
||||
</Modal.Columns>
|
||||
<Modal.Columns hint={t<string>('The symbol that will represent this asset.')}>
|
||||
<Input
|
||||
defaultValue={initial?.assetSymbol}
|
||||
isError={!isValidSymbol}
|
||||
label={t<string>('asset symbol')}
|
||||
onChange={setAssetSymbol}
|
||||
/>
|
||||
</Modal.Columns>
|
||||
<Modal.Columns hint={t<string>('The number of decimals for this token. Max allowed via the UI is set to 20.')}>
|
||||
<InputNumber
|
||||
defaultValue={initial?.assetDecimals}
|
||||
isError={!isValidDecimals}
|
||||
label={t<string>('asset decimals')}
|
||||
onChange={setAssetDecimals}
|
||||
/>
|
||||
</Modal.Columns>
|
||||
</Modal.Content>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Metadata);
|
||||
@ -1,7 +1,6 @@
|
||||
// Copyright 2017-2021 @polkadot/app-assets authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type BN from 'bn.js';
|
||||
import type { TeamState } from './types';
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
@ -12,14 +11,13 @@ import { useApi } from '@polkadot/react-hooks';
|
||||
import { useTranslation } from '../../translate';
|
||||
|
||||
interface Props {
|
||||
accountId?: string;
|
||||
assetId?: BN;
|
||||
accountId: string;
|
||||
className?: string;
|
||||
defaultValue: TeamState | null;
|
||||
onChange: (info: TeamState | null) => void;
|
||||
}
|
||||
|
||||
function Team ({ accountId, assetId, className = '', defaultValue, onChange }: Props): React.ReactElement<Props> {
|
||||
function Team ({ accountId, className = '', defaultValue, onChange }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const [initial] = useState(() => defaultValue);
|
||||
@ -29,13 +27,11 @@ function Team ({ accountId, assetId, className = '', defaultValue, onChange }: P
|
||||
|
||||
useEffect((): void => {
|
||||
onChange(
|
||||
assetId && accountId && adminId && freezerId && issuerId
|
||||
? adminId !== accountId || freezerId !== accountId || issuerId !== accountId
|
||||
? { adminId, freezerId, issuerId, teamTx: api.tx.assets.setTeam(assetId, issuerId, adminId, freezerId) }
|
||||
: { adminId, freezerId, issuerId, teamTx: null }
|
||||
adminId && freezerId && issuerId
|
||||
? { adminId, freezerId, issuerId }
|
||||
: null
|
||||
);
|
||||
}, [api, assetId, accountId, adminId, freezerId, issuerId, onChange]);
|
||||
}, [api, adminId, freezerId, issuerId, onChange]);
|
||||
|
||||
return (
|
||||
<Modal.Content className={className}>
|
||||
@ -47,7 +43,7 @@ function Team ({ accountId, assetId, className = '', defaultValue, onChange }: P
|
||||
type='account'
|
||||
/>
|
||||
</Modal.Columns>
|
||||
<Modal.Columns hint={t<string>('The account that is to be used for issuing for this token.')}>
|
||||
<Modal.Columns hint={t<string>('The account that is to be used for issuing this token.')}>
|
||||
<InputAddress
|
||||
defaultValue={initial?.issuerId || accountId}
|
||||
label={t<string>('issuer account')}
|
||||
|
||||
@ -2,25 +2,18 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type BN from 'bn.js';
|
||||
import type { SubmittableExtrinsic } from '@polkadot/api/types';
|
||||
|
||||
export interface InfoState {
|
||||
accountId: string;
|
||||
assetId: BN;
|
||||
createTx: SubmittableExtrinsic<'promise'>;
|
||||
minBalance: BN;
|
||||
}
|
||||
|
||||
export interface MetadataState {
|
||||
assetDecimals: BN;
|
||||
assetId: BN;
|
||||
assetName: string;
|
||||
assetSymbol: string;
|
||||
metadataTx: SubmittableExtrinsic<'promise'>;
|
||||
minBalance: BN;
|
||||
}
|
||||
|
||||
export interface TeamState {
|
||||
adminId: string;
|
||||
issuerId: string;
|
||||
freezerId: string;
|
||||
teamTx: SubmittableExtrinsic<'promise'> | null;
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { useApi } from '@polkadot/react-hooks';
|
||||
import { BN_ONE, BN_TEN, BN_TWO, BN_ZERO, formatBalance, isBn } from '@polkadot/util';
|
||||
import { BN_ONE, BN_TEN, BN_TWO, BN_ZERO, formatBalance, isBn, isUndefined } from '@polkadot/util';
|
||||
|
||||
import { BitLengthOption } from './constants';
|
||||
import Dropdown from './Dropdown';
|
||||
@ -80,12 +80,14 @@ function getSiOptions (symbol: string, decimals?: number): { text: string; value
|
||||
}));
|
||||
}
|
||||
|
||||
function getSiPowers (si: SiDef | null): [BN, number, number] {
|
||||
function getSiPowers (si: SiDef | null, decimals?: number): [BN, number, number] {
|
||||
if (!si) {
|
||||
return [BN_ZERO, 0, 0];
|
||||
}
|
||||
|
||||
const basePower = formatBalance.getDefaults().decimals;
|
||||
const basePower = isUndefined(decimals)
|
||||
? formatBalance.getDefaults().decimals
|
||||
: decimals;
|
||||
|
||||
return [new BN(basePower + si.power), basePower, si.power];
|
||||
}
|
||||
@ -109,8 +111,8 @@ function isValidNumber (bn: BN, bitLength: BitLength, isZeroable: boolean, maxVa
|
||||
return true;
|
||||
}
|
||||
|
||||
function inputToBn (api: ApiPromise, input: string, si: SiDef | null, bitLength: BitLength, isZeroable: boolean, maxValue?: BN): [BN, boolean] {
|
||||
const [siPower, basePower, siUnitPower] = getSiPowers(si);
|
||||
function inputToBn (api: ApiPromise, input: string, si: SiDef | null, bitLength: BitLength, isZeroable: boolean, maxValue?: BN, decimals?: number): [BN, boolean] {
|
||||
const [siPower, basePower, siUnitPower] = getSiPowers(si, decimals);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-regexp-exec
|
||||
const isDecimalValue = input.match(/^(\d+)\.(\d+)$/);
|
||||
@ -140,8 +142,8 @@ function inputToBn (api: ApiPromise, input: string, si: SiDef | null, bitLength:
|
||||
];
|
||||
}
|
||||
|
||||
function getValuesFromString (api: ApiPromise, value: string, si: SiDef | null, bitLength: BitLength, isZeroable: boolean, maxValue?: BN): [string, BN, boolean] {
|
||||
const [valueBn, isValid] = inputToBn(api, value, si, bitLength, isZeroable, maxValue);
|
||||
function getValuesFromString (api: ApiPromise, value: string, si: SiDef | null, bitLength: BitLength, isZeroable: boolean, maxValue?: BN, decimals?: number): [string, BN, boolean] {
|
||||
const [valueBn, isValid] = inputToBn(api, value, si, bitLength, isZeroable, maxValue, decimals);
|
||||
|
||||
return [
|
||||
value,
|
||||
@ -150,9 +152,12 @@ function getValuesFromString (api: ApiPromise, value: string, si: SiDef | null,
|
||||
];
|
||||
}
|
||||
|
||||
function getValuesFromBn (valueBn: BN, si: SiDef | null, isZeroable: boolean): [string, BN, boolean] {
|
||||
function getValuesFromBn (valueBn: BN, si: SiDef | null, isZeroable: boolean, _decimals?: number): [string, BN, boolean] {
|
||||
const decimals = isUndefined(_decimals)
|
||||
? formatBalance.getDefaults().decimals
|
||||
: _decimals;
|
||||
const value = si
|
||||
? valueBn.div(BN_TEN.pow(new BN(formatBalance.getDefaults().decimals + si.power))).toString()
|
||||
? valueBn.div(BN_TEN.pow(new BN(decimals + si.power))).toString()
|
||||
: valueBn.toString();
|
||||
|
||||
return [
|
||||
@ -162,10 +167,10 @@ function getValuesFromBn (valueBn: BN, si: SiDef | null, isZeroable: boolean): [
|
||||
];
|
||||
}
|
||||
|
||||
function getValues (api: ApiPromise, value: BN | string = BN_ZERO, si: SiDef | null, bitLength: BitLength, isZeroable: boolean, maxValue?: BN): [string, BN, boolean] {
|
||||
function getValues (api: ApiPromise, value: BN | string = BN_ZERO, si: SiDef | null, bitLength: BitLength, isZeroable: boolean, maxValue?: BN, decimals?: number): [string, BN, boolean] {
|
||||
return isBn(value)
|
||||
? getValuesFromBn(value, si, isZeroable)
|
||||
: getValuesFromString(api, value, si, bitLength, isZeroable, maxValue);
|
||||
? getValuesFromBn(value, si, isZeroable, decimals)
|
||||
: getValuesFromString(api, value, si, bitLength, isZeroable, maxValue, decimals);
|
||||
}
|
||||
|
||||
function InputNumber ({ autoFocus, bitLength = DEFAULT_BITLENGTH, children, className = '', defaultValue, help, isDecimal, isFull, isSi, isDisabled, isError = false, isWarning, isZeroable = true, label, labelExtra, maxLength, maxValue, onChange, onEnter, onEscape, placeholder, siDecimals, siSymbol, value: propsValue }: Props): React.ReactElement<Props> {
|
||||
@ -174,7 +179,7 @@ function InputNumber ({ autoFocus, bitLength = DEFAULT_BITLENGTH, children, clas
|
||||
const [si, setSi] = useState<SiDef | null>(isSi ? formatBalance.findSi('-') : null);
|
||||
const [isPreKeyDown, setIsPreKeyDown] = useState(false);
|
||||
const [[value, valueBn, isValid], setValues] = useState<[string, BN, boolean]>(
|
||||
getValues(api, propsValue || defaultValue, si, bitLength, isZeroable, maxValue)
|
||||
getValues(api, propsValue || defaultValue, si, bitLength, isZeroable, maxValue, siDecimals)
|
||||
);
|
||||
|
||||
const siOptions = useMemo(
|
||||
@ -188,9 +193,9 @@ function InputNumber ({ autoFocus, bitLength = DEFAULT_BITLENGTH, children, clas
|
||||
|
||||
const _onChangeWithSi = useCallback(
|
||||
(input: string, si: SiDef | null) => setValues(
|
||||
getValuesFromString(api, input, si, bitLength, isZeroable, maxValue)
|
||||
getValuesFromString(api, input, si, bitLength, isZeroable, maxValue, siDecimals)
|
||||
),
|
||||
[api, bitLength, isZeroable, maxValue]
|
||||
[api, bitLength, isZeroable, maxValue, siDecimals]
|
||||
);
|
||||
|
||||
const _onChange = useCallback(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user