mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Add frontend parser for text references
This commit is contained in:
parent
83242dfb69
commit
cd4792e96c
|
@ -4,7 +4,7 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepare": "lezer-generator src/components/RSInput/rslang/rslangFull.grammar -o src/components/RSInput/rslang/parser.ts",
|
"prepare": "lezer-generator src/components/RSInput/rslang/rslangFull.grammar -o src/components/RSInput/rslang/parser.ts && lezer-generator src/components/RefsInput/parse/refsText.grammar -o src/components/RefsInput/parse/parser.ts",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "tsc && vite build",
|
"build": "tsc && vite build",
|
||||||
|
|
|
@ -45,7 +45,7 @@ const editorSetup: BasicSetupOptions = {
|
||||||
|
|
||||||
interface RSInputProps
|
interface RSInputProps
|
||||||
extends Pick<ReactCodeMirrorProps,
|
extends Pick<ReactCodeMirrorProps,
|
||||||
'id'| 'editable' | 'height' | 'value' | 'className' | 'onFocus' | 'onBlur'
|
'id'| 'editable' | 'height' | 'value' | 'className' | 'onFocus' | 'onBlur' | 'placeholder'
|
||||||
> {
|
> {
|
||||||
label?: string
|
label?: string
|
||||||
innerref?: RefObject<ReactCodeMirrorRef> | undefined
|
innerref?: RefObject<ReactCodeMirrorRef> | undefined
|
||||||
|
|
172
rsconcept/frontend/src/components/RefsInput/index.tsx
Normal file
172
rsconcept/frontend/src/components/RefsInput/index.tsx
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
|
||||||
|
import { Extension } from '@codemirror/state';
|
||||||
|
import { tags } from '@lezer/highlight';
|
||||||
|
import { createTheme } from '@uiw/codemirror-themes';
|
||||||
|
import CodeMirror, { BasicSetupOptions, ReactCodeMirrorProps, ReactCodeMirrorRef } from '@uiw/react-codemirror';
|
||||||
|
import { EditorView } from 'codemirror';
|
||||||
|
import { RefObject, useCallback, useMemo, useRef, useState } from 'react';
|
||||||
|
|
||||||
|
import { useRSForm } from '../../context/RSFormContext';
|
||||||
|
import { useConceptTheme } from '../../context/ThemeContext';
|
||||||
|
import useResolveText from '../../hooks/useResolveText';
|
||||||
|
import Label from '../Common/Label';
|
||||||
|
import Modal from '../Common/Modal';
|
||||||
|
import PrettyJson from '../Common/PrettyJSON';
|
||||||
|
import { NaturalLanguage } from './parse';
|
||||||
|
import { rshoverTooltip as rsHoverTooltip } from './tooltip';
|
||||||
|
|
||||||
|
const editorSetup: BasicSetupOptions = {
|
||||||
|
highlightSpecialChars: false,
|
||||||
|
history: true,
|
||||||
|
drawSelection: false,
|
||||||
|
syntaxHighlighting: false,
|
||||||
|
defaultKeymap: true,
|
||||||
|
historyKeymap: true,
|
||||||
|
|
||||||
|
lineNumbers: false,
|
||||||
|
highlightActiveLineGutter: false,
|
||||||
|
foldGutter: false,
|
||||||
|
dropCursor: false,
|
||||||
|
allowMultipleSelections: false,
|
||||||
|
indentOnInput: false,
|
||||||
|
bracketMatching: false,
|
||||||
|
closeBrackets: false,
|
||||||
|
autocompletion: false,
|
||||||
|
rectangularSelection: false,
|
||||||
|
crosshairCursor: false,
|
||||||
|
highlightActiveLine: false,
|
||||||
|
highlightSelectionMatches: false,
|
||||||
|
closeBracketsKeymap: false,
|
||||||
|
searchKeymap: false,
|
||||||
|
foldKeymap: false,
|
||||||
|
completionKeymap: false,
|
||||||
|
lintKeymap: false
|
||||||
|
};
|
||||||
|
|
||||||
|
interface RefsInputInputProps
|
||||||
|
extends Pick<ReactCodeMirrorProps,
|
||||||
|
'id'| 'editable' | 'height' | 'value' | 'className' | 'onFocus' | 'onBlur' | 'placeholder'
|
||||||
|
> {
|
||||||
|
label?: string
|
||||||
|
innerref?: RefObject<ReactCodeMirrorRef> | undefined
|
||||||
|
onChange?: (newValue: string) => void
|
||||||
|
|
||||||
|
initialValue?: string
|
||||||
|
value?: string
|
||||||
|
resolved?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function RefsInput({
|
||||||
|
id, label, innerref, onChange, editable,
|
||||||
|
initialValue, value, resolved,
|
||||||
|
onFocus, onBlur,
|
||||||
|
...props
|
||||||
|
}: RefsInputInputProps) {
|
||||||
|
const { darkMode, colors } = useConceptTheme();
|
||||||
|
const { schema } = useRSForm();
|
||||||
|
|
||||||
|
const { resolveText, refsData } = useResolveText({schema: schema});
|
||||||
|
|
||||||
|
const [showResolve, setShowResolve] = useState(false);
|
||||||
|
const [isFocused, setIsFocused] = useState(false);
|
||||||
|
|
||||||
|
const internalRef = useRef<ReactCodeMirrorRef>(null);
|
||||||
|
const thisRef = useMemo(
|
||||||
|
() => {
|
||||||
|
return innerref ?? internalRef;
|
||||||
|
}, [internalRef, innerref]);
|
||||||
|
|
||||||
|
const cursor = useMemo(() => editable ? 'cursor-text': 'cursor-default', [editable]);
|
||||||
|
const customTheme: Extension = useMemo(
|
||||||
|
() => createTheme({
|
||||||
|
theme: darkMode ? 'dark' : 'light',
|
||||||
|
settings: {
|
||||||
|
fontFamily: 'inherit',
|
||||||
|
background: editable ? colors.bgInput : colors.bgDefault,
|
||||||
|
foreground: colors.fgDefault,
|
||||||
|
selection: colors.bgHover
|
||||||
|
},
|
||||||
|
styles: [
|
||||||
|
{ tag: tags.name, color: colors.fgPurple }, // GlobalID
|
||||||
|
{ tag: tags.literal, color: colors.fgBlue }, // literals
|
||||||
|
]
|
||||||
|
}), [editable, colors, darkMode]);
|
||||||
|
|
||||||
|
const editorExtensions = useMemo(
|
||||||
|
() => [
|
||||||
|
EditorView.lineWrapping,
|
||||||
|
NaturalLanguage,
|
||||||
|
rsHoverTooltip(schema?.items || []),
|
||||||
|
], [schema?.items]);
|
||||||
|
|
||||||
|
function handleChange(newValue: string) {
|
||||||
|
if (onChange) onChange(newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleFocusIn(event: React.FocusEvent<HTMLDivElement>) {
|
||||||
|
setIsFocused(true);
|
||||||
|
if (onFocus) onFocus(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleFocusOut(event: React.FocusEvent<HTMLDivElement>) {
|
||||||
|
setIsFocused(false);
|
||||||
|
if (onBlur) onBlur(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleInput = useCallback(
|
||||||
|
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||||
|
if (!thisRef.current) {
|
||||||
|
event.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (event.altKey) {
|
||||||
|
if (event.key === 'r' && value) {
|
||||||
|
event.preventDefault();
|
||||||
|
resolveText(value, () => {
|
||||||
|
setShowResolve(true);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [thisRef, resolveText, value]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{ showResolve &&
|
||||||
|
<Modal
|
||||||
|
readonly
|
||||||
|
hideWindow={() => setShowResolve(false)}
|
||||||
|
>
|
||||||
|
<div className='max-h-[60vh] max-w-[80vw] overflow-auto'>
|
||||||
|
<PrettyJson data={refsData} />
|
||||||
|
</div>
|
||||||
|
</Modal>}
|
||||||
|
<div className={`flex flex-col w-full ${cursor}`}>
|
||||||
|
{label &&
|
||||||
|
<Label
|
||||||
|
text={label}
|
||||||
|
required={false}
|
||||||
|
htmlFor={id}
|
||||||
|
className='mb-2'
|
||||||
|
/>}
|
||||||
|
<CodeMirror id={id}
|
||||||
|
ref={thisRef}
|
||||||
|
basicSetup={editorSetup}
|
||||||
|
theme={customTheme}
|
||||||
|
extensions={editorExtensions}
|
||||||
|
|
||||||
|
value={isFocused ? value : (value !== initialValue ? value : resolved)}
|
||||||
|
|
||||||
|
indentWithTab={false}
|
||||||
|
onChange={handleChange}
|
||||||
|
editable={editable}
|
||||||
|
onKeyDown={handleInput}
|
||||||
|
onFocus={handleFocusIn}
|
||||||
|
onBlur={handleFocusOut}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RefsInput;
|
|
@ -0,0 +1,10 @@
|
||||||
|
import {styleTags, tags} from '@lezer/highlight';
|
||||||
|
|
||||||
|
export const highlighting = styleTags({
|
||||||
|
RefEntity: tags.name,
|
||||||
|
Global: tags.name,
|
||||||
|
Gram: tags.name,
|
||||||
|
|
||||||
|
RefSyntactic: tags.literal,
|
||||||
|
Offset: tags.literal,
|
||||||
|
});
|
|
@ -0,0 +1,8 @@
|
||||||
|
import {LRLanguage} from '@codemirror/language'
|
||||||
|
|
||||||
|
import { parser } from './parser';
|
||||||
|
|
||||||
|
export const NaturalLanguage = LRLanguage.define({
|
||||||
|
parser: parser,
|
||||||
|
languageData: {}
|
||||||
|
});
|
|
@ -0,0 +1,10 @@
|
||||||
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
||||||
|
export const
|
||||||
|
Text = 1,
|
||||||
|
RefEntity = 2,
|
||||||
|
Global = 3,
|
||||||
|
Gram = 4,
|
||||||
|
RefSyntactic = 5,
|
||||||
|
Offset = 6,
|
||||||
|
Nominal = 7,
|
||||||
|
Word = 8
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { printTree } from '../../../utils/print-lezer-tree';
|
||||||
|
import { parser } from './parser';
|
||||||
|
|
||||||
|
const testData = [
|
||||||
|
['', '[Text]'],
|
||||||
|
['тест русский', '[Text[Word][Word]]'],
|
||||||
|
['test english', '[Text[Word][Word]]'],
|
||||||
|
['test greek σσσ', '[Text[Word][Word][Word]]'],
|
||||||
|
['X1 раз два X2', '[Text[Word][Word][Word][Word]]'],
|
||||||
|
|
||||||
|
['@{1| черный }', '[Text[RefSyntactic[Offset][Nominal[Word]]]]'],
|
||||||
|
['@{-1| черный }', '[Text[RefSyntactic[Offset][Nominal[Word]]]]'],
|
||||||
|
['@{-100| черный слон }', '[Text[RefSyntactic[Offset][Nominal[Word][Word]]]]'],
|
||||||
|
['@{X1|VERB,past,sing}', '[Text[RefEntity[Global][Gram][Gram][Gram]]]'],
|
||||||
|
['@{X12|VERB,past,sing}', '[Text[RefEntity[Global][Gram][Gram][Gram]]]'],
|
||||||
|
];
|
||||||
|
|
||||||
|
describe('Testing NaturalParser', () => {
|
||||||
|
it.each(testData)('Parse %p',
|
||||||
|
(input: string, expectedTree: string) => {
|
||||||
|
// NOTE: use strict parser to determine exact error position
|
||||||
|
// const tree = parser.configure({strict: true}).parse(input);
|
||||||
|
const tree = parser.parse(input);
|
||||||
|
expect(printTree(tree)).toBe(expectedTree);
|
||||||
|
});
|
||||||
|
});
|
18
rsconcept/frontend/src/components/RefsInput/parse/parser.ts
Normal file
18
rsconcept/frontend/src/components/RefsInput/parse/parser.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
||||||
|
import {LRParser} from "@lezer/lr"
|
||||||
|
import {highlighting} from "./highlight.ts"
|
||||||
|
export const parser = LRParser.deserialize({
|
||||||
|
version: 14,
|
||||||
|
states: "#rQVQPOOO_QQO'#C^OOQO'#Ck'#CkOOQO'#Cj'#CjOOQO'#Ce'#CeQVQPOOOgQPO,58xOlQPO,58{OOQO-E6c-E6cOqQSO1G.dOvQPO1G.gO{QQO'#CoO!TQPO7+$OOOQO'#Cf'#CfO!YQPO'#CcO!bQPO7+$ROqQSO,59ZOOQO<<Gj<<GjOOQO-E6d-E6dOOQO<<Gm<<GmOOQO1G.u1G.u",
|
||||||
|
stateData: "!j~O]OS~OWROaPO~ORUOUVO~ObXO~ObYO~OSZO~OW]O~Od`O`cX~O`aO~OW]O`VX~O`cO~OW]~",
|
||||||
|
goto: "!WdPPePPePiPlrPPPx|PPP!QTQOTR_YQTORWTQ^YRb^TSOTTROTQ[XRd`",
|
||||||
|
nodeNames: "⚠ Text RefEntity Global Gram RefSyntactic Offset Nominal Word",
|
||||||
|
maxTerm: 20,
|
||||||
|
propSources: [highlighting],
|
||||||
|
skippedNodes: [0],
|
||||||
|
repeatNodeCount: 2,
|
||||||
|
tokenData: "-}~R!TOX$bXZ%SZ^%w^p$bpq%Sq|$b|}'p}!O(^!O!Q$b!Q!R)a!R![*a![!b$b!b!c+c!c!d+n!d!e)a!e!f+n!f!g+n!g!h)a!h!i+n!i!r)a!r!s+n!s!t)a!t!u+n!u!v+n!v!w+n!w!z)a!z!{+n!{!})a!}#T$b#T#o)a#p#q-s#q#r-x#r#y$b#y#z%w#z$f$b$f$g%w$g#BY$b#BY#BZ%w#BZ$IS$b$IS$I_%w$I_$I|$b$I|$JO%w$JO$JT$b$JT$JU%w$JU$KV$b$KV$KW%w$KW&FU$b&FU&FV%w&FV;'S$b;'S;=`$|<%lO$bP$gVWPOX$bZp$bq!b$b!c#o$b#r;'S$b;'S;=`$|<%lO$bP%PP;=`<%l$b~%XY]~X^%Spq%S#y#z%S$f$g%S#BY#BZ%S$IS$I_%S$I|$JO%S$JT$JU%S$KV$KW%S&FU&FV%S~&OjWP]~OX$bXZ%SZ^%w^p$bpq%Sq!b$b!c#o$b#r#y$b#y#z%w#z$f$b$f$g%w$g#BY$b#BY#BZ%w#BZ$IS$b$IS$I_%w$I_$I|$b$I|$JO%w$JO$JT$b$JT$JU%w$JU$KV$b$KV$KW%w$KW&FU$b&FU&FV%w&FV;'S$b;'S;=`$|<%lO$bR'wVdQWPOX$bZp$bq!b$b!c#o$b#r;'S$b;'S;=`$|<%lO$bV(e^SSWPOX$bZp$bq}$b}!O)a!O!Q$b!Q!R)a!R![*a![!b$b!c!})a!}#T$b#T#o)a#r;'S$b;'S;=`$|<%lO$bT)h]SSWPOX$bZp$bq}$b}!O)a!O!Q$b!Q![)a![!b$b!c!})a!}#T$b#T#o)a#r;'S$b;'S;=`$|<%lO$bV*j]SSUQWPOX$bZp$bq}$b}!O)a!O!Q$b!Q![*a![!b$b!c!})a!}#T$b#T#o)a#r;'S$b;'S;=`$|<%lO$b~+fP#o#p+i~+nOa~V+u^SSWPOX$bZp$bq}$b}!O)a!O!Q$b!Q!R)a!R![,q![!b$b!c!})a!}#T$b#T#o)a#r;'S$b;'S;=`$|<%lO$bV,z]RQSSWPOX$bZp$bq}$b}!O)a!O!Q$b!Q![,q![!b$b!c!})a!}#T$b#T#o)a#r;'S$b;'S;=`$|<%lO$b~-xOb~~-}O`~",
|
||||||
|
tokenizers: [0, 1, 2],
|
||||||
|
topRules: {"Text":[0,1]},
|
||||||
|
tokenPrec: 69
|
||||||
|
})
|
|
@ -0,0 +1,50 @@
|
||||||
|
@precedence {
|
||||||
|
p1
|
||||||
|
p2
|
||||||
|
}
|
||||||
|
|
||||||
|
@top Text { textItem* }
|
||||||
|
|
||||||
|
@skip { space }
|
||||||
|
|
||||||
|
@tokens {
|
||||||
|
space { @whitespace+ }
|
||||||
|
|
||||||
|
Offset { $[-]?$[1-9]$[0-9]* }
|
||||||
|
Global { $[XCSDATFPR]$[1-9]$[0-9]* }
|
||||||
|
|
||||||
|
Word { ![@{|} \t\n]+ }
|
||||||
|
|
||||||
|
Gram { $[-a-zA-Z0-9]+ }
|
||||||
|
|
||||||
|
@precedence { Word, space }
|
||||||
|
}
|
||||||
|
|
||||||
|
textItem {
|
||||||
|
!p1 ref |
|
||||||
|
!p2 Word
|
||||||
|
}
|
||||||
|
|
||||||
|
ref {
|
||||||
|
RefEntity |
|
||||||
|
RefSyntactic
|
||||||
|
}
|
||||||
|
|
||||||
|
RefEntity {
|
||||||
|
"@{" Global "|" grams "}"
|
||||||
|
}
|
||||||
|
|
||||||
|
RefSyntactic {
|
||||||
|
"@{" Offset "|" Nominal "}"
|
||||||
|
}
|
||||||
|
|
||||||
|
Nominal { Word+ }
|
||||||
|
|
||||||
|
grams {
|
||||||
|
Gram |
|
||||||
|
Gram "," grams
|
||||||
|
}
|
||||||
|
|
||||||
|
@detectDelim
|
||||||
|
|
||||||
|
@external propSource highlighting from "./highlight.ts"
|
63
rsconcept/frontend/src/components/RefsInput/tooltip.ts
Normal file
63
rsconcept/frontend/src/components/RefsInput/tooltip.ts
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
import { Extension } from '@codemirror/state';
|
||||||
|
import { hoverTooltip } from '@codemirror/view';
|
||||||
|
|
||||||
|
import { IConstituenta } from '../../models/rsform';
|
||||||
|
import { labelCstTypification } from '../../utils/labels';
|
||||||
|
|
||||||
|
function createTooltipFor(cst: IConstituenta) {
|
||||||
|
const dom = document.createElement('div');
|
||||||
|
dom.className = 'overflow-y-auto border shadow-md max-h-[25rem] max-w-[25rem] min-w-[10rem] w-fit z-tooltip text-sm px-2 py-2';
|
||||||
|
const alias = document.createElement('p');
|
||||||
|
alias.innerHTML = `<b>${cst.alias}:</b> ${labelCstTypification(cst)}`;
|
||||||
|
dom.appendChild(alias);
|
||||||
|
if (cst.term_resolved) {
|
||||||
|
const term = document.createElement('p');
|
||||||
|
term.innerHTML = `<b>Термин:</b> ${cst.term_resolved}`;
|
||||||
|
dom.appendChild(term);
|
||||||
|
}
|
||||||
|
if (cst.definition_formal) {
|
||||||
|
const expression = document.createElement('p');
|
||||||
|
expression.innerHTML = `<b>Выражение:</b> ${cst.definition_formal}`;
|
||||||
|
dom.appendChild(expression);
|
||||||
|
}
|
||||||
|
if (cst.definition_resolved) {
|
||||||
|
const definition = document.createElement('p');
|
||||||
|
definition.innerHTML = `<b>Определение:</b> ${cst.definition_resolved}`;
|
||||||
|
dom.appendChild(definition);
|
||||||
|
}
|
||||||
|
if (cst.convention) {
|
||||||
|
const convention = document.createElement('p');
|
||||||
|
convention.innerHTML = `<b>Конвенция:</b> ${cst.convention}`;
|
||||||
|
dom.appendChild(convention);
|
||||||
|
}
|
||||||
|
return { dom: dom }
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getHoverTooltip = (items: IConstituenta[]) => {
|
||||||
|
return hoverTooltip((view, pos, side) => {
|
||||||
|
const {from, to, text} = view.state.doc.lineAt(pos);
|
||||||
|
let start = pos, end = pos;
|
||||||
|
while (start > from && /\w/.test(text[start - from - 1]))
|
||||||
|
start--;
|
||||||
|
while (end < to && /\w/.test(text[end - from]))
|
||||||
|
end++;
|
||||||
|
if (start === pos && side < 0 || end === pos && side > 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const alias = text.slice(start - from, end - from);
|
||||||
|
const cst = items.find(cst => cst.alias === alias);
|
||||||
|
if (!cst) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
pos: start,
|
||||||
|
end: end,
|
||||||
|
above: false,
|
||||||
|
create: () => createTooltipFor(cst)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function rshoverTooltip(items: IConstituenta[]): Extension {
|
||||||
|
return [getHoverTooltip(items)];
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import SubmitButton from '../../components/Common/SubmitButton';
|
||||||
import TextArea from '../../components/Common/TextArea';
|
import TextArea from '../../components/Common/TextArea';
|
||||||
import HelpConstituenta from '../../components/Help/HelpConstituenta';
|
import HelpConstituenta from '../../components/Help/HelpConstituenta';
|
||||||
import { DumpBinIcon, HelpIcon, PenIcon, SaveIcon, SmallPlusIcon } from '../../components/Icons';
|
import { DumpBinIcon, HelpIcon, PenIcon, SaveIcon, SmallPlusIcon } from '../../components/Icons';
|
||||||
|
import RefsInput from '../../components/RefsInput';
|
||||||
import { useRSForm } from '../../context/RSFormContext';
|
import { useRSForm } from '../../context/RSFormContext';
|
||||||
import useWindowSize from '../../hooks/useWindowSize';
|
import useWindowSize from '../../hooks/useWindowSize';
|
||||||
import { EditMode } from '../../models/miscelanious';
|
import { EditMode } from '../../models/miscelanious';
|
||||||
|
@ -144,7 +145,7 @@ function EditorConstituenta({
|
||||||
<MiniButton
|
<MiniButton
|
||||||
tooltip={`Редактировать словоформы термина: ${activeCst.term_forms.length}`}
|
tooltip={`Редактировать словоформы термина: ${activeCst.term_forms.length}`}
|
||||||
disabled={!isEnabled}
|
disabled={!isEnabled}
|
||||||
dimensions='w-fit ml-[3.2rem] pt-[0.4rem]'
|
dimensions='w-fit ml-[3.2rem] pt-[0.3rem]'
|
||||||
noHover
|
noHover
|
||||||
onClick={onEditTerm}
|
onClick={onEditTerm}
|
||||||
icon={<PenIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
|
icon={<PenIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
|
||||||
|
@ -219,15 +220,15 @@ function EditorConstituenta({
|
||||||
onChange={newValue => setExpression(newValue)}
|
onChange={newValue => setExpression(newValue)}
|
||||||
setTypification={setTypification}
|
setTypification={setTypification}
|
||||||
/>
|
/>
|
||||||
<ReferenceInput id='definition' label='Текстовое определение'
|
<RefsInput id='definition' label='Текстовое определение'
|
||||||
placeholder='Лингвистическая интерпретация формального выражения'
|
placeholder='Лингвистическая интерпретация формального выражения'
|
||||||
rows={4}
|
height='6.3rem'
|
||||||
value={textDefinition}
|
value={textDefinition}
|
||||||
initialValue={activeCst?.definition_raw ?? ''}
|
initialValue={activeCst?.definition_raw ?? ''}
|
||||||
resolved={activeCst?.definition_resolved ?? ''}
|
resolved={activeCst?.definition_resolved ?? ''}
|
||||||
disabled={!isEnabled}
|
editable={isEnabled}
|
||||||
spellCheck
|
// spellCheck
|
||||||
onChange={event => setTextDefinition(event.target.value)}
|
onChange={newValue => setTextDefinition(newValue)}
|
||||||
onFocus={() => setEditMode(EditMode.TEXT)}
|
onFocus={() => setEditMode(EditMode.TEXT)}
|
||||||
/>
|
/>
|
||||||
<TextArea id='convention' label='Конвенция / Комментарий'
|
<TextArea id='convention' label='Конвенция / Комментарий'
|
||||||
|
|
Loading…
Reference in New Issue
Block a user