@rabbitio/ui-kit 1.0.0-beta.43 → 1.0.0-beta.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/coverage/clover.xml +5262 -821
  2. package/coverage/coverage-final.json +25 -1
  3. package/coverage/index.html +311 -26
  4. package/coverage/rabbit-ui-kit/index.html +1 -1
  5. package/coverage/rabbit-ui-kit/index.js.html +1 -1
  6. package/coverage/rabbit-ui-kit/src/common/adapters/axiosAdapter.js.html +1 -1
  7. package/coverage/rabbit-ui-kit/src/common/adapters/index.html +1 -1
  8. package/coverage/rabbit-ui-kit/src/common/amountUtils.js.html +1 -1
  9. package/coverage/rabbit-ui-kit/src/common/errorUtils.js.html +1 -1
  10. package/coverage/rabbit-ui-kit/src/common/external-apis/apiGroups.js.html +1 -1
  11. package/coverage/rabbit-ui-kit/src/common/external-apis/index.html +1 -1
  12. package/coverage/rabbit-ui-kit/src/common/external-apis/ipAddressProviders.js.html +1 -1
  13. package/coverage/rabbit-ui-kit/src/common/fiatCurrenciesService.js.html +1 -1
  14. package/coverage/rabbit-ui-kit/src/common/index.html +1 -1
  15. package/coverage/rabbit-ui-kit/src/common/models/blockchain.js.html +1 -1
  16. package/coverage/rabbit-ui-kit/src/common/models/coin.js.html +1 -1
  17. package/coverage/rabbit-ui-kit/src/common/models/index.html +1 -1
  18. package/coverage/rabbit-ui-kit/src/common/models/protocol.js.html +1 -1
  19. package/coverage/rabbit-ui-kit/src/common/utils/cache.js.html +1 -1
  20. package/coverage/rabbit-ui-kit/src/common/utils/emailAPI.js.html +1 -1
  21. package/coverage/rabbit-ui-kit/src/common/utils/index.html +1 -1
  22. package/coverage/rabbit-ui-kit/src/common/utils/logging/index.html +1 -1
  23. package/coverage/rabbit-ui-kit/src/common/utils/logging/logger.js.html +1 -1
  24. package/coverage/rabbit-ui-kit/src/common/utils/logging/logsStorage.js.html +1 -1
  25. package/coverage/rabbit-ui-kit/src/common/utils/postponeExecution.js.html +1 -1
  26. package/coverage/rabbit-ui-kit/src/common/utils/safeStringify.js.html +1 -1
  27. package/coverage/rabbit-ui-kit/src/components/atoms/AssetIcon/AssetIcon.jsx.html +1 -1
  28. package/coverage/rabbit-ui-kit/src/components/atoms/AssetIcon/index.html +1 -1
  29. package/coverage/rabbit-ui-kit/src/components/atoms/AssetSelection/AssetSelection.jsx.html +364 -0
  30. package/coverage/rabbit-ui-kit/src/components/atoms/AssetSelection/index.html +116 -0
  31. package/coverage/rabbit-ui-kit/src/components/atoms/BackgroundTitle/BackgroundTitle.jsx.html +217 -0
  32. package/coverage/rabbit-ui-kit/src/components/atoms/BackgroundTitle/index.html +116 -0
  33. package/coverage/rabbit-ui-kit/src/components/atoms/LoadingDots/LoadingDots.jsx.html +1 -1
  34. package/coverage/rabbit-ui-kit/src/components/atoms/LoadingDots/index.html +1 -1
  35. package/coverage/rabbit-ui-kit/src/components/atoms/NoticeIcon/NoticeIcon.jsx.html +298 -0
  36. package/coverage/rabbit-ui-kit/src/components/atoms/NoticeIcon/index.html +116 -0
  37. package/coverage/rabbit-ui-kit/src/components/atoms/SupportChat/SupportChat.jsx.html +1 -1
  38. package/coverage/rabbit-ui-kit/src/components/atoms/SupportChat/index.html +1 -1
  39. package/coverage/rabbit-ui-kit/src/components/atoms/TitleBox/TitleBox.jsx.html +574 -0
  40. package/coverage/rabbit-ui-kit/src/components/atoms/TitleBox/index.html +116 -0
  41. package/coverage/rabbit-ui-kit/src/components/atoms/Tooltip/Tooltip.jsx.html +370 -0
  42. package/coverage/rabbit-ui-kit/src/components/atoms/Tooltip/index.html +116 -0
  43. package/coverage/rabbit-ui-kit/src/components/atoms/Validation/Validation.jsx.html +475 -0
  44. package/coverage/rabbit-ui-kit/src/components/atoms/Validation/index.html +116 -0
  45. package/coverage/rabbit-ui-kit/src/components/atoms/buttons/Button/Button.jsx.html +1 -1
  46. package/coverage/rabbit-ui-kit/src/components/atoms/buttons/Button/index.html +1 -1
  47. package/coverage/rabbit-ui-kit/src/components/atoms/buttons/Close/Close.jsx.html +277 -0
  48. package/coverage/rabbit-ui-kit/src/components/atoms/buttons/Close/index.html +116 -0
  49. package/coverage/rabbit-ui-kit/src/components/atoms/buttons/LinkButton/LinkButton.jsx.html +448 -0
  50. package/coverage/rabbit-ui-kit/src/components/atoms/buttons/LinkButton/index.html +116 -0
  51. package/coverage/rabbit-ui-kit/src/components/hooks/index.html +1 -1
  52. package/coverage/rabbit-ui-kit/src/components/hooks/useCallHandlingErrors.js.html +1 -1
  53. package/coverage/rabbit-ui-kit/src/components/hooks/useReferredState.js.html +1 -1
  54. package/coverage/rabbit-ui-kit/src/components/molecules/AmountInput/AmountInput.jsx.html +1510 -0
  55. package/coverage/rabbit-ui-kit/src/components/molecules/AmountInput/index.html +116 -0
  56. package/coverage/rabbit-ui-kit/src/components/organisms/Dialog/Dialog.jsx.html +1630 -0
  57. package/coverage/rabbit-ui-kit/src/components/organisms/Dialog/DialogButtons/DialogButtons.jsx.html +451 -0
  58. package/coverage/rabbit-ui-kit/src/components/organisms/Dialog/DialogButtons/index.html +116 -0
  59. package/coverage/rabbit-ui-kit/src/components/organisms/Dialog/DialogStep/DialogStep.jsx.html +2077 -0
  60. package/coverage/rabbit-ui-kit/src/components/organisms/Dialog/DialogStep/index.html +116 -0
  61. package/coverage/rabbit-ui-kit/src/components/organisms/Dialog/index.html +116 -0
  62. package/coverage/rabbit-ui-kit/src/components/organisms/SwapForm/SwapForm.jsx.html +3538 -0
  63. package/coverage/rabbit-ui-kit/src/components/organisms/SwapForm/index.html +116 -0
  64. package/coverage/rabbit-ui-kit/src/components/utils/index.html +24 -9
  65. package/coverage/rabbit-ui-kit/src/components/utils/inputValueProviders.js.html +1 -1
  66. package/coverage/rabbit-ui-kit/src/components/utils/textUtils.js.html +139 -0
  67. package/coverage/rabbit-ui-kit/src/components/utils/uiUtils.js.html +1 -1
  68. package/coverage/rabbit-ui-kit/src/components/utils/urlQueryUtils.js.html +1 -1
  69. package/coverage/rabbit-ui-kit/src/constants/organisms/dialog/DialogStep/dialogStep.js.html +88 -0
  70. package/coverage/rabbit-ui-kit/src/constants/organisms/dialog/DialogStep/index.html +116 -0
  71. package/coverage/rabbit-ui-kit/src/constants/organisms/dialog/dialog.js.html +172 -0
  72. package/coverage/rabbit-ui-kit/src/constants/organisms/dialog/index.html +116 -0
  73. package/coverage/rabbit-ui-kit/src/index.html +5 -5
  74. package/coverage/rabbit-ui-kit/src/index.js.html +65 -5
  75. package/coverage/rabbit-ui-kit/src/robustExteranlApiCallerService/cacheAndConcurrentRequestsResolver.js.html +1 -1
  76. package/coverage/rabbit-ui-kit/src/robustExteranlApiCallerService/cachedRobustExternalApiCallerService.js.html +1 -1
  77. package/coverage/rabbit-ui-kit/src/robustExteranlApiCallerService/cancelProcessing.js.html +1 -1
  78. package/coverage/rabbit-ui-kit/src/robustExteranlApiCallerService/concurrentCalculationsMetadataHolder.js.html +1 -1
  79. package/coverage/rabbit-ui-kit/src/robustExteranlApiCallerService/externalApiProvider.js.html +1 -1
  80. package/coverage/rabbit-ui-kit/src/robustExteranlApiCallerService/externalServicesStatsCollector.js.html +1 -1
  81. package/coverage/rabbit-ui-kit/src/robustExteranlApiCallerService/index.html +1 -1
  82. package/coverage/rabbit-ui-kit/src/robustExteranlApiCallerService/robustExternalAPICallerService.js.html +1 -1
  83. package/coverage/rabbit-ui-kit/src/swaps-lib/external-apis/index.html +1 -1
  84. package/coverage/rabbit-ui-kit/src/swaps-lib/external-apis/swapProvider.js.html +1 -1
  85. package/coverage/rabbit-ui-kit/src/swaps-lib/external-apis/swapspaceSwapProvider.js.html +1 -1
  86. package/coverage/rabbit-ui-kit/src/swaps-lib/models/baseSwapCreationInfo.js.html +1 -1
  87. package/coverage/rabbit-ui-kit/src/swaps-lib/models/existingSwap.js.html +1 -1
  88. package/coverage/rabbit-ui-kit/src/swaps-lib/models/existingSwapWithFiatData.js.html +1 -1
  89. package/coverage/rabbit-ui-kit/src/swaps-lib/models/index.html +1 -1
  90. package/coverage/rabbit-ui-kit/src/swaps-lib/services/index.html +1 -1
  91. package/coverage/rabbit-ui-kit/src/swaps-lib/services/publicSwapService.js.html +1 -1
  92. package/coverage/rabbit-ui-kit/src/swaps-lib/utils/index.html +1 -1
  93. package/coverage/rabbit-ui-kit/src/swaps-lib/utils/swapUtils.js.html +1 -1
  94. package/coverage/rabbit-ui-kit/stories/atoms/BackgroundTitle.stories.jsx.html +202 -0
  95. package/coverage/rabbit-ui-kit/stories/atoms/LoadingDots.stories.jsx.html +1 -1
  96. package/coverage/rabbit-ui-kit/stories/atoms/Validation.stories.jsx.html +178 -0
  97. package/coverage/rabbit-ui-kit/stories/atoms/buttons/Button.stories.jsx.html +1 -1
  98. package/coverage/rabbit-ui-kit/stories/atoms/buttons/Close.stories.jsx.html +211 -0
  99. package/coverage/rabbit-ui-kit/stories/atoms/buttons/LinkButton.stories.jsx.html +298 -0
  100. package/coverage/rabbit-ui-kit/stories/atoms/buttons/index.html +35 -5
  101. package/coverage/rabbit-ui-kit/stories/atoms/index.html +35 -5
  102. package/coverage/rabbit-ui-kit/stories/organisms/Dialog/Dialog.stories.jsx.html +574 -0
  103. package/coverage/rabbit-ui-kit/stories/organisms/Dialog/DialogButtons/DialogButtons.stories.jsx.html +328 -0
  104. package/coverage/rabbit-ui-kit/stories/organisms/Dialog/DialogButtons/index.html +116 -0
  105. package/coverage/rabbit-ui-kit/stories/organisms/Dialog/DialogStep/DialogStep.stories.jsx.html +352 -0
  106. package/coverage/rabbit-ui-kit/stories/organisms/Dialog/DialogStep/index.html +116 -0
  107. package/coverage/rabbit-ui-kit/stories/organisms/Dialog/index.html +116 -0
  108. package/coverage/rabbit-ui-kit/stories/stubs/exampleContent.jsx.html +145 -0
  109. package/coverage/rabbit-ui-kit/stories/stubs/index.html +116 -0
  110. package/dist/index.cjs +3022 -231
  111. package/dist/index.cjs.map +1 -1
  112. package/dist/index.css +40976 -0
  113. package/dist/index.css.map +1 -1
  114. package/dist/index.modern.js +2568 -183
  115. package/dist/index.modern.js.map +1 -1
  116. package/dist/index.module.js +3010 -239
  117. package/dist/index.module.js.map +1 -1
  118. package/dist/index.umd.js +3019 -234
  119. package/dist/index.umd.js.map +1 -1
  120. package/package.json +7 -1
  121. package/src/assets/image/icons/arrow-darker.svg +14 -0
  122. package/src/assets/image/icons/arrow-tosca.svg +3 -0
  123. package/src/assets/image/icons/arrow-white.svg +14 -0
  124. package/src/assets/image/icons/dark-rectangle.svg +3 -0
  125. package/src/assets/image/icons/failed-validation-icon.svg +15 -0
  126. package/src/assets/image/icons/successful-validation-icon.svg +10 -0
  127. package/src/assets/image/icons/wallet-gray-small.svg +6 -0
  128. package/src/components/atoms/AssetSelection/AssetSelection.jsx +93 -0
  129. package/src/components/atoms/AssetSelection/asset-selection.module.scss +55 -0
  130. package/src/components/atoms/BackgroundTitle/BackgroundTitle.jsx +44 -0
  131. package/src/components/atoms/BackgroundTitle/background-title.module.scss +52 -0
  132. package/src/components/atoms/NoticeIcon/NoticeIcon.jsx +71 -0
  133. package/src/components/atoms/NoticeIcon/notice-icon.module.scss +14 -0
  134. package/src/components/atoms/TitleBox/TitleBox.jsx +163 -0
  135. package/src/components/atoms/TitleBox/title-box.module.scss +30 -0
  136. package/src/components/atoms/Tooltip/Tooltip.jsx +95 -0
  137. package/src/components/atoms/Tooltip/tooltip.module.scss +231 -0
  138. package/src/components/atoms/Validation/Validation.jsx +130 -0
  139. package/src/components/atoms/Validation/validation.module.scss +15 -0
  140. package/src/components/atoms/buttons/Close/Close.jsx +64 -0
  141. package/src/components/atoms/buttons/Close/close.module.scss +75 -0
  142. package/src/components/atoms/buttons/LinkButton/LinkButton.jsx +121 -0
  143. package/src/components/atoms/buttons/LinkButton/link-button.module.scss +45 -0
  144. package/src/components/molecules/AmountInput/AmountInput.jsx +475 -0
  145. package/src/components/molecules/AmountInput/amount-input.module.scss +189 -0
  146. package/src/components/organisms/Dialog/Dialog.jsx +515 -0
  147. package/src/components/organisms/Dialog/DialogButtons/DialogButtons.jsx +122 -0
  148. package/src/components/organisms/Dialog/DialogButtons/dialog-buttons.module.scss +25 -0
  149. package/src/components/organisms/Dialog/DialogStep/DialogStep.jsx +664 -0
  150. package/src/components/organisms/Dialog/DialogStep/dialog-step.module.scss +362 -0
  151. package/src/components/organisms/Dialog/dialog.module.scss +223 -0
  152. package/src/components/organisms/SwapForm/SwapForm.jsx +1151 -0
  153. package/src/components/organisms/SwapForm/swap-form.module.scss +120 -0
  154. package/src/components/utils/textUtils.js +18 -0
  155. package/src/constants/organisms/dialog/DialogStep/dialogStep.js +1 -0
  156. package/src/constants/organisms/dialog/dialog.js +29 -0
  157. package/src/index.js +21 -1
  158. package/stories/stubs/exampleContent.jsx +20 -0
  159. package/styles/fonts/NunitoSans-Bold.ttf +0 -0
  160. package/styles/fonts/NunitoSans-ExtraBold.ttf +0 -0
  161. package/styles/fonts/NunitoSans-Light.ttf +0 -0
  162. package/styles/fonts/NunitoSans-Regular.ttf +0 -0
  163. package/styles/fonts/NunitoSans-SemiBold.ttf +0 -0
  164. package/styles/index.scss +5 -3
@@ -0,0 +1,121 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import PropTypes from "prop-types";
3
+
4
+ import { useCallHandlingErrors } from "../../../hooks/useCallHandlingErrors";
5
+
6
+ import s from "./link-button.module.scss";
7
+ import { LoadingDots } from "../../LoadingDots/LoadingDots";
8
+
9
+ export const iconRotateOptions = {
10
+ rotate0: "0deg",
11
+ rotate90: "90deg",
12
+ rotate180: "180deg",
13
+ rotate270: "270deg",
14
+ };
15
+
16
+ /**
17
+ * LinkButton renders a clickable button which can optionally display an icon and loading animation.
18
+ * It can also be styled to be colored or disabled. This button supports rotating the icon according to specified degrees.
19
+ *
20
+ * @component
21
+ * @param {Object} props - Properties passed down to the component.
22
+ * @param {Function} props.onClick - Callback function triggered on button click. It should handle any post-click logic like resetting loading state.
23
+ * @param {boolean} props.isDisabled - If true, the button will be disabled and non-interactable.
24
+ * @param {boolean} props.isLoadable - If true, the button will display a loading indicator upon being clicked.
25
+ * @param {string} props.content - Text content displayed on the button.
26
+ * @param {boolean} props.isColored - If true, applies additional styling to the button.
27
+ * @param {string} props.icon - URL of an icon image to be displayed on the button.
28
+ * @param {string} props.iconRotate - Rotation angle for the icon. Valid values are defined in `iconRotateOptions`.
29
+ * @param {Object} props.IconComponent - Icon component, if SVG is imported directly.
30
+ *
31
+ * @returns {JSX.Element} A React component that renders a clickable and optionally loadable and icon-displaying button.
32
+ */
33
+ export const LinkButton = ({
34
+ onClick = (resetButtonLoader) => {},
35
+ isDisabled = false,
36
+ isLoadable = false,
37
+ content = "",
38
+ isColored = true,
39
+ icon,
40
+ iconRotate,
41
+ IconComponent,
42
+ }) => {
43
+ const callHandlingErrors = useCallHandlingErrors();
44
+
45
+ const [isLoading, setIsLoading] = useState(false);
46
+ const [processedIconRotation, setProcessedIconRotation] = useState(null);
47
+
48
+ const handleClick = () => {
49
+ callHandlingErrors(() => {
50
+ if (!isDisabled) {
51
+ if (isLoadable) {
52
+ setIsLoading(true);
53
+ }
54
+ // TODO: [bug, moderate] Click can be called when there isLoading=true task_id=a15979a4ca2042b29dfd1d128a16c281
55
+ onClick(() => setIsLoading(false));
56
+ }
57
+ });
58
+ };
59
+
60
+ useEffect(() => {
61
+ if (
62
+ iconRotate &&
63
+ Object.keys(iconRotateOptions).find(
64
+ (key) => iconRotateOptions[key] === iconRotate
65
+ )
66
+ )
67
+ setProcessedIconRotation(iconRotate);
68
+ // eslint-disable-next-line react-hooks/exhaustive-deps
69
+ }, [iconRotate]);
70
+
71
+ return isLoading ? (
72
+ <LoadingDots isColored={true} />
73
+ ) : (
74
+ <div
75
+ className={
76
+ s["link-button"] +
77
+ ` ${
78
+ processedIconRotation &&
79
+ processedIconRotation !== iconRotateOptions.rotate0
80
+ ? " " + s["icon-rotate-" + processedIconRotation]
81
+ : ""
82
+ } ${isDisabled ? " " + s["disabled"] : ""}`
83
+ }
84
+ onClick={handleClick}
85
+ >
86
+ {icon ? <img src={icon} alt="link button alt" /> : null}
87
+ {IconComponent ? <IconComponent /> : null}
88
+ <p
89
+ className={
90
+ s["link-button-text"] +
91
+ ` ${isColored ? s["colored"] : ""} ${
92
+ isDisabled ? s["disabled"] : ""
93
+ }`
94
+ }
95
+ >
96
+ {content}
97
+ </p>
98
+ </div>
99
+ );
100
+ };
101
+
102
+ LinkButton.propTypes = {
103
+ onClick: PropTypes.func,
104
+ isDisabled: PropTypes.bool,
105
+ isLoadable: PropTypes.bool,
106
+ content: PropTypes.string,
107
+ icon: PropTypes.string,
108
+ isColored: PropTypes.bool,
109
+ iconRotate: PropTypes.oneOf(Object.values(iconRotateOptions)),
110
+ IconComponent: PropTypes.elementType,
111
+ };
112
+
113
+ LinkButton.defaultProps = {
114
+ onClick: (resetButtonLoader) => {},
115
+ isDisabled: false,
116
+ isLoadable: false,
117
+ content: "",
118
+ icon: undefined,
119
+ isColored: true,
120
+ iconRotate: iconRotateOptions.rotate0,
121
+ };
@@ -0,0 +1,45 @@
1
+ @import "../../../../../styles/index";
2
+
3
+ .link-button {
4
+ display: flex;
5
+ align-items: center;
6
+
7
+ &:not(.disabled) {
8
+ @extend %hover-state;
9
+ }
10
+
11
+ &.icon-rotate-90deg img {
12
+ transform: rotate(90deg);
13
+ }
14
+ &.icon-rotate-180deg img {
15
+ transform: rotate(180deg);
16
+ }
17
+ &.icon-rotate-270deg img {
18
+ transform: rotate(270deg);
19
+ }
20
+
21
+ img {
22
+ margin-left: -3px;
23
+ margin-right: Margin("1");
24
+ }
25
+
26
+ &-text {
27
+ @extend %text-bold;
28
+ font-size: 14px;
29
+ color: $white;
30
+ text-decoration: none;
31
+ text-align: center;
32
+ line-height: 14px;
33
+ // padding-bottom: 1px;
34
+ margin: 0;
35
+
36
+ &.colored {
37
+ color: SolidColor("tosca");
38
+ }
39
+
40
+ &.disabled {
41
+ color: SolidColor("grey");
42
+ cursor: default;
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,475 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { BigNumber } from "bignumber.js";
3
+
4
+ import s from "./amount-input.module.scss";
5
+ // import { ReactComponent as WalletIcon } from "../../../assets/image/icons/wallet-gray-small.svg";
6
+
7
+ import { useCallHandlingErrors } from "../../hooks/useCallHandlingErrors.js";
8
+ import { InputValuesProviders } from "../../utils/inputValueProviders.js";
9
+ import { logErrorOrOutputToConsole } from "../../../common/errorUtils.js";
10
+
11
+ import { TitleBox } from "../../atoms/TitleBox/TitleBox.jsx";
12
+ import { AmountUtils } from "../../../common/amountUtils.js";
13
+ import { LoadingDots } from "../../atoms/LoadingDots/LoadingDots.jsx";
14
+ import { AssetSelection } from "../../atoms/AssetSelection/AssetSelection.jsx";
15
+ import { Validation } from "../../atoms/Validation/Validation.jsx";
16
+
17
+ const WalletIcon = () => (
18
+ <svg
19
+ width="16"
20
+ height="16"
21
+ viewBox="0 0 16 16"
22
+ fill="none"
23
+ xmlns="http://www.w3.org/2000/svg"
24
+ >
25
+ <path
26
+ d="M12.6265 10.4119V12.2379C12.6265 12.7338 12.193 13.1356 11.6583 13.1356H3.26825C2.73352 13.1356 2.29999 12.7338 2.29999 12.2379V3.79771C2.29999 3.30178 2.73352 2.89999 3.26825 2.89999H11.6583C12.193 2.89999 12.6265 3.30178 12.6265 3.79771V5.84996"
27
+ stroke="#8F95A2"
28
+ stroke-linecap="round"
29
+ stroke-linejoin="round"
30
+ />
31
+ <path
32
+ fill-rule="evenodd"
33
+ clip-rule="evenodd"
34
+ d="M13.0952 10.1922H10.2664C9.0847 10.1922 8.12704 9.23439 8.12704 8.05246C8.12704 6.87052 9.0847 5.91269 10.2664 5.91269H13.0952C13.4072 5.91269 13.66 6.16552 13.66 6.47758V9.62689C13.66 9.93939 13.4072 10.1922 13.0952 10.1922Z"
35
+ stroke="#8F95A2"
36
+ stroke-linecap="round"
37
+ stroke-linejoin="round"
38
+ />
39
+ <path
40
+ d="M2.29999 4.73721H4.99884"
41
+ stroke="#8F95A2"
42
+ stroke-linecap="round"
43
+ stroke-linejoin="round"
44
+ />
45
+ <path
46
+ d="M2.29999 11.3122H4.99884"
47
+ stroke="#8F95A2"
48
+ stroke-linecap="round"
49
+ stroke-linejoin="round"
50
+ />
51
+ </svg>
52
+ );
53
+
54
+ export const AmountInput = React.forwardRef(
55
+ (
56
+ {
57
+ label = "",
58
+ handleCoinAmountChange = (btcAmount) => {},
59
+ handleFiatAmountChange = (fiatAmount) => {},
60
+ handleChangeAssetClick = () => {},
61
+ handleBalanceValidationChange = (isValid) => {},
62
+ disabled,
63
+ alertText,
64
+ predefinedValue,
65
+ children,
66
+ ticker,
67
+ tickerPrintable,
68
+ assetDecimalPlaces,
69
+ assetBalance = { fiatAmount: null, assetAmount: null },
70
+ assetIconSrc,
71
+ assetIconProtocolSrc,
72
+ fallbackAssetIconSrc,
73
+ isSendAll = null,
74
+ handleSendAllClick = () => {},
75
+ showBalance = false,
76
+ showBalanceValidation = false,
77
+ showChangeAssetButton = false,
78
+ changeAssetButtonProtocol,
79
+ changeAssetButtonDisabled = false,
80
+ upperFormPosition,
81
+ lowerFormPosition,
82
+ errorEncountered,
83
+ updateAssetInputTo = null,
84
+ estimateAmount = false,
85
+ isLoading = false,
86
+ cryptoAssetToFiatRate = null,
87
+ fiatCurrencyCode = null,
88
+ fiatCurrencyDecimals = null,
89
+ linkButtonActiveText = null,
90
+ linkButtonInactiveText = null,
91
+ balanceLoaderText = null,
92
+ fiatInputPlaceholderText = null,
93
+ },
94
+ buttonForwardRef
95
+ ) => {
96
+ // const { t } = useTranslation();
97
+ const callHandlingErrors = useCallHandlingErrors();
98
+
99
+ const [coinAmountValue, setCoinAmountValue] = useState("");
100
+ const [coinAmountPlaceholder, setCoinAmountPlaceholder] = useState("0");
101
+ const [fiatAmountValue, setFiatAmountValue] = useState("");
102
+ const [interactedWith, setInteractedWith] = useState(false);
103
+ const [fiatAmountAutoFocus, setFiatAmountAutoFocus] = useState(false);
104
+ const [isInFocus, setIsInFocus] = useState(false);
105
+ const [highlightBalance, setHighlightBalance] = useState(false);
106
+ const [highlightInput, setHighlightInput] = useState(false);
107
+
108
+ const resetToDefault = () => {
109
+ setInteractedWith(false);
110
+ setFiatAmountAutoFocus(false);
111
+ };
112
+
113
+ useEffect(() => {
114
+ if (updateAssetInputTo !== null)
115
+ handleChangeAmount(updateAssetInputTo?.toString(), false);
116
+ // eslint-disable-next-line react-hooks/exhaustive-deps
117
+ }, [updateAssetInputTo]);
118
+
119
+ const handleChangeAmount = (newAmountString, handlerEnabled = true) => {
120
+ (async () => {
121
+ try {
122
+ const correctedAmount =
123
+ InputValuesProviders.provideFormatOfFloatValueByInputString(
124
+ newAmountString,
125
+ assetDecimalPlaces
126
+ );
127
+ setCoinAmountValue(correctedAmount);
128
+ if (handlerEnabled) handleCoinAmountChange(correctedAmount);
129
+
130
+ if (
131
+ correctedAmount !== "" &&
132
+ cryptoAssetToFiatRate != null
133
+ ) {
134
+ const fiatAmount = BigNumber(correctedAmount)
135
+ .times(cryptoAssetToFiatRate)
136
+ .toFixed(fiatCurrencyDecimals);
137
+ setFiatAmountValue(fiatAmount);
138
+ handleFiatAmountChange(fiatAmount);
139
+ } else {
140
+ setFiatAmountValue("");
141
+ }
142
+ } catch (e) {
143
+ setFiatAmountValue(null);
144
+ logErrorOrOutputToConsole(e);
145
+ }
146
+ })();
147
+ setInteractedWith(true);
148
+ };
149
+
150
+ const handleChangeAmountFiat = (newAmountString) => {
151
+ if (cryptoAssetToFiatRate == null) return;
152
+ (async () => {
153
+ try {
154
+ const correctedFiatAmount =
155
+ InputValuesProviders.provideFormatOfFloatValueByInputString(
156
+ newAmountString,
157
+ fiatCurrencyDecimals
158
+ );
159
+ setFiatAmountValue(correctedFiatAmount);
160
+ handleFiatAmountChange(correctedFiatAmount);
161
+
162
+ const coinAmount =
163
+ correctedFiatAmount !== ""
164
+ ? BigNumber(correctedFiatAmount)
165
+ .div(cryptoAssetToFiatRate)
166
+ .toFixed(assetDecimalPlaces)
167
+ : "0";
168
+ const coinsAmount = BigNumber(coinAmount).isZero()
169
+ ? ""
170
+ : coinAmount;
171
+ setCoinAmountValue(coinsAmount);
172
+ handleCoinAmountChange(coinsAmount);
173
+ } catch (e) {
174
+ setFiatAmountValue(null);
175
+ logErrorOrOutputToConsole(e);
176
+ }
177
+ })();
178
+ };
179
+
180
+ const placeholderByDecimalCount = (decimalCount) =>
181
+ "0" + (decimalCount > 0 ? "." + "0".repeat(decimalCount) : "");
182
+
183
+ const handleFiatInteraction = () => {
184
+ if (disabled) return;
185
+ setFiatAmountAutoFocus(true);
186
+ setInteractedWith(true);
187
+ };
188
+
189
+ useEffect(() => {
190
+ predefinedValue != null && handleChangeAmount(predefinedValue + "");
191
+ // eslint-disable-next-line react-hooks/exhaustive-deps
192
+ }, [predefinedValue]);
193
+
194
+ useEffect(() => {
195
+ try {
196
+ setCoinAmountPlaceholder(
197
+ placeholderByDecimalCount(assetDecimalPlaces)
198
+ );
199
+ } catch (e) {
200
+ logErrorOrOutputToConsole(e);
201
+ }
202
+ resetToDefault();
203
+ // eslint-disable-next-line react-hooks/exhaustive-deps
204
+ }, [ticker]);
205
+
206
+ // Check if input & balance highlights are needed after a change in either the asset amount or the balance
207
+ useEffect(() => {
208
+ if (!showBalanceValidation || assetBalance?.assetAmount == null)
209
+ return;
210
+
211
+ let enableHighlight = BigNumber(coinAmountValue).gt(
212
+ assetBalance?.assetAmount
213
+ );
214
+
215
+ handleBalanceValidationChange(enableHighlight);
216
+ setHighlightBalance(enableHighlight);
217
+ setHighlightInput(enableHighlight);
218
+
219
+ // eslint-disable-next-line react-hooks/exhaustive-deps
220
+ }, [coinAmountValue, assetBalance]);
221
+
222
+ // Clearing the custom focus upon disabling or enabling the form
223
+ useEffect(() => setIsInFocus(false), [disabled]);
224
+
225
+ return (
226
+ <>
227
+ <TitleBox
228
+ title={label}
229
+ linkText={
230
+ isSendAll !== null
231
+ ? isSendAll
232
+ ? linkButtonActiveText
233
+ : linkButtonInactiveText
234
+ : // ? t("molecules.AmountInput.send-all-enabled")
235
+ // : t("molecules.AmountInput.send-all-disabled")
236
+ null
237
+ }
238
+ linkButtonClick={handleSendAllClick}
239
+ >
240
+ <div
241
+ className={[
242
+ s["amount-input-container"],
243
+ isInFocus ? s["focus"] : "",
244
+ errorEncountered || highlightInput
245
+ ? s["error-encountered"]
246
+ : "",
247
+ upperFormPosition ? s["upper-form-position"] : "",
248
+ lowerFormPosition ? s["lower-form-position"] : "",
249
+ ].join(" ")}
250
+ >
251
+ <div
252
+ className={`${
253
+ s["amount-input-container-input-wrapper"]
254
+ } ${disabled ? s["disabled"] : ""}
255
+ ${children ? s["bottom-margin"] : ""}`}
256
+ >
257
+ {showBalance ? (
258
+ <div
259
+ className={
260
+ s["asset-balance"] +
261
+ " " +
262
+ (highlightBalance ? s["red"] : "")
263
+ }
264
+ >
265
+ <WalletIcon />
266
+ <p>
267
+ {assetBalance?.assetAmount != null &&
268
+ assetBalance?.fiatAmount != null &&
269
+ ticker &&
270
+ fiatCurrencyCode ? (
271
+ <>
272
+ {AmountUtils.cryptoFull(
273
+ assetBalance.assetAmount,
274
+ tickerPrintable,
275
+ assetDecimalPlaces
276
+ )}
277
+ <span>
278
+ {" ~ " +
279
+ AmountUtils.fiat(
280
+ assetBalance.fiatAmount,
281
+ fiatCurrencyCode
282
+ )}
283
+ </span>
284
+ </>
285
+ ) : (
286
+ balanceLoaderText
287
+ )}
288
+ </p>
289
+ </div>
290
+ ) : (
291
+ ""
292
+ )}
293
+
294
+ <div className={s["requested-amount-coin"]}>
295
+ <span
296
+ className={
297
+ s["requested-amount-coin-currency"]
298
+ }
299
+ >
300
+ {tickerPrintable
301
+ ? (estimateAmount ? "~ " : "") +
302
+ tickerPrintable
303
+ : ""}
304
+ </span>
305
+ {!isLoading ? (
306
+ <input
307
+ type="text"
308
+ inputMode="decimal"
309
+ value={coinAmountValue}
310
+ onChange={(e) =>
311
+ handleChangeAmount(e.target.value)
312
+ }
313
+ placeholder={coinAmountPlaceholder}
314
+ className={
315
+ s["requested-amount-coin-input"]
316
+ }
317
+ disabled={disabled}
318
+ onFocus={(e) =>
319
+ callHandlingErrors(
320
+ () => setIsInFocus(true),
321
+ e
322
+ )
323
+ }
324
+ onBlur={(e) =>
325
+ callHandlingErrors(
326
+ () => setIsInFocus(false),
327
+ e
328
+ )
329
+ }
330
+ />
331
+ ) : (
332
+ <div
333
+ className={
334
+ s["requested-amount-coin-skeleton"]
335
+ }
336
+ >
337
+ <span
338
+ className={
339
+ s[
340
+ "requested-amount-coin-skeleton-content"
341
+ ] +
342
+ " " +
343
+ s["skeleton-dark"]
344
+ }
345
+ ></span>
346
+ </div>
347
+ )}
348
+ </div>
349
+ {fiatCurrencyCode !== null ? (
350
+ <>
351
+ <div
352
+ className={
353
+ s["requested-amount-fiat"] +
354
+ (interactedWith
355
+ ? " " + s["interacted"]
356
+ : "")
357
+ }
358
+ >
359
+ {interactedWith ? (
360
+ <>
361
+ <span
362
+ className={
363
+ s[
364
+ "requested-amount-fiat-currency"
365
+ ]
366
+ }
367
+ >
368
+ {(estimateAmount
369
+ ? "~ "
370
+ : "") +
371
+ fiatCurrencyCode}
372
+ </span>
373
+ <input
374
+ type="text"
375
+ inputMode="decimal"
376
+ className={
377
+ s[
378
+ "requested-amount-fiat-input"
379
+ ]
380
+ }
381
+ value={fiatAmountValue}
382
+ disabled={disabled}
383
+ onChange={(e) =>
384
+ handleChangeAmountFiat(
385
+ e.target.value
386
+ )
387
+ }
388
+ placeholder={placeholderByDecimalCount(
389
+ fiatCurrencyDecimals
390
+ )}
391
+ autoFocus={
392
+ fiatAmountAutoFocus
393
+ }
394
+ onFocus={(e) =>
395
+ callHandlingErrors(
396
+ () =>
397
+ setIsInFocus(
398
+ true
399
+ ),
400
+ e
401
+ )
402
+ }
403
+ onBlur={(e) =>
404
+ callHandlingErrors(
405
+ () =>
406
+ setIsInFocus(
407
+ false
408
+ ),
409
+ e
410
+ )
411
+ }
412
+ />
413
+ </>
414
+ ) : (
415
+ <span
416
+ className={
417
+ s[
418
+ "requested-amount-fiat-placeholder"
419
+ ]
420
+ }
421
+ onClick={(e) =>
422
+ callHandlingErrors(
423
+ () =>
424
+ handleFiatInteraction(),
425
+ e
426
+ )
427
+ }
428
+ >
429
+ {fiatInputPlaceholderText}
430
+ {/*{t(*/}
431
+ {/* "molecules.AmountInput.fiat-placeholder-text",*/}
432
+ {/* {*/}
433
+ {/* currencyCode:*/}
434
+ {/* fiatCurrencyCode,*/}
435
+ {/* }*/}
436
+ {/*)}*/}
437
+ </span>
438
+ )}
439
+ </div>
440
+ </>
441
+ ) : (
442
+ <LoadingDots
443
+ isColored={true}
444
+ noMargins={false}
445
+ align="left"
446
+ />
447
+ )}
448
+ </div>
449
+ {showChangeAssetButton && ticker ? (
450
+ <div
451
+ className={
452
+ s["amount-input-container-button-wrapper"]
453
+ }
454
+ ref={buttonForwardRef}
455
+ >
456
+ <AssetSelection
457
+ assetIconSrc={assetIconSrc}
458
+ assetIconProtocolSrc={assetIconProtocolSrc}
459
+ fallbackSrc={fallbackAssetIconSrc}
460
+ handleClick={handleChangeAssetClick}
461
+ disabled={changeAssetButtonDisabled}
462
+ protocolName={changeAssetButtonProtocol}
463
+ />
464
+ </div>
465
+ ) : (
466
+ ""
467
+ )}
468
+ {children}
469
+ </div>
470
+ </TitleBox>
471
+ {alertText ? <Validation text={alertText} /> : null}
472
+ </>
473
+ );
474
+ }
475
+ );