// @ts-nocheck import React, { isValidElement } from 'react'; import { Text, TouchableOpacity, View, StyleSheet, ImageProps, ImageStyle, StyleProp, Keyboard, } from 'react-native'; import { Button, Input, ShouldRender } from '@xrnjs/ui'; import { addThousandSeparators } from '../Input/utils'; import Select from '../Select'; import { IconXLowersmall1 } from '../../icons'; import { AmountInputProps, Group } from './interface'; import createStyle from './styles/AmountInput.style'; import { useMemoizedFn, useControllableValue } from 'ahooks'; import { useLocale } from '../Locale/locale'; import merge from 'lodash/merge'; import { useTheme } from '../Theme/Theme'; import Image from '../Image'; import { InputInstance } from '../Input/interface'; import withDecimalKeyboard from './hocs/withDecimalKeyboard'; import { Fill } from '../../index'; const initValue = { amount: '', currency: '', canUseAmount: 0, }; const digitRegex = /^(0|[1-9]\d*)((\.|,)\d*)?$/; const AmountInput = ({ onChange, onChangeSelect, onSelectAll, formatBalance, showSelectCurrency = true, options = [], showSellAll = true, value = initValue, selectProps = {}, inputProps = {}, selectTitle, disabled, placeholder, currencyInputProps, showBalance, allText, style, availableBalanceText, availableBalanceColon = ':', selectPosition = 'prefix', autoClear = true, decimalNum, precision = 2, inputRef, onReady, renderMessage, ...props }: AmountInputProps & { inputRef?: React.RefObject; onReady?: () => void; }) => { const _precision = decimalNum ?? precision; const token = useTheme(); const styles = createStyle(token); const decimalSeparator = inputProps?.decimalSeparator ?? '.'; const thousandSeparator = inputProps?.thousandSeparator ?? ','; const locale = useLocale(); const [visible, setVisible] = useControllableValue(props, { defaultValue: false, valuePropName: 'selectVisible', trigger: 'onSelectVisibleChange', }); const findOption = (val: string) => { let opt = null; if (options.length < 1) return opt; const firstOpt = options?.[0] as Group; if (firstOpt?.children instanceof Array) { const groups = options as Group[]; groups.some((opts) => { opt = opts?.children?.find((x) => x.value === val); return !!opt; }); } else { opt = options?.find?.((x) => x.value === val); } return opt; }; const onChangeCurrency = useMemoizedFn((ccy: string) => { setVisible(false); if (ccy === value.currency) { return; } const balance = findOption(ccy)?.balance; onChange?.({ amount: autoClear ? '' : value.amount, currency: ccy, canUseAmount: balance ? Number(balance) : 0, }); onChangeSelect?.(ccy); }); const balance = findOption(value.currency)?.balance; const onCancel = useMemoizedFn(() => { setVisible(false); }); const onChangeAmount = useMemoizedFn((amount: string) => { // 基础组件层拦截同态更新,防止死循环 if (amount === (value.amount || '')) { return; } if (digitRegex.test(amount) || amount === '') { onChange?.({ ...value, amount: amount ?? '', }); } }); const sellAll = useMemoizedFn(() => { onChange?.({ ...value, amount: balance ? balance?.toString() : '', }); onSelectAll?.(balance ? balance?.toString() : ''); }); const getCurrencyImg = () => findOption(value.currency)?.prefixIcon?.toString(); const getCurrencyNode = () => findOption(value.currency)?.prefixIcon; const showCurrencyModel = () => { if (disabled) return; Keyboard.dismiss(); showSelectCurrency && setVisible(true); }; const renderIcon = () => { const node = getCurrencyNode(); if (isValidElement(node)) { return React.cloneElement( node, merge( { ...node.props, style: StyleSheet.flatten([ disabled && styles.imgDisabled, node.props.style, currencyInputProps?.imageStyle, ]), }, currencyInputProps?.imageProps ) ); } const isShowIcon = !!getCurrencyImg(); return ( , ])} source={{ uri: getCurrencyImg(), }} /> ); }; const selectView = ( {renderIcon()} {value.currency} {locale.AmountInput.selectPlaceholder} {showSelectCurrency && options.length > 0 && ( )} ); const isPrefix = selectPosition === 'prefix'; const loadingProps = isPrefix ? { style: { left: undefined, right: 0 }, ...inputProps?.loadingProps } : inputProps?.loadingProps; const onAmountBlur = () => { let processedAmount = String(value.amount ?? ''); if (processedAmount.endsWith('.')) { processedAmount = processedAmount.slice(0, -1); onChange?.({ ...value, amount: processedAmount, }); } inputProps?.onBlur?.(); }; const availableBalanceNote = availableBalanceText || locale.AmountInput.availableBalance; const inputOnLayout = useMemoizedFn((event) => { if (inputProps.onLayout) { inputProps.onLayout(event); } if (onReady) { onReady(); } }, []); return ( {renderMessage && renderMessage()} {availableBalanceNote} {availableBalanceColon} {formatBalance ? formatBalance(balance) : addThousandSeparators( balance ? String(Number(balance).toFixed(_precision)).replace( '.', decimalSeparator ) : 0, thousandSeparator )}{' '} {value.currency}