import { memo, useState } from 'react';
import { InputText } from 'exchange-elements/v2';
import styles from './styles.module.scss';
interface TextFieldProps {
label: string;
initialValue: string;
onValueChange: (value: string) => void;
normalizeValue?: (value: string) => string;
}
export const TextField = memo(function TextField({
label,
initialValue,
onValueChange,
normalizeValue,
}: TextFieldProps) {
const [value, setValue] = useState(initialValue);
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const rawValue = event.currentTarget.value;
const nextValue = normalizeValue ? normalizeValue(rawValue) : rawValue;
setValue(nextValue);
onValueChange(nextValue);
};
return (
<InputText
className={styles.input}
value={value}
onChange={handleChange}
label={label}
labelPos="top"
size="sm"
/>
);
});
import { useRef } from 'react';
import { Flex } from 'exchange-elements/v2';
import { TextField, SelectField } from '@src/components/Fields';
import { MaIndicatorSettings, MaSource } from '@src/core/Indicators/settings';
interface IndicatorSettingsModalProps {
settings: MaIndicatorSettings;
onSettingsChange?: (settings: MaIndicatorSettings) => void;
}
const sourceOptions: { label: string; value: MaSource }[] = [
{ label: 'Цена открытия', value: 'open' },
{ label: 'Максимум', value: 'high' },
{ label: 'Минимум', value: 'low' },
{ label: 'Цена закрытия', value: 'close' },
];
export function IndicatorSettingsModal({ settings, onSettingsChange }: IndicatorSettingsModalProps) {
const draftSettingsRef = useRef({ ...settings });
const emitSettingsChange = () => {
onSettingsChange?.({ ...draftSettingsRef.current });
};
const normalizeLengthValue = (value: string) => value.replace(/[^\d]/g, '');
const normalizeOffsetValue = (value: string) => value.replace(/[^\d-]/g, '');
const handleLengthValueChange = (nextLengthValue: string) => {
const nextLength = Number(nextLengthValue);
draftSettingsRef.current = {
...draftSettingsRef.current,
length: Number.isFinite(nextLength) && nextLength > 0 ? nextLength : 1,
};
emitSettingsChange();
};
const handleSourceValueChange = (nextSource: string) => {
draftSettingsRef.current = {
...draftSettingsRef.current,
source: nextSource as MaSource,
};
emitSettingsChange();
};
const handleOffsetValueChange = (nextOffsetValue: string) => {
const nextOffset = Number(nextOffsetValue);
draftSettingsRef.current = {
...draftSettingsRef.current,
offset: Number.isFinite(nextOffset) ? nextOffset : 0,
};
emitSettingsChange();
};
return (
<Flex
direction="column"
divider={null}
spacing="0500"
wrap="nowrap"
>
<TextField
label="Длина"
initialValue={String(settings.length)}
normalizeValue={normalizeLengthValue}
onValueChange={handleLengthValueChange}
/>
<SelectField
label="Данные"
initialValue={settings.source}
options={sourceOptions}
onValueChange={handleSourceValueChange}
/>
<TextField
label="Отступ"
initialValue={String(settings.offset)}
normalizeValue={normalizeOffsetValue}
onValueChange={handleOffsetValueChange}
/>
</Flex>
);
}