mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 04:50:36 +03:00
F: Improve styling pt2
This commit is contained in:
parent
4f9a94c933
commit
20022ea648
|
@ -25,7 +25,7 @@ export function ApplicationLayout() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavigationState>
|
<NavigationState>
|
||||||
<div className='min-w-80 antialiased h-full max-w-[120rem] mx-auto'>
|
<div className='min-w-80 antialiased h-full max-w-480 mx-auto'>
|
||||||
<ToasterThemed
|
<ToasterThemed
|
||||||
className='text-[14px]'
|
className='text-[14px]'
|
||||||
style={{ marginTop: noNavigationAnimation ? '1.5rem' : '3.5rem' }}
|
style={{ marginTop: noNavigationAnimation ? '1.5rem' : '3.5rem' }}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import { useNavigation } from 'react-router';
|
import { useNavigation } from 'react-router';
|
||||||
import clsx from 'clsx';
|
|
||||||
import { useDebounce } from 'use-debounce';
|
import { useDebounce } from 'use-debounce';
|
||||||
|
|
||||||
import { Loader } from '@/components/Loader';
|
import { Loader } from '@/components/Loader';
|
||||||
|
import { ModalBackdrop } from '@/components/Modal/ModalBackdrop';
|
||||||
import { PARAMETER } from '@/utils/constants';
|
import { PARAMETER } from '@/utils/constants';
|
||||||
|
|
||||||
// TODO: add animation
|
|
||||||
export function GlobalLoader() {
|
export function GlobalLoader() {
|
||||||
const navigation = useNavigation();
|
const navigation = useNavigation();
|
||||||
|
|
||||||
|
@ -17,16 +16,9 @@ export function GlobalLoader() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='fixed top-0 left-0 w-full h-full z-modal cursor-default'>
|
<div className='cc-modal-wrapper'>
|
||||||
<div className={clsx('z-navigation', 'fixed top-0 left-0', 'w-full h-full', 'backdrop-blur-[3px] opacity-50')} />
|
<ModalBackdrop />
|
||||||
<div className={clsx('z-navigation', 'fixed top-0 left-0', 'w-full h-full', 'bg-prim-0 opacity-25')} />
|
<div className='cc-fade-in px-10 border rounded-xl bg-prim-100'>
|
||||||
<div
|
|
||||||
className={clsx(
|
|
||||||
'px-10 mb-10',
|
|
||||||
'z-modal absolute bottom-1/2 left-1/2 -translate-x-1/2 translate-y-1/2',
|
|
||||||
'border rounded-xl bg-prim-100'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Loader scale={6} />
|
<Loader scale={6} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { useMutationErrors } from '@/backend/useMutationErrors';
|
import { useMutationErrors } from '@/backend/useMutationErrors';
|
||||||
import { Button } from '@/components/Control';
|
import { Button } from '@/components/Control';
|
||||||
import { DescribeError } from '@/components/InfoError';
|
import { DescribeError } from '@/components/InfoError';
|
||||||
|
import { ModalBackdrop } from '@/components/Modal/ModalBackdrop';
|
||||||
import { useEscapeKey } from '@/hooks/useEscapeKey';
|
import { useEscapeKey } from '@/hooks/useEscapeKey';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
|
|
||||||
|
@ -19,18 +18,11 @@ export function MutationErrors() {
|
||||||
hideDialog();
|
hideDialog();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='fixed top-0 left-0 w-full h-full z-modal cursor-default'>
|
<div className='cc-modal-wrapper'>
|
||||||
<div className={clsx('z-navigation', 'fixed top-0 left-0', 'w-full h-full', 'backdrop-blur-[3px] opacity-50')} />
|
<ModalBackdrop onHide={resetErrors} />
|
||||||
<div className={clsx('z-navigation', 'fixed top-0 left-0', 'w-full h-full', 'bg-prim-0 opacity-25')} />
|
<div className='px-10 py-3 flex flex-col items-center border rounded-xl bg-prim-100' role='alertdialog'>
|
||||||
<div
|
|
||||||
className={clsx(
|
|
||||||
'px-10 mb-10 py-3 flex flex-col items-center',
|
|
||||||
'z-modal absolute bottom-1/2 left-1/2 -translate-x-1/2 translate-y-1/2',
|
|
||||||
'border rounded-xl bg-prim-100'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<h1 className='py-2 select-none'>Ошибка при обработке</h1>
|
<h1 className='py-2 select-none'>Ошибка при обработке</h1>
|
||||||
<div className={clsx('px-3 flex flex-col', 'text-warn-600 text-sm font-semibold', 'select-text')}>
|
<div className='px-3 flex flex-col text-warn-600 text-sm font-semibold select-text'>
|
||||||
<DescribeError error={mutationErrors[0]} />
|
<DescribeError error={mutationErrors[0]} />
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={resetErrors} className='w-fit' text='Закрыть' />
|
<Button onClick={resetErrors} className='w-fit' text='Закрыть' />
|
||||||
|
|
|
@ -8,6 +8,7 @@ export function Logo() {
|
||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
alt=''
|
alt=''
|
||||||
|
aria-hidden
|
||||||
className='max-h-7 w-fit max-w-46'
|
className='max-h-7 w-fit max-w-46'
|
||||||
src={size.isSmall ? '/logo_sign.svg' : !darkMode ? '/logo_full.svg' : '/logo_full_dark.svg'}
|
src={size.isSmall ? '/logo_sign.svg' : !darkMode ? '/logo_full.svg' : '/logo_full_dark.svg'}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { IconLibrary2, IconManuals, IconNewItem2 } from '@/components/Icons';
|
import { IconLibrary2, IconManuals, IconNewItem2 } from '@/components/Icons';
|
||||||
import { useWindowSize } from '@/hooks/useWindowSize';
|
import { useWindowSize } from '@/hooks/useWindowSize';
|
||||||
import { useAppLayoutStore } from '@/stores/appLayout';
|
import { useAppLayoutStore } from '@/stores/appLayout';
|
||||||
import { PARAMETER } from '@/utils/constants';
|
|
||||||
|
|
||||||
import { urls } from '../urls';
|
import { urls } from '../urls';
|
||||||
|
|
||||||
|
@ -28,34 +25,16 @@ export function Navigation() {
|
||||||
router.push({ path: urls.create_schema, newTab: event.ctrlKey || event.metaKey });
|
router.push({ path: urls.create_schema, newTab: event.ctrlKey || event.metaKey });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav
|
<nav className='z-navigation sticky top-0 left-0 right-0 select-none bg-prim-100'>
|
||||||
className={clsx(
|
|
||||||
'z-navigation', //
|
|
||||||
'sticky top-0 left-0 right-0',
|
|
||||||
'select-none',
|
|
||||||
'bg-prim-100'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<ToggleNavigation />
|
<ToggleNavigation />
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className='pl-2 pr-6 sm:pr-4 h-12 flex cc-shadow-border'
|
||||||
'pl-2 pr-6 sm:pr-4 h-12', //
|
|
||||||
'flex',
|
|
||||||
'cc-shadow-border'
|
|
||||||
)}
|
|
||||||
style={{
|
style={{
|
||||||
willChange: 'max-height, translate',
|
|
||||||
transitionProperty: 'max-height, translate',
|
|
||||||
transitionDuration: `${PARAMETER.moveDuration}ms`,
|
|
||||||
maxHeight: noNavigationAnimation ? '0rem' : '3rem',
|
maxHeight: noNavigationAnimation ? '0rem' : '3rem',
|
||||||
translate: noNavigationAnimation ? '0 -1.5rem' : '0'
|
translate: noNavigationAnimation ? '0 -1.5rem' : '0'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div className='flex items-center mr-auto cursor-pointer' onClick={!size.isSmall ? navigateHome : undefined}>
|
||||||
tabIndex={-1}
|
|
||||||
className={clsx('flex items-center mr-auto', !size.isSmall && 'cursor-pointer')}
|
|
||||||
onClick={!size.isSmall ? navigateHome : undefined}
|
|
||||||
>
|
|
||||||
<Logo />
|
<Logo />
|
||||||
</div>
|
</div>
|
||||||
<div className='flex gap-2 items-center'>
|
<div className='flex gap-2 items-center'>
|
||||||
|
|
|
@ -17,7 +17,7 @@ export function Divider({ vertical, margins = 'mx-2', className, ...restProps }:
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
margins, //prettier: split-lines
|
margins, //
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
'border-x': vertical,
|
'border-x': vertical,
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { type Table } from '@tanstack/react-table';
|
import { type Table } from '@tanstack/react-table';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { prefixes } from '@/utils/constants';
|
import { prefixes } from '@/utils/constants';
|
||||||
|
|
||||||
|
@ -34,7 +33,7 @@ export function PaginationTools<TData>({
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={clsx('flex justify-end items-center', 'my-2', 'text-sm', 'clr-text-controls', 'select-none')}>
|
<div className='flex justify-end items-center my-2 text-sm clr-text-controls select-none'>
|
||||||
<span className='mr-3'>
|
<span className='mr-3'>
|
||||||
{`${table.getState().pagination.pageIndex * table.getState().pagination.pageSize + 1}
|
{`${table.getState().pagination.pageIndex * table.getState().pagination.pageSize + 1}
|
||||||
-
|
-
|
||||||
|
|
|
@ -41,7 +41,7 @@ export function FileInput({ id, label, acceptType, title, className, style, onCh
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={clsx('py-2', 'flex flex-col gap-2 items-center', className)} style={style}>
|
<div className={clsx('py-2 flex flex-col gap-2 items-center', className)} style={style}>
|
||||||
<input
|
<input
|
||||||
id={id}
|
id={id}
|
||||||
type='file'
|
type='file'
|
||||||
|
|
|
@ -109,7 +109,7 @@ export function SelectMulti<Option, Group extends GroupBase<Option> = GroupBase<
|
||||||
...theme,
|
...theme,
|
||||||
borderRadius: 0,
|
borderRadius: 0,
|
||||||
spacing: {
|
spacing: {
|
||||||
...theme.spacing, // prettier: split-lines
|
...theme.spacing,
|
||||||
baseUnit: size.isSmall ? 2 : 4,
|
baseUnit: size.isSmall ? 2 : 4,
|
||||||
menuGutter: size.isSmall ? 4 : 8,
|
menuGutter: size.isSmall ? 4 : 8,
|
||||||
controlHeight: size.isSmall ? 28 : 38
|
controlHeight: size.isSmall ? 28 : 38
|
||||||
|
|
|
@ -107,7 +107,7 @@ export function SelectSingle<Option, Group extends GroupBase<Option> = GroupBase
|
||||||
...theme,
|
...theme,
|
||||||
borderRadius: 0,
|
borderRadius: 0,
|
||||||
spacing: {
|
spacing: {
|
||||||
...theme.spacing, // prettier: split-lines
|
...theme.spacing,
|
||||||
baseUnit: size.isSmall ? 2 : 4,
|
baseUnit: size.isSmall ? 2 : 4,
|
||||||
menuGutter: 2,
|
menuGutter: 2,
|
||||||
controlHeight: size.isSmall ? 28 : 38
|
controlHeight: size.isSmall ? 28 : 38
|
||||||
|
|
|
@ -50,13 +50,13 @@ export function SelectTree<ItemType>({
|
||||||
setFolded(items.filter(item => getParent(value) !== item && getParent(getParent(value)) !== item));
|
setFolded(items.filter(item => getParent(value) !== item && getParent(getParent(value)) !== item));
|
||||||
}, [value, getParent, items]);
|
}, [value, getParent, items]);
|
||||||
|
|
||||||
function onFoldItem(target: ItemType, showChildren: boolean) {
|
function onFoldItem(target: ItemType) {
|
||||||
setFolded(prev =>
|
setFolded(prev =>
|
||||||
items.filter(item => {
|
items.filter(item => {
|
||||||
if (item === target) {
|
if (item === target) {
|
||||||
return !showChildren;
|
return !prev.includes(target);
|
||||||
}
|
}
|
||||||
if (!showChildren && (getParent(item) === target || getParent(getParent(item)) === target)) {
|
if (!prev.includes(target) && (getParent(item) === target || getParent(getParent(item)) === target)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return prev.includes(item);
|
return prev.includes(item);
|
||||||
|
@ -65,17 +65,21 @@ export function SelectTree<ItemType>({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleClickFold(event: React.MouseEvent<Element>, target: ItemType, showChildren: boolean) {
|
function handleClickFold(event: React.MouseEvent<Element>, target: ItemType) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
onFoldItem(target, showChildren);
|
onFoldItem(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSetValue(event: React.MouseEvent<Element>, target: ItemType) {
|
function handleClickItem(event: React.MouseEvent<Element>, target: ItemType) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
if (event.ctrlKey || event.metaKey) {
|
||||||
|
onFoldItem(target);
|
||||||
|
} else {
|
||||||
onChange(target);
|
onChange(target);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div tabIndex={-1} {...restProps}>
|
<div tabIndex={-1} {...restProps}>
|
||||||
|
@ -95,7 +99,7 @@ export function SelectTree<ItemType>({
|
||||||
)}
|
)}
|
||||||
data-tooltip-id={globalIDs.tooltip}
|
data-tooltip-id={globalIDs.tooltip}
|
||||||
data-tooltip-html={getDescription(item)}
|
data-tooltip-html={getDescription(item)}
|
||||||
onClick={event => handleSetValue(event, item)}
|
onClick={event => handleClickItem(event, item)}
|
||||||
style={{
|
style={{
|
||||||
borderBottomWidth: isActive ? '1px' : '0px',
|
borderBottomWidth: isActive ? '1px' : '0px',
|
||||||
willChange: 'max-height, opacity, padding',
|
willChange: 'max-height, opacity, padding',
|
||||||
|
@ -109,11 +113,11 @@ export function SelectTree<ItemType>({
|
||||||
>
|
>
|
||||||
{foldable.has(item) ? (
|
{foldable.has(item) ? (
|
||||||
<MiniButton
|
<MiniButton
|
||||||
className={clsx('absolute left-[0.3rem]', !folded.includes(item) ? 'top-[0.4rem]' : 'top-1')}
|
className={clsx('absolute left-1', !folded.includes(item) ? 'top-1.5' : 'top-1')}
|
||||||
noPadding
|
noPadding
|
||||||
noHover
|
noHover
|
||||||
icon={!folded.includes(item) ? <IconDropArrow size='1rem' /> : <IconPageRight size='1.25rem' />}
|
icon={!folded.includes(item) ? <IconDropArrow size='1rem' /> : <IconPageRight size='1.25rem' />}
|
||||||
onClick={event => handleClickFold(event, item, folded.includes(item))}
|
onClick={event => handleClickFold(event, item)}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{getParent(item) === item ? getLabel(item) : `- ${getLabel(item).toLowerCase()}`}
|
{getParent(item) === item ? getLabel(item) : `- ${getLabel(item).toLowerCase()}`}
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
interface ModalBackdropProps {
|
interface ModalBackdropProps {
|
||||||
onHide: () => void;
|
onHide?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ModalBackdrop({ onHide }: ModalBackdropProps) {
|
export function ModalBackdrop({ onHide }: ModalBackdropProps) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={clsx('z-bottom', 'fixed top-0 left-0', 'w-full h-full', 'backdrop-blur-[3px] opacity-50')} />
|
<div className='z-bottom fixed inset-0 backdrop-blur-[3px] opacity-50' />
|
||||||
<div
|
<div className='z-bottom fixed inset-0 bg-prim-0 opacity-25' onClick={onHide} />
|
||||||
className={clsx('z-bottom', 'fixed top-0 left-0', 'w-full h-full', 'bg-prim-0 opacity-25')}
|
|
||||||
onClick={onHide}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,15 +87,10 @@ export function ModalForm({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='fixed top-0 left-0 w-full h-full z-modal isolate cursor-default'>
|
<div className='cc-modal-wrapper'>
|
||||||
<ModalBackdrop onHide={handleCancel} />
|
<ModalBackdrop onHide={handleCancel} />
|
||||||
<form
|
<form
|
||||||
className={clsx(
|
className='cc-animate-modal grid border rounded-xl bg-prim-100'
|
||||||
'cc-animate-modal',
|
|
||||||
'absolute bottom-1/2 left-1/2 -translate-x-1/2 translate-y-1/2',
|
|
||||||
'grid',
|
|
||||||
'border rounded-xl bg-prim-100'
|
|
||||||
)}
|
|
||||||
role='dialog'
|
role='dialog'
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
aria-labelledby='modal-title'
|
aria-labelledby='modal-title'
|
||||||
|
|
|
@ -1,19 +1,12 @@
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { Loader } from '@/components/Loader';
|
import { Loader } from '@/components/Loader';
|
||||||
|
|
||||||
|
import { ModalBackdrop } from './ModalBackdrop';
|
||||||
|
|
||||||
export function ModalLoader() {
|
export function ModalLoader() {
|
||||||
return (
|
return (
|
||||||
<div className='fixed top-0 left-0 w-full h-full z-modal isolate cursor-default'>
|
<div className='cc-modal-wrapper'>
|
||||||
<div className={clsx('z-bottom fixed top-0 left-0', 'w-full h-full', 'backdrop-blur-[3px] opacity-50')} />
|
<ModalBackdrop />
|
||||||
<div className={clsx('z-bottom fixed top-0 left-0', 'w-full h-full', 'bg-prim-0 opacity-25')} />
|
<div className='cc-animate-modal p-20 border rounded-xl bg-prim-100'>
|
||||||
<div
|
|
||||||
className={clsx(
|
|
||||||
'cc-animate-modal p-20',
|
|
||||||
'z-modal absolute bottom-1/2 left-1/2 -translate-x-1/2 translate-y-1/2',
|
|
||||||
'border rounded-xl bg-prim-100'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Loader circular scale={6} />
|
<Loader circular scale={6} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -32,17 +32,9 @@ export function ModalView({
|
||||||
useEscapeKey(hideDialog);
|
useEscapeKey(hideDialog);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='fixed top-0 left-0 w-full h-full z-modal isolate cursor-default'>
|
<div className='cc-modal-wrapper'>
|
||||||
<ModalBackdrop onHide={hideDialog} />
|
<ModalBackdrop onHide={hideDialog} />
|
||||||
<div
|
<div className='cc-animate-modal grid border rounded-xl bg-prim-100' role='dialog'>
|
||||||
className={clsx(
|
|
||||||
'cc-animate-modal',
|
|
||||||
'absolute bottom-1/2 left-1/2 -translate-x-1/2 translate-y-1/2',
|
|
||||||
'grid',
|
|
||||||
'border rounded-xl bg-prim-100'
|
|
||||||
)}
|
|
||||||
role='dialog'
|
|
||||||
>
|
|
||||||
{helpTopic && !hideHelpWhen?.() ? (
|
{helpTopic && !hideHelpWhen?.() ? (
|
||||||
<BadgeHelp
|
<BadgeHelp
|
||||||
topic={helpTopic}
|
topic={helpTopic}
|
||||||
|
|
|
@ -20,5 +20,5 @@ interface ValueStatsProps extends Styling, Titled {
|
||||||
* Displays statistics value with an icon.
|
* Displays statistics value with an icon.
|
||||||
*/
|
*/
|
||||||
export function ValueStats(props: ValueStatsProps) {
|
export function ValueStats(props: ValueStatsProps) {
|
||||||
return <ValueIcon dense smallThreshold={SMALL_THRESHOLD} textClassName='min-w-[1.4rem]' {...props} />;
|
return <ValueIcon dense smallThreshold={SMALL_THRESHOLD} textClassName='min-w-5' {...props} />;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { urls, useConceptNavigation } from '@/app';
|
import { urls, useConceptNavigation } from '@/app';
|
||||||
|
|
||||||
|
@ -56,11 +55,11 @@ export function LoginPage() {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
className={clsx('cc-column cc-fade-in', 'w-[24rem] mx-auto', 'pt-12 pb-6 px-6')}
|
className='cc-column cc-fade-in w-96 mx-auto pt-12 pb-6 px-6'
|
||||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||||
onChange={resetErrors}
|
onChange={resetErrors}
|
||||||
>
|
>
|
||||||
<img alt='Концепт Портал' src={resources.logo} className='max-h-[2.5rem] min-w-[2.5rem] mb-3' />
|
<img alt='Концепт Портал' src={resources.logo} className='max-h-10 min-w-10 mb-3' />
|
||||||
<TextInput
|
<TextInput
|
||||||
id='username'
|
id='username'
|
||||||
autoComplete='username'
|
autoComplete='username'
|
||||||
|
@ -82,7 +81,7 @@ export function LoginPage() {
|
||||||
error={errors.password}
|
error={errors.password}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SubmitButton text='Войти' className='self-center w-[12rem] mt-3' loading={isPending} />
|
<SubmitButton text='Войти' className='self-center w-48 mt-3' loading={isPending} />
|
||||||
<div className='flex flex-col text-sm'>
|
<div className='flex flex-col text-sm'>
|
||||||
<TextURL text='Восстановить пароль...' href='/restore-password' />
|
<TextURL text='Восстановить пароль...' href='/restore-password' />
|
||||||
<TextURL text='Нет аккаунта? Зарегистрируйтесь...' href='/signup' />
|
<TextURL text='Нет аккаунта? Зарегистрируйтесь...' href='/signup' />
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { isAxiosError } from '@/backend/apiTransport';
|
import { isAxiosError } from '@/backend/apiTransport';
|
||||||
import { SubmitButton, TextURL } from '@/components/Control';
|
import { SubmitButton, TextURL } from '@/components/Control';
|
||||||
|
@ -33,11 +32,7 @@ export function Component() {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<form
|
<form className='cc-fade-in cc-column w-96 mx-auto px-6 mt-3' onSubmit={handleSubmit} onChange={clearServerError}>
|
||||||
className={clsx('cc-fade-in cc-column', 'w-[24rem] mx-auto', 'px-6 mt-3')}
|
|
||||||
onSubmit={handleSubmit}
|
|
||||||
onChange={clearServerError}
|
|
||||||
>
|
|
||||||
<TextInput
|
<TextInput
|
||||||
id='email'
|
id='email'
|
||||||
autoComplete='email'
|
autoComplete='email'
|
||||||
|
@ -48,12 +43,7 @@ export function Component() {
|
||||||
onChange={event => setEmail(event.target.value)}
|
onChange={event => setEmail(event.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SubmitButton
|
<SubmitButton text='Запросить пароль' className='self-center w-48 mt-3' loading={isPending} disabled={!email} />
|
||||||
text='Запросить пароль'
|
|
||||||
className='self-center w-[12rem] mt-3'
|
|
||||||
loading={isPending}
|
|
||||||
disabled={!email}
|
|
||||||
/>
|
|
||||||
{serverError ? <ServerError error={serverError} /> : null}
|
{serverError ? <ServerError error={serverError} /> : null}
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|
|
@ -52,7 +52,7 @@ export function BadgeHelp({ topic, padding = 'p-1', className, contentClass, sty
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
<Suspense fallback={<Loader />}>
|
<Suspense fallback={<Loader />}>
|
||||||
<div className='absolute right-1 text-sm top-[0.4rem] clr-input' onClick={event => event.stopPropagation()}>
|
<div className='absolute right-1 text-sm top-2 clr-input' onClick={event => event.stopPropagation()}>
|
||||||
<TextURL text='Справка...' href={`/manuals?topic=${topic}`} />
|
<TextURL text='Справка...' href={`/manuals?topic=${topic}`} />
|
||||||
</div>
|
</div>
|
||||||
<TopicPage topic={topic} />
|
<TopicPage topic={topic} />
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { CstClass } from '@/features/rsform';
|
import { CstClass } from '@/features/rsform';
|
||||||
import { colorBgCstClass } from '@/features/rsform/colors';
|
import { colorBgCstClass } from '@/features/rsform/colors';
|
||||||
import { describeCstClass, labelCstClass } from '@/features/rsform/labels';
|
import { describeCstClass, labelCstClass } from '@/features/rsform/labels';
|
||||||
|
@ -18,7 +16,7 @@ export function InfoCstClass({ header }: InfoCstClassProps) {
|
||||||
return (
|
return (
|
||||||
<p key={`${prefixes.cst_status_list}${index}`}>
|
<p key={`${prefixes.cst_status_list}${index}`}>
|
||||||
<span
|
<span
|
||||||
className={clsx('inline-block', 'min-w-28', 'px-1', 'border', 'text-center text-sm font-controls')}
|
className='inline-block min-w-28 px-1 border text-center text-sm font-controls'
|
||||||
style={{ backgroundColor: colorBgCstClass(cstClass) }}
|
style={{ backgroundColor: colorBgCstClass(cstClass) }}
|
||||||
>
|
>
|
||||||
{labelCstClass(cstClass)}
|
{labelCstClass(cstClass)}
|
||||||
|
|
|
@ -21,7 +21,7 @@ export function InfoCstStatus({ title }: InfoCstStatusProps) {
|
||||||
<span
|
<span
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'inline-block', //
|
'inline-block', //
|
||||||
'min-w-[7rem]',
|
'min-w-28',
|
||||||
'px-1',
|
'px-1',
|
||||||
'border',
|
'border',
|
||||||
'text-center text-sm font-controls'
|
'text-center text-sm font-controls'
|
||||||
|
|
|
@ -69,7 +69,7 @@ export function HelpRSGraphTerm() {
|
||||||
<Divider margins='my-3' className='hidden sm:block' />
|
<Divider margins='my-3' className='hidden sm:block' />
|
||||||
|
|
||||||
<div className='flex flex-col-reverse mb-3 sm:flex-row'>
|
<div className='flex flex-col-reverse mb-3 sm:flex-row'>
|
||||||
<div className='sm:w-[14rem]'>
|
<div className='sm:w-56'>
|
||||||
<h1>Общие</h1>
|
<h1>Общие</h1>
|
||||||
<li>
|
<li>
|
||||||
<IconOSS className='inline-icon' /> переход к связанной <LinkTopic text='ОСС' topic={HelpTopic.CC_OSS} />
|
<IconOSS className='inline-icon' /> переход к связанной <LinkTopic text='ОСС' topic={HelpTopic.CC_OSS} />
|
||||||
|
@ -88,7 +88,7 @@ export function HelpRSGraphTerm() {
|
||||||
|
|
||||||
<Divider vertical margins='mx-3' className='hidden sm:block' />
|
<Divider vertical margins='mx-3' className='hidden sm:block' />
|
||||||
|
|
||||||
<div className='dense w-[21rem]'>
|
<div className='dense w-84'>
|
||||||
<h1>Выделение</h1>
|
<h1>Выделение</h1>
|
||||||
<li>
|
<li>
|
||||||
<IconGraphCollapse className='inline-icon' /> все влияющие
|
<IconGraphCollapse className='inline-icon' /> все влияющие
|
||||||
|
|
|
@ -67,7 +67,7 @@ export function HelpRSMenu() {
|
||||||
|
|
||||||
<Divider vertical margins='mx-3' />
|
<Divider vertical margins='mx-3' />
|
||||||
|
|
||||||
<div className='w-[18rem]'>
|
<div className='w-72'>
|
||||||
<h2>Режимы работы</h2>
|
<h2>Режимы работы</h2>
|
||||||
<li>
|
<li>
|
||||||
<IconAlert size='1.25rem' className='inline-icon icon-red' /> работа в анонимном режиме. Переход на страницу
|
<IconAlert size='1.25rem' className='inline-icon icon-red' /> работа в анонимном режиме. Переход на страницу
|
||||||
|
|
|
@ -27,7 +27,7 @@ export function ManualsPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex mx-auto max-w-[80rem]' role='manuals' style={{ minHeight: mainHeight }}>
|
<div className='flex mx-auto max-w-320' role='manuals' style={{ minHeight: mainHeight }}>
|
||||||
<TopicsList activeTopic={activeTopic} onChangeTopic={topic => onSelectTopic(topic)} />
|
<TopicsList activeTopic={activeTopic} onChangeTopic={topic => onSelectTopic(topic)} />
|
||||||
<ViewTopic topic={activeTopic} />
|
<ViewTopic topic={activeTopic} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -31,7 +31,7 @@ export function TopicsDropdown({ activeTopic, onChangeTopic }: TopicsDropdownPro
|
||||||
<div
|
<div
|
||||||
ref={menu.ref}
|
ref={menu.ref}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'absolute left-0 w-54', // prettier: split-lines
|
'absolute left-0 w-54', //
|
||||||
'flex flex-col',
|
'flex flex-col',
|
||||||
'z-topmost',
|
'z-topmost',
|
||||||
'text-xs sm:text-sm',
|
'text-xs sm:text-sm',
|
||||||
|
@ -59,11 +59,7 @@ export function TopicsDropdown({ activeTopic, onChangeTopic }: TopicsDropdownPro
|
||||||
getParent={item => topicParent.get(item) ?? item}
|
getParent={item => topicParent.get(item) ?? item}
|
||||||
getLabel={labelHelpTopic}
|
getLabel={labelHelpTopic}
|
||||||
getDescription={describeHelpTopic}
|
getDescription={describeHelpTopic}
|
||||||
className={clsx(
|
className='border-r border-t rounded-none cc-scroll-y bg-prim-200'
|
||||||
'border-r border-t rounded-none', // prettier: split-lines
|
|
||||||
'cc-scroll-y',
|
|
||||||
'bg-prim-200'
|
|
||||||
)}
|
|
||||||
style={{
|
style={{
|
||||||
maxHeight: treeHeight,
|
maxHeight: treeHeight,
|
||||||
willChange: 'clip-path',
|
willChange: 'clip-path',
|
||||||
|
|
|
@ -25,7 +25,7 @@ export function TopicsStatic({ activeTopic, onChangeTopic }: TopicsStaticProps)
|
||||||
getDescription={describeHelpTopic}
|
getDescription={describeHelpTopic}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'sticky top-0 left-0',
|
'sticky top-0 left-0',
|
||||||
'min-w-[14.5rem] max-w-[14.5rem] sm:min-w-[12.5rem] sm:max-w-[12.5rem] md:min-w-[14.5rem] md:max-w-[14.5rem]',
|
'min-w-58 max-w-58 sm:min-w-50 sm:max-w-50 md:min-w-58 md:max-w-58',
|
||||||
'cc-scroll-y',
|
'cc-scroll-y',
|
||||||
'self-start',
|
'self-start',
|
||||||
'border-x border-t rounded-none',
|
'border-x border-t rounded-none',
|
||||||
|
|
|
@ -119,7 +119,7 @@ export function PickSchema({
|
||||||
className='mt-1'
|
className='mt-1'
|
||||||
onClick={() => locationMenu.toggle()}
|
onClick={() => locationMenu.toggle()}
|
||||||
/>
|
/>
|
||||||
<Dropdown isOpen={locationMenu.isOpen} stretchLeft className='w-[20rem] h-[12.5rem]'>
|
<Dropdown isOpen={locationMenu.isOpen} stretchLeft className='w-80 h-50'>
|
||||||
<SelectLocation
|
<SelectLocation
|
||||||
value={filterLocation}
|
value={filterLocation}
|
||||||
prefix={prefixes.folders_list}
|
prefix={prefixes.folders_list}
|
||||||
|
@ -147,7 +147,7 @@ export function PickSchema({
|
||||||
columns={columns}
|
columns={columns}
|
||||||
conditionalRowStyles={conditionalRowStyles}
|
conditionalRowStyles={conditionalRowStyles}
|
||||||
noDataComponent={
|
noDataComponent={
|
||||||
<div className='cc-column dense p-3 items-center min-h-[6rem]'>
|
<div className='cc-column dense p-3 items-center min-h-24'>
|
||||||
<p>Список схем пуст</p>
|
<p>Список схем пуст</p>
|
||||||
<p>Измените параметры фильтра</p>
|
<p>Измените параметры фильтра</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -51,14 +51,14 @@ export function SelectLocation({ value, dense, prefix, onClick, className, style
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={clsx('flex flex-col', 'cc-scroll-y', className)} style={style}>
|
<div className={clsx('flex flex-col cc-scroll-y', className)} style={style}>
|
||||||
{items.map((item, index) =>
|
{items.map((item, index) =>
|
||||||
!item.parent || !folded.includes(item.parent) ? (
|
!item.parent || !folded.includes(item.parent) ? (
|
||||||
<div
|
<div
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
key={`${prefix}${index}`}
|
key={`${prefix}${index}`}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
!dense && 'min-h-[2.0825rem] sm:min-h-[2.3125rem]',
|
!dense && 'h-7 sm:h-8',
|
||||||
'pr-3 py-1 flex items-center gap-2',
|
'pr-3 py-1 flex items-center gap-2',
|
||||||
'cc-scroll-row',
|
'cc-scroll-row',
|
||||||
'clr-hover cc-animate-color',
|
'clr-hover cc-animate-color',
|
||||||
|
|
|
@ -35,22 +35,14 @@ export function SelectLocationContext({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div ref={menu.ref} className={clsx('relative h-full -mt-1 -ml-6 text-right self-start', className)} {...restProps}>
|
||||||
ref={menu.ref}
|
|
||||||
className={clsx('relative h-full mt-[-0.25rem] ml-[-1.5rem]', 'text-right self-start', className)}
|
|
||||||
{...restProps}
|
|
||||||
>
|
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title={title}
|
title={title}
|
||||||
hideTitle={menu.isOpen}
|
hideTitle={menu.isOpen}
|
||||||
icon={<IconFolderTree size='1.25rem' className='icon-green' />}
|
icon={<IconFolderTree size='1.25rem' className='icon-green' />}
|
||||||
onClick={() => menu.toggle()}
|
onClick={() => menu.toggle()}
|
||||||
/>
|
/>
|
||||||
<Dropdown
|
<Dropdown isOpen={menu.isOpen} className={clsx('w-80 h-50 z-tooltip', dropdownHeight)}>
|
||||||
isOpen={menu.isOpen}
|
|
||||||
className={clsx('w-[20rem] h-[12.5rem] z-tooltip', dropdownHeight)}
|
|
||||||
margin='mt-[-0.25rem]'
|
|
||||||
>
|
|
||||||
<SelectLocation
|
<SelectLocation
|
||||||
value={value}
|
value={value}
|
||||||
prefix={prefixes.folders_list}
|
prefix={prefixes.folders_list}
|
||||||
|
|
|
@ -34,7 +34,7 @@ export function SelectVersion({ id, className, items, value, onChange, ...restPr
|
||||||
return (
|
return (
|
||||||
<SelectSingle
|
<SelectSingle
|
||||||
id={id}
|
id={id}
|
||||||
className={clsx('min-w-[12rem] text-ellipsis', className)}
|
className={clsx('min-w-48 text-ellipsis', className)}
|
||||||
options={options}
|
options={options}
|
||||||
value={{ value: value, label: labelVersion(value, items) }}
|
value={{ value: value, label: labelVersion(value, items) }}
|
||||||
onChange={data => onChange(data?.value ?? 'latest')}
|
onChange={data => onChange(data?.value ?? 'latest')}
|
||||||
|
|
|
@ -40,7 +40,7 @@ export function ToolbarItemAccess({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='absolute z-bottom top-[4.5rem] right-0 w-[12rem] flex pr-2'>
|
<div className='absolute z-bottom top-18 right-0 w-48 flex pr-2'>
|
||||||
<Label text='Доступ' className='self-center select-none' />
|
<Label text='Доступ' className='self-center select-none' />
|
||||||
<div className='ml-auto cc-icons'>
|
<div className='ml-auto cc-icons'>
|
||||||
<SelectAccessPolicy
|
<SelectAccessPolicy
|
||||||
|
@ -68,7 +68,7 @@ export function ToolbarItemAccess({
|
||||||
onClick={toggleReadOnly}
|
onClick={toggleReadOnly}
|
||||||
disabled={role === UserRole.READER || isProcessing}
|
disabled={role === UserRole.READER || isProcessing}
|
||||||
/>
|
/>
|
||||||
<BadgeHelp topic={HelpTopic.ACCESS} className='mt-[0.125rem]' offset={4} />
|
<BadgeHelp topic={HelpTopic.ACCESS} className='mt-0.5' offset={4} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import { Controller, useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import clsx from 'clsx';
|
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { useAuthSuspense } from '@/features/auth';
|
import { useAuthSuspense } from '@/features/auth';
|
||||||
|
@ -57,9 +56,9 @@ export function DlgChangeLocation() {
|
||||||
submitInvalidTooltip={`Допустимы буквы, цифры, подчерк, пробел и "!". Сегмент пути не может начинаться и заканчиваться пробелом. Общая длина (с корнем) не должна превышать ${limits.location_len}`}
|
submitInvalidTooltip={`Допустимы буквы, цифры, подчерк, пробел и "!". Сегмент пути не может начинаться и заканчиваться пробелом. Общая длина (с корнем) не должна превышать ${limits.location_len}`}
|
||||||
canSubmit={isValid && isDirty}
|
canSubmit={isValid && isDirty}
|
||||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||||
className={clsx('w-[35rem]', 'pb-3 px-6 flex gap-3 h-[9rem]')}
|
className='w-140 pb-3 px-6 flex gap-3 h-36'
|
||||||
>
|
>
|
||||||
<div className='flex flex-col gap-2 min-w-[7rem]'>
|
<div className='flex flex-col gap-2 min-w-28'>
|
||||||
<Label className='select-none' text='Корень' />
|
<Label className='select-none' text='Корень' />
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
|
@ -77,11 +76,11 @@ export function DlgChangeLocation() {
|
||||||
control={control}
|
control={control}
|
||||||
name='location'
|
name='location'
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<SelectLocationContext dropdownHeight='max-h-[9.2rem]' value={field.value} onChange={field.onChange} />
|
<SelectLocationContext dropdownHeight='max-h-36' value={field.value} onChange={field.onChange} />
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Controller
|
<Controller
|
||||||
control={control} //
|
control={control}
|
||||||
name='location'
|
name='location'
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<TextArea
|
<TextArea
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import { Controller, useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { urls, useConceptNavigation } from '@/app';
|
import { urls, useConceptNavigation } from '@/app';
|
||||||
import { useAuthSuspense } from '@/features/auth';
|
import { useAuthSuspense } from '@/features/auth';
|
||||||
|
@ -69,7 +68,7 @@ export function DlgCloneLibraryItem() {
|
||||||
submitText='Создать'
|
submitText='Создать'
|
||||||
canSubmit={isValid}
|
canSubmit={isValid}
|
||||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||||
className={clsx('px-6 py-2', 'cc-column', 'max-h-full w-[30rem]')}
|
className='px-6 py-2 cc-column h-fit w-120'
|
||||||
>
|
>
|
||||||
<TextInput
|
<TextInput
|
||||||
id='dlg_full_name' //
|
id='dlg_full_name' //
|
||||||
|
@ -77,14 +76,9 @@ export function DlgCloneLibraryItem() {
|
||||||
{...register('title')}
|
{...register('title')}
|
||||||
error={errors.title}
|
error={errors.title}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className='flex justify-between gap-3'>
|
<div className='flex justify-between gap-3'>
|
||||||
<TextInput
|
<TextInput id='dlg_alias' label='Сокращение' className='w-64' {...register('alias')} error={errors.alias} />
|
||||||
id='dlg_alias'
|
|
||||||
label='Сокращение'
|
|
||||||
className='w-[16rem]'
|
|
||||||
{...register('alias')}
|
|
||||||
error={errors.alias}
|
|
||||||
/>
|
|
||||||
<div className='flex flex-col gap-2'>
|
<div className='flex flex-col gap-2'>
|
||||||
<Label text='Доступ' className='self-center select-none' />
|
<Label text='Доступ' className='self-center select-none' />
|
||||||
<div className='ml-auto cc-icons'>
|
<div className='ml-auto cc-icons'>
|
||||||
|
@ -115,7 +109,7 @@ export function DlgCloneLibraryItem() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex gap-3'>
|
<div className='flex gap-3'>
|
||||||
<div className='flex flex-col gap-2 w-[7rem]'>
|
<div className='flex flex-col gap-2 w-28'>
|
||||||
<Label text='Корень' />
|
<Label text='Корень' />
|
||||||
<Controller
|
<Controller
|
||||||
control={control} //
|
control={control} //
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import { Controller, useForm, useWatch } from 'react-hook-form';
|
import { Controller, useForm, useWatch } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { Checkbox, TextArea, TextInput } from '@/components/Input';
|
import { Checkbox, TextArea, TextInput } from '@/components/Input';
|
||||||
import { ModalForm } from '@/components/Modal';
|
import { ModalForm } from '@/components/Modal';
|
||||||
|
@ -45,13 +44,13 @@ export function DlgCreateVersion() {
|
||||||
return (
|
return (
|
||||||
<ModalForm
|
<ModalForm
|
||||||
header='Создание версии'
|
header='Создание версии'
|
||||||
className={clsx('cc-column', 'w-[30rem]', 'py-2 px-6')}
|
className='cc-column w-120 py-2 px-6'
|
||||||
canSubmit={canSubmit}
|
canSubmit={canSubmit}
|
||||||
submitInvalidTooltip={errorMsg.versionTaken}
|
submitInvalidTooltip={errorMsg.versionTaken}
|
||||||
submitText='Создать'
|
submitText='Создать'
|
||||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||||
>
|
>
|
||||||
<TextInput id='dlg_version' {...register('version')} dense label='Версия' className='w-[16rem]' />
|
<TextInput id='dlg_version' {...register('version')} dense label='Версия' className='w-64' />
|
||||||
<TextArea id='dlg_description' {...register('description')} spellCheck label='Описание' rows={3} />
|
<TextArea id='dlg_description' {...register('description')} spellCheck label='Описание' rows={3} />
|
||||||
{selected.length > 0 ? (
|
{selected.length > 0 ? (
|
||||||
<Controller
|
<Controller
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
import { Controller, useForm, useWatch } from 'react-hook-form';
|
import { Controller, useForm, useWatch } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { urls, useConceptNavigation } from '@/app';
|
import { urls, useConceptNavigation } from '@/app';
|
||||||
import { useAuthSuspense } from '@/features/auth';
|
import { useAuthSuspense } from '@/features/auth';
|
||||||
|
@ -103,7 +102,7 @@ export function FormCreateItem() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
className={clsx('cc-fade-in cc-column', 'min-w-120 max-w-120 mx-auto', 'px-6 py-3')}
|
className='cc-fade-in cc-column min-w-120 max-w-120 mx-auto px-6 py-3'
|
||||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||||
onChange={resetErrors}
|
onChange={resetErrors}
|
||||||
>
|
>
|
||||||
|
|
|
@ -63,7 +63,7 @@ export function TableLibraryItems({ items }: TableLibraryItemsProps) {
|
||||||
className={clsx('text-xs sm:text-sm cc-scroll-y h-fit border-b', { 'border-l': folderMode })}
|
className={clsx('text-xs sm:text-sm cc-scroll-y h-fit border-b', { 'border-l': folderMode })}
|
||||||
style={{ maxHeight: tableHeight }}
|
style={{ maxHeight: tableHeight }}
|
||||||
noDataComponent={
|
noDataComponent={
|
||||||
<div className='cc-column dense p-3 items-center min-h-[6rem]'>
|
<div className='cc-column dense p-3 items-center min-h-24'>
|
||||||
<p>Список схем пуст</p>
|
<p>Список схем пуст</p>
|
||||||
<p className='flex gap-6'>
|
<p className='flex gap-6'>
|
||||||
<TextURL text='Создать схему' href='/library/create' />
|
<TextURL text='Создать схему' href='/library/create' />
|
||||||
|
|
|
@ -75,21 +75,12 @@ export function ToolbarSearch({ total, filtered }: ToolbarSearchProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className='sticky top-0 h-9 flex gap-3 border-b text-sm clr-input items-center'>
|
||||||
className={clsx(
|
<div className='ml-3 min-w-18 sm:min-w-30 select-none whitespace-nowrap'>
|
||||||
'sticky top-0', //
|
|
||||||
'h-9',
|
|
||||||
'flex items-center gap-3',
|
|
||||||
'border-b',
|
|
||||||
'text-sm',
|
|
||||||
'clr-input'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div className={clsx('ml-3 pt-1 self-center', 'min-w-18 sm:min-w-30', 'select-none', 'whitespace-nowrap')}>
|
|
||||||
{filtered} из {total}
|
{filtered} из {total}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='cc-icons'>
|
<div className='cc-icons h-full items-center'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title='Видимость'
|
title='Видимость'
|
||||||
icon={<IconItemVisibility value={true} className={tripleToggleColor(isVisible)} />}
|
icon={<IconItemVisibility value={true} className={tripleToggleColor(isVisible)} />}
|
||||||
|
@ -103,7 +94,7 @@ export function ToolbarSearch({ total, filtered }: ToolbarSearchProps) {
|
||||||
icon={<IconUserSearch size='1.25rem' className={userActive ? 'icon-green' : 'icon-primary'} />}
|
icon={<IconUserSearch size='1.25rem' className={userActive ? 'icon-green' : 'icon-primary'} />}
|
||||||
onClick={userMenu.toggle}
|
onClick={userMenu.toggle}
|
||||||
/>
|
/>
|
||||||
<Dropdown isOpen={userMenu.isOpen} margin='mt-[0.2rem]'>
|
<Dropdown isOpen={userMenu.isOpen}>
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
text='Я - Владелец'
|
text='Я - Владелец'
|
||||||
icon={<IconOwner size='1.25rem' className={tripleToggleColor(isOwned)} />}
|
icon={<IconOwner size='1.25rem' className={tripleToggleColor(isOwned)} />}
|
||||||
|
@ -142,10 +133,10 @@ export function ToolbarSearch({ total, filtered }: ToolbarSearchProps) {
|
||||||
onChangeQuery={setQuery}
|
onChangeQuery={setQuery}
|
||||||
/>
|
/>
|
||||||
{!folderMode ? (
|
{!folderMode ? (
|
||||||
<div ref={headMenu.ref} className='relative flex items-center h-full py-1 select-none'>
|
<div ref={headMenu.ref} className='relative flex items-center h-full select-none'>
|
||||||
<SelectorButton
|
<SelectorButton
|
||||||
transparent
|
transparent
|
||||||
className='h-full rounded-lg'
|
className='rounded-lg py-1'
|
||||||
titleHtml={(head ? describeLocationHead(head) : 'Выберите каталог') + '<br/>Ctrl + клик - Проводник'}
|
titleHtml={(head ? describeLocationHead(head) : 'Выберите каталог') + '<br/>Ctrl + клик - Проводник'}
|
||||||
hideTitle={headMenu.isOpen}
|
hideTitle={headMenu.isOpen}
|
||||||
icon={
|
icon={
|
||||||
|
|
|
@ -85,7 +85,7 @@ export function ViewSideLocation({ isVisible, onRenameLocation }: ViewSideLocati
|
||||||
) : null}
|
) : null}
|
||||||
{!!location ? (
|
{!!location ? (
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title={subfolders ? 'Вложенные папки: Вкл' : 'Вложенные папки: Выкл'} // prettier: split-lines
|
title={subfolders ? 'Вложенные папки: Вкл' : 'Вложенные папки: Выкл'}
|
||||||
icon={<IconShowSubfolders value={subfolders} />}
|
icon={<IconShowSubfolders value={subfolders} />}
|
||||||
onClick={toggleSubfolders}
|
onClick={toggleSubfolders}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -12,7 +12,7 @@ export function OperationTooltip() {
|
||||||
clickable
|
clickable
|
||||||
id={globalIDs.operation_tooltip}
|
id={globalIDs.operation_tooltip}
|
||||||
layer='z-topmost'
|
layer='z-topmost'
|
||||||
className='max-w-[35rem] dense'
|
className='max-w-140 dense'
|
||||||
style={{ maxHeight: '30rem', overflowY: 'auto' }}
|
style={{ maxHeight: '30rem', overflowY: 'auto' }}
|
||||||
hidden={!hoverOperation}
|
hidden={!hoverOperation}
|
||||||
>
|
>
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import { Controller, useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { type ILibraryItem, LibraryItemType } from '@/features/library';
|
import { type ILibraryItem, LibraryItemType } from '@/features/library';
|
||||||
import { useLibrary } from '@/features/library/backend/useLibrary';
|
import { useLibrary } from '@/features/library/backend/useLibrary';
|
||||||
|
@ -55,7 +54,7 @@ export function DlgChangeInputSchema() {
|
||||||
header='Выбор концептуальной схемы'
|
header='Выбор концептуальной схемы'
|
||||||
submitText='Подтвердить выбор'
|
submitText='Подтвердить выбор'
|
||||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||||
className={clsx('w-[35rem]', 'pb-3 px-6 cc-column')}
|
className='w-140 pb-3 px-6 cc-column'
|
||||||
>
|
>
|
||||||
<div className='flex justify-between gap-3 items-center'>
|
<div className='flex justify-between gap-3 items-center'>
|
||||||
<div className='flex gap-3'>
|
<div className='flex gap-3'>
|
||||||
|
|
|
@ -64,7 +64,7 @@ export function TabInputOperation() {
|
||||||
<TextInput
|
<TextInput
|
||||||
id='operation_alias' //
|
id='operation_alias' //
|
||||||
label='Сокращение'
|
label='Сокращение'
|
||||||
className='w-[16rem]'
|
className='w-64'
|
||||||
{...register('item_data.alias')}
|
{...register('item_data.alias')}
|
||||||
error={errors.item_data?.alias}
|
error={errors.item_data?.alias}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -29,7 +29,7 @@ export function TabSynthesisOperation() {
|
||||||
<TextInput
|
<TextInput
|
||||||
id='operation_alias'
|
id='operation_alias'
|
||||||
label='Сокращение'
|
label='Сокращение'
|
||||||
className='w-[16rem]'
|
className='w-64'
|
||||||
{...register('item_data.alias')}
|
{...register('item_data.alias')}
|
||||||
error={errors.item_data?.alias}
|
error={errors.item_data?.alias}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import { Controller, useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { HelpTopic } from '@/features/help';
|
import { HelpTopic } from '@/features/help';
|
||||||
|
|
||||||
|
@ -44,7 +43,7 @@ export function DlgDeleteOperation() {
|
||||||
header='Удаление операции'
|
header='Удаление операции'
|
||||||
submitText='Подтвердить удаление'
|
submitText='Подтвердить удаление'
|
||||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||||
className={clsx('w-[35rem]', 'pb-3 px-6 cc-column', 'select-none')}
|
className='w-140 pb-3 px-6 cc-column select-none'
|
||||||
helpTopic={HelpTopic.CC_PROPAGATION}
|
helpTopic={HelpTopic.CC_PROPAGATION}
|
||||||
>
|
>
|
||||||
<TextInput disabled dense noBorder id='operation_alias' label='Операция' value={target.alias} />
|
<TextInput disabled dense noBorder id='operation_alias' label='Операция' value={target.alias} />
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Controller, useForm, useWatch } from 'react-hook-form';
|
import { Controller, useForm, useWatch } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { HelpTopic } from '@/features/help';
|
import { HelpTopic } from '@/features/help';
|
||||||
import { type ILibraryItem } from '@/features/library';
|
import { type ILibraryItem } from '@/features/library';
|
||||||
|
@ -120,7 +119,7 @@ export function DlgRelocateConstituents() {
|
||||||
submitText='Переместить'
|
submitText='Переместить'
|
||||||
canSubmit={isValid && destinationItem !== undefined}
|
canSubmit={isValid && destinationItem !== undefined}
|
||||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||||
className={clsx('w-160 h-[33rem]', 'py-3 px-6')}
|
className='w-160 h-132 py-3 px-6'
|
||||||
helpTopic={HelpTopic.UI_RELOCATE_CST}
|
helpTopic={HelpTopic.UI_RELOCATE_CST}
|
||||||
>
|
>
|
||||||
<div className='flex flex-col border'>
|
<div className='flex flex-col border'>
|
||||||
|
|
|
@ -13,7 +13,7 @@ export function OssStats({ stats }: OssStatsProps) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'mt-3 md:ml-5 md:mt-8 md:w-[12rem] w-[14rem] h-min mx-auto', // prettier: split-lines
|
'mt-3 md:ml-5 md:mt-8 md:w-48 w-56 h-min mx-auto', //
|
||||||
'grid grid-cols-3 gap-1 justify-items-end'
|
'grid grid-cols-3 gap-1 justify-items-end'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
import { APP_COLORS } from '@/styling/colors';
|
||||||
|
|
||||||
import { colorFgGrammeme } from '../colors';
|
import { colorFgGrammeme } from '../colors';
|
||||||
|
@ -17,12 +15,7 @@ interface BadgeGrammemeProps {
|
||||||
export function BadgeGrammeme({ grammeme }: BadgeGrammemeProps) {
|
export function BadgeGrammeme({ grammeme }: BadgeGrammemeProps) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className='min-w-12 px-1 border rounded-md text-sm font-medium text-center whitespace-nowrap'
|
||||||
'min-w-12', //
|
|
||||||
'px-1',
|
|
||||||
'border rounded-md',
|
|
||||||
'text-sm font-medium text-center whitespace-nowrap'
|
|
||||||
)}
|
|
||||||
style={{
|
style={{
|
||||||
borderColor: colorFgGrammeme(grammeme),
|
borderColor: colorFgGrammeme(grammeme),
|
||||||
color: colorFgGrammeme(grammeme),
|
color: colorFgGrammeme(grammeme),
|
||||||
|
|
|
@ -12,12 +12,10 @@ interface InfoConstituentaProps extends React.ComponentProps<'div'> {
|
||||||
|
|
||||||
export function InfoConstituenta({ data, className, ...restProps }: InfoConstituentaProps) {
|
export function InfoConstituenta({ data, className, ...restProps }: InfoConstituentaProps) {
|
||||||
return (
|
return (
|
||||||
<div className={clsx('dense min-w-[15rem] break-words', className)} {...restProps}>
|
<div className={clsx('dense min-w-60 break-words', className)} {...restProps}>
|
||||||
<h2 className='cursor-default' title={data.is_inherited ? ' наследник' : undefined}>
|
<h2 className='cursor-default' title={data.is_inherited ? ' наследник' : undefined}>
|
||||||
{data.alias}
|
{data.alias}
|
||||||
{data.is_inherited ? (
|
{data.is_inherited ? <IconChild size='1rem' className='inline-icon align-middle ml-1 mt-1' /> : null}
|
||||||
<IconChild size='1rem' className='inline-icon translate-y-[-0.1rem] translate-x-[0.125rem]' />
|
|
||||||
) : null}
|
|
||||||
</h2>
|
</h2>
|
||||||
{data.term_resolved ? (
|
{data.term_resolved ? (
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -93,7 +93,7 @@ export function PickConstituenta({
|
||||||
columns={columns}
|
columns={columns}
|
||||||
conditionalRowStyles={conditionalRowStyles}
|
conditionalRowStyles={conditionalRowStyles}
|
||||||
noDataComponent={
|
noDataComponent={
|
||||||
<NoData className='min-h-[6rem]'>
|
<NoData className='min-h-24'>
|
||||||
<p>Список конституент пуст</p>
|
<p>Список конституент пуст</p>
|
||||||
<p>Измените параметры фильтра</p>
|
<p>Измените параметры фильтра</p>
|
||||||
</NoData>
|
</NoData>
|
||||||
|
|
|
@ -99,14 +99,14 @@ export function PickMultiConstituenta({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={clsx(noBorder ? '' : 'border', className)} {...restProps}>
|
<div className={clsx(noBorder ? '' : 'border', className)} {...restProps}>
|
||||||
<div className={clsx('px-3 flex justify-between items-center', 'clr-input', 'border-b', 'rounded-t-md')}>
|
<div className='px-3 flex justify-between items-center clr-input border-b rounded-t-md'>
|
||||||
<div className='w-[24ch] select-none whitespace-nowrap'>
|
<div className='w-[24ch] select-none whitespace-nowrap'>
|
||||||
{items.length > 0 ? `Выбраны ${value.length} из ${items.length}` : 'Конституенты'}
|
{items.length > 0 ? `Выбраны ${value.length} из ${items.length}` : 'Конституенты'}
|
||||||
</div>
|
</div>
|
||||||
<SearchBar
|
<SearchBar
|
||||||
id='dlg_constituents_search'
|
id='dlg_constituents_search'
|
||||||
noBorder
|
noBorder
|
||||||
className='min-w-[6rem] pr-2 grow'
|
className='min-w-24 pr-2 grow'
|
||||||
query={filterText}
|
query={filterText}
|
||||||
onChangeQuery={setFilterText}
|
onChangeQuery={setFilterText}
|
||||||
/>
|
/>
|
||||||
|
@ -122,6 +122,7 @@ export function PickMultiConstituenta({
|
||||||
className='w-fit'
|
className='w-fit'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<DataTable
|
<DataTable
|
||||||
id={id}
|
id={id}
|
||||||
dense
|
dense
|
||||||
|
|
|
@ -167,7 +167,7 @@ export function PickSubstitutions({
|
||||||
columnHelper.accessor(item => item.substitution_source.alias, {
|
columnHelper.accessor(item => item.substitution_source.alias, {
|
||||||
id: 'left_schema',
|
id: 'left_schema',
|
||||||
size: 100,
|
size: 100,
|
||||||
cell: props => <div className='min-w-[10.5rem] text-ellipsis text-left'>{props.getValue()}</div>
|
cell: props => <div className='min-w-43 text-ellipsis text-left'>{props.getValue()}</div>
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor(item => item.substitution.alias, {
|
columnHelper.accessor(item => item.substitution.alias, {
|
||||||
id: 'left_alias',
|
id: 'left_alias',
|
||||||
|
@ -230,8 +230,8 @@ export function PickSubstitutions({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={clsx('flex flex-col', className)} {...restProps}>
|
<div className={clsx('flex flex-col', className)} {...restProps}>
|
||||||
<div className='flex items-end gap-3 justify-stretch'>
|
<div className='flex items-center gap-3'>
|
||||||
<div className='grow flex flex-col basis-1/2 gap-[0.125rem] border-x border-t clr-input rounded-t-md'>
|
<div className='grow flex flex-col basis-1/2 gap-1 border-x border-t clr-input rounded-t-md'>
|
||||||
<SelectLibraryItem
|
<SelectLibraryItem
|
||||||
noBorder
|
noBorder
|
||||||
placeholder='Выберите аргумент'
|
placeholder='Выберите аргумент'
|
||||||
|
@ -241,7 +241,7 @@ export function PickSubstitutions({
|
||||||
/>
|
/>
|
||||||
<SelectConstituenta noBorder items={leftItems} value={leftCst} onChange={setLeftCst} />
|
<SelectConstituenta noBorder items={leftItems} value={leftCst} onChange={setLeftCst} />
|
||||||
</div>
|
</div>
|
||||||
<div className='flex flex-col gap-1'>
|
<div className='flex flex-col justify-center gap-1'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title={deleteRight ? 'Заменить правую' : 'Заменить левую'}
|
title={deleteRight ? 'Заменить правую' : 'Заменить левую'}
|
||||||
onClick={toggleDelete}
|
onClick={toggleDelete}
|
||||||
|
@ -255,14 +255,14 @@ export function PickSubstitutions({
|
||||||
/>
|
/>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title='Добавить в таблицу отождествлений'
|
title='Добавить в таблицу отождествлений'
|
||||||
className='mb-[0.375rem] grow-0'
|
className='grow-0'
|
||||||
icon={<IconReplace size='1.5rem' className='icon-primary' />}
|
icon={<IconReplace size='1.5rem' className='icon-primary' />}
|
||||||
disabled={!leftCst || !rightCst || (leftCst === rightCst && !allowSelfSubstitution)}
|
disabled={!leftCst || !rightCst || (leftCst === rightCst && !allowSelfSubstitution)}
|
||||||
onClick={addSubstitution}
|
onClick={addSubstitution}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='grow basis-1/2 flex flex-col gap-[0.125rem] border-x border-t clr-input rounded-t-md'>
|
<div className='grow basis-1/2 flex flex-col gap-1 border-x border-t clr-input rounded-t-md'>
|
||||||
<SelectLibraryItem
|
<SelectLibraryItem
|
||||||
noBorder
|
noBorder
|
||||||
placeholder='Выберите аргумент'
|
placeholder='Выберите аргумент'
|
||||||
|
@ -285,7 +285,7 @@ export function PickSubstitutions({
|
||||||
columns={columns}
|
columns={columns}
|
||||||
headPosition='0'
|
headPosition='0'
|
||||||
noDataComponent={
|
noDataComponent={
|
||||||
<NoData className='min-h-[2rem]'>
|
<NoData className='min-h-8'>
|
||||||
<p>Список пуст</p>
|
<p>Список пуст</p>
|
||||||
<p>Добавьте отождествление</p>
|
<p>Добавьте отождествление</p>
|
||||||
</NoData>
|
</NoData>
|
||||||
|
|
|
@ -29,7 +29,7 @@ import { rsHoverTooltip } from './tooltip';
|
||||||
interface RSInputProps
|
interface RSInputProps
|
||||||
extends Pick<
|
extends Pick<
|
||||||
ReactCodeMirrorProps,
|
ReactCodeMirrorProps,
|
||||||
| 'id' // prettier: split-lines
|
| 'id' //
|
||||||
| 'height'
|
| 'height'
|
||||||
| 'minHeight'
|
| 'minHeight'
|
||||||
| 'maxHeight'
|
| 'maxHeight'
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { type Extension } from '@codemirror/state';
|
import { type Extension } from '@codemirror/state';
|
||||||
import { hoverTooltip, type TooltipView } from '@codemirror/view';
|
import { hoverTooltip, type TooltipView } from '@codemirror/view';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { labelCstTypification } from '../../labels';
|
import { labelCstTypification } from '../../labels';
|
||||||
import { type IConstituenta, type IRSForm } from '../../models/rsform';
|
import { type IConstituenta, type IRSForm } from '../../models/rsform';
|
||||||
|
@ -33,14 +32,7 @@ export function rsHoverTooltip(schema: IRSForm, canClick?: boolean): Extension {
|
||||||
*/
|
*/
|
||||||
function domTooltipConstituenta(cst?: IConstituenta, canClick?: boolean): TooltipView {
|
function domTooltipConstituenta(cst?: IConstituenta, canClick?: boolean): TooltipView {
|
||||||
const dom = document.createElement('div');
|
const dom = document.createElement('div');
|
||||||
dom.className = clsx(
|
dom.className = 'max-h-100 max-w-100 min-w-40 dense p-2 border shadow-md cc-scroll-y text-sm font-main';
|
||||||
'max-h-[25rem] max-w-[25rem] min-w-[10rem]',
|
|
||||||
'dense',
|
|
||||||
'p-2',
|
|
||||||
'border shadow-md',
|
|
||||||
'cc-scroll-y',
|
|
||||||
'text-sm font-main'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!cst) {
|
if (!cst) {
|
||||||
const text = document.createElement('p');
|
const text = document.createElement('p');
|
||||||
|
|
|
@ -60,7 +60,7 @@ const editorSetup: BasicSetupOptions = {
|
||||||
interface RefsInputInputProps
|
interface RefsInputInputProps
|
||||||
extends Pick<
|
extends Pick<
|
||||||
ReactCodeMirrorProps,
|
ReactCodeMirrorProps,
|
||||||
| 'id' // prettier: split-lines
|
| 'id' //
|
||||||
| 'height'
|
| 'height'
|
||||||
| 'minHeight'
|
| 'minHeight'
|
||||||
| 'maxHeight'
|
| 'maxHeight'
|
||||||
|
@ -85,7 +85,7 @@ interface RefsInputInputProps
|
||||||
export const RefsInput = forwardRef<ReactCodeMirrorRef, RefsInputInputProps>(
|
export const RefsInput = forwardRef<ReactCodeMirrorRef, RefsInputInputProps>(
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
id, // prettier: split-lines
|
id, //
|
||||||
label,
|
label,
|
||||||
disabled,
|
disabled,
|
||||||
schema,
|
schema,
|
||||||
|
|
|
@ -65,7 +65,7 @@ export function refsHoverTooltip(schema: IRSForm, canClick?: boolean): Extension
|
||||||
function domTooltipEntityReference(ref: IEntityReference, cst: IConstituenta | null, canClick?: boolean): TooltipView {
|
function domTooltipEntityReference(ref: IEntityReference, cst: IConstituenta | null, canClick?: boolean): TooltipView {
|
||||||
const dom = document.createElement('div');
|
const dom = document.createElement('div');
|
||||||
dom.className = clsx(
|
dom.className = clsx(
|
||||||
'max-h-[25rem] max-w-[25rem] min-w-[10rem]',
|
'max-h-100 max-w-100 min-w-40',
|
||||||
'dense',
|
'dense',
|
||||||
'p-2 flex flex-col',
|
'p-2 flex flex-col',
|
||||||
'border shadow-md',
|
'border shadow-md',
|
||||||
|
@ -87,12 +87,7 @@ function domTooltipEntityReference(ref: IEntityReference, cst: IConstituenta | n
|
||||||
parseGrammemes(ref.form).forEach(gramStr => {
|
parseGrammemes(ref.form).forEach(gramStr => {
|
||||||
const gram = document.createElement('div');
|
const gram = document.createElement('div');
|
||||||
gram.id = `tooltip-${gramStr}`;
|
gram.id = `tooltip-${gramStr}`;
|
||||||
gram.className = clsx(
|
gram.className = 'min-w-12 px-1 border rounded-md text-sm text-center whitespace-nowrap';
|
||||||
'min-w-[3rem]', //
|
|
||||||
'px-1',
|
|
||||||
'border rounded-md',
|
|
||||||
'text-sm text-center whitespace-nowrap'
|
|
||||||
);
|
|
||||||
gram.style.borderWidth = '1px';
|
gram.style.borderWidth = '1px';
|
||||||
gram.style.borderColor = colorFgGrammeme(gramStr);
|
gram.style.borderColor = colorFgGrammeme(gramStr);
|
||||||
gram.style.color = colorFgGrammeme(gramStr);
|
gram.style.color = colorFgGrammeme(gramStr);
|
||||||
|
@ -123,7 +118,7 @@ function domTooltipSyntacticReference(
|
||||||
): TooltipView {
|
): TooltipView {
|
||||||
const dom = document.createElement('div');
|
const dom = document.createElement('div');
|
||||||
dom.className = clsx(
|
dom.className = clsx(
|
||||||
'max-h-[25rem] max-w-[25rem] min-w-[10rem]',
|
'max-h-100 max-w-100 min-w-40',
|
||||||
'dense',
|
'dense',
|
||||||
'p-2 flex flex-col',
|
'p-2 flex flex-col',
|
||||||
'border shadow-md',
|
'border shadow-md',
|
||||||
|
|
|
@ -17,7 +17,7 @@ export function WordformButton({ text, example, grams, onSelectGrams, isSelected
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
onClick={() => onSelectGrams([...grams])}
|
onClick={() => onSelectGrams([...grams])}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'min-w-[3.75rem] sm:min-w-[5.5rem]',
|
'min-w-15 sm:min-w-20',
|
||||||
'p-1',
|
'p-1',
|
||||||
'border rounded-none',
|
'border rounded-none',
|
||||||
'cursor-pointer',
|
'cursor-pointer',
|
||||||
|
|
|
@ -43,7 +43,7 @@ export function DlgCreateCst() {
|
||||||
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
|
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
|
||||||
submitInvalidTooltip={errorMsg.aliasInvalid}
|
submitInvalidTooltip={errorMsg.aliasInvalid}
|
||||||
submitText='Создать'
|
submitText='Создать'
|
||||||
className='cc-column w-[35rem] max-h-[30rem] py-2 px-6'
|
className='cc-column w-140 max-h-120 py-2 px-6'
|
||||||
>
|
>
|
||||||
<FormProvider {...methods}>
|
<FormProvider {...methods}>
|
||||||
<FormCreateCst schema={schema} />
|
<FormCreateCst schema={schema} />
|
||||||
|
|
|
@ -43,15 +43,8 @@ export function FormCreateCst({ schema }: FormCreateCstProps) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className='flex items-center self-center gap-3'>
|
<div className='flex items-center self-center gap-3'>
|
||||||
<SelectCstType id='dlg_cst_type' className='w-[16rem]' value={cst_type} onChange={handleTypeChange} />
|
<SelectCstType id='dlg_cst_type' className='w-64' value={cst_type} onChange={handleTypeChange} />
|
||||||
<TextInput
|
<TextInput id='dlg_cst_alias' dense label='Имя' className='w-28' {...register('alias')} error={errors.alias} />
|
||||||
id='dlg_cst_alias'
|
|
||||||
dense
|
|
||||||
label='Имя'
|
|
||||||
className='w-[7rem]'
|
|
||||||
{...register('alias')}
|
|
||||||
error={errors.alias}
|
|
||||||
/>
|
|
||||||
<BadgeHelp topic={HelpTopic.CC_CONSTITUENTA} offset={16} contentClass='sm:max-w-160' />
|
<BadgeHelp topic={HelpTopic.CC_CONSTITUENTA} offset={16} contentClass='sm:max-w-160' />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -61,7 +54,7 @@ export function FormCreateCst({ schema }: FormCreateCstProps) {
|
||||||
spellCheck
|
spellCheck
|
||||||
label='Термин'
|
label='Термин'
|
||||||
placeholder='Обозначение для текстовых определений'
|
placeholder='Обозначение для текстовых определений'
|
||||||
className='max-h-[3.6rem]'
|
className='max-h-15'
|
||||||
{...register('term_raw')}
|
{...register('term_raw')}
|
||||||
error={errors.term_raw}
|
error={errors.term_raw}
|
||||||
/>
|
/>
|
||||||
|
@ -105,7 +98,7 @@ export function FormCreateCst({ schema }: FormCreateCstProps) {
|
||||||
fitContent
|
fitContent
|
||||||
label='Текстовое определение'
|
label='Текстовое определение'
|
||||||
placeholder='Текстовая интерпретация формального выражения'
|
placeholder='Текстовая интерпретация формального выражения'
|
||||||
className='max-h-[3.6rem]'
|
className='max-h-15'
|
||||||
value={field.value}
|
value={field.value}
|
||||||
onChange={field.onChange}
|
onChange={field.onChange}
|
||||||
/>
|
/>
|
||||||
|
@ -132,7 +125,7 @@ export function FormCreateCst({ schema }: FormCreateCstProps) {
|
||||||
fitContent
|
fitContent
|
||||||
label={isBasic ? 'Конвенция' : 'Комментарий'}
|
label={isBasic ? 'Конвенция' : 'Комментарий'}
|
||||||
placeholder={isBasic ? 'Договоренность об интерпретации' : 'Пояснение разработчика'}
|
placeholder={isBasic ? 'Договоренность об интерпретации' : 'Пояснение разработчика'}
|
||||||
className='max-h-[5.4rem]'
|
className='max-h-20'
|
||||||
{...register('convention')}
|
{...register('convention')}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
import { Suspense, useState } from 'react';
|
import { Suspense, useState } from 'react';
|
||||||
import { FormProvider, useForm, useWatch } from 'react-hook-form';
|
import { FormProvider, useForm, useWatch } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { HelpTopic } from '@/features/help';
|
import { HelpTopic } from '@/features/help';
|
||||||
|
|
||||||
|
@ -65,7 +64,7 @@ export function DlgCstTemplate() {
|
||||||
<ModalForm
|
<ModalForm
|
||||||
header='Создание конституенты из шаблона'
|
header='Создание конституенты из шаблона'
|
||||||
submitText='Создать'
|
submitText='Создать'
|
||||||
className='w-[43rem] h-[35rem] px-6'
|
className='w-172 h-140 px-6'
|
||||||
canSubmit={isValid}
|
canSubmit={isValid}
|
||||||
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
|
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
|
||||||
helpTopic={HelpTopic.RSL_TEMPLATES}
|
helpTopic={HelpTopic.RSL_TEMPLATES}
|
||||||
|
@ -76,7 +75,7 @@ export function DlgCstTemplate() {
|
||||||
selectedIndex={activeTab}
|
selectedIndex={activeTab}
|
||||||
onSelect={setActiveTab}
|
onSelect={setActiveTab}
|
||||||
>
|
>
|
||||||
<TabList className={clsx('mb-3 self-center', 'flex', 'border divide-x rounded-none', 'bg-prim-200')}>
|
<TabList className='mb-4 self-center flex border divide-x rounded-none bg-prim-200'>
|
||||||
<TabLabel label='Шаблон' title='Выбор шаблона выражения' className='w-32' />
|
<TabLabel label='Шаблон' title='Выбор шаблона выражения' className='w-32' />
|
||||||
<TabLabel label='Аргументы' title='Подстановка аргументов шаблона' className='w-32' />
|
<TabLabel label='Аргументы' title='Подстановка аргументов шаблона' className='w-32' />
|
||||||
<TabLabel label='Конституента' title='Редактирование конституенты' className='w-32' />
|
<TabLabel label='Конституента' title='Редактирование конституенты' className='w-32' />
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useFormContext, useWatch } from 'react-hook-form';
|
import { useFormContext, useWatch } from 'react-hook-form';
|
||||||
import { createColumnHelper } from '@tanstack/react-table';
|
import { createColumnHelper } from '@tanstack/react-table';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { MiniButton } from '@/components/Control';
|
import { MiniButton } from '@/components/Control';
|
||||||
import { DataTable, type IConditionalStyle } from '@/components/DataTable';
|
import { DataTable, type IConditionalStyle } from '@/components/DataTable';
|
||||||
|
@ -79,16 +78,7 @@ export function TabArguments() {
|
||||||
argumentsHelper.accessor(arg => arg.typification, {
|
argumentsHelper.accessor(arg => arg.typification, {
|
||||||
id: 'type',
|
id: 'type',
|
||||||
enableHiding: true,
|
enableHiding: true,
|
||||||
cell: props => (
|
cell: props => <div className='w-36 text-sm break-words'>{props.getValue()}</div>
|
||||||
<div
|
|
||||||
className={clsx(
|
|
||||||
'min-w-[9.3rem] max-w-[9.3rem]', //
|
|
||||||
'text-sm break-words'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{props.getValue()}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}),
|
}),
|
||||||
argumentsHelper.display({
|
argumentsHelper.display({
|
||||||
id: 'actions',
|
id: 'actions',
|
||||||
|
@ -120,27 +110,15 @@ export function TabArguments() {
|
||||||
dense
|
dense
|
||||||
noFooter
|
noFooter
|
||||||
noHeader
|
noHeader
|
||||||
className={clsx(
|
className='h-23 cc-scroll-y text-sm border select-none'
|
||||||
'max-h-[5.8rem] min-h-[5.8rem]', //
|
|
||||||
'cc-scroll-y',
|
|
||||||
'text-sm',
|
|
||||||
'border',
|
|
||||||
'select-none'
|
|
||||||
)}
|
|
||||||
data={args}
|
data={args}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
conditionalRowStyles={conditionalRowStyles}
|
conditionalRowStyles={conditionalRowStyles}
|
||||||
noDataComponent={<NoData className='min-h-[3.6rem]'>Аргументы отсутствуют</NoData>}
|
noDataComponent={<NoData className='min-h-14'>Аргументы отсутствуют</NoData>}
|
||||||
onRowClicked={handleSelectArgument}
|
onRowClicked={handleSelectArgument}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div className='my-3 flex gap-2 justify-center items-center select-none'>
|
||||||
className={clsx(
|
|
||||||
'my-4', //
|
|
||||||
'flex gap-2 justify-center items-center',
|
|
||||||
'select-none'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<span
|
<span
|
||||||
title='Выберите аргумент из списка сверху и значение из списка снизу'
|
title='Выберите аргумент из списка сверху и значение из списка снизу'
|
||||||
className='font-semibold text-center'
|
className='font-semibold text-center'
|
||||||
|
@ -181,7 +159,7 @@ export function TabArguments() {
|
||||||
noTooltip
|
noTooltip
|
||||||
id='result'
|
id='result'
|
||||||
placeholder='Итоговое определение'
|
placeholder='Итоговое определение'
|
||||||
className='mt-[1.1rem]'
|
className='mt-4'
|
||||||
height='5.1rem'
|
height='5.1rem'
|
||||||
value={definition}
|
value={definition}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -60,7 +60,7 @@ export function TabTemplate() {
|
||||||
<SelectSingle
|
<SelectSingle
|
||||||
noBorder
|
noBorder
|
||||||
placeholder='Источник'
|
placeholder='Источник'
|
||||||
className='w-[12rem]'
|
className='w-48'
|
||||||
options={templateSelector}
|
options={templateSelector}
|
||||||
value={templateID ? { value: templateID, label: templates.find(item => item.id == templateID)!.title } : null}
|
value={templateID ? { value: templateID, label: templates.find(item => item.id == templateID)!.title } : null}
|
||||||
onChange={data => onChangeTemplateID(data ? data.value : null)}
|
onChange={data => onChangeTemplateID(data ? data.value : null)}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { Checkbox } from '@/components/Input';
|
import { Checkbox } from '@/components/Input';
|
||||||
import { ModalForm } from '@/components/Modal';
|
import { ModalForm } from '@/components/Modal';
|
||||||
|
@ -40,7 +39,7 @@ export function DlgDeleteCst() {
|
||||||
header='Удаление конституент'
|
header='Удаление конституент'
|
||||||
submitText={expandOut ? 'Удалить с зависимыми' : 'Удалить'}
|
submitText={expandOut ? 'Удалить с зависимыми' : 'Удалить'}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className={clsx('cc-column', 'max-w-[60vw] min-w-[30rem]', 'px-6')}
|
className='cc-column max-w-[60vw] min-w-120 px-6'
|
||||||
>
|
>
|
||||||
<ListConstituents title='Выбраны к удалению' list={selected} schema={schema} prefix={prefixes.cst_delete_list} />
|
<ListConstituents title='Выбраны к удалению' list={selected} schema={schema} prefix={prefixes.cst_delete_list} />
|
||||||
<ListConstituents
|
<ListConstituents
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { labelConstituenta } from '../../labels';
|
import { labelConstituenta } from '../../labels';
|
||||||
import { type IRSForm } from '../../models/rsform';
|
import { type IRSForm } from '../../models/rsform';
|
||||||
|
|
||||||
|
@ -18,7 +16,7 @@ export function ListConstituents({ list, schema, title, prefix }: ListConstituen
|
||||||
{title}: <b>{list.length}</b>
|
{title}: <b>{list.length}</b>
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
<div className={clsx('h-[9rem]', 'px-3', 'cc-scroll-y', 'border', 'whitespace-nowrap')}>
|
<div className='h-36 px-3 cc-scroll-y border whitespace-nowrap'>
|
||||||
{list.map(id => {
|
{list.map(id => {
|
||||||
const cst = schema.cstByID.get(id);
|
const cst = schema.cstByID.get(id);
|
||||||
return cst ? <p key={`${prefix}${cst.id}`}>{labelConstituenta(cst)}</p> : null;
|
return cst ? <p key={`${prefix}${cst.id}`}>{labelConstituenta(cst)}</p> : null;
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { FormProvider, useForm } from 'react-hook-form';
|
import { FormProvider, useForm } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import clsx from 'clsx';
|
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { HelpTopic } from '@/features/help';
|
import { HelpTopic } from '@/features/help';
|
||||||
|
@ -102,7 +101,7 @@ export function DlgEditReference() {
|
||||||
canSubmit={methods.formState.isValid}
|
canSubmit={methods.formState.isValid}
|
||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
|
onSubmit={event => void methods.handleSubmit(onSubmit)(event)}
|
||||||
className='w-160 px-6 h-[32rem]'
|
className='w-160 px-6 h-128'
|
||||||
helpTopic={HelpTopic.TERM_CONTROL}
|
helpTopic={HelpTopic.TERM_CONTROL}
|
||||||
>
|
>
|
||||||
<Tabs
|
<Tabs
|
||||||
|
@ -111,7 +110,7 @@ export function DlgEditReference() {
|
||||||
selectedIndex={activeTab}
|
selectedIndex={activeTab}
|
||||||
onSelect={handleChangeTab}
|
onSelect={handleChangeTab}
|
||||||
>
|
>
|
||||||
<TabList className={clsx('mb-3 self-center', 'flex', 'border divide-x rounded-none', 'bg-prim-200')}>
|
<TabList className='mb-3 self-center flex border divide-x rounded-none bg-prim-200'>
|
||||||
<TabLabel title='Отсылка на термин в заданной словоформе' label={labelReferenceType(ReferenceType.ENTITY)} />
|
<TabLabel title='Отсылка на термин в заданной словоформе' label={labelReferenceType(ReferenceType.ENTITY)} />
|
||||||
<TabLabel
|
<TabLabel
|
||||||
title='Установление синтаксической связи с отсылкой на термин'
|
title='Установление синтаксической связи с отсылкой на термин'
|
||||||
|
|
|
@ -46,7 +46,7 @@ export function TabEntityReference() {
|
||||||
dense
|
dense
|
||||||
label='Конституента'
|
label='Конституента'
|
||||||
placeholder='Имя'
|
placeholder='Имя'
|
||||||
className='w-[11rem]'
|
className='w-44'
|
||||||
{...register('entity.entity')}
|
{...register('entity.entity')}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
|
|
|
@ -28,7 +28,7 @@ export function TabSyntacticReference() {
|
||||||
type='number'
|
type='number'
|
||||||
dense
|
dense
|
||||||
label='Смещение'
|
label='Смещение'
|
||||||
className='max-w-[10rem]'
|
className='max-w-40'
|
||||||
{...register('syntactic.offset')}
|
{...register('syntactic.offset')}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { MiniButton } from '@/components/Control';
|
import { MiniButton } from '@/components/Control';
|
||||||
import { createColumnHelper, DataTable } from '@/components/DataTable';
|
import { createColumnHelper, DataTable } from '@/components/DataTable';
|
||||||
import { IconRemove } from '@/components/Icons';
|
import { IconRemove } from '@/components/Icons';
|
||||||
|
@ -37,7 +35,7 @@ export function TableWordForms({ forms, setForms, onFormSelect }: TableWordForms
|
||||||
size: 350,
|
size: 350,
|
||||||
minSize: 500,
|
minSize: 500,
|
||||||
maxSize: 500,
|
maxSize: 500,
|
||||||
cell: props => <div className='min-w-[25rem]'>{props.getValue()}</div>
|
cell: props => <div className='min-w-100'>{props.getValue()}</div>
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor('grams', {
|
columnHelper.accessor('grams', {
|
||||||
id: 'grams',
|
id: 'grams',
|
||||||
|
@ -65,12 +63,12 @@ export function TableWordForms({ forms, setForms, onFormSelect }: TableWordForms
|
||||||
dense
|
dense
|
||||||
noFooter
|
noFooter
|
||||||
noHeader
|
noHeader
|
||||||
className={clsx('mb-2', 'max-h-[17.4rem] min-h-[17.4rem]', 'border', 'text-sm', 'cc-scroll-y')}
|
className='mb-2 max-h-70 min-h-70 border text-sm cc-scroll-y'
|
||||||
data={forms}
|
data={forms}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
headPosition='0'
|
headPosition='0'
|
||||||
noDataComponent={
|
noDataComponent={
|
||||||
<NoData className='min-h-[2rem]'>
|
<NoData className='min-h-8'>
|
||||||
<p>Список пуст</p>
|
<p>Список пуст</p>
|
||||||
<p>Добавьте словоформу</p>
|
<p>Добавьте словоформу</p>
|
||||||
</NoData>
|
</NoData>
|
||||||
|
|
|
@ -26,7 +26,7 @@ export function DlgGraphParams() {
|
||||||
header='Настройки графа термов'
|
header='Настройки графа термов'
|
||||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||||
submitText='Применить'
|
submitText='Применить'
|
||||||
className='flex gap-6 justify-between px-6 pb-3 w-[30rem]'
|
className='flex gap-6 justify-between px-6 pb-3 w-120'
|
||||||
>
|
>
|
||||||
<div className='flex flex-col gap-1'>
|
<div className='flex flex-col gap-1'>
|
||||||
<h1 className='mb-2'>Преобразования</h1>
|
<h1 className='mb-2'>Преобразования</h1>
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import { useForm, useWatch } from 'react-hook-form';
|
import { useForm, useWatch } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { HelpTopic } from '@/features/help';
|
import { HelpTopic } from '@/features/help';
|
||||||
|
|
||||||
|
@ -53,12 +52,12 @@ export function DlgRenameCst() {
|
||||||
submitInvalidTooltip='Введите незанятое имя, соответствующее типу'
|
submitInvalidTooltip='Введите незанятое имя, соответствующее типу'
|
||||||
canSubmit={isValid}
|
canSubmit={isValid}
|
||||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||||
className={clsx('w-[30rem]', 'py-6 pr-3 pl-6 flex gap-3 justify-center items-center ')}
|
className='w-120 py-6 pr-3 pl-6 flex gap-3 justify-center items-center'
|
||||||
helpTopic={HelpTopic.CC_CONSTITUENTA}
|
helpTopic={HelpTopic.CC_CONSTITUENTA}
|
||||||
>
|
>
|
||||||
<SelectCstType
|
<SelectCstType
|
||||||
id='dlg_cst_type'
|
id='dlg_cst_type'
|
||||||
className='w-[16rem]'
|
className='w-64'
|
||||||
value={cst_type}
|
value={cst_type}
|
||||||
onChange={handleChangeType}
|
onChange={handleChangeType}
|
||||||
disabled={target.is_inherited}
|
disabled={target.is_inherited}
|
||||||
|
@ -68,7 +67,7 @@ export function DlgRenameCst() {
|
||||||
{...register('alias')}
|
{...register('alias')}
|
||||||
dense
|
dense
|
||||||
label='Имя'
|
label='Имя'
|
||||||
className='w-[7rem]'
|
className='w-28'
|
||||||
/>
|
/>
|
||||||
</ModalForm>
|
</ModalForm>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import clsx from 'clsx';
|
|
||||||
import { QRCodeSVG } from 'qrcode.react';
|
import { QRCodeSVG } from 'qrcode.react';
|
||||||
|
|
||||||
import { ModalView } from '@/components/Modal';
|
import { ModalView } from '@/components/Modal';
|
||||||
|
@ -13,7 +12,7 @@ export interface DlgShowQRProps {
|
||||||
export function DlgShowQR() {
|
export function DlgShowQR() {
|
||||||
const { target } = useDialogsStore(state => state.props as DlgShowQRProps);
|
const { target } = useDialogsStore(state => state.props as DlgShowQRProps);
|
||||||
return (
|
return (
|
||||||
<ModalView className={clsx('w-[25rem]', 'pb-6 pt-12 flex justify-center items-center')}>
|
<ModalView className='w-100 pb-6 pt-12 flex justify-center items-center'>
|
||||||
<div className='bg-[#ffffff] p-4 border'>
|
<div className='bg-[#ffffff] p-4 border'>
|
||||||
<QRCodeSVG value={target} size={256} />
|
<QRCodeSVG value={target} size={256} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import { Controller, useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { HelpTopic } from '@/features/help';
|
import { HelpTopic } from '@/features/help';
|
||||||
|
|
||||||
|
@ -47,7 +46,7 @@ export function DlgSubstituteCst() {
|
||||||
submitInvalidTooltip='Выберите две различные конституенты'
|
submitInvalidTooltip='Выберите две различные конституенты'
|
||||||
canSubmit={isValid}
|
canSubmit={isValid}
|
||||||
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
onSubmit={event => void handleSubmit(onSubmit)(event)}
|
||||||
className={clsx('w-160', 'px-6 pb-3')}
|
className='w-160 px-6 pb-3'
|
||||||
helpTopic={HelpTopic.UI_SUBSTITUTIONS}
|
helpTopic={HelpTopic.UI_SUBSTITUTIONS}
|
||||||
>
|
>
|
||||||
<Controller
|
<Controller
|
||||||
|
|
|
@ -44,7 +44,7 @@ export function DlgUploadRSForm() {
|
||||||
canSubmit={!!file}
|
canSubmit={!!file}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
submitText='Загрузить'
|
submitText='Загрузить'
|
||||||
className='w-[25rem] px-6'
|
className='w-100 px-6'
|
||||||
>
|
>
|
||||||
<FileInput label='Выбрать файл' acceptType={EXTEOR_TRS_FILE} onChange={handleFile} />
|
<FileInput label='Выбрать файл' acceptType={EXTEOR_TRS_FILE} onChange={handleFile} />
|
||||||
<Checkbox
|
<Checkbox
|
||||||
|
|
|
@ -76,8 +76,8 @@ export function EditorConstituenta() {
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'relative',
|
'relative',
|
||||||
'cc-fade-in',
|
'cc-fade-in',
|
||||||
'min-h-[20rem] max-w-[calc(min(100vw,95rem))] mx-auto',
|
'min-h-80 max-w-[calc(min(100vw,95rem))] mx-auto',
|
||||||
'flex pt-[1.9rem]',
|
'flex pt-8',
|
||||||
'overflow-y-auto overflow-x-clip',
|
'overflow-y-auto overflow-x-clip',
|
||||||
{ 'flex-col md:items-center': isNarrow }
|
{ 'flex-col md:items-center': isNarrow }
|
||||||
)}
|
)}
|
||||||
|
@ -90,7 +90,7 @@ export function EditorConstituenta() {
|
||||||
onSubmit={initiateSubmit}
|
onSubmit={initiateSubmit}
|
||||||
onReset={() => setToggleReset(prev => !prev)}
|
onReset={() => setToggleReset(prev => !prev)}
|
||||||
/>
|
/>
|
||||||
<div className='mx-0 md:mx-auto pt-[2rem] md:w-[48.8rem] shrink-0 xs:pt-0'>
|
<div className='mx-0 md:mx-auto pt-8 md:w-195 shrink-0 xs:pt-0'>
|
||||||
{activeCst ? (
|
{activeCst ? (
|
||||||
<FormConstituenta
|
<FormConstituenta
|
||||||
id={globalIDs.constituenta_editor}
|
id={globalIDs.constituenta_editor}
|
||||||
|
|
|
@ -28,7 +28,7 @@ export function EditorControls({ constituenta, disabled, onEditTerm }: EditorCon
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='absolute z-pop top-0 left-[4.7rem] flex select-none'>
|
<div className='absolute z-pop top-0 left-19 flex select-none'>
|
||||||
{!disabled || isProcessing ? (
|
{!disabled || isProcessing ? (
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title={isModified ? tooltipText.unsaved : `Редактировать словоформы термина`}
|
title={isModified ? tooltipText.unsaved : `Редактировать словоформы термина`}
|
||||||
|
@ -40,10 +40,10 @@ export function EditorControls({ constituenta, disabled, onEditTerm }: EditorCon
|
||||||
) : null}
|
) : null}
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'pt-1 sm:pl-[1.375rem] pl-1', //
|
'pt-1 sm:pl-5 pl-1',
|
||||||
'text-sm font-medium whitespace-nowrap',
|
'text-sm font-medium whitespace-nowrap',
|
||||||
'select-text cursor-default',
|
'select-text cursor-default',
|
||||||
disabled && !isProcessing && 'pl-[1.6rem] sm:pl-[2.8rem]'
|
disabled && !isProcessing && 'pl-6 sm:pl-11'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span>Имя </span>
|
<span>Имя </span>
|
||||||
|
|
|
@ -91,7 +91,7 @@ export function RSEditorControls({ isOpen, disabled, onEdit }: RSEditorControlsP
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'max-w-[28rem] min-w-[28rem] xs:max-w-[38.5rem] xs:min-w-[38.5rem] sm:max-w-160 sm:min-w-160 md:max-w-fit mx-1 sm:mx-0',
|
'max-w-112 min-w-112 xs:max-w-154 xs:min-w-154 sm:max-w-160 sm:min-w-160 md:max-w-fit mx-1 sm:mx-0',
|
||||||
'flex-wrap',
|
'flex-wrap',
|
||||||
'divide-solid',
|
'divide-solid',
|
||||||
'text-xs md:text-sm',
|
'text-xs md:text-sm',
|
||||||
|
|
|
@ -31,7 +31,7 @@ export function RSLocalButton({
|
||||||
data-tooltip-content={title}
|
data-tooltip-content={title}
|
||||||
data-tooltip-hidden={hideTitle}
|
data-tooltip-hidden={hideTitle}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'w-[1.7rem] sm:w-[2rem] h-5 sm:h-6',
|
'w-7 sm:w-8 h-5 sm:h-6',
|
||||||
'cursor-pointer disabled:cursor-default',
|
'cursor-pointer disabled:cursor-default',
|
||||||
'rounded-none',
|
'rounded-none',
|
||||||
'clr-hover clr-text-controls cc-animate-color',
|
'clr-hover clr-text-controls cc-animate-color',
|
||||||
|
|
|
@ -27,8 +27,8 @@ export function RSTokenButton({ token, disabled, onInsert }: RSTokenButtonProps)
|
||||||
'font-math',
|
'font-math',
|
||||||
'cursor-pointer disabled:cursor-default',
|
'cursor-pointer disabled:cursor-default',
|
||||||
{
|
{
|
||||||
'w-[3.7rem] md:w-[4.5rem]': label.length > 3,
|
'w-14.5 md:w-18': label.length > 3,
|
||||||
'w-[1.85rem] md:w-[2.25rem]': label.length <= 3
|
'w-7.25 md:w-9': label.length <= 3
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
data-tooltip-id={globalIDs.tooltip}
|
data-tooltip-id={globalIDs.tooltip}
|
||||||
|
|
|
@ -38,7 +38,12 @@ export function StatusBar({ isModified, processing, activeCst, parseData, onAnal
|
||||||
})();
|
})();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={clsx('absolute z-pop -top-2 right-1/2 translate-x-1/2 w-fit', 'pl-34 xs:pl-8 flex gap-1')}>
|
<div
|
||||||
|
className={clsx(
|
||||||
|
'absolute z-pop -top-2 right-1/2 translate-x-1/2 w-fit', //
|
||||||
|
'pl-34 xs:pl-8 flex gap-1'
|
||||||
|
)}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
|
|
|
@ -16,7 +16,7 @@ export function ToolbarRSExpression({ disabled, showTypeGraph, showAST }: Toolba
|
||||||
const toggleControls = usePreferencesStore(state => state.toggleShowExpressionControls);
|
const toggleControls = usePreferencesStore(state => state.toggleShowExpressionControls);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='absolute z-pop top-[-0.5rem] right-0 cc-icons'>
|
<div className='absolute z-pop -top-2 right-0 cc-icons'>
|
||||||
{!disabled || isProcessing ? (
|
{!disabled || isProcessing ? (
|
||||||
<MiniButton
|
<MiniButton
|
||||||
title='Отображение специальной клавиатуры'
|
title='Отображение специальной клавиатуры'
|
||||||
|
|
|
@ -36,10 +36,10 @@ export function EditorRSFormCard() {
|
||||||
<div
|
<div
|
||||||
onKeyDown={handleInput}
|
onKeyDown={handleInput}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'relative',
|
'relative', //
|
||||||
'cc-fade-in',
|
'cc-fade-in',
|
||||||
'md:w-fit md:max-w-fit max-w-[32rem]',
|
'md:w-fit md:max-w-fit max-w-128',
|
||||||
'flex flex-row flex-wrap px-6 pt-[1.9rem]'
|
'flex flex-row flex-wrap px-6 pt-8'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<ToolbarItemCard onSubmit={initiateSubmit} schema={schema} isMutable={isMutable} deleteSchema={deleteSchema} />
|
<ToolbarItemCard onSubmit={initiateSubmit} schema={schema} isMutable={isMutable} deleteSchema={deleteSchema} />
|
||||||
|
|
|
@ -32,7 +32,7 @@ export function RSFormStats({ stats, isArchive }: RSFormStatsProps) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'mt-3 md:ml-5 md:mt-8 md:w-56 w-80 h-min mx-auto', // prettier: split-lines
|
'mt-3 md:ml-5 md:mt-8 md:w-56 w-80 h-min mx-auto', //
|
||||||
'grid grid-cols-4 gap-1 justify-items-end'
|
'grid grid-cols-4 gap-1 justify-items-end'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -55,7 +55,7 @@ export function ToolbarVersioning({ blockReload }: ToolbarVersioningProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='absolute z-bottom top-[-0.4rem] right-[0rem] pr-2 cc-icons'>
|
<div className='absolute z-bottom -top-2 right-0 pr-2 cc-icons'>
|
||||||
{isMutable ? (
|
{isMutable ? (
|
||||||
<>
|
<>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { TextURL } from '@/components/Control';
|
import { TextURL } from '@/components/Control';
|
||||||
import { createColumnHelper, DataTable, type RowSelectionState, type VisibilityState } from '@/components/DataTable';
|
import { createColumnHelper, DataTable, type RowSelectionState, type VisibilityState } from '@/components/DataTable';
|
||||||
import { NoData, TextContent } from '@/components/View';
|
import { NoData, TextContent } from '@/components/View';
|
||||||
|
@ -124,7 +122,7 @@ export function TableRSList({
|
||||||
<DataTable
|
<DataTable
|
||||||
dense
|
dense
|
||||||
noFooter
|
noFooter
|
||||||
className={clsx('min-h-64', 'cc-scroll-y', 'text-sm', 'select-none')}
|
className='min-h-64 cc-scroll-y text-sm select-none'
|
||||||
style={{ maxHeight: maxHeight }}
|
style={{ maxHeight: maxHeight }}
|
||||||
data={items ?? []}
|
data={items ?? []}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
|
|
|
@ -74,8 +74,8 @@ export function ViewHidden({ items }: ViewHiddenProps) {
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'flex flex-wrap justify-center gap-2 py-2 -mt-2',
|
'flex flex-wrap justify-center gap-2 py-2 -mt-2',
|
||||||
'text-sm',
|
|
||||||
'clr-input border-x border-b rounded-b-md',
|
'clr-input border-x border-b rounded-b-md',
|
||||||
|
'text-sm',
|
||||||
'cc-scroll-y'
|
'cc-scroll-y'
|
||||||
)}
|
)}
|
||||||
style={{
|
style={{
|
||||||
|
|
|
@ -76,7 +76,7 @@ export function RSTabs({ activeID, activeTab }: RSTabsProps) {
|
||||||
onSelect={onSelectTab}
|
onSelect={onSelectTab}
|
||||||
defaultFocus
|
defaultFocus
|
||||||
selectedTabClassName='clr-selected'
|
selectedTabClassName='clr-selected'
|
||||||
className='relative flex flex-col mx-auto min-w-fit items-center'
|
className='relative flex flex-col min-w-fit items-center'
|
||||||
>
|
>
|
||||||
<TabList
|
<TabList
|
||||||
className={clsx(
|
className={clsx(
|
||||||
|
|
|
@ -26,13 +26,10 @@ export function ViewConstituents({ isBottom, isMounted }: ViewConstituentsProps)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside
|
<aside
|
||||||
className={clsx(
|
className={clsx('border', {
|
||||||
'border', // prettier: split-lines
|
|
||||||
{
|
|
||||||
'mt-9 rounded-l-md rounded-r-none h-fit overflow-visible': !isBottom,
|
'mt-9 rounded-l-md rounded-r-none h-fit overflow-visible': !isBottom,
|
||||||
'mt-3 mx-6 rounded-md overflow-hidden': isBottom
|
'mt-3 mx-6 rounded-md overflow-hidden': isBottom
|
||||||
}
|
})}
|
||||||
)}
|
|
||||||
style={{
|
style={{
|
||||||
willChange: 'opacity, max-width',
|
willChange: 'opacity, max-width',
|
||||||
transitionProperty: 'opacity, max-width',
|
transitionProperty: 'opacity, max-width',
|
||||||
|
|
|
@ -4,15 +4,25 @@
|
||||||
|
|
||||||
@import './constants.css' layer(base);
|
@import './constants.css' layer(base);
|
||||||
|
|
||||||
|
/* Uncomment to debug layering and overflow */
|
||||||
|
/* *,
|
||||||
|
*::after,
|
||||||
|
*::before {
|
||||||
|
background: hsla(135, 50%, 50%, 0.05) !important;
|
||||||
|
outline: 2px solid hotpink !important;
|
||||||
|
|
||||||
|
:focus,
|
||||||
|
:focus-visible,
|
||||||
|
:focus-within {
|
||||||
|
outline: 2px solid hotpink !important;
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
@layer utilities {
|
@layer utilities {
|
||||||
*,
|
*,
|
||||||
*::after,
|
*::after,
|
||||||
*::before {
|
*::before {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
/* Uncomment to debug layering and overflow */
|
|
||||||
/* background: hsla(135, 50%, 50%, 0.05); */
|
|
||||||
/* outline: 2px solid hotpink; */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -253,3 +253,14 @@
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@utility cc-modal-wrapper {
|
||||||
|
isolation: isolate;
|
||||||
|
z-index: var(--z-index-modal);
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user