R: Refactor layout definitions

This commit is contained in:
Ivan 2025-03-11 12:47:00 +03:00
parent aea9dececf
commit 3d63c25845
22 changed files with 141 additions and 147 deletions

View File

@ -1,3 +1,5 @@
import clsx from 'clsx';
import { HelpTopic } from '@/features/help'; import { HelpTopic } from '@/features/help';
import { BadgeHelp } from '@/features/help/components'; import { BadgeHelp } from '@/features/help/components';
import { useRoleStore, UserRole } from '@/features/users'; import { useRoleStore, UserRole } from '@/features/users';
@ -20,9 +22,11 @@ interface ToolbarItemAccessProps {
toggleReadOnly: () => void; toggleReadOnly: () => void;
schema: ILibraryItem; schema: ILibraryItem;
isAttachedToOSS: boolean; isAttachedToOSS: boolean;
className?: string;
} }
export function ToolbarItemAccess({ export function ToolbarItemAccess({
className,
visible, visible,
toggleVisible, toggleVisible,
readOnly, readOnly,
@ -40,7 +44,7 @@ export function ToolbarItemAccess({
} }
return ( return (
<div className='absolute z-bottom top-18 right-0 w-48 flex pr-2'> <div className={clsx('w-46 flex', className)}>
<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

View File

@ -1,5 +1,7 @@
'use client'; 'use client';
import clsx from 'clsx';
import { urls, useConceptNavigation } from '@/app'; import { urls, useConceptNavigation } from '@/app';
import { HelpTopic } from '@/features/help'; import { HelpTopic } from '@/features/help';
import { BadgeHelp } from '@/features/help/components'; import { BadgeHelp } from '@/features/help/components';
@ -18,13 +20,14 @@ import { useMutatingLibrary } from '../backend/useMutatingLibrary';
import { MiniSelectorOSS } from './MiniSelectorOSS'; import { MiniSelectorOSS } from './MiniSelectorOSS';
interface ToolbarItemCardProps { interface ToolbarItemCardProps {
className?: string;
onSubmit: () => void; onSubmit: () => void;
isMutable: boolean; isMutable: boolean;
schema: ILibraryItem; schema: ILibraryItem;
deleteSchema: () => void; deleteSchema: () => void;
} }
export function ToolbarItemCard({ schema, onSubmit, isMutable, deleteSchema }: ToolbarItemCardProps) { export function ToolbarItemCard({ className, schema, onSubmit, isMutable, deleteSchema }: ToolbarItemCardProps) {
const role = useRoleStore(state => state.role); const role = useRoleStore(state => state.role);
const router = useConceptNavigation(); const router = useConceptNavigation();
const { isModified } = useModificationStore(); const { isModified } = useModificationStore();
@ -48,7 +51,7 @@ export function ToolbarItemCard({ schema, onSubmit, isMutable, deleteSchema }: T
})(); })();
return ( return (
<div className='cc-tab-tools cc-icons'> <div className={clsx('cc-icons', className)}>
{ossSelector} {ossSelector}
{isMutable || isModified ? ( {isMutable || isModified ? (
<MiniButton <MiniButton

View File

@ -34,7 +34,13 @@ export function EditorOssCard() {
return ( return (
<> <>
<ToolbarItemCard onSubmit={initiateSubmit} schema={schema} isMutable={isMutable} deleteSchema={deleteSchema} /> <ToolbarItemCard
className='cc-tab-tools'
onSubmit={initiateSubmit}
schema={schema}
isMutable={isMutable}
deleteSchema={deleteSchema}
/>
<div <div
onKeyDown={handleInput} onKeyDown={handleInput}
className={clsx( className={clsx(
@ -48,7 +54,7 @@ export function EditorOssCard() {
<EditorLibraryItem schema={schema} isAttachedToOSS={false} /> <EditorLibraryItem schema={schema} isAttachedToOSS={false} />
</div> </div>
<OssStats stats={schema.stats} /> <OssStats className='mt-3 md:mt-8 md:ml-5 w-56 md:w-48 mx-auto h-min' stats={schema.stats} />
</div> </div>
</> </>
); );

View File

@ -78,6 +78,7 @@ export function FormOSS() {
error={errors.alias} error={errors.alias}
/> />
<ToolbarItemAccess <ToolbarItemAccess
className='absolute top-18 right-2'
visible={visible} visible={visible}
toggleVisible={() => setValue('visible', !visible, { shouldDirty: true })} toggleVisible={() => setValue('visible', !visible, { shouldDirty: true })}
readOnly={readOnly} readOnly={readOnly}

View File

@ -6,17 +6,13 @@ import { ValueStats } from '@/components/View';
import { type IOperationSchemaStats } from '../../../models/oss'; import { type IOperationSchemaStats } from '../../../models/oss';
interface OssStatsProps { interface OssStatsProps {
className?: string;
stats: IOperationSchemaStats; stats: IOperationSchemaStats;
} }
export function OssStats({ stats }: OssStatsProps) { export function OssStats({ className, stats }: OssStatsProps) {
return ( return (
<div <div className={clsx('grid grid-cols-3 gap-1 justify-items-end', className)}>
className={clsx(
'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'
)}
>
<div id='count_operations' className='w-fit flex gap-3 hover:cursor-default '> <div id='count_operations' className='w-fit flex gap-3 hover:cursor-default '>
<span>Всего</span> <span>Всего</span>
<span>{stats.count_operations}</span> <span>{stats.count_operations}</span>

View File

@ -85,11 +85,13 @@ export function EditorConstituenta() {
onKeyDown={handleInput} onKeyDown={handleInput}
> >
<ToolbarConstituenta <ToolbarConstituenta
className='cc-tab-tools right-1/2 translate-x-0 xs:right-4 xs:-translate-x-1/2 md:right-1/2 md:translate-x-0 cc-animate-position'
activeCst={activeCst} activeCst={activeCst}
disabled={disabled} disabled={disabled}
onSubmit={initiateSubmit} onSubmit={initiateSubmit}
onReset={() => setToggleReset(prev => !prev)} onReset={() => setToggleReset(prev => !prev)}
/> />
<div className='mx-0 md:mx-auto pt-8 md:w-195 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
@ -102,7 +104,11 @@ export function EditorConstituenta() {
/> />
) : null} ) : null}
</div> </div>
<ViewConstituents isMounted={showList} isBottom={isNarrow} /> <ViewConstituents
className={isNarrow ? 'mt-3 mx-6 overflow-hidden' : 'mt-9 h-fit overflow-visible'}
isMounted={showList}
isBottom={isNarrow}
/>
</div> </div>
); );
} }

View File

@ -1,63 +0,0 @@
import clsx from 'clsx';
import { MiniButton } from '@/components/Control';
import { IconEdit } from '@/components/Icons';
import { useDialogsStore } from '@/stores/dialogs';
import { useModificationStore } from '@/stores/modification';
import { tooltipText } from '@/utils/labels';
import { useMutatingRSForm } from '../../../backend/useMutatingRSForm';
import { type IConstituenta } from '../../../models/rsform';
import { useRSEdit } from '../RSEditContext';
interface EditorControlsProps {
constituenta: IConstituenta;
disabled: boolean;
onEditTerm: () => void;
}
export function EditorControls({ constituenta, disabled, onEditTerm }: EditorControlsProps) {
const schema = useRSEdit().schema;
const { isModified } = useModificationStore();
const isProcessing = useMutatingRSForm();
const showRenameCst = useDialogsStore(state => state.showRenameCst);
function handleRenameCst() {
showRenameCst({ schema: schema, target: constituenta });
}
return (
<div className='absolute z-pop top-0 left-19 flex select-none'>
{!disabled || isProcessing ? (
<MiniButton
title={isModified ? tooltipText.unsaved : `Редактировать словоформы термина`}
noHover
onClick={onEditTerm}
icon={<IconEdit size='1rem' className='icon-primary' />}
disabled={isModified}
/>
) : null}
<div
className={clsx(
'pt-1 sm:pl-5 pl-1',
'text-sm font-medium whitespace-nowrap',
'select-text cursor-default',
disabled && !isProcessing && 'pl-6 sm:pl-11'
)}
>
<span>Имя </span>
<span className='ml-1'>{constituenta?.alias ?? ''}</span>
</div>
{!disabled || isProcessing ? (
<MiniButton
noHover
title={isModified ? tooltipText.unsaved : 'Переименовать конституенту'}
onClick={handleRenameCst}
icon={<IconEdit size='1rem' className='icon-primary' />}
disabled={isModified}
/>
) : null}
</div>
);
}

View File

@ -6,13 +6,13 @@ import { Controller, useForm } from 'react-hook-form';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import { SubmitButton } from '@/components/Control'; import { MiniButton, SubmitButton } from '@/components/Control';
import { IconChild, IconPredecessor, IconSave } from '@/components/Icons'; import { IconChild, IconEdit, IconPredecessor, IconSave } from '@/components/Icons';
import { TextArea } from '@/components/Input'; import { TextArea } from '@/components/Input';
import { Indicator } from '@/components/View'; import { Indicator } from '@/components/View';
import { useDialogsStore } from '@/stores/dialogs'; import { useDialogsStore } from '@/stores/dialogs';
import { useModificationStore } from '@/stores/modification'; import { useModificationStore } from '@/stores/modification';
import { errorMsg } from '@/utils/labels'; import { errorMsg, tooltipText } from '@/utils/labels';
import { promptUnsaved } from '@/utils/utils'; import { promptUnsaved } from '@/utils/utils';
import { import {
@ -30,8 +30,6 @@ import { type IConstituenta, type IRSForm } from '../../../models/rsform';
import { isBaseSet, isBasicConcept, isFunctional } from '../../../models/rsformAPI'; import { isBaseSet, isBasicConcept, isFunctional } from '../../../models/rsformAPI';
import { EditorRSExpression } from '../EditorRSExpression'; import { EditorRSExpression } from '../EditorRSExpression';
import { EditorControls } from './EditorControls';
interface FormConstituentaProps { interface FormConstituentaProps {
id?: string; id?: string;
disabled: boolean; disabled: boolean;
@ -57,6 +55,7 @@ export function FormConstituenta({ disabled, id, toggleReset, schema, activeCst,
const { cstUpdate } = useCstUpdate(); const { cstUpdate } = useCstUpdate();
const showTypification = useDialogsStore(state => state.showShowTypeGraph); const showTypification = useDialogsStore(state => state.showShowTypeGraph);
const showEditTerm = useDialogsStore(state => state.showEditWordForms); const showEditTerm = useDialogsStore(state => state.showEditWordForms);
const showRenameCst = useDialogsStore(state => state.showRenameCst);
const [localParse, setLocalParse] = useState<IExpressionParseDTO | null>(null); const [localParse, setLocalParse] = useState<IExpressionParseDTO | null>(null);
@ -129,9 +128,38 @@ export function FormConstituenta({ disabled, id, toggleReset, schema, activeCst,
showEditTerm({ itemID: schema.id, target: activeCst }); showEditTerm({ itemID: schema.id, target: activeCst });
} }
function handleRenameCst() {
showRenameCst({ schema: schema, target: activeCst });
}
return ( return (
<form id={id} className='relative cc-column mt-1 px-6 py-1' onSubmit={event => void handleSubmit(onSubmit)(event)}> <form id={id} className='relative cc-column mt-1 px-6 py-1' onSubmit={event => void handleSubmit(onSubmit)(event)}>
<EditorControls disabled={disabled} constituenta={activeCst} onEditTerm={handleEditTermForms} /> {!disabled || isProcessing ? (
<MiniButton
title={isModified ? tooltipText.unsaved : `Редактировать словоформы термина`}
noHover
onClick={handleEditTermForms}
className='absolute z-pop top-0 left-[calc(7ch+4px)]'
icon={<IconEdit size='1rem' className='icon-primary' />}
disabled={isModified}
/>
) : null}
<div className='absolute z-pop top-0 left-[calc(7ch+4px+3rem)] flex select-none'>
<div className='pt-1 text-sm font-medium whitespace-nowrap select-text cursor-default'>
<span>Имя </span>
<span className='ml-1'>{activeCst?.alias ?? ''}</span>
</div>
{!disabled || isProcessing ? (
<MiniButton
noHover
title={isModified ? tooltipText.unsaved : 'Переименовать конституенту'}
onClick={handleRenameCst}
icon={<IconEdit size='1rem' className='icon-primary' />}
disabled={isModified}
/>
) : null}
</div>
<Controller <Controller
control={control} control={control}

View File

@ -31,6 +31,7 @@ import { type IConstituenta } from '../../../models/rsform';
import { RSTabID, useRSEdit } from '../RSEditContext'; import { RSTabID, useRSEdit } from '../RSEditContext';
interface ToolbarConstituentaProps { interface ToolbarConstituentaProps {
className?: string;
activeCst: IConstituenta | null; activeCst: IConstituenta | null;
disabled: boolean; disabled: boolean;
@ -39,6 +40,7 @@ interface ToolbarConstituentaProps {
} }
export function ToolbarConstituenta({ export function ToolbarConstituenta({
className,
activeCst, activeCst,
disabled, disabled,
@ -78,14 +80,7 @@ export function ToolbarConstituenta({
} }
return ( return (
<div <div className={clsx('px-1 rounded-b-2xl cc-blur cc-icons cc-animate-position outline-hidden', className)}>
className={clsx(
'absolute z-pop right-1/2 translate-x-0 xs:right-4 xs:-translate-x-1/2 md:right-1/2 md:translate-x-0',
'px-1 rounded-b-2xl',
'cc-blur',
'cc-tab-tools cc-icons cc-animate-position outline-hidden'
)}
>
{schema.oss.length > 0 ? ( {schema.oss.length > 0 ? (
<MiniSelectorOSS <MiniSelectorOSS
items={schema.oss} items={schema.oss}

View File

@ -155,9 +155,15 @@ export function EditorRSExpression({
return ( return (
<div className='relative cc-fade-in'> <div className='relative cc-fade-in'>
<ToolbarRSExpression disabled={disabled} showAST={handleShowAST} showTypeGraph={onShowTypeGraph} /> <ToolbarRSExpression
className='absolute -top-2 right-0'
disabled={disabled}
showAST={handleShowAST}
showTypeGraph={onShowTypeGraph}
/>
<StatusBar <StatusBar
className='absolute -top-2 right-1/2 translate-x-1/2'
processing={isPending} processing={isPending}
isModified={isModified} isModified={isModified}
activeCst={activeCst} activeCst={activeCst}

View File

@ -18,6 +18,7 @@ import { ExpressionStatus, type IConstituenta } from '../../../models/rsform';
import { inferStatus } from '../../../models/rsformAPI'; import { inferStatus } from '../../../models/rsformAPI';
interface StatusBarProps { interface StatusBarProps {
className?: string;
processing: boolean; processing: boolean;
isModified: boolean; isModified: boolean;
parseData: IExpressionParseDTO | null; parseData: IExpressionParseDTO | null;
@ -25,7 +26,7 @@ interface StatusBarProps {
onAnalyze: () => void; onAnalyze: () => void;
} }
export function StatusBar({ isModified, processing, activeCst, parseData, onAnalyze }: StatusBarProps) { export function StatusBar({ className, isModified, processing, activeCst, parseData, onAnalyze }: StatusBarProps) {
const status = (() => { const status = (() => {
if (isModified) { if (isModified) {
return ExpressionStatus.UNKNOWN; return ExpressionStatus.UNKNOWN;
@ -38,12 +39,7 @@ export function StatusBar({ isModified, processing, activeCst, parseData, onAnal
})(); })();
return ( return (
<div <div className={clsx('pl-34 xs:pl-8 flex gap-1', className)}>
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(

View File

@ -1,3 +1,5 @@
import clsx from 'clsx';
import { MiniButton } from '@/components/Control'; import { MiniButton } from '@/components/Control';
import { IconControls, IconTree, IconTypeGraph } from '@/components/Icons'; import { IconControls, IconTree, IconTypeGraph } from '@/components/Icons';
import { usePreferencesStore } from '@/stores/preferences'; import { usePreferencesStore } from '@/stores/preferences';
@ -5,18 +7,19 @@ import { usePreferencesStore } from '@/stores/preferences';
import { useMutatingRSForm } from '../../../backend/useMutatingRSForm'; import { useMutatingRSForm } from '../../../backend/useMutatingRSForm';
interface ToolbarRSExpressionProps { interface ToolbarRSExpressionProps {
className?: string;
disabled?: boolean; disabled?: boolean;
showAST: (event: React.MouseEvent<Element>) => void; showAST: (event: React.MouseEvent<Element>) => void;
showTypeGraph: (event: React.MouseEvent<Element>) => void; showTypeGraph: (event: React.MouseEvent<Element>) => void;
} }
export function ToolbarRSExpression({ disabled, showTypeGraph, showAST }: ToolbarRSExpressionProps) { export function ToolbarRSExpression({ className, disabled, showTypeGraph, showAST }: ToolbarRSExpressionProps) {
const isProcessing = useMutatingRSForm(); const isProcessing = useMutatingRSForm();
const showControls = usePreferencesStore(state => state.showExpressionControls); const showControls = usePreferencesStore(state => state.showExpressionControls);
const toggleControls = usePreferencesStore(state => state.toggleShowExpressionControls); const toggleControls = usePreferencesStore(state => state.toggleShowExpressionControls);
return ( return (
<div className='absolute z-pop -top-2 right-0 cc-icons'> <div className={clsx('cc-icons', className)}>
{!disabled || isProcessing ? ( {!disabled || isProcessing ? (
<MiniButton <MiniButton
title='Отображение специальной клавиатуры' title='Отображение специальной клавиатуры'

View File

@ -42,14 +42,24 @@ export function EditorRSFormCard() {
'flex flex-row flex-wrap px-6 pt-8' 'flex flex-row flex-wrap px-6 pt-8'
)} )}
> >
<ToolbarItemCard onSubmit={initiateSubmit} schema={schema} isMutable={isMutable} deleteSchema={deleteSchema} /> <ToolbarItemCard
className='cc-tab-tools'
onSubmit={initiateSubmit}
schema={schema}
isMutable={isMutable}
deleteSchema={deleteSchema}
/>
<div className='cc-column shrink'> <div className='cc-column shrink'>
<FormRSForm /> <FormRSForm />
<EditorLibraryItem schema={schema} isAttachedToOSS={isAttachedToOSS} /> <EditorLibraryItem schema={schema} isAttachedToOSS={isAttachedToOSS} />
</div> </div>
<RSFormStats stats={schema.stats} isArchive={isArchive} /> <RSFormStats
className='mt-3 md:mt-8 md:ml-5 w-80 md:w-56 mx-auto h-min'
stats={schema.stats}
isArchive={isArchive}
/>
</div> </div>
); );
} }

View File

@ -90,17 +90,13 @@ export function FormRSForm() {
disabled={!isContentEditable} disabled={!isContentEditable}
error={errors.alias} error={errors.alias}
/> />
<div className='relative flex flex-col'> <div className='relative flex flex-col gap-2'>
<ToolbarVersioning blockReload={schema.oss.length > 0} /> <ToolbarVersioning
<ToolbarItemAccess className='absolute -top-2 right-2' //
visible={visible} blockReload={schema.oss.length > 0}
toggleVisible={() => setValue('visible', !visible, { shouldDirty: true })}
readOnly={readOnly}
toggleReadOnly={() => setValue('read_only', !readOnly, { shouldDirty: true })}
schema={schema}
isAttachedToOSS={isAttachedToOSS}
/> />
<Label text='Версия' className='mb-2 select-none' />
<Label text='Версия' className='select-none w-fit' />
<SelectVersion <SelectVersion
id='schema_version' id='schema_version'
className='select-none' className='select-none'
@ -108,6 +104,16 @@ export function FormRSForm() {
items={schema.versions} items={schema.versions}
onChange={handleSelectVersion} onChange={handleSelectVersion}
/> />
<ToolbarItemAccess
className='absolute top-18 right-2'
visible={visible}
toggleVisible={() => setValue('visible', !visible, { shouldDirty: true })}
readOnly={readOnly}
toggleReadOnly={() => setValue('read_only', !readOnly, { shouldDirty: true })}
schema={schema}
isAttachedToOSS={isAttachedToOSS}
/>
</div> </div>
</div> </div>

View File

@ -24,18 +24,14 @@ import { ValueStats } from '@/components/View';
import { type IRSFormStats } from '../../../models/rsform'; import { type IRSFormStats } from '../../../models/rsform';
interface RSFormStatsProps { interface RSFormStatsProps {
className?: string;
isArchive: boolean; isArchive: boolean;
stats: IRSFormStats; stats: IRSFormStats;
} }
export function RSFormStats({ stats, isArchive }: RSFormStatsProps) { export function RSFormStats({ className, stats, isArchive }: RSFormStatsProps) {
return ( return (
<div <div className={clsx('grid grid-cols-4 gap-1 justify-items-end', className)}>
className={clsx(
'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'
)}
>
<div id='count_all' className='col-span-2 w-fit flex gap-3 hover:cursor-default '> <div id='count_all' className='col-span-2 w-fit flex gap-3 hover:cursor-default '>
<span>Всего</span> <span>Всего</span>
<span>{stats.count_all}</span> <span>{stats.count_all}</span>

View File

@ -1,5 +1,7 @@
'use client'; 'use client';
import clsx from 'clsx';
import { HelpTopic } from '@/features/help'; import { HelpTopic } from '@/features/help';
import { BadgeHelp } from '@/features/help/components'; import { BadgeHelp } from '@/features/help/components';
import { useVersionRestore } from '@/features/library/backend/useVersionRestore'; import { useVersionRestore } from '@/features/library/backend/useVersionRestore';
@ -15,9 +17,10 @@ import { useRSEdit } from '../RSEditContext';
interface ToolbarVersioningProps { interface ToolbarVersioningProps {
blockReload?: boolean; blockReload?: boolean;
className?: string;
} }
export function ToolbarVersioning({ blockReload }: ToolbarVersioningProps) { export function ToolbarVersioning({ blockReload, className }: ToolbarVersioningProps) {
const { isModified } = useModificationStore(); const { isModified } = useModificationStore();
const { versionRestore } = useVersionRestore(); const { versionRestore } = useVersionRestore();
const { schema, isMutable, isContentEditable, navigateVersion, activeVersion, selected } = useRSEdit(); const { schema, isMutable, isContentEditable, navigateVersion, activeVersion, selected } = useRSEdit();
@ -55,7 +58,7 @@ export function ToolbarVersioning({ blockReload }: ToolbarVersioningProps) {
} }
return ( return (
<div className='absolute z-bottom -top-2 right-0 pr-2 cc-icons'> <div className={clsx('cc-icons', className)}>
{isMutable ? ( {isMutable ? (
<> <>
<MiniButton <MiniButton

View File

@ -127,7 +127,9 @@ export function EditorRSList() {
return ( return (
<div tabIndex={-1} onKeyDown={handleKeyDown} className='relative cc-fade-in pt-8'> <div tabIndex={-1} onKeyDown={handleKeyDown} className='relative cc-fade-in pt-8'>
{isContentEditable ? <ToolbarRSList /> : null} {isContentEditable ? (
<ToolbarRSList className='cc-tab-tools right-4 md:right-1/2 -translate-x-1/2 md:translate-x-0 cc-animate-position' />
) : null}
{isContentEditable ? ( {isContentEditable ? (
<div className='flex items-center border-b'> <div className='flex items-center border-b'>
<div className='px-2'> <div className='px-2'>

View File

@ -24,7 +24,11 @@ import { IconCstType } from '../../../components/IconCstType';
import { getCstTypeShortcut, labelCstType } from '../../../labels'; import { getCstTypeShortcut, labelCstType } from '../../../labels';
import { useRSEdit } from '../RSEditContext'; import { useRSEdit } from '../RSEditContext';
export function ToolbarRSList() { interface ToolbarRSListProps {
className?: string;
}
export function ToolbarRSList({ className }: ToolbarRSListProps) {
const isProcessing = useMutatingRSForm(); const isProcessing = useMutatingRSForm();
const insertMenu = useDropdown(); const insertMenu = useDropdown();
const { const {
@ -42,13 +46,7 @@ export function ToolbarRSList() {
} = useRSEdit(); } = useRSEdit();
return ( return (
<div <div className={clsx('cc-icons items-start outline-hidden', className)}>
className={clsx(
'cc-tab-tools right-4 md:right-1/2 -translate-x-1/2 md:translate-x-0',
'cc-icons items-start',
'outline-hidden cc-animate-position'
)}
>
{schema.oss.length > 0 ? ( {schema.oss.length > 0 ? (
<MiniSelectorOSS <MiniSelectorOSS
items={schema.oss} items={schema.oss}

View File

@ -12,7 +12,6 @@ import {
useReactFlow, useReactFlow,
useStoreApi useStoreApi
} from 'reactflow'; } from 'reactflow';
import clsx from 'clsx';
import { useMainHeight } from '@/stores/appLayout'; import { useMainHeight } from '@/stores/appLayout';
import { PARAMETER } from '@/utils/constants'; import { PARAMETER } from '@/utils/constants';
@ -181,13 +180,7 @@ export function TGFlow() {
) : null} ) : null}
</div> </div>
<div <div className='absolute z-pop top-18 sm:top-16 left-2 sm:left-3 w-54 flex flex-col pointer-events-none'>
className={clsx(
'absolute z-pop top-18 sm:top-16 left-2 sm:left-3 w-54',
'flex flex-col',
'pointer-events-none'
)}
>
<span className='px-2 pb-1 select-none whitespace-nowrap cc-blur rounded-xl'> <span className='px-2 pb-1 select-none whitespace-nowrap cc-blur rounded-xl'>
Выбор {selected.length} из {schema.stats?.count_all ?? 0} Выбор {selected.length} из {schema.stats?.count_all ?? 0}
</span> </span>

View File

@ -15,21 +15,26 @@ import { TableSideConstituents } from './TableSideConstituents';
const COLUMN_DENSE_SEARCH_THRESHOLD = 1100; const COLUMN_DENSE_SEARCH_THRESHOLD = 1100;
interface ViewConstituentsProps { interface ViewConstituentsProps {
className?: string;
isBottom?: boolean; isBottom?: boolean;
isMounted: boolean; isMounted: boolean;
} }
export function ViewConstituents({ isBottom, isMounted }: ViewConstituentsProps) { export function ViewConstituents({ className, isBottom, isMounted }: ViewConstituentsProps) {
const windowSize = useWindowSize(); const windowSize = useWindowSize();
const role = useRoleStore(state => state.role); const role = useRoleStore(state => state.role);
const listHeight = useFitHeight(!isBottom ? '8.2rem' : role !== UserRole.READER ? '42rem' : '35rem', '10rem'); const listHeight = useFitHeight(!isBottom ? '8.2rem' : role !== UserRole.READER ? '42rem' : '35rem', '10rem');
return ( return (
<aside <aside
className={clsx('border', { className={clsx(
'mt-9 rounded-l-md rounded-r-none h-fit overflow-visible': !isBottom, 'border',
'mt-3 mx-6 rounded-md overflow-hidden': isBottom {
})} 'rounded-l-md rounded-r-none': !isBottom,
'rounded-md': isBottom
},
className
)}
style={{ style={{
willChange: 'opacity, max-width', willChange: 'opacity, max-width',
transitionProperty: 'opacity, max-width', transitionProperty: 'opacity, max-width',

View File

@ -35,7 +35,7 @@ export function EditorPassword() {
return ( return (
<form <form
className='max-w-64 px-6 py-2 flex flex-col justify-between border-l-2' className='max-w-64 px-6 py-2 flex flex-col gap-2 justify-between border-l-2'
onSubmit={event => void handleSubmit(onSubmit)(event)} onSubmit={event => void handleSubmit(onSubmit)(event)}
onChange={resetErrors} onChange={resetErrors}
> >
@ -69,7 +69,7 @@ export function EditorPassword() {
/> />
{serverError ? <ServerError error={serverError} /> : null} {serverError ? <ServerError error={serverError} /> : null}
</div> </div>
<SubmitButton text='Сменить пароль' className='self-center mt-2' loading={isPending} /> <SubmitButton text='Сменить пароль' className='self-center' loading={isPending} />
</form> </form>
); );
} }