import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react'; import Button from '../../components/Common/Button'; import Label from '../../components/Common/Label'; import { useRSForm } from '../../context/RSFormContext'; import { toast } from 'react-toastify'; import RSTokenButton from './RSTokenButton'; import { CstType, TokenID } from '../../utils/models'; import useCheckExpression from '../../hooks/useCheckExpression'; import ParsingResult from './ParsingResult'; import { Loader } from '../../components/Common/Loader'; import StatusBar from './StatusBar'; import { AxiosResponse } from 'axios'; import { TextWrapper, getSymbolSubstitute } from './textEditing'; import RSLocalButton from './RSLocalButton'; interface ExpressionEditorProps { id: string label: string isActive: boolean disabled?: boolean placeholder?: string value: any onChange: (event: React.ChangeEvent) => void toggleEditMode: () => void setTypification: (typificaiton: string) => void setValue: (expression: string) => void } function ExpressionEditor({ id, label, disabled, isActive, placeholder, value, setValue, toggleEditMode, setTypification, onChange }: ExpressionEditorProps) { const { schema, activeCst } = useRSForm(); const [isModified, setIsModified] = useState(false); const { parseData, checkExpression, resetParse, loading } = useCheckExpression({schema: schema}); const expressionCtrl = useRef(null); useLayoutEffect(() => { setIsModified(false); resetParse(); }, [activeCst, resetParse]); const handleCheckExpression = useCallback(() => { const prefix = activeCst?.alias + (activeCst?.cstType === CstType.STRUCTURED ? '::=' : ':=='); const expression = prefix + value; checkExpression(expression, (response: AxiosResponse) => { // TODO: update cursor position setIsModified(false); setTypification(response.data['typification']); toast.success('проверка завершена'); }); }, [value, checkExpression, activeCst, setTypification]); const handleEdit = useCallback((id: TokenID, key?: string) => { if (!expressionCtrl.current) { toast.error('Нет доступа к полю редактирования формального выражения'); return; } let text = new TextWrapper(expressionCtrl.current); if (id === TokenID.ID_LOCAL) { text.insertChar(key!); } else { text.insertToken(id); } text.finalize(); text.focus(); setValue(text.value); setIsModified(true); }, [setValue]); const handleChange = useCallback((event: React.ChangeEvent) => { onChange(event); setIsModified(true); }, [setIsModified, onChange]); const handleInput = useCallback((event: React.KeyboardEvent) => { if (event.altKey) { let text = new TextWrapper(expressionCtrl.current!); if (text.processAltKey(event.key)) { event.preventDefault(); text.finalize(); setValue(text.value); setIsModified(true); } } else if (!event.ctrlKey) { const newSymbol = getSymbolSubstitute(event.key); if (newSymbol) { event.preventDefault(); let text = new TextWrapper(expressionCtrl.current!); text.replaceWith(newSymbol); text.finalize(); setValue(text.value); setIsModified(true); } } }, [expressionCtrl, setValue]); const handleFocusIn = useCallback(() => { toggleEditMode() }, [toggleEditMode]); const EditButtons = useMemo( () => { return (
); }, [handleEdit]) return (