InputBalance.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // Copyright 2017-2020 @polkadot/react-components authors & contributors
  2. // This software may be modified and distributed under the terms
  3. // of the Apache-2.0 license. See the LICENSE file for details.
  4. import { BitLength } from './types';
  5. import BN from 'bn.js';
  6. import React, { useEffect, useState } from 'react';
  7. import styled from 'styled-components';
  8. import { BitLengthOption } from '@polkadot/react-components/constants';
  9. import { BN_TEN, BN_THOUSAND, formatBalance, isBn } from '@polkadot/util';
  10. import InputNumber from './InputNumber';
  11. interface Props {
  12. autoFocus?: boolean;
  13. children?: React.ReactNode;
  14. className?: string;
  15. defaultValue?: BN | string;
  16. help?: React.ReactNode;
  17. isDisabled?: boolean;
  18. isError?: boolean;
  19. isFull?: boolean;
  20. isWarning?: boolean;
  21. isZeroable?: boolean;
  22. label?: React.ReactNode;
  23. labelExtra?: React.ReactNode;
  24. maxValue?: BN;
  25. onChange?: (value?: BN) => void;
  26. onEnter?: () => void;
  27. onEscape?: () => void;
  28. placeholder?: string;
  29. value?: BN;
  30. withEllipsis?: boolean;
  31. withLabel?: boolean;
  32. withMax?: boolean;
  33. }
  34. const DEFAULT_BITLENGTH = BitLengthOption.CHAIN_SPEC as BitLength;
  35. function reformat (value: string | BN, isDisabled?: boolean): string {
  36. if (isBn(value)) {
  37. let fmt = (value.mul(BN_THOUSAND).div(BN_TEN.pow(new BN(formatBalance.getDefaults().decimals))).toNumber() / 1000).toFixed(3);
  38. while (fmt.length !== 1 && ['.', '0'].includes(fmt[fmt.length - 1])) {
  39. const isLast = fmt.endsWith('.');
  40. fmt = fmt.substr(0, fmt.length - 1);
  41. if (isLast) {
  42. break;
  43. }
  44. }
  45. return fmt;
  46. }
  47. return formatBalance(value, { forceUnit: '-', withSi: false }).replace(',', isDisabled ? ',' : '');
  48. }
  49. function InputBalance ({ autoFocus, children, className = '', defaultValue: inDefault, help, isDisabled, isError, isFull, isWarning, isZeroable, label, labelExtra, maxValue, onChange, onEnter, onEscape, placeholder, value, withEllipsis, withLabel, withMax }: Props): React.ReactElement<Props> {
  50. const [defaultValue, setDefaultValue] = useState<string | undefined>();
  51. useEffect((): void => {
  52. inDefault && setDefaultValue(
  53. reformat(inDefault, isDisabled)
  54. );
  55. }, [inDefault, isDisabled]);
  56. return (
  57. <InputNumber
  58. autoFocus={autoFocus}
  59. bitLength={DEFAULT_BITLENGTH}
  60. className={`ui--InputBalance ${className}`}
  61. defaultValue={defaultValue}
  62. help={help}
  63. isDisabled={isDisabled}
  64. isError={isError}
  65. isFull={isFull}
  66. isSi
  67. isWarning={isWarning}
  68. isZeroable={isZeroable}
  69. label={label}
  70. labelExtra={labelExtra}
  71. maxValue={maxValue}
  72. onChange={onChange}
  73. onEnter={onEnter}
  74. onEscape={onEscape}
  75. placeholder={placeholder}
  76. value={value}
  77. withEllipsis={withEllipsis}
  78. withLabel={withLabel}
  79. withMax={withMax}
  80. >
  81. {children}
  82. </InputNumber>
  83. );
  84. }
  85. export default React.memo(styled(InputBalance)`
  86. &&:not(.label-small) .labelExtra {
  87. right: 6.5rem;
  88. }
  89. .ui.action.input.ui--Input > .buttons {
  90. align-items: stretch;
  91. .ui.disabled.button.compact.floating.selection.dropdown.ui--SiDropdown {
  92. border-style: solid;
  93. opacity: 1 !important;
  94. }
  95. }
  96. `);