Refactoring and small UI fix

This commit is contained in:
IRBorisov 2023-12-27 18:44:37 +03:00
parent 31899c49ce
commit 6e12aff5c6
7 changed files with 56 additions and 34 deletions

View File

@ -50,6 +50,7 @@
"forceatlas", "forceatlas",
"Grammeme", "Grammeme",
"Grammemes", "Grammemes",
"Keymap",
"lezer", "lezer",
"moprho", "moprho",
"nooverlap", "nooverlap",

View File

@ -6,7 +6,7 @@ import { createTheme } from '@uiw/codemirror-themes';
import CodeMirror, { BasicSetupOptions, ReactCodeMirrorProps, ReactCodeMirrorRef } from '@uiw/react-codemirror'; import CodeMirror, { BasicSetupOptions, ReactCodeMirrorProps, ReactCodeMirrorRef } from '@uiw/react-codemirror';
import clsx from 'clsx'; import clsx from 'clsx';
import { EditorView } from 'codemirror'; import { EditorView } from 'codemirror';
import { RefObject, useCallback, useMemo, useRef } from 'react'; import { forwardRef, useCallback, useMemo, useRef } from 'react';
import Label from '@/components/Common/Label'; import Label from '@/components/Common/Label';
import { useRSForm } from '@/context/RSFormContext'; import { useRSForm } from '@/context/RSFormContext';
@ -53,25 +53,22 @@ extends Pick<ReactCodeMirrorProps,
label?: string label?: string
disabled?: boolean disabled?: boolean
noTooltip?: boolean noTooltip?: boolean
innerref?: RefObject<ReactCodeMirrorRef> | undefined
onChange?: (newValue: string) => void onChange?: (newValue: string) => void
onAnalyze?: () => void onAnalyze?: () => void
} }
function RSInput({ const RSInput = forwardRef<ReactCodeMirrorRef, RSInputProps>(
id, label, innerref, onChange, onAnalyze, ({
disabled, noTooltip, id, label, onChange, onAnalyze,
className, style, disabled, noTooltip,
...restProps className, style,
}: RSInputProps) { ...restProps
}, ref) => {
const { darkMode, colors } = useConceptTheme(); const { darkMode, colors } = useConceptTheme();
const { schema } = useRSForm(); const { schema } = useRSForm();
const internalRef = useRef<ReactCodeMirrorRef>(null); const internalRef = useRef<ReactCodeMirrorRef>(null);
const thisRef = useMemo( const thisRef = useMemo(() => (!ref || typeof ref === 'function' ? internalRef : ref), [internalRef, ref]);
() => {
return innerref ?? internalRef;
}, [internalRef, innerref]);
const cursor = useMemo(() => !disabled ? 'cursor-text': 'cursor-default', [disabled]); const cursor = useMemo(() => !disabled ? 'cursor-text': 'cursor-default', [disabled]);
const customTheme: Extension = useMemo( const customTheme: Extension = useMemo(
@ -90,7 +87,7 @@ function RSInput({
{ tag: tags.keyword, color: colors.fgBlue }, // keywords { tag: tags.keyword, color: colors.fgBlue }, // keywords
{ tag: tags.literal, color: colors.fgBlue }, // literals { tag: tags.literal, color: colors.fgBlue }, // literals
{ tag: tags.controlKeyword, fontWeight: '500'}, // R | I | D { tag: tags.controlKeyword, fontWeight: '500'}, // R | I | D
{ tag: tags.unit, fontSize: '0.75rem' }, // indicies { tag: tags.unit, fontSize: '0.75rem' }, // indices
{ tag: tags.brace, color:colors.fgPurple, fontWeight: '700' }, // braces (curly brackets) { tag: tags.brace, color:colors.fgPurple, fontWeight: '700' }, // braces (curly brackets)
] ]
}), [disabled, colors, darkMode]); }), [disabled, colors, darkMode]);
@ -150,6 +147,6 @@ function RSInput({
{...restProps} {...restProps}
/> />
</div>); </div>);
} });
export default RSInput; export default RSInput;

View File

@ -7,7 +7,7 @@ import CodeMirror, { BasicSetupOptions, ReactCodeMirrorProps, ReactCodeMirrorRef
import clsx from 'clsx'; import clsx from 'clsx';
import { EditorView } from 'codemirror'; import { EditorView } from 'codemirror';
import { AnimatePresence } from 'framer-motion'; import { AnimatePresence } from 'framer-motion';
import { RefObject, useCallback, useMemo, useRef, useState } from 'react'; import { forwardRef, useCallback, useMemo, useRef, useState } from 'react';
import Label from '@/components/Common/Label'; import Label from '@/components/Common/Label';
import { useRSForm } from '@/context/RSFormContext'; import { useRSForm } from '@/context/RSFormContext';
@ -54,7 +54,6 @@ extends Pick<ReactCodeMirrorProps,
'id'| 'height' | 'value' | 'className' | 'onFocus' | 'onBlur' | 'placeholder' 'id'| 'height' | 'value' | 'className' | 'onFocus' | 'onBlur' | 'placeholder'
> { > {
label?: string label?: string
innerref?: RefObject<ReactCodeMirrorRef> | undefined
onChange?: (newValue: string) => void onChange?: (newValue: string) => void
items?: IConstituenta[] items?: IConstituenta[]
disabled?: boolean disabled?: boolean
@ -64,12 +63,13 @@ extends Pick<ReactCodeMirrorProps,
resolved?: string resolved?: string
} }
function RefsInput({ const RefsInput = forwardRef<ReactCodeMirrorRef, RefsInputInputProps>(
id, label, innerref, disabled, items, ({
initialValue, value, resolved, id, label, disabled, items,
onFocus, onBlur, onChange, initialValue, value, resolved,
...restProps onFocus, onBlur, onChange,
}: RefsInputInputProps) { ...restProps
}, ref) => {
const { darkMode, colors } = useConceptTheme(); const { darkMode, colors } = useConceptTheme();
const { schema } = useRSForm(); const { schema } = useRSForm();
@ -83,10 +83,7 @@ function RefsInput({
const [mainRefs, setMainRefs] = useState<string[]>([]); const [mainRefs, setMainRefs] = useState<string[]>([]);
const internalRef = useRef<ReactCodeMirrorRef>(null); const internalRef = useRef<ReactCodeMirrorRef>(null);
const thisRef = useMemo( const thisRef = useMemo(() => (!ref || typeof ref === 'function' ? internalRef : ref), [internalRef, ref]);
() => {
return innerref ?? internalRef;
}, [internalRef, innerref]);
const cursor = useMemo(() => !disabled ? 'cursor-text': 'cursor-default', [disabled]); const cursor = useMemo(() => !disabled ? 'cursor-text': 'cursor-default', [disabled]);
const customTheme: Extension = useMemo( const customTheme: Extension = useMemo(
@ -204,6 +201,6 @@ function RefsInput({
/> />
</div> </div>
</>); </>);
} });
export default RefsInput; export default RefsInput;

View File

@ -173,7 +173,7 @@ function EditorRSExpression({
/> />
</Overlay> </Overlay>
<RSInput innerref={rsInput} <RSInput ref={rsInput}
value={value} value={value}
minHeight='3.8rem' minHeight='3.8rem'
disabled={disabled} disabled={disabled}

View File

@ -4,7 +4,7 @@ import clsx from 'clsx';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { IExpressionParse, IRSErrorDescription } from '@/models/rslang'; import { IExpressionParse, IRSErrorDescription } from '@/models/rslang';
import { animateRSControl } from '@/utils/animations'; import { animateParseResults } from '@/utils/animations';
import { describeRSError } from '@/utils/labels'; import { describeRSError } from '@/utils/labels';
import { getRSErrorPrefix } from '@/utils/misc'; import { getRSErrorPrefix } from '@/utils/misc';
@ -22,15 +22,13 @@ function ParsingResult({ isOpen, data, disabled, onShowError }: ParsingResultPro
return ( return (
<motion.div <motion.div
className={clsx( className={clsx(
'px-2 pt-1',
'h-[4.5rem] mt-3',
'text-sm',
'border', 'border',
'text-sm',
'overflow-y-auto' 'overflow-y-auto'
)} )}
initial={false} initial={false}
animate={isOpen ? 'open' : 'closed'} animate={isOpen ? 'open' : 'closed'}
variants={animateRSControl} variants={animateParseResults}
> >
<p>Ошибок: <b>{errorCount}</b> | Предупреждений: <b>{warningsCount}</b></p> <p>Ошибок: <b>{errorCount}</b> | Предупреждений: <b>{warningsCount}</b></p>
{data?.errors.map( {data?.errors.map(

View File

@ -90,7 +90,7 @@ interface RSEditorControlsProps {
function RSEditorControls({ isOpen, disabled, onEdit }: RSEditorControlsProps) { function RSEditorControls({ isOpen, disabled, onEdit }: RSEditorControlsProps) {
return ( return (
<motion.div <motion.div
className='flex-wrap mt-1 text-sm divide-solid' className='flex-wrap text-sm divide-solid'
initial={false} initial={false}
animate={isOpen ? 'open' : 'closed'} animate={isOpen ? 'open' : 'closed'}
variants={animateRSControl} variants={animateRSControl}

View File

@ -97,6 +97,7 @@ export const animateDropdownItem: Variants = {
export const animateRSControl: Variants = { export const animateRSControl: Variants = {
open: { open: {
clipPath: 'inset(0% 0% 0% 0%)', clipPath: 'inset(0% 0% 0% 0%)',
marginTop: '0.25rem',
height: 'max-content', height: 'max-content',
transition: { transition: {
type: 'spring', type: 'spring',
@ -106,6 +107,34 @@ export const animateRSControl: Variants = {
}, },
closed: { closed: {
clipPath: 'inset(0% 0% 100% 0%)', clipPath: 'inset(0% 0% 100% 0%)',
marginTop: '0',
height: 0,
transition: {
type: 'spring',
bounce: 0,
duration: 0.3
}
}
};
export const animateParseResults: Variants = {
open: {
clipPath: 'inset(0% 0% 0% 0%)',
marginTop: '0.75rem',
padding: '0.25rem 0.5rem 0.25rem 0.5rem',
borderWidth: '1px',
height: '4.5rem',
transition: {
type: 'spring',
bounce: 0,
duration: 0.4
}
},
closed: {
clipPath: 'inset(0% 0% 100% 0%)',
marginTop: '0',
borderWidth: '0',
padding: '0 0 0 0',
height: 0, height: 0,
transition: { transition: {
type: 'spring', type: 'spring',