D: Improve TSDocs for frontend components
This commit is contained in:
parent
c7df031041
commit
4172e387c2
|
@ -50,6 +50,7 @@ This readme file is used mostly to document project dependencies and conventions
|
|||
- @uiw/react-codemirror
|
||||
- @uiw/codemirror-themes
|
||||
- @lezer/lr
|
||||
- @dagrejs/dagre
|
||||
</pre>
|
||||
</details>
|
||||
<details>
|
||||
|
|
|
@ -24,7 +24,7 @@ function UserMenu() {
|
|||
<AnimatePresence mode='wait'>
|
||||
{loading ? (
|
||||
<AnimateFade key='nav_user_badge_loader'>
|
||||
<Loader circular size={3} />
|
||||
<Loader circular scale={1.5} />
|
||||
</AnimateFade>
|
||||
) : null}
|
||||
{!user && !loading ? (
|
||||
|
|
|
@ -45,6 +45,7 @@ export interface DomIconProps<RequestData> extends IconProps {
|
|||
value: RequestData;
|
||||
}
|
||||
|
||||
/** Icon for library item type. */
|
||||
export function ItemTypeIcon({ value, size = '1.25rem', className }: DomIconProps<LibraryItemType>) {
|
||||
switch (value) {
|
||||
case LibraryItemType.RSFORM:
|
||||
|
@ -54,6 +55,7 @@ export function ItemTypeIcon({ value, size = '1.25rem', className }: DomIconProp
|
|||
}
|
||||
}
|
||||
|
||||
/** Icon for access policy. */
|
||||
export function PolicyIcon({ value, size = '1.25rem', className }: DomIconProps<AccessPolicy>) {
|
||||
switch (value) {
|
||||
case AccessPolicy.PRIVATE:
|
||||
|
@ -65,6 +67,7 @@ export function PolicyIcon({ value, size = '1.25rem', className }: DomIconProps<
|
|||
}
|
||||
}
|
||||
|
||||
/** Icon for visibility. */
|
||||
export function VisibilityIcon({ value, size = '1.25rem', className }: DomIconProps<boolean>) {
|
||||
if (value) {
|
||||
return <IconShow size={size} className={className ?? 'clr-text-green'} />;
|
||||
|
@ -73,6 +76,7 @@ export function VisibilityIcon({ value, size = '1.25rem', className }: DomIconPr
|
|||
}
|
||||
}
|
||||
|
||||
/** Icon for subfolders. */
|
||||
export function SubfoldersIcon({ value, size = '1.25rem', className }: DomIconProps<boolean>) {
|
||||
if (value) {
|
||||
return <IconSubfolders size={size} className={className ?? 'clr-text-green'} />;
|
||||
|
@ -81,6 +85,7 @@ export function SubfoldersIcon({ value, size = '1.25rem', className }: DomIconPr
|
|||
}
|
||||
}
|
||||
|
||||
/** Icon for location. */
|
||||
export function LocationIcon({ value, size = '1.25rem', className }: DomIconProps<string>) {
|
||||
switch (value.substring(0, 2) as LocationHead) {
|
||||
case LocationHead.COMMON:
|
||||
|
@ -94,6 +99,7 @@ export function LocationIcon({ value, size = '1.25rem', className }: DomIconProp
|
|||
}
|
||||
}
|
||||
|
||||
/** Icon for term graph dependency mode. */
|
||||
export function DependencyIcon({ value, size = '1.25rem', className }: DomIconProps<DependencyMode>) {
|
||||
switch (value) {
|
||||
case DependencyMode.ALL:
|
||||
|
@ -109,6 +115,7 @@ export function DependencyIcon({ value, size = '1.25rem', className }: DomIconPr
|
|||
}
|
||||
}
|
||||
|
||||
/** Icon for constituenta match mode. */
|
||||
export function MatchModeIcon({ value, size = '1.25rem', className }: DomIconProps<CstMatchMode>) {
|
||||
switch (value) {
|
||||
case CstMatchMode.ALL:
|
||||
|
@ -124,6 +131,7 @@ export function MatchModeIcon({ value, size = '1.25rem', className }: DomIconPro
|
|||
}
|
||||
}
|
||||
|
||||
/** Icon for expression status. */
|
||||
export function StatusIcon({ value, size = '1.25rem', className }: DomIconProps<ExpressionStatus>) {
|
||||
switch (value) {
|
||||
case ExpressionStatus.VERIFIED:
|
||||
|
@ -141,6 +149,7 @@ export function StatusIcon({ value, size = '1.25rem', className }: DomIconProps<
|
|||
}
|
||||
}
|
||||
|
||||
/** Icon for constituenta type. */
|
||||
export function CstTypeIcon({ value, size = '1.25rem', className }: DomIconProps<CstType>) {
|
||||
switch (value) {
|
||||
case CstType.BASE:
|
||||
|
@ -162,6 +171,7 @@ export function CstTypeIcon({ value, size = '1.25rem', className }: DomIconProps
|
|||
}
|
||||
}
|
||||
|
||||
/** Icon for relocation direction. */
|
||||
export function RelocateUpIcon({ value, size = '1.25rem', className }: DomIconProps<boolean>) {
|
||||
if (value) {
|
||||
return <IconMoveUp size={size} className={className ?? 'clr-text-primary'} />;
|
||||
|
|
|
@ -7,11 +7,19 @@ import { CProps } from '../props';
|
|||
import TooltipConstituenta from './TooltipConstituenta';
|
||||
|
||||
interface BadgeConstituentaProps extends CProps.Styling {
|
||||
/** Prefix for tooltip ID. */
|
||||
prefixID?: string;
|
||||
|
||||
/** Constituenta to display. */
|
||||
value: IConstituenta;
|
||||
|
||||
/** Color theme to use. */
|
||||
theme: IColorTheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a badge with a constituenta alias and information tooltip.
|
||||
*/
|
||||
function BadgeConstituenta({ value, prefixID, className, style, theme }: BadgeConstituentaProps) {
|
||||
return (
|
||||
<div
|
||||
|
|
|
@ -6,9 +6,13 @@ import { colorFgGrammeme } from '@/styling/color';
|
|||
import { labelGrammeme } from '@/utils/labels';
|
||||
|
||||
interface BadgeGrammemeProps {
|
||||
/** Grammeme to display. */
|
||||
grammeme: GramData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a badge with a grammeme tag.
|
||||
*/
|
||||
function BadgeGrammeme({ grammeme }: BadgeGrammemeProps) {
|
||||
const { colors } = useConceptOptions();
|
||||
return (
|
||||
|
|
|
@ -8,12 +8,22 @@ import { IconHelp } from '../Icons';
|
|||
import { CProps } from '../props';
|
||||
|
||||
interface BadgeHelpProps extends CProps.Styling {
|
||||
/** Topic to display in a tooltip. */
|
||||
topic: HelpTopic;
|
||||
|
||||
/** Offset from the cursor to the tooltip. */
|
||||
offset?: number;
|
||||
|
||||
/** Classname for padding. */
|
||||
padding?: string;
|
||||
|
||||
/** Place of the tooltip in relation to the cursor. */
|
||||
place?: PlacesType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display help icon with a manual page tooltip.
|
||||
*/
|
||||
function BadgeHelp({ topic, padding = 'p-1', ...restProps }: BadgeHelpProps) {
|
||||
const { showHelp } = useConceptOptions();
|
||||
|
||||
|
|
|
@ -3,9 +3,13 @@ import { globals } from '@/utils/constants';
|
|||
import { LocationIcon } from '../DomainIcons';
|
||||
|
||||
interface BadgeLocationProps {
|
||||
/** Location to display. */
|
||||
location: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays location icon with a full text tooltip.
|
||||
*/
|
||||
function BadgeLocation({ location }: BadgeLocationProps) {
|
||||
return (
|
||||
<div className='pl-2' data-tooltip-id={globals.tooltip} data-tooltip-content={location}>
|
||||
|
|
|
@ -3,10 +3,16 @@ import { IWordForm } from '@/models/language';
|
|||
import BadgeGrammeme from './BadgeGrammeme';
|
||||
|
||||
interface BadgeWordFormProps {
|
||||
keyPrefix?: string;
|
||||
/** Word form to display. */
|
||||
form: IWordForm;
|
||||
|
||||
/** Prefix for grammemes keys. */
|
||||
keyPrefix?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a badge with grammemes of a word form.
|
||||
*/
|
||||
function BadgeWordForm({ keyPrefix, form }: BadgeWordFormProps) {
|
||||
return (
|
||||
<div className='flex flex-wrap justify-start gap-1 select-none w-fit'>
|
||||
|
|
|
@ -98,8 +98,8 @@ function PickConstituenta({
|
|||
id={id ? `${id}__search` : undefined}
|
||||
className='clr-input rounded-t-md'
|
||||
noBorder
|
||||
value={filterText}
|
||||
onChange={newValue => setFilterText(newValue)}
|
||||
query={filterText}
|
||||
onChangeQuery={newValue => setFilterText(newValue)}
|
||||
/>
|
||||
<DataTable
|
||||
id={id}
|
||||
|
|
|
@ -132,8 +132,8 @@ function PickMultiConstituenta({
|
|||
id='dlg_constituents_search'
|
||||
noBorder
|
||||
className='min-w-[6rem] pr-2 flex-grow'
|
||||
value={filterText}
|
||||
onChange={setFilterText}
|
||||
query={filterText}
|
||||
onChangeQuery={setFilterText}
|
||||
/>
|
||||
<ToolbarGraphSelection
|
||||
graph={foldedGraph}
|
||||
|
|
|
@ -129,8 +129,8 @@ function PickSchema({
|
|||
id={id ? `${id}__search` : undefined}
|
||||
className='clr-input flex-grow rounded-t-md'
|
||||
noBorder
|
||||
value={filterText}
|
||||
onChange={newValue => setFilterText(newValue)}
|
||||
query={filterText}
|
||||
onChangeQuery={newValue => setFilterText(newValue)}
|
||||
/>
|
||||
<div ref={locationMenu.ref}>
|
||||
<MiniButton
|
||||
|
|
|
@ -25,45 +25,84 @@ import TableHeader from './TableHeader';
|
|||
|
||||
export { type ColumnSort, createColumnHelper, type RowSelectionState, type VisibilityState };
|
||||
|
||||
/** Style to conditionally apply to rows. */
|
||||
export interface IConditionalStyle<TData> {
|
||||
/** Callback to determine if the style should be applied. */
|
||||
when: (rowData: TData) => boolean;
|
||||
|
||||
/** Style to apply. */
|
||||
style: React.CSSProperties;
|
||||
}
|
||||
|
||||
export interface DataTableProps<TData extends RowData>
|
||||
extends CProps.Styling,
|
||||
Pick<TableOptions<TData>, 'data' | 'columns' | 'onRowSelectionChange' | 'onColumnVisibilityChange'> {
|
||||
/** Id of the component. */
|
||||
id?: string;
|
||||
|
||||
/** Indicates that padding should be minimal. */
|
||||
dense?: boolean;
|
||||
|
||||
/** Number of rows to display. */
|
||||
rows?: number;
|
||||
|
||||
/** Height of the content. */
|
||||
contentHeight?: string;
|
||||
|
||||
/** Top position of sticky header (0 if no other sticky elements are present). */
|
||||
headPosition?: string;
|
||||
|
||||
/** Disable header. */
|
||||
noHeader?: boolean;
|
||||
|
||||
/** Disable footer. */
|
||||
noFooter?: boolean;
|
||||
|
||||
/** List of styles to conditionally apply to rows. */
|
||||
conditionalRowStyles?: IConditionalStyle<TData>[];
|
||||
|
||||
/** Component to display when there is no data. */
|
||||
noDataComponent?: React.ReactNode;
|
||||
|
||||
/** Callback to be called when a row is clicked. */
|
||||
onRowClicked?: (rowData: TData, event: CProps.EventMouse) => void;
|
||||
|
||||
/** Callback to be called when a row is double clicked. */
|
||||
onRowDoubleClicked?: (rowData: TData, event: CProps.EventMouse) => void;
|
||||
|
||||
/** Enable row selection. */
|
||||
enableRowSelection?: boolean;
|
||||
|
||||
/** Current row selection. */
|
||||
rowSelection?: RowSelectionState;
|
||||
|
||||
/** Enable hiding of columns. */
|
||||
enableHiding?: boolean;
|
||||
|
||||
/** Current column visibility. */
|
||||
columnVisibility?: VisibilityState;
|
||||
|
||||
/** Enable pagination. */
|
||||
enablePagination?: boolean;
|
||||
|
||||
/** Number of rows per page. */
|
||||
paginationPerPage?: number;
|
||||
|
||||
/** List of options to choose from for pagination. */
|
||||
paginationOptions?: number[];
|
||||
|
||||
/** Callback to be called when the pagination option is changed. */
|
||||
onChangePaginationOption?: (newValue: number) => void;
|
||||
|
||||
/** Enable sorting. */
|
||||
enableSorting?: boolean;
|
||||
|
||||
/** Initial sorting. */
|
||||
initialSorting?: ColumnSort;
|
||||
}
|
||||
|
||||
/**
|
||||
* UI element: data representation as a table.
|
||||
* Dta representation as a table.
|
||||
*
|
||||
* @param headPosition - Top position of sticky header (0 if no other sticky elements are present).
|
||||
* No sticky header if omitted
|
||||
|
|
|
@ -7,18 +7,24 @@ import { useConceptOptions } from '@/context/ConceptOptionsContext';
|
|||
import AnimateFade from '../wrap/AnimateFade';
|
||||
|
||||
interface LoaderProps {
|
||||
size?: number;
|
||||
/** Scale of the loader from 1 to 10. */
|
||||
scale?: number;
|
||||
|
||||
/** Show a circular loader. */
|
||||
circular?: boolean;
|
||||
}
|
||||
|
||||
function Loader({ size = 10, circular }: LoaderProps) {
|
||||
/**
|
||||
* Displays animated loader.
|
||||
*/
|
||||
function Loader({ scale = 5, circular }: LoaderProps) {
|
||||
const { colors } = useConceptOptions();
|
||||
return (
|
||||
<AnimateFade noFadeIn className='flex justify-center'>
|
||||
{circular ? (
|
||||
<ThreeCircles color={colors.bgPrimary} height={size * 10} width={size * 10} />
|
||||
<ThreeCircles color={colors.bgPrimary} height={scale * 20} width={scale * 20} />
|
||||
) : (
|
||||
<ThreeDots color={colors.bgPrimary} height={size * 10} width={size * 10} radius={size} />
|
||||
<ThreeDots color={colors.bgPrimary} height={scale * 20} width={scale * 20} radius={scale * 2} />
|
||||
)}
|
||||
</AnimateFade>
|
||||
);
|
||||
|
|
|
@ -5,11 +5,19 @@ import { globals } from '@/utils/constants';
|
|||
import { CProps } from '../props';
|
||||
|
||||
interface MiniButtonProps extends CProps.Button {
|
||||
/** Icon to display in the button. */
|
||||
icon: React.ReactNode;
|
||||
|
||||
/** Disable hover effect. */
|
||||
noHover?: boolean;
|
||||
|
||||
/** Disable padding. */
|
||||
noPadding?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays small transparent button with an icon.
|
||||
*/
|
||||
function MiniButton({
|
||||
icon,
|
||||
noHover,
|
||||
|
|
|
@ -18,23 +18,46 @@ import MiniButton from './MiniButton';
|
|||
import Overlay from './Overlay';
|
||||
|
||||
export interface ModalProps extends CProps.Styling {
|
||||
/** Title of the modal window. */
|
||||
header?: string;
|
||||
|
||||
/** Text of the submit button. */
|
||||
submitText?: string;
|
||||
|
||||
/** Tooltip for the submit button when the form is invalid. */
|
||||
submitInvalidTooltip?: string;
|
||||
|
||||
/** Indicates that form is readonly. */
|
||||
readonly?: boolean;
|
||||
|
||||
/** Indicates that submit button is enabled. */
|
||||
canSubmit?: boolean;
|
||||
|
||||
/** Indicates that the modal window should be scrollable. */
|
||||
overflowVisible?: boolean;
|
||||
|
||||
/** Callback to be called when the modal window is closed. */
|
||||
hideWindow: () => void;
|
||||
|
||||
/** Callback to be called before submit. */
|
||||
beforeSubmit?: () => boolean;
|
||||
|
||||
/** Callback to be called after submit. */
|
||||
onSubmit?: () => void;
|
||||
|
||||
/** Callback to be called after cancel. */
|
||||
onCancel?: () => void;
|
||||
|
||||
/** Help topic to be displayed in the modal window. */
|
||||
helpTopic?: HelpTopic;
|
||||
|
||||
/** Callback to determine if help should be displayed. */
|
||||
hideHelpWhen?: () => boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a customizable modal window.
|
||||
*/
|
||||
function Modal({
|
||||
children,
|
||||
|
||||
|
|
|
@ -2,6 +2,9 @@ import clsx from 'clsx';
|
|||
|
||||
import { CProps } from '../props';
|
||||
|
||||
/**
|
||||
* Wraps content in a div with a centered text.
|
||||
*/
|
||||
function NoData({ className, children, ...restProps }: CProps.Div) {
|
||||
return (
|
||||
<div className={clsx('p-3 flex flex-col items-center text-center select-none w-full', className)} {...restProps}>
|
||||
|
|
|
@ -3,11 +3,19 @@ import clsx from 'clsx';
|
|||
import { CProps } from '../props';
|
||||
|
||||
interface OverlayProps extends CProps.Styling {
|
||||
/** Id of the overlay. */
|
||||
id?: string;
|
||||
|
||||
/** Classnames for position of the overlay. */
|
||||
position?: string;
|
||||
|
||||
/** Classname for z-index of the overlay. */
|
||||
layer?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a transparent overlay over the main content.
|
||||
*/
|
||||
function Overlay({
|
||||
children,
|
||||
className,
|
||||
|
|
|
@ -5,15 +5,26 @@ import { useMemo } from 'react';
|
|||
import { useConceptOptions } from '@/context/ConceptOptionsContext';
|
||||
import useWindowSize from '@/hooks/useWindowSize';
|
||||
|
||||
/** Maximum width of the viewer. */
|
||||
const MAXIMUM_WIDTH = 1600;
|
||||
|
||||
/** Minimum width of the viewer. */
|
||||
const MINIMUM_WIDTH = 300;
|
||||
|
||||
interface PDFViewerProps {
|
||||
/** PDF file to display. */
|
||||
file?: string;
|
||||
|
||||
/** Offset from the left side of the window. */
|
||||
offsetXpx?: number;
|
||||
|
||||
/** Minimum width of the viewer. */
|
||||
minWidth?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a PDF file using an embedded viewer.
|
||||
*/
|
||||
function PDFViewer({ file, offsetXpx, minWidth = MINIMUM_WIDTH }: PDFViewerProps) {
|
||||
const windowSize = useWindowSize();
|
||||
const { calculateHeight } = useConceptOptions();
|
||||
|
|
|
@ -2,6 +2,9 @@ interface PrettyJsonProps {
|
|||
data: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays JSON data in a formatted string.
|
||||
*/
|
||||
function PrettyJson({ data }: PrettyJsonProps) {
|
||||
return <pre>{JSON.stringify(data, null, 2)}</pre>;
|
||||
}
|
||||
|
|
|
@ -6,15 +6,37 @@ import Overlay from './Overlay';
|
|||
import TextInput from './TextInput';
|
||||
|
||||
interface SearchBarProps extends CProps.Styling {
|
||||
value: string;
|
||||
noIcon?: boolean;
|
||||
/** Id of the search bar. */
|
||||
id?: string;
|
||||
|
||||
/** Search query. */
|
||||
query: string;
|
||||
|
||||
/** Placeholder text. */
|
||||
placeholder?: string;
|
||||
onChange?: (newValue: string) => void;
|
||||
|
||||
/** Callback to be called when the search query changes. */
|
||||
onChangeQuery?: (newValue: string) => void;
|
||||
|
||||
/** Disable search icon. */
|
||||
noIcon?: boolean;
|
||||
|
||||
/** Disable border. */
|
||||
noBorder?: boolean;
|
||||
}
|
||||
|
||||
function SearchBar({ id, value, noIcon, onChange, noBorder, placeholder = 'Поиск', ...restProps }: SearchBarProps) {
|
||||
/**
|
||||
* Displays a search bar with a search icon and text input.
|
||||
*/
|
||||
function SearchBar({
|
||||
id,
|
||||
query,
|
||||
noIcon,
|
||||
onChangeQuery,
|
||||
noBorder,
|
||||
placeholder = 'Поиск',
|
||||
...restProps
|
||||
}: SearchBarProps) {
|
||||
return (
|
||||
<div {...restProps}>
|
||||
{!noIcon ? (
|
||||
|
@ -29,8 +51,8 @@ function SearchBar({ id, value, noIcon, onChange, noBorder, placeholder = 'По
|
|||
type='search'
|
||||
className={clsx('outline-none bg-transparent', !noIcon && 'pl-10')}
|
||||
noBorder={noBorder}
|
||||
value={value}
|
||||
onChange={event => (onChange ? onChange(event.target.value) : undefined)}
|
||||
value={query}
|
||||
onChange={event => (onChangeQuery ? onChangeQuery(event.target.value) : undefined)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -45,6 +45,9 @@ export interface SelectMultiProps<Option, Group extends GroupBase<Option> = Grou
|
|||
noPortal?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a multi-select component.
|
||||
*/
|
||||
function SelectMulti<Option, Group extends GroupBase<Option> = GroupBase<Option>>({
|
||||
noPortal,
|
||||
...restProps
|
||||
|
|
|
@ -46,6 +46,9 @@ export interface SelectSingleProps<Option, Group extends GroupBase<Option> = Gro
|
|||
noBorder?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a single-select component.
|
||||
*/
|
||||
function SelectSingle<Option, Group extends GroupBase<Option> = GroupBase<Option>>({
|
||||
noPortal,
|
||||
noBorder,
|
||||
|
|
|
@ -11,22 +11,38 @@ import MiniButton from './MiniButton';
|
|||
import Overlay from './Overlay';
|
||||
|
||||
interface SelectTreeProps<ItemType> extends CProps.Styling {
|
||||
items: ItemType[];
|
||||
/** Current value. */
|
||||
value: ItemType;
|
||||
setValue: (newItem: ItemType) => void;
|
||||
getParent: (item: ItemType) => ItemType;
|
||||
getLabel: (item: ItemType) => string;
|
||||
getDescription: (item: ItemType) => string;
|
||||
|
||||
/** List of available items. */
|
||||
items: ItemType[];
|
||||
|
||||
/** Prefix for the ids of the elements. */
|
||||
prefix: string;
|
||||
|
||||
/** Callback to be called when the value changes. */
|
||||
onChangeValue: (newItem: ItemType) => void;
|
||||
|
||||
/** Callback providing the parent of the item. */
|
||||
getParent: (item: ItemType) => ItemType;
|
||||
|
||||
/** Callback providing the label of the item. */
|
||||
getLabel: (item: ItemType) => string;
|
||||
|
||||
/** Callback providing the description of the item. */
|
||||
getDescription: (item: ItemType) => string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a tree of items and allows user to select one.
|
||||
*/
|
||||
function SelectTree<ItemType>({
|
||||
items,
|
||||
value,
|
||||
getParent,
|
||||
getLabel,
|
||||
getDescription,
|
||||
setValue,
|
||||
onChangeValue,
|
||||
prefix,
|
||||
...restProps
|
||||
}: SelectTreeProps<ItemType>) {
|
||||
|
@ -71,9 +87,9 @@ function SelectTree<ItemType>({
|
|||
(event: CProps.EventMouse, target: ItemType) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
setValue(target);
|
||||
onChangeValue(target);
|
||||
},
|
||||
[setValue]
|
||||
[onChangeValue]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -5,13 +5,22 @@ import { globals } from '@/utils/constants';
|
|||
import { CProps } from '../props';
|
||||
|
||||
interface SelectorButtonProps extends CProps.Button {
|
||||
/** Text to display in the button. */
|
||||
text?: string;
|
||||
|
||||
/** Icon to display in the button. */
|
||||
icon?: React.ReactNode;
|
||||
|
||||
/** Classnames for the colors of the button. */
|
||||
colors?: string;
|
||||
|
||||
/** Indicates if button background should be transparent. */
|
||||
transparent?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a button with an icon and text that opens a dropdown menu.
|
||||
*/
|
||||
function SelectorButton({
|
||||
text,
|
||||
icon,
|
||||
|
|
|
@ -3,11 +3,19 @@ import clsx from 'clsx';
|
|||
import { CProps } from '../props';
|
||||
|
||||
interface SubmitButtonProps extends CProps.Button {
|
||||
/** Text to display in the button. */
|
||||
text?: string;
|
||||
loading?: boolean;
|
||||
|
||||
/** Icon to display in the button. */
|
||||
icon?: React.ReactNode;
|
||||
|
||||
/** Indicates that loading is in progress. */
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays submit type button with icon and text.
|
||||
*/
|
||||
function SubmitButton({ text = 'ОК', icon, disabled, loading, className, ...restProps }: SubmitButtonProps) {
|
||||
return (
|
||||
<button
|
||||
|
|
|
@ -7,9 +7,13 @@ import { globals } from '@/utils/constants';
|
|||
import { CProps } from '../props';
|
||||
|
||||
interface TabLabelProps extends Omit<TabPropsImpl, 'children'>, CProps.Titled {
|
||||
/** Label to display in the tab. */
|
||||
label?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a tab header with a label.
|
||||
*/
|
||||
function TabLabel({ label, title, titleHtml, hideTitle, className, ...otherProps }: TabLabelProps) {
|
||||
return (
|
||||
<TabImpl
|
||||
|
|
|
@ -4,11 +4,19 @@ import { CProps } from '../props';
|
|||
import Label from './Label';
|
||||
|
||||
export interface TextAreaProps extends CProps.Editor, CProps.Colors, CProps.TextArea {
|
||||
/** Indicates that padding should be minimal. */
|
||||
dense?: boolean;
|
||||
|
||||
/** Disable resize when content overflows. */
|
||||
noResize?: boolean;
|
||||
|
||||
/** Disable resize to fit content. */
|
||||
fitContent?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a customizable textarea with a label.
|
||||
*/
|
||||
function TextArea({
|
||||
id,
|
||||
label,
|
||||
|
|
|
@ -6,11 +6,19 @@ import { truncateToLastWord } from '@/utils/utils';
|
|||
import { CProps } from '../props';
|
||||
|
||||
export interface TextContentProps extends CProps.Styling {
|
||||
/** Text to display. */
|
||||
text: string;
|
||||
|
||||
/** Maximum number of symbols to display. */
|
||||
maxLength?: number;
|
||||
|
||||
/** Disable full text in a tooltip. */
|
||||
noTooltip?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays text limited to a certain number of symbols.
|
||||
*/
|
||||
function TextContent({ className, text, maxLength, noTooltip, ...restProps }: TextContentProps) {
|
||||
const truncated = maxLength ? truncateToLastWord(text, maxLength) : text;
|
||||
const isTruncated = maxLength && text.length > maxLength;
|
||||
|
|
|
@ -4,7 +4,10 @@ import { CProps } from '../props';
|
|||
import Label from './Label';
|
||||
|
||||
interface TextInputProps extends CProps.Editor, CProps.Colors, CProps.Input {
|
||||
/** Indicates that padding should be minimal. */
|
||||
dense?: boolean;
|
||||
|
||||
/** Capture enter key. */
|
||||
allowEnter?: boolean;
|
||||
}
|
||||
|
||||
|
@ -14,6 +17,9 @@ function preventEnterCapture(event: React.KeyboardEvent<HTMLInputElement>) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a customizable input with a label.
|
||||
*/
|
||||
function TextInput({
|
||||
id,
|
||||
label,
|
||||
|
|
|
@ -1,13 +1,25 @@
|
|||
import { Link } from 'react-router-dom';
|
||||
|
||||
interface TextURLProps {
|
||||
/** Text to display. */
|
||||
text: string;
|
||||
|
||||
/** Tooltip for the link. */
|
||||
title?: string;
|
||||
|
||||
/** URL to link to. */
|
||||
href?: string;
|
||||
|
||||
/** Color of the link. */
|
||||
color?: string;
|
||||
|
||||
/** Callback to be called when the link is clicked. */
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a text with a clickable link.
|
||||
*/
|
||||
function TextURL({ text, href, title, color = 'clr-text-url', onClick }: TextURLProps) {
|
||||
const design = `cursor-pointer hover:underline ${color}`;
|
||||
if (href) {
|
||||
|
|
|
@ -10,10 +10,16 @@ import { useConceptOptions } from '@/context/ConceptOptionsContext';
|
|||
export type { PlacesType } from 'react-tooltip';
|
||||
|
||||
interface TooltipProps extends Omit<ITooltip, 'variant'> {
|
||||
layer?: string;
|
||||
/** Text to display in the tooltip. */
|
||||
text?: string;
|
||||
|
||||
/** Classname for z-index */
|
||||
layer?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays content in a tooltip container.
|
||||
*/
|
||||
function Tooltip({
|
||||
text,
|
||||
children,
|
||||
|
|
|
@ -7,16 +7,34 @@ import { CProps } from '../props';
|
|||
import MiniButton from './MiniButton';
|
||||
|
||||
interface ValueIconProps extends CProps.Styling, CProps.Titled {
|
||||
/** Id of the component. */
|
||||
id?: string;
|
||||
icon: React.ReactNode;
|
||||
|
||||
/** Value to display. */
|
||||
value: string | number;
|
||||
|
||||
/** Icon to display. */
|
||||
icon: React.ReactNode;
|
||||
|
||||
/** Classname for the text. */
|
||||
textClassName?: string;
|
||||
|
||||
/** Callback to be called when the component is clicked. */
|
||||
onClick?: (event: CProps.EventMouse) => void;
|
||||
|
||||
/** Number of symbols to display in a small size. */
|
||||
smallThreshold?: number;
|
||||
|
||||
/** Indicates that padding should be minimal. */
|
||||
dense?: boolean;
|
||||
|
||||
/** Disable interaction. */
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a value with an icon that can be clicked.
|
||||
*/
|
||||
function ValueIcon({
|
||||
id,
|
||||
dense,
|
||||
|
|
|
@ -3,12 +3,22 @@ import clsx from 'clsx';
|
|||
import { CProps } from '../props';
|
||||
|
||||
interface ValueLabeledProps extends CProps.Styling {
|
||||
/** Id of the component. */
|
||||
id?: string;
|
||||
|
||||
/** Label to display. */
|
||||
label: string;
|
||||
|
||||
/** Value to display. */
|
||||
text: string | number;
|
||||
|
||||
/** Tooltip for the component. */
|
||||
title?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a labeled value.
|
||||
*/
|
||||
function ValueLabeled({ id, label, text, title, className, ...restProps }: ValueLabeledProps) {
|
||||
return (
|
||||
<div className={clsx('flex justify-between gap-6', className)} {...restProps}>
|
||||
|
|
|
@ -4,11 +4,19 @@ import { CProps } from '../props';
|
|||
import ValueIcon from './ValueIcon';
|
||||
|
||||
interface ValueStatsProps extends CProps.Styling, CProps.Titled {
|
||||
/** Id of the component. */
|
||||
id: string;
|
||||
|
||||
/** Icon to display. */
|
||||
icon: React.ReactNode;
|
||||
|
||||
/** Value to display. */
|
||||
value: string | number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays statistics value with an icon.
|
||||
*/
|
||||
function ValueStats(props: ValueStatsProps) {
|
||||
return <ValueIcon dense smallThreshold={PARAMETER.statSmallThreshold} textClassName='min-w-[1.4rem]' {...props} />;
|
||||
}
|
||||
|
|
|
@ -190,8 +190,8 @@ function ToolbarSearch({
|
|||
placeholder='Поиск'
|
||||
noBorder
|
||||
className={clsx('min-w-[7rem] sm:min-w-[10rem] max-w-[20rem]', folderMode && 'flex-grow')}
|
||||
value={query}
|
||||
onChange={onChangeQuery}
|
||||
query={query}
|
||||
onChangeQuery={onChangeQuery}
|
||||
/>
|
||||
{!folderMode ? (
|
||||
<div ref={headMenu.ref} className='flex items-center h-full py-1 select-none'>
|
||||
|
@ -249,8 +249,8 @@ function ToolbarSearch({
|
|||
noIcon
|
||||
noBorder
|
||||
className='w-[4.5rem] sm:w-[5rem] flex-grow'
|
||||
value={path}
|
||||
onChange={onChangePath}
|
||||
query={path}
|
||||
onChangeQuery={onChangePath}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
|
@ -69,7 +69,7 @@ function TopicsDropdown({ activeTopic, onChangeTopic }: TopicsDropdownProps) {
|
|||
<SelectTree
|
||||
items={Object.values(HelpTopic).map(item => item as HelpTopic)}
|
||||
value={activeTopic}
|
||||
setValue={handleSelectTopic}
|
||||
onChangeValue={handleSelectTopic}
|
||||
prefix={prefixes.topic_list}
|
||||
getParent={item => topicParent.get(item) ?? item}
|
||||
getLabel={labelHelpTopic}
|
||||
|
|
|
@ -17,7 +17,7 @@ function TopicsStatic({ activeTopic, onChangeTopic }: TopicsStaticProps) {
|
|||
<SelectTree
|
||||
items={Object.values(HelpTopic).map(item => item as HelpTopic)}
|
||||
value={activeTopic}
|
||||
setValue={onChangeTopic}
|
||||
onChangeValue={onChangeTopic}
|
||||
prefix={prefixes.topic_list}
|
||||
getParent={item => topicParent.get(item) ?? item}
|
||||
getLabel={labelHelpTopic}
|
||||
|
|
|
@ -54,7 +54,7 @@ function StatusBar({ isModified, processing, activeCst, parseData, onAnalyze }:
|
|||
onClick={onAnalyze}
|
||||
>
|
||||
<AnimatePresence mode='wait'>
|
||||
{processing ? <Loader key='status-loader' size={3} /> : null}
|
||||
{processing ? <Loader key='status-loader' scale={3} /> : null}
|
||||
{!processing ? (
|
||||
<>
|
||||
<StatusIcon key='status-icon' size='1rem' value={status} />
|
||||
|
|
|
@ -152,8 +152,8 @@ function EditorRSList({ onOpenEdit }: EditorRSListProps) {
|
|||
id='constituents_search'
|
||||
noBorder
|
||||
className='w-[8rem]'
|
||||
value={filterText}
|
||||
onChange={setFilterText}
|
||||
query={filterText}
|
||||
onChangeQuery={setFilterText}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
|
|
|
@ -74,8 +74,8 @@ function ConstituentsSearch({ schema, activeID, activeExpression, dense, setFilt
|
|||
id='constituents_search'
|
||||
noBorder
|
||||
className='min-w-[6rem] pr-2 flex-grow'
|
||||
value={filterText}
|
||||
onChange={setFilterText}
|
||||
query={filterText}
|
||||
onChangeQuery={setFilterText}
|
||||
/>
|
||||
{selectMatchMode}
|
||||
{selectGraph}
|
||||
|
|
Loading…
Reference in New Issue
Block a user