mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-25 20:40:36 +03:00
F: Improve color and animation styling
This commit is contained in:
parent
3b26457b83
commit
f0715df343
2
.vscode/extensions.json
vendored
2
.vscode/extensions.json
vendored
|
@ -6,11 +6,11 @@
|
||||||
"fractalbrew.backticks",
|
"fractalbrew.backticks",
|
||||||
"streetsidesoftware.code-spell-checker",
|
"streetsidesoftware.code-spell-checker",
|
||||||
"streetsidesoftware.code-spell-checker-russian",
|
"streetsidesoftware.code-spell-checker-russian",
|
||||||
"kamikillerto.vscode-colorize",
|
|
||||||
"batisteo.vscode-django",
|
"batisteo.vscode-django",
|
||||||
"ms-azuretools.vscode-docker",
|
"ms-azuretools.vscode-docker",
|
||||||
"dbaeumer.vscode-eslint",
|
"dbaeumer.vscode-eslint",
|
||||||
"seyyedkhandon.firacode",
|
"seyyedkhandon.firacode",
|
||||||
|
"nize.oklch-preview",
|
||||||
"ms-python.isort",
|
"ms-python.isort",
|
||||||
"ms-vscode.powershell",
|
"ms-vscode.powershell",
|
||||||
"esbenp.prettier-vscode",
|
"esbenp.prettier-vscode",
|
||||||
|
|
|
@ -85,7 +85,7 @@ This readme file is used mostly to document project dependencies and conventions
|
||||||
<summary>VS Code plugins</summary>
|
<summary>VS Code plugins</summary>
|
||||||
<pre>
|
<pre>
|
||||||
- ESLint
|
- ESLint
|
||||||
- Colorize
|
- Oklch Color Preview
|
||||||
- Tailwind CSS IntelliSense
|
- Tailwind CSS IntelliSense
|
||||||
- Code Spell Checker (eng + rus)
|
- Code Spell Checker (eng + rus)
|
||||||
- Backticks
|
- Backticks
|
||||||
|
|
|
@ -34,7 +34,7 @@ export function Navigation() {
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'pl-2 sm:pr-4 h-12 flex cc-shadow-border',
|
'pl-2 sm:pr-4 h-12 flex cc-shadow-border',
|
||||||
'transition-[max-height,translate] ease-bezier duration-(--duration-move)',
|
'transition-[max-height,translate] ease-bezier duration-move',
|
||||||
noNavigationAnimation ? '-translate-y-6 max-h-0' : 'max-h-12'
|
noNavigationAnimation ? '-translate-y-6 max-h-0' : 'max-h-12'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -19,19 +19,10 @@ import { PaginationTools } from './pagination-tools';
|
||||||
import { TableBody } from './table-body';
|
import { TableBody } from './table-body';
|
||||||
import { TableFooter } from './table-footer';
|
import { TableFooter } from './table-footer';
|
||||||
import { TableHeader } from './table-header';
|
import { TableHeader } from './table-header';
|
||||||
import { useDataTable } from './use-data-table';
|
import { type IConditionalStyle, useDataTable } from './use-data-table';
|
||||||
|
|
||||||
export { createColumnHelper, type RowSelectionState, type VisibilityState };
|
export { 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>
|
export interface DataTableProps<TData extends RowData>
|
||||||
extends Styling,
|
extends Styling,
|
||||||
Pick<TableOptions<TData>, 'data' | 'columns' | 'onRowSelectionChange' | 'onColumnVisibilityChange'> {
|
Pick<TableOptions<TData>, 'data' | 'columns' | 'onRowSelectionChange' | 'onColumnVisibilityChange'> {
|
||||||
|
|
|
@ -1,7 +1,2 @@
|
||||||
export {
|
export { createColumnHelper, DataTable, type RowSelectionState, type VisibilityState } from './data-table';
|
||||||
createColumnHelper,
|
export { type IConditionalStyle } from './use-data-table';
|
||||||
DataTable,
|
|
||||||
type IConditionalStyle,
|
|
||||||
type RowSelectionState,
|
|
||||||
type VisibilityState
|
|
||||||
} from './data-table';
|
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
'use no memo';
|
'use no memo';
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useCallback } from 'react';
|
|
||||||
import { type Table } from '@tanstack/react-table';
|
import { type Table } from '@tanstack/react-table';
|
||||||
|
|
||||||
import { prefixes } from '@/utils/constants';
|
|
||||||
|
|
||||||
import { IconPageFirst, IconPageLast, IconPageLeft, IconPageRight } from '../icons';
|
import { IconPageFirst, IconPageLast, IconPageLeft, IconPageRight } from '../icons';
|
||||||
|
|
||||||
|
import { SelectPagination } from './select-pagination';
|
||||||
|
|
||||||
interface PaginationToolsProps<TData> {
|
interface PaginationToolsProps<TData> {
|
||||||
id?: string;
|
id?: string;
|
||||||
table: Table<TData>;
|
table: Table<TData>;
|
||||||
|
@ -21,15 +20,6 @@ export function PaginationTools<TData>({
|
||||||
onChangePaginationOption,
|
onChangePaginationOption,
|
||||||
paginationOptions
|
paginationOptions
|
||||||
}: PaginationToolsProps<TData>) {
|
}: PaginationToolsProps<TData>) {
|
||||||
const handlePaginationOptionsChange = useCallback(
|
|
||||||
(event: React.ChangeEvent<HTMLSelectElement>) => {
|
|
||||||
const perPage = Number(event.target.value);
|
|
||||||
table.setPageSize(perPage);
|
|
||||||
onChangePaginationOption?.(perPage);
|
|
||||||
},
|
|
||||||
[table, onChangePaginationOption]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex justify-end items-center my-2 text-sm cc-controls select-none'>
|
<div className='flex justify-end items-center my-2 text-sm cc-controls select-none'>
|
||||||
<span className='mr-3'>
|
<span className='mr-3'>
|
||||||
|
@ -93,19 +83,12 @@ export function PaginationTools<TData>({
|
||||||
<IconPageLast size='1.5rem' />
|
<IconPageLast size='1.5rem' />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<select
|
<SelectPagination
|
||||||
id={id ? `${id}__per_page` : undefined}
|
id={id ? `${id}__per_page` : undefined}
|
||||||
aria-label='Выбор количества строчек на странице'
|
table={table}
|
||||||
value={table.getState().pagination.pageSize}
|
paginationOptions={paginationOptions}
|
||||||
onChange={handlePaginationOptionsChange}
|
onChange={onChangePaginationOption}
|
||||||
className='mx-2 cursor-pointer bg-transparent focus-outline'
|
/>
|
||||||
>
|
|
||||||
{paginationOptions.map(pageSize => (
|
|
||||||
<option key={`${prefixes.page_size}${pageSize}`} value={pageSize} aria-label={`${pageSize} на страницу`}>
|
|
||||||
{pageSize} на стр
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
'use no memo';
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
import { type Table } from '@tanstack/react-table';
|
||||||
|
|
||||||
|
import { prefixes } from '@/utils/constants';
|
||||||
|
|
||||||
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../input/select';
|
||||||
|
|
||||||
|
interface SelectPaginationProps<TData> {
|
||||||
|
id?: string;
|
||||||
|
table: Table<TData>;
|
||||||
|
paginationOptions: number[];
|
||||||
|
onChange?: (newValue: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SelectPagination<TData>({ id, table, paginationOptions, onChange }: SelectPaginationProps<TData>) {
|
||||||
|
const handlePaginationOptionsChange = useCallback(
|
||||||
|
(newValue: string) => {
|
||||||
|
const perPage = Number(newValue);
|
||||||
|
table.setPageSize(perPage);
|
||||||
|
onChange?.(perPage);
|
||||||
|
},
|
||||||
|
[table, onChange]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select onValueChange={handlePaginationOptionsChange} defaultValue={String(table.getState().pagination.pageSize)}>
|
||||||
|
<SelectTrigger
|
||||||
|
id={id}
|
||||||
|
aria-label='Выбор количества строчек на странице'
|
||||||
|
className='mx-2 cursor-pointer bg-transparent focus-outline border-0 w-28 max-h-6 px-2 justify-end'
|
||||||
|
>
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{paginationOptions?.map(option => (
|
||||||
|
<SelectItem key={`${prefixes.page_size}${option}`} value={String(option)}>
|
||||||
|
{option} на стр
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
'use no memo';
|
'use no memo';
|
||||||
|
'use client';
|
||||||
|
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { type Cell, flexRender, type Row, type Table } from '@tanstack/react-table';
|
import { type Row, type Table } from '@tanstack/react-table';
|
||||||
import clsx from 'clsx';
|
|
||||||
|
|
||||||
import { SelectRow } from './select-row';
|
import { TableRow } from './table-row';
|
||||||
import { type IConditionalStyle } from '.';
|
import { type IConditionalStyle } from './use-data-table';
|
||||||
|
|
||||||
interface TableBodyProps<TData> {
|
interface TableBodyProps<TData> {
|
||||||
table: Table<TData>;
|
table: Table<TData>;
|
||||||
|
@ -30,82 +30,43 @@ export function TableBody<TData>({
|
||||||
onRowClicked,
|
onRowClicked,
|
||||||
onRowDoubleClicked
|
onRowDoubleClicked
|
||||||
}: TableBodyProps<TData>) {
|
}: TableBodyProps<TData>) {
|
||||||
const handleRowClicked = useCallback(
|
const getRowStyles = useCallback(
|
||||||
(target: Row<TData>, event: React.MouseEvent<Element>) => {
|
(row: Row<TData>) =>
|
||||||
onRowClicked?.(target.original, event);
|
conditionalRowStyles
|
||||||
if (table.options.enableRowSelection && target.getCanSelect()) {
|
?.filter(item => !!item.style && item.when(row.original))
|
||||||
if (event.shiftKey && !!lastSelected && lastSelected !== target.id) {
|
?.reduce((prev, item) => ({ ...prev, ...item.style }), {}),
|
||||||
const { rows, rowsById } = table.getRowModel();
|
|
||||||
const lastIndex = rowsById[lastSelected].index;
|
[conditionalRowStyles]
|
||||||
const currentIndex = target.index;
|
|
||||||
const toggleRows = rows.slice(
|
|
||||||
lastIndex > currentIndex ? currentIndex : lastIndex + 1,
|
|
||||||
lastIndex > currentIndex ? lastIndex : currentIndex + 1
|
|
||||||
);
|
|
||||||
const newSelection: Record<string, boolean> = {};
|
|
||||||
toggleRows.forEach(row => {
|
|
||||||
newSelection[row.id] = !target.getIsSelected();
|
|
||||||
});
|
|
||||||
table.setRowSelection(prev => ({ ...prev, ...newSelection }));
|
|
||||||
onChangeLastSelected(null);
|
|
||||||
} else {
|
|
||||||
onChangeLastSelected(target.id);
|
|
||||||
target.toggleSelected(!target.getIsSelected());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[table, lastSelected, onChangeLastSelected, onRowClicked]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const getRowStyles = useCallback(
|
const getRowClasses = useCallback(
|
||||||
(row: Row<TData>) => {
|
(row: Row<TData>) => {
|
||||||
return {
|
return conditionalRowStyles
|
||||||
...conditionalRowStyles!
|
?.filter(item => !!item.className && item.when(row.original))
|
||||||
.filter(item => item.when(row.original))
|
?.reduce((prev, item) => {
|
||||||
.reduce((prev, item) => ({ ...prev, ...item.style }), {})
|
prev.push(item.className!);
|
||||||
};
|
return prev;
|
||||||
|
}, [] as string[]);
|
||||||
},
|
},
|
||||||
[conditionalRowStyles]
|
[conditionalRowStyles]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tbody>
|
<tbody>
|
||||||
{table.getRowModel().rows.map((row: Row<TData>, index) => (
|
{table.getRowModel().rows.map((row: Row<TData>) => (
|
||||||
<tr
|
<TableRow
|
||||||
key={row.id}
|
key={row.id}
|
||||||
className={clsx(
|
table={table}
|
||||||
'cc-scroll-row',
|
row={row}
|
||||||
'cc-hover cc-animate-background duration-(--duration-fade)',
|
className={getRowClasses(row)?.join(' ')}
|
||||||
!noHeader && 'scroll-mt-[calc(2px+2rem)]',
|
style={conditionalRowStyles ? { ...getRowStyles(row) } : undefined}
|
||||||
table.options.enableRowSelection && row.getIsSelected()
|
noHeader={noHeader}
|
||||||
? 'cc-selected'
|
dense={dense}
|
||||||
: 'odd:bg-secondary even:bg-background'
|
lastSelected={lastSelected}
|
||||||
)}
|
onChangeLastSelected={onChangeLastSelected}
|
||||||
style={{ ...(conditionalRowStyles ? getRowStyles(row) : []) }}
|
onRowClicked={onRowClicked}
|
||||||
onClick={event => handleRowClicked(row, event)}
|
onRowDoubleClicked={onRowDoubleClicked}
|
||||||
onDoubleClick={event => onRowDoubleClicked?.(row.original, event)}
|
/>
|
||||||
>
|
|
||||||
{table.options.enableRowSelection ? (
|
|
||||||
<td key={`select-${row.id}`} className='pl-2 border-y'>
|
|
||||||
<SelectRow row={row} onChangeLastSelected={onChangeLastSelected} />
|
|
||||||
</td>
|
|
||||||
) : null}
|
|
||||||
{row.getVisibleCells().map((cell: Cell<TData, unknown>) => (
|
|
||||||
<td
|
|
||||||
key={cell.id}
|
|
||||||
className={clsx(
|
|
||||||
'px-2 align-middle border-y',
|
|
||||||
dense ? 'py-1' : 'py-2',
|
|
||||||
onRowClicked || onRowDoubleClicked ? 'cursor-pointer' : 'cursor-auto'
|
|
||||||
)}
|
|
||||||
style={{
|
|
||||||
width: noHeader && index === 0 ? `calc(var(--col-${cell.column.id}-size) * 1px)` : undefined
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
||||||
</td>
|
|
||||||
))}
|
|
||||||
</tr>
|
|
||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
'use no memo';
|
'use no memo';
|
||||||
|
'use client';
|
||||||
|
|
||||||
import { flexRender, type Header, type HeaderGroup, type Table } from '@tanstack/react-table';
|
import { flexRender, type Header, type HeaderGroup, type Table } from '@tanstack/react-table';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
108
rsconcept/frontend/src/components/data-table/table-row.tsx
Normal file
108
rsconcept/frontend/src/components/data-table/table-row.tsx
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
'use no memo';
|
||||||
|
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
import { type Cell, flexRender, type Row, type Table } from '@tanstack/react-table';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
|
||||||
|
import { cn } from '../utils';
|
||||||
|
|
||||||
|
import { SelectRow } from './select-row';
|
||||||
|
|
||||||
|
interface TableRowProps<TData> {
|
||||||
|
table: Table<TData>;
|
||||||
|
row: Row<TData>;
|
||||||
|
|
||||||
|
className?: string;
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
|
||||||
|
noHeader?: boolean;
|
||||||
|
dense?: boolean;
|
||||||
|
|
||||||
|
lastSelected: string | null;
|
||||||
|
onChangeLastSelected: (newValue: string | null) => void;
|
||||||
|
|
||||||
|
onRowClicked?: (rowData: TData, event: React.MouseEvent<Element>) => void;
|
||||||
|
onRowDoubleClicked?: (rowData: TData, event: React.MouseEvent<Element>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TableRow<TData>({
|
||||||
|
table,
|
||||||
|
row,
|
||||||
|
className,
|
||||||
|
style,
|
||||||
|
noHeader,
|
||||||
|
dense,
|
||||||
|
lastSelected,
|
||||||
|
onChangeLastSelected,
|
||||||
|
onRowClicked,
|
||||||
|
onRowDoubleClicked
|
||||||
|
}: TableRowProps<TData>) {
|
||||||
|
const hasBG = className?.includes('bg-') ?? false;
|
||||||
|
|
||||||
|
const handleRowClicked = useCallback(
|
||||||
|
(target: Row<TData>, event: React.MouseEvent<Element>) => {
|
||||||
|
onRowClicked?.(target.original, event);
|
||||||
|
if (table.options.enableRowSelection && target.getCanSelect()) {
|
||||||
|
if (event.shiftKey && !!lastSelected && lastSelected !== target.id) {
|
||||||
|
const { rows, rowsById } = table.getRowModel();
|
||||||
|
const lastIndex = rowsById[lastSelected].index;
|
||||||
|
const currentIndex = target.index;
|
||||||
|
const toggleRows = rows.slice(
|
||||||
|
lastIndex > currentIndex ? currentIndex : lastIndex + 1,
|
||||||
|
lastIndex > currentIndex ? lastIndex : currentIndex + 1
|
||||||
|
);
|
||||||
|
const newSelection: Record<string, boolean> = {};
|
||||||
|
toggleRows.forEach(row => {
|
||||||
|
newSelection[row.id] = !target.getIsSelected();
|
||||||
|
});
|
||||||
|
table.setRowSelection(prev => ({ ...prev, ...newSelection }));
|
||||||
|
onChangeLastSelected(null);
|
||||||
|
} else {
|
||||||
|
onChangeLastSelected(target.id);
|
||||||
|
target.toggleSelected(!target.getIsSelected());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[table, lastSelected, onChangeLastSelected, onRowClicked]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<tr
|
||||||
|
className={cn(
|
||||||
|
'cc-scroll-row',
|
||||||
|
'cc-hover cc-animate-background duration-fade',
|
||||||
|
!noHeader && 'scroll-mt-[calc(2px+2rem)]',
|
||||||
|
table.options.enableRowSelection && row.getIsSelected()
|
||||||
|
? 'cc-selected'
|
||||||
|
: !hasBG
|
||||||
|
? 'odd:bg-secondary even:bg-background'
|
||||||
|
: '',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
style={style}
|
||||||
|
onClick={event => handleRowClicked(row, event)}
|
||||||
|
onDoubleClick={event => onRowDoubleClicked?.(row.original, event)}
|
||||||
|
>
|
||||||
|
{table.options.enableRowSelection ? (
|
||||||
|
<td key={`select-${row.id}`} className='pl-2 border-y'>
|
||||||
|
<SelectRow row={row} onChangeLastSelected={onChangeLastSelected} />
|
||||||
|
</td>
|
||||||
|
) : null}
|
||||||
|
{row.getVisibleCells().map((cell: Cell<TData, unknown>) => (
|
||||||
|
<td
|
||||||
|
key={cell.id}
|
||||||
|
className={clsx(
|
||||||
|
'px-2 align-middle border-y',
|
||||||
|
dense ? 'py-1' : 'py-2',
|
||||||
|
onRowClicked || onRowDoubleClicked ? 'cursor-pointer' : 'cursor-auto'
|
||||||
|
)}
|
||||||
|
style={{
|
||||||
|
width: noHeader && row.index === 0 ? `calc(var(--col-${cell.column.id}-size) * 1px)` : undefined
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||||
|
</td>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
}
|
|
@ -21,7 +21,10 @@ export interface IConditionalStyle<TData> {
|
||||||
when: (rowData: TData) => boolean;
|
when: (rowData: TData) => boolean;
|
||||||
|
|
||||||
/** Style to apply. */
|
/** Style to apply. */
|
||||||
style: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
|
|
||||||
|
/** Classname to apply. */
|
||||||
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UseDataTableProps<TData extends RowData>
|
interface UseDataTableProps<TData extends RowData>
|
||||||
|
|
|
@ -200,7 +200,7 @@ export function IconLogin(props: IconProps) {
|
||||||
|
|
||||||
export function CheckboxChecked() {
|
export function CheckboxChecked() {
|
||||||
return (
|
return (
|
||||||
<svg className='w-4 h-4 p-0.75 -ml-0.25' viewBox='0 0 512 512' fill='#ffffff'>
|
<svg className='w-4 h-4 p-0.75 -ml-0.25 -mt-0.25' viewBox='0 0 512 512' fill='#ffffff'>
|
||||||
<path d='M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7l233.4-233.3c12.5-12.5 32.8-12.5 45.3 0z' />
|
<path d='M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7l233.4-233.3c12.5-12.5 32.8-12.5 45.3 0z' />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
@ -208,7 +208,7 @@ export function CheckboxChecked() {
|
||||||
|
|
||||||
export function CheckboxNull() {
|
export function CheckboxNull() {
|
||||||
return (
|
return (
|
||||||
<svg className='w-4 h-4 px-0.25' viewBox='0 0 16 16' fill='#ffffff'>
|
<svg className='w-4 h-4 px-0.25 -ml-0.25 -mt-0.25' viewBox='0 0 16 16' fill='#ffffff'>
|
||||||
<path d='M2 7.75A.75.75 0 012.75 7h10a.75.75 0 010 1.5h-10A.75.75 0 012 7.75z' />
|
<path d='M2 7.75A.75.75 0 012.75 7h10a.75.75 0 010 1.5h-10A.75.75 0 012 7.75z' />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
|
||||||
|
|
||||||
interface LoaderProps {
|
interface LoaderProps {
|
||||||
/** Scale of the loader from 1 to 10. */
|
/** Scale of the loader from 1 to 10. */
|
||||||
scale?: number;
|
scale?: number;
|
||||||
|
@ -57,8 +55,8 @@ const animatePulse = (startBig: boolean, duration: string) => {
|
||||||
export function Loader({ scale = 5, circular }: LoaderProps) {
|
export function Loader({ scale = 5, circular }: LoaderProps) {
|
||||||
if (circular) {
|
if (circular) {
|
||||||
return (
|
return (
|
||||||
<div className='flex justify-center' aria-label='three-circles-loading' aria-busy='true' role='progressbar'>
|
<div className='flex justify-center text-primary' aria-busy='true' role='progressbar'>
|
||||||
<svg height={`${scale * 20}`} width={`${scale * 20}`} viewBox='0 0 100 100' fill={APP_COLORS.bgPrimary}>
|
<svg height={`${scale * 20}`} width={`${scale * 20}`} viewBox='0 0 100 100' fill='currentColor'>
|
||||||
<path d='M31.6,3.5C5.9,13.6-6.6,42.7,3.5,68.4c10.1,25.7,39.2,38.3,64.9,28.1l-3.1-7.9c-21.3,8.4-45.4-2-53.8-23.3 c-8.4-21.3,2-45.4,23.3-53.8L31.6,3.5z'>
|
<path d='M31.6,3.5C5.9,13.6-6.6,42.7,3.5,68.4c10.1,25.7,39.2,38.3,64.9,28.1l-3.1-7.9c-21.3,8.4-45.4-2-53.8-23.3 c-8.4-21.3,2-45.4,23.3-53.8L31.6,3.5z'>
|
||||||
{animateRotation('2.25s')}
|
{animateRotation('2.25s')}
|
||||||
</path>
|
</path>
|
||||||
|
@ -73,8 +71,8 @@ export function Loader({ scale = 5, circular }: LoaderProps) {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div className='flex justify-center' aria-busy='true' role='progressbar'>
|
<div className='flex justify-center text-primary' aria-busy='true' role='progressbar'>
|
||||||
<svg height={`${scale * 20}`} width={`${scale * 20}`} viewBox='0 0 120 30' fill={APP_COLORS.bgPrimary}>
|
<svg height={`${scale * 20}`} width={`${scale * 20}`} viewBox='0 0 120 30' fill='currentColor'>
|
||||||
<circle cx='15' cy='15' r='16'>
|
<circle cx='15' cy='15' r='16'>
|
||||||
{animatePulse(true, '0.8s')}
|
{animatePulse(true, '0.8s')}
|
||||||
</circle>
|
</circle>
|
||||||
|
|
|
@ -28,7 +28,7 @@ export function TabLabel({
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'min-w-20 h-full',
|
'min-w-20 h-full',
|
||||||
'px-2 py-1 flex justify-center',
|
'px-2 py-1 flex justify-center',
|
||||||
'cc-hover cc-animate-color duration-150',
|
'cc-hover cc-animate-color duration-select',
|
||||||
'text-sm whitespace-nowrap font-controls',
|
'text-sm whitespace-nowrap font-controls',
|
||||||
'select-none hover:cursor-pointer',
|
'select-none hover:cursor-pointer',
|
||||||
'outline-hidden',
|
'outline-hidden',
|
||||||
|
|
|
@ -51,7 +51,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-2 bg-input' onClick={event => event.stopPropagation()}>
|
<div className='absolute right-1 text-sm top-2 bg-' onClick={event => event.stopPropagation()}>
|
||||||
<TextURL text='Справка...' href={`/manuals?topic=${topic}`} />
|
<TextURL text='Справка...' href={`/manuals?topic=${topic}`} />
|
||||||
</div>
|
</div>
|
||||||
<TopicPage topic={topic} />
|
<TopicPage topic={topic} />
|
||||||
|
|
|
@ -71,12 +71,12 @@ export function HelpRSEditor() {
|
||||||
<span className='bg-selected'>текущая конституента</span>
|
<span className='bg-selected'>текущая конституента</span>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span className='bg-(--acc-bg-green50)'>
|
<span className='bg-accent-green50'>
|
||||||
<LinkTopic text='основа' topic={HelpTopic.CC_RELATIONS} /> текущей
|
<LinkTopic text='основа' topic={HelpTopic.CC_RELATIONS} /> текущей
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span className='bg-(--acc-bg-orange50)'>
|
<span className='bg-accent-orange50'>
|
||||||
<LinkTopic text='порожденные' topic={HelpTopic.CC_RELATIONS} /> текущей
|
<LinkTopic text='порожденные' topic={HelpTopic.CC_RELATIONS} /> текущей
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -8,7 +8,6 @@ import { IconClose, IconFolderTree } from '@/components/icons';
|
||||||
import { SearchBar } from '@/components/input';
|
import { SearchBar } from '@/components/input';
|
||||||
import { type Styling } from '@/components/props';
|
import { type Styling } from '@/components/props';
|
||||||
import { cn } from '@/components/utils';
|
import { cn } from '@/components/utils';
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
|
||||||
import { prefixes } from '@/utils/constants';
|
import { prefixes } from '@/utils/constants';
|
||||||
|
|
||||||
import { type ILibraryItem, type LibraryItemType } from '../backend/types';
|
import { type ILibraryItem, type LibraryItemType } from '../backend/types';
|
||||||
|
@ -91,7 +90,7 @@ export function PickSchema({
|
||||||
const conditionalRowStyles: IConditionalStyle<ILibraryItem>[] = [
|
const conditionalRowStyles: IConditionalStyle<ILibraryItem>[] = [
|
||||||
{
|
{
|
||||||
when: (item: ILibraryItem) => item.id === value,
|
when: (item: ILibraryItem) => item.id === value,
|
||||||
style: { backgroundColor: APP_COLORS.bgSelected }
|
className: 'bg-selected'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ export function SelectLocation({ value, dense, prefix, onClick, className, style
|
||||||
!dense && 'h-7 sm:h-8',
|
!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',
|
||||||
'cc-hover cc-animate-color',
|
'cc-hover cc-animate-color duration-fade',
|
||||||
'cursor-pointer',
|
'cursor-pointer',
|
||||||
'leading-3 sm:leading-4',
|
'leading-3 sm:leading-4',
|
||||||
activeNode === item && 'cc-selected'
|
activeNode === item && 'cc-selected'
|
||||||
|
|
|
@ -5,7 +5,6 @@ import { useIntl } from 'react-intl';
|
||||||
import { MiniButton } from '@/components/control';
|
import { MiniButton } from '@/components/control';
|
||||||
import { createColumnHelper, DataTable, type IConditionalStyle } from '@/components/data-table';
|
import { createColumnHelper, DataTable, type IConditionalStyle } from '@/components/data-table';
|
||||||
import { IconRemove } from '@/components/icons';
|
import { IconRemove } from '@/components/icons';
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
|
||||||
|
|
||||||
import { type IVersionInfo } from '../../backend/types';
|
import { type IVersionInfo } from '../../backend/types';
|
||||||
|
|
||||||
|
@ -77,9 +76,7 @@ export function TableVersions({ processing, items, onDelete, selected, onSelect
|
||||||
const conditionalRowStyles: IConditionalStyle<IVersionInfo>[] = [
|
const conditionalRowStyles: IConditionalStyle<IVersionInfo>[] = [
|
||||||
{
|
{
|
||||||
when: (version: IVersionInfo) => version.id === selected,
|
when: (version: IVersionInfo) => version.id === selected,
|
||||||
style: {
|
className: 'bg-selected'
|
||||||
backgroundColor: APP_COLORS.bgSelected
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ import { DataTable, type IConditionalStyle, type VisibilityState } from '@/compo
|
||||||
import { useWindowSize } from '@/hooks/use-window-size';
|
import { useWindowSize } from '@/hooks/use-window-size';
|
||||||
import { useFitHeight } from '@/stores/app-layout';
|
import { useFitHeight } from '@/stores/app-layout';
|
||||||
import { usePreferencesStore } from '@/stores/preferences';
|
import { usePreferencesStore } from '@/stores/preferences';
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
|
||||||
|
|
||||||
import { type ILibraryItem, LibraryItemType } from '../../backend/types';
|
import { type ILibraryItem, LibraryItemType } from '../../backend/types';
|
||||||
import { useLibrarySearchStore } from '../../stores/library-search';
|
import { useLibrarySearchStore } from '../../stores/library-search';
|
||||||
|
@ -35,9 +34,7 @@ export function TableLibraryItems({ items }: TableLibraryItemsProps) {
|
||||||
const conditionalRowStyles: IConditionalStyle<ILibraryItem>[] = [
|
const conditionalRowStyles: IConditionalStyle<ILibraryItem>[] = [
|
||||||
{
|
{
|
||||||
when: (item: ILibraryItem) => item.item_type === LibraryItemType.OSS,
|
when: (item: ILibraryItem) => item.item_type === LibraryItemType.OSS,
|
||||||
style: {
|
className: 'text-accent-green-foreground'
|
||||||
color: APP_COLORS.fgGreen
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
const tableHeight = useFitHeight('2.25rem');
|
const tableHeight = useFitHeight('2.25rem');
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globalIDs } from '@/utils/constants';
|
||||||
|
|
||||||
import { colorFgCstStatus } from '../colors';
|
import { colorFgCstStatus } from '../colors';
|
||||||
|
@ -24,11 +23,14 @@ export function BadgeConstituenta({ value, prefixID }: BadgeConstituentaProps) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
id={prefixID ? `${prefixID}${value.id}` : undefined}
|
id={prefixID ? `${prefixID}${value.id}` : undefined}
|
||||||
className={clsx('cc-badge-constituenta', value.is_inherited && 'border-dashed')}
|
className={clsx(
|
||||||
|
'cc-badge-constituenta',
|
||||||
|
value.is_inherited && 'border-dashed',
|
||||||
|
value.cst_class === CstClass.BASIC ? 'bg-accent-green25' : 'bg-input'
|
||||||
|
)}
|
||||||
style={{
|
style={{
|
||||||
borderColor: colorFgCstStatus(value.status),
|
borderColor: colorFgCstStatus(value.status),
|
||||||
color: colorFgCstStatus(value.status),
|
color: colorFgCstStatus(value.status)
|
||||||
backgroundColor: value.cst_class === CstClass.BASIC ? APP_COLORS.bgGreen25 : APP_COLORS.bgInput
|
|
||||||
}}
|
}}
|
||||||
data-tooltip-id={globalIDs.constituenta_tooltip}
|
data-tooltip-id={globalIDs.constituenta_tooltip}
|
||||||
onMouseEnter={() => setActiveCst(value)}
|
onMouseEnter={() => setActiveCst(value)}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import { SearchBar } from '@/components/input';
|
||||||
import { type Styling } from '@/components/props';
|
import { type Styling } from '@/components/props';
|
||||||
import { cn } from '@/components/utils';
|
import { cn } from '@/components/utils';
|
||||||
import { NoData } from '@/components/view';
|
import { NoData } from '@/components/view';
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
|
||||||
|
|
||||||
import { describeConstituenta } from '../labels';
|
import { describeConstituenta } from '../labels';
|
||||||
import { type IConstituenta } from '../models/rsform';
|
import { type IConstituenta } from '../models/rsform';
|
||||||
|
@ -68,7 +67,7 @@ export function PickConstituenta({
|
||||||
const conditionalRowStyles: IConditionalStyle<IConstituenta>[] = [
|
const conditionalRowStyles: IConditionalStyle<IConstituenta>[] = [
|
||||||
{
|
{
|
||||||
when: (cst: IConstituenta) => cst.id === value?.id,
|
when: (cst: IConstituenta) => cst.id === value?.id,
|
||||||
style: { backgroundColor: APP_COLORS.bgSelected }
|
className: 'bg-selected'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ import { IconAccept, IconPageLeft, IconPageRight, IconRemove, IconReplace } from
|
||||||
import { type Styling } from '@/components/props';
|
import { type Styling } from '@/components/props';
|
||||||
import { cn } from '@/components/utils';
|
import { cn } from '@/components/utils';
|
||||||
import { NoData } from '@/components/view';
|
import { NoData } from '@/components/view';
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
|
||||||
import { errorMsg } from '@/utils/labels';
|
import { errorMsg } from '@/utils/labels';
|
||||||
|
|
||||||
import { type ICstSubstitute } from '../backend/types';
|
import { type ICstSubstitute } from '../backend/types';
|
||||||
|
@ -224,7 +223,7 @@ export function PickSubstitutions({
|
||||||
const conditionalRowStyles: IConditionalStyle<IMultiSubstitution>[] = [
|
const conditionalRowStyles: IConditionalStyle<IMultiSubstitution>[] = [
|
||||||
{
|
{
|
||||||
when: (item: IMultiSubstitution) => item.is_suggestion,
|
when: (item: IMultiSubstitution) => item.is_suggestion,
|
||||||
style: { backgroundColor: APP_COLORS.bgOrange50 }
|
className: 'bg-accent-orange50'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ 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 clsx from 'clsx';
|
||||||
|
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
|
||||||
import { findContainedNodes } from '@/utils/codemirror';
|
import { findContainedNodes } from '@/utils/codemirror';
|
||||||
|
|
||||||
import { describeConstituentaTerm, labelGrammeme } from '../../labels';
|
import { describeConstituentaTerm, labelGrammeme } from '../../labels';
|
||||||
|
@ -67,9 +66,9 @@ function domTooltipEntityReference(ref: IEntityReference, cst: IConstituenta | n
|
||||||
'max-h-100 max-w-100 min-w-40',
|
'max-h-100 max-w-100 min-w-40',
|
||||||
'dense',
|
'dense',
|
||||||
'p-2 flex flex-col',
|
'p-2 flex flex-col',
|
||||||
'border shadow-md',
|
'rounded-md shadow-md',
|
||||||
'cc-scroll-y',
|
'cc-scroll-y',
|
||||||
'text-sm',
|
'text-sm bg-card',
|
||||||
'select-none cursor-auto'
|
'select-none cursor-auto'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -86,9 +85,8 @@ 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 = 'min-w-12 px-1 border rounded-lg text-sm text-center whitespace-nowrap';
|
gram.className = 'min-w-12 px-1 border rounded-lg text-sm text-center whitespace-nowrap bg-accent';
|
||||||
gram.style.borderWidth = '1px';
|
gram.style.borderWidth = '1px';
|
||||||
gram.style.backgroundColor = APP_COLORS.bgInput;
|
|
||||||
gram.innerText = labelGrammeme(gramStr);
|
gram.innerText = labelGrammeme(gramStr);
|
||||||
grams.appendChild(gram);
|
grams.appendChild(gram);
|
||||||
});
|
});
|
||||||
|
@ -117,9 +115,9 @@ function domTooltipSyntacticReference(
|
||||||
'max-h-100 max-w-100 min-w-40',
|
'max-h-100 max-w-100 min-w-40',
|
||||||
'dense',
|
'dense',
|
||||||
'p-2 flex flex-col',
|
'p-2 flex flex-col',
|
||||||
'border shadow-md',
|
'rounded-md shadow-md',
|
||||||
'cc-scroll-y',
|
'cc-scroll-y',
|
||||||
'text-sm',
|
'text-sm bg-card',
|
||||||
'select-none cursor-auto'
|
'select-none cursor-auto'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
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';
|
||||||
|
@ -32,7 +33,15 @@ 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 = 'max-h-100 max-w-100 min-w-40 dense p-2 border shadow-md cc-scroll-y text-sm font-main';
|
dom.className = clsx(
|
||||||
|
'max-h-100 max-w-100 min-w-40',
|
||||||
|
'dense',
|
||||||
|
'p-2',
|
||||||
|
'rounded-md shadow-md',
|
||||||
|
'cc-scroll-y',
|
||||||
|
'text-sm font-main bg-card',
|
||||||
|
'select-none cursor-auto'
|
||||||
|
);
|
||||||
|
|
||||||
if (!cst) {
|
if (!cst) {
|
||||||
const text = document.createElement('p');
|
const text = document.createElement('p');
|
||||||
|
|
|
@ -21,7 +21,7 @@ export function WordformButton({ text, example, grams, onSelectGrams, isSelected
|
||||||
'p-1',
|
'p-1',
|
||||||
'border rounded-none',
|
'border rounded-none',
|
||||||
'cursor-pointer',
|
'cursor-pointer',
|
||||||
'cc-controls cc-hover cc-animate-color',
|
'cc-controls hover:bg-accent hover:text-foreground cc-animate-color',
|
||||||
isSelected && 'cc-selected'
|
isSelected && 'cc-selected'
|
||||||
)}
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import { DataTable, type IConditionalStyle } from '@/components/data-table';
|
||||||
import { IconAccept, IconRemove, IconReset } from '@/components/icons';
|
import { IconAccept, IconRemove, IconReset } from '@/components/icons';
|
||||||
import { NoData } from '@/components/view';
|
import { NoData } from '@/components/view';
|
||||||
import { useDialogsStore } from '@/stores/dialogs';
|
import { useDialogsStore } from '@/stores/dialogs';
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
|
||||||
|
|
||||||
import { type ICstCreateDTO } from '../../backend/types';
|
import { type ICstCreateDTO } from '../../backend/types';
|
||||||
import { PickConstituenta } from '../../components/pick-constituenta';
|
import { PickConstituenta } from '../../components/pick-constituenta';
|
||||||
|
@ -100,7 +99,7 @@ export function TabArguments() {
|
||||||
const conditionalRowStyles: IConditionalStyle<IArgumentValue>[] = [
|
const conditionalRowStyles: IConditionalStyle<IArgumentValue>[] = [
|
||||||
{
|
{
|
||||||
when: (arg: IArgumentValue) => arg.alias === selectedArgument?.alias,
|
when: (arg: IArgumentValue) => arg.alias === selectedArgument?.alias,
|
||||||
style: { backgroundColor: APP_COLORS.bgSelected }
|
className: 'bg-selected'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ export function DlgShowAST() {
|
||||||
{!isDragging && hoverNodeDebounced ? (
|
{!isDragging && hoverNodeDebounced ? (
|
||||||
<div key={hoverNodeDebounced.uid}>
|
<div key={hoverNodeDebounced.uid}>
|
||||||
<span>{expression.slice(0, hoverNodeDebounced.start)}</span>
|
<span>{expression.slice(0, hoverNodeDebounced.start)}</span>
|
||||||
<span className='bg-selected cc-animate-background starting:bg-background duration-500'>
|
<span className='bg-selected cc-animate-background starting:bg-background duration-move'>
|
||||||
{expression.slice(hoverNodeDebounced.start, hoverNodeDebounced.finish)}
|
{expression.slice(hoverNodeDebounced.start, hoverNodeDebounced.finish)}
|
||||||
</span>
|
</span>
|
||||||
<span>{expression.slice(hoverNodeDebounced.finish)}</span>
|
<span>{expression.slice(hoverNodeDebounced.finish)}</span>
|
||||||
|
|
|
@ -49,7 +49,7 @@ export function StatusBar({ className, isModified, processing, activeCst, parseD
|
||||||
'select-none',
|
'select-none',
|
||||||
'cursor-pointer',
|
'cursor-pointer',
|
||||||
'focus-frame outline-none',
|
'focus-frame outline-none',
|
||||||
'transition-colors duration-500'
|
'transition-colors duration-fade'
|
||||||
)}
|
)}
|
||||||
style={{ backgroundColor: processing ? APP_COLORS.bgDefault : colorStatusBar(status) }}
|
style={{ backgroundColor: processing ? APP_COLORS.bgDefault : colorStatusBar(status) }}
|
||||||
data-tooltip-id={globalIDs.tooltip}
|
data-tooltip-id={globalIDs.tooltip}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { useEffect } from 'react';
|
||||||
|
|
||||||
import { createColumnHelper, DataTable, type IConditionalStyle } from '@/components/data-table';
|
import { createColumnHelper, DataTable, type IConditionalStyle } from '@/components/data-table';
|
||||||
import { NoData, TextContent } from '@/components/view';
|
import { NoData, TextContent } from '@/components/view';
|
||||||
import { APP_COLORS } from '@/styling/colors';
|
|
||||||
import { PARAMETER, prefixes } from '@/utils/constants';
|
import { PARAMETER, prefixes } from '@/utils/constants';
|
||||||
|
|
||||||
import { BadgeConstituenta } from '../../../components/badge-constituenta';
|
import { BadgeConstituenta } from '../../../components/badge-constituenta';
|
||||||
|
@ -66,21 +65,15 @@ export function TableSideConstituents({ autoScroll = true, maxHeight }: TableSid
|
||||||
const conditionalRowStyles: IConditionalStyle<IConstituenta>[] = [
|
const conditionalRowStyles: IConditionalStyle<IConstituenta>[] = [
|
||||||
{
|
{
|
||||||
when: (cst: IConstituenta) => !!activeCst && cst.id === activeCst.id,
|
when: (cst: IConstituenta) => !!activeCst && cst.id === activeCst.id,
|
||||||
style: {
|
className: 'bg-selected'
|
||||||
backgroundColor: APP_COLORS.bgSelected
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
when: (cst: IConstituenta) => !!activeCst && cst.spawner === activeCst.id && cst.id !== activeCst.id,
|
when: (cst: IConstituenta) => !!activeCst && cst.spawner === activeCst.id && cst.id !== activeCst.id,
|
||||||
style: {
|
className: 'bg-accent-orange50'
|
||||||
backgroundColor: APP_COLORS.bgOrange50
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
when: (cst: IConstituenta) => !!activeCst && cst.spawn.includes(activeCst.id),
|
when: (cst: IConstituenta) => !!activeCst && cst.spawn.includes(activeCst.id),
|
||||||
style: {
|
className: 'bg-accent-green50'
|
||||||
backgroundColor: APP_COLORS.bgGreen50
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,23 @@
|
||||||
--color-sec-400: var(--clr-sec-400);
|
--color-sec-400: var(--clr-sec-400);
|
||||||
--color-sec-600: var(--clr-sec-600);
|
--color-sec-600: var(--clr-sec-600);
|
||||||
|
|
||||||
|
--color-accent-red: var(--acc-bg-red);
|
||||||
|
--color-accent-green: var(--acc-bg-green);
|
||||||
|
--color-accent-green25: var(--acc-bg-green25);
|
||||||
|
--color-accent-green50: var(--acc-bg-green50);
|
||||||
|
--color-accent-blue: var(--acc-bg-blue);
|
||||||
|
--color-accent-purple: var(--acc-bg-purple);
|
||||||
|
--color-accent-teal: var(--acc-bg-teal);
|
||||||
|
--color-accent-orange: var(--acc-bg-orange);
|
||||||
|
--color-accent-orange50: var(--acc-bg-orange50);
|
||||||
|
|
||||||
|
--color-accent-red-foreground: var(--acc-fg-red);
|
||||||
|
--color-accent-green-foreground: var(--acc-fg-green);
|
||||||
|
--color-accent-blue-foreground: var(--acc-fg-blue);
|
||||||
|
--color-accent-purple-foreground: var(--acc-fg-purple);
|
||||||
|
--color-accent-teal-foreground: var(--acc-fg-teal);
|
||||||
|
--color-accent-orange-foreground: var(--acc-fg-orange);
|
||||||
|
|
||||||
/* stylelint-disable-next-line custom-property-pattern */
|
/* stylelint-disable-next-line custom-property-pattern */
|
||||||
--z-index-*: initial;
|
--z-index-*: initial;
|
||||||
--z-index-bottom: 0;
|
--z-index-bottom: 0;
|
||||||
|
@ -66,11 +83,12 @@
|
||||||
|
|
||||||
--ease-bezier: cubic-bezier(0.4, 0, 0.2, 1);
|
--ease-bezier: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
|
||||||
--duration-move: 500ms;
|
/* Animation durations */
|
||||||
|
--duration-select: 100ms;
|
||||||
|
--duration-dropdown: 200ms;
|
||||||
--duration-modal: 300ms;
|
--duration-modal: 300ms;
|
||||||
--duration-fade: 300ms;
|
--duration-fade: 300ms;
|
||||||
--duration-dropdown: 200ms;
|
--duration-move: 500ms;
|
||||||
--duration-select: 100ms;
|
|
||||||
|
|
||||||
/* ========= shadcn theme ============ */
|
/* ========= shadcn theme ============ */
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,6 @@ export const APP_COLORS = {
|
||||||
|
|
||||||
bgGreen25: 'var(--acc-bg-green25)',
|
bgGreen25: 'var(--acc-bg-green25)',
|
||||||
bgGreen50: 'var(--acc-bg-green50)',
|
bgGreen50: 'var(--acc-bg-green50)',
|
||||||
bgOrange50: 'var(--acc-bg-orange50)',
|
|
||||||
|
|
||||||
fgRed: 'var(--acc-fg-red)',
|
fgRed: 'var(--acc-fg-red)',
|
||||||
fgGreen: 'var(--acc-fg-green)',
|
fgGreen: 'var(--acc-fg-green)',
|
||||||
|
|
|
@ -9,13 +9,21 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
transition-property: background-color;
|
transition-property: background-color, color;
|
||||||
transition-timing-function: var(--ease-bezier);
|
transition-timing-function: var(--ease-bezier);
|
||||||
transition-duration: 500ms;
|
transition-duration: 500ms;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--color-accent);
|
background-color: var(--color-accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dark & {
|
||||||
|
color: color-mix(in oklab, var(--color-foreground) 70%, transparent);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--color-foreground);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility cc-btn-primary {
|
@utility cc-btn-primary {
|
||||||
|
|
|
@ -28,10 +28,10 @@
|
||||||
--clr-prim-999: oklch(000% 0 0deg);
|
--clr-prim-999: oklch(000% 0 0deg);
|
||||||
|
|
||||||
--clr-sec-0: oklch(100% 0 0deg);
|
--clr-sec-0: oklch(100% 0 0deg);
|
||||||
--clr-sec-100: oklch(095% 0.050 262deg);
|
--clr-sec-100: oklch(095% 0.025 262deg);
|
||||||
--clr-sec-200: oklch(088% 0.050 262deg);
|
--clr-sec-200: oklch(090% 0.050 262deg);
|
||||||
--clr-sec-400: oklch(075% 0.150 262deg);
|
--clr-sec-400: oklch(073% 0.140 262deg);
|
||||||
--clr-sec-600: oklch(060% 0.250 262deg);
|
--clr-sec-600: oklch(060% 0.230 262deg);
|
||||||
|
|
||||||
--clr-warn-600: oklch(060% 0.250 27deg);
|
--clr-warn-600: oklch(060% 0.250 27deg);
|
||||||
--clr-ok-600: oklch(060% 0.250 138deg);
|
--clr-ok-600: oklch(060% 0.250 138deg);
|
||||||
|
@ -39,23 +39,27 @@
|
||||||
--clr-select-node: oklch(080% 0.250 180deg);
|
--clr-select-node: oklch(080% 0.250 180deg);
|
||||||
|
|
||||||
/* Highlight accents */
|
/* Highlight accents */
|
||||||
--acc-bg-red: oklch(085% 0.150 27deg);
|
--acc-bg-red: oklch(083% 0.120 27deg);
|
||||||
--acc-bg-green: oklch(085% 0.150 138deg);
|
--acc-bg-green: oklch(085% 0.150 138deg);
|
||||||
--acc-bg-blue: oklch(085% 0.150 262deg);
|
--acc-bg-blue: oklch(085% 0.150 262deg);
|
||||||
--acc-bg-purple: oklch(085% 0.200 295deg);
|
--acc-bg-purple: oklch(085% 0.200 295deg);
|
||||||
--acc-bg-teal: oklch(085% 0.200 210deg);
|
--acc-bg-teal: oklch(082% 0.180 210deg);
|
||||||
--acc-bg-orange: oklch(085% 0.150 62deg);
|
--acc-bg-orange: oklch(085% 0.130 62deg);
|
||||||
|
|
||||||
--acc-bg-green25: oklch(097% 0.150 138deg);
|
--acc-bg-green25: oklch(097% 0.080 138deg);
|
||||||
--acc-bg-green50: oklch(090% 0.150 138deg);
|
--acc-bg-green50: oklch(092% 0.150 138deg);
|
||||||
--acc-bg-orange50: oklch(090% 0.044 62deg);
|
--acc-bg-orange50: oklch(090% 0.044 62deg);
|
||||||
|
|
||||||
--acc-fg-red: oklch(060% 0.220 27deg);
|
--acc-fg-red: oklch(060% 0.220 27deg);
|
||||||
--acc-fg-green: oklch(060% 0.250 138deg);
|
--acc-fg-green: oklch(060% 0.220 138deg);
|
||||||
--acc-fg-blue: oklch(060% 0.300 262deg);
|
--acc-fg-blue: oklch(060% 0.230 262deg);
|
||||||
--acc-fg-purple: oklch(060% 0.250 295deg);
|
--acc-fg-purple: oklch(060% 0.250 295deg);
|
||||||
--acc-fg-teal: oklch(060% 0.150 210deg);
|
--acc-fg-teal: oklch(060% 0.140 210deg);
|
||||||
--acc-fg-orange: oklch(060% 0.150 62deg);
|
--acc-fg-orange: oklch(060% 0.150 62deg);
|
||||||
|
|
||||||
|
/* React Tooltip */
|
||||||
|
--rt-color-white: var(--clr-prim-0);
|
||||||
|
--rt-color-dark: var(--clr-prim-999);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dark Theme */
|
/* Dark Theme */
|
||||||
|
@ -69,15 +73,15 @@
|
||||||
--clr-prim-999: oklch(095% 0 0deg);
|
--clr-prim-999: oklch(095% 0 0deg);
|
||||||
|
|
||||||
--clr-sec-0: oklch(100% 0 0deg);
|
--clr-sec-0: oklch(100% 0 0deg);
|
||||||
--clr-sec-100: oklch(025% 0.200 295deg);
|
--clr-sec-100: oklch(030% 0.075 70deg);
|
||||||
--clr-sec-200: oklch(035% 0.150 295deg);
|
--clr-sec-200: oklch(040% 0.150 295deg);
|
||||||
--clr-sec-400: oklch(055% 0.200 295deg);
|
--clr-sec-400: oklch(055% 0.200 295deg);
|
||||||
--clr-sec-600: oklch(070% 0.250 295deg);
|
--clr-sec-600: oklch(070% 0.170 295deg);
|
||||||
|
|
||||||
--clr-warn-600: oklch(065% 0.200 27deg);
|
--clr-warn-600: oklch(065% 0.200 27deg);
|
||||||
--clr-ok-600: oklch(065% 0.200 138deg);
|
--clr-ok-600: oklch(065% 0.200 138deg);
|
||||||
|
|
||||||
--clr-select-node: oklch(070% 0.250 180deg);
|
--clr-select-node: oklch(070% 0.160 180deg);
|
||||||
|
|
||||||
/* Highlight accents */
|
/* Highlight accents */
|
||||||
--acc-bg-red: oklch(050% 0.150 27deg);
|
--acc-bg-red: oklch(050% 0.150 27deg);
|
||||||
|
@ -91,10 +95,14 @@
|
||||||
--acc-bg-green50: oklch(038% 0.200 138deg);
|
--acc-bg-green50: oklch(038% 0.200 138deg);
|
||||||
--acc-bg-orange50: oklch(038% 0.075 62deg);
|
--acc-bg-orange50: oklch(038% 0.075 62deg);
|
||||||
|
|
||||||
--acc-fg-red: oklch(075% 0.200 27deg);
|
--acc-fg-red: oklch(073% 0.200 27deg);
|
||||||
--acc-fg-green: oklch(075% 0.150 138deg);
|
--acc-fg-green: oklch(075% 0.150 138deg);
|
||||||
--acc-fg-blue: oklch(075% 0.150 262deg);
|
--acc-fg-blue: oklch(075% 0.135 262deg);
|
||||||
--acc-fg-purple: oklch(075% 0.250 295deg);
|
--acc-fg-purple: oklch(075% 0.150 295deg);
|
||||||
--acc-fg-teal: oklch(075% 0.150 210deg);
|
--acc-fg-teal: oklch(075% 0.150 210deg);
|
||||||
--acc-fg-orange: oklch(075% 0.150 62deg);
|
--acc-fg-orange: oklch(075% 0.150 62deg);
|
||||||
|
|
||||||
|
/* React Tooltip */
|
||||||
|
--rt-color-white: var(--clr-prim-999);
|
||||||
|
--rt-color-dark: var(--clr-prim-0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
|
|
||||||
.cm-tooltip {
|
.cm-tooltip {
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
|
||||||
|
border-color: var(--clr-prim-400);
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-selectionBackground {
|
.cm-selectionBackground {
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
|
|
||||||
@utility cc-hover {
|
@utility cc-hover {
|
||||||
&:hover:not(:disabled) {
|
&:hover:not(:disabled) {
|
||||||
color: var(--color-accent-foreground);
|
|
||||||
background-color: var(--color-accent);
|
background-color: var(--color-accent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,3 +180,28 @@
|
||||||
|
|
||||||
mask-composite: intersect;
|
mask-composite: intersect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@utility duration-select {
|
||||||
|
--tw-duration: var(--duration-select);
|
||||||
|
transition-duration: var(--duration-select);
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility duration-dropdown {
|
||||||
|
--tw-duration: var(--duration-dropdown);
|
||||||
|
transition-duration: var(--duration-dropdown);
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility duration-modal {
|
||||||
|
--tw-duration: var(--duration-modal);
|
||||||
|
transition-duration: var(--duration-modal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility duration-fade {
|
||||||
|
--tw-duration: var(--duration-fade);
|
||||||
|
transition-duration: var(--duration-fade);
|
||||||
|
}
|
||||||
|
|
||||||
|
@utility duration-move {
|
||||||
|
--tw-duration: var(--duration-move);
|
||||||
|
transition-duration: var(--duration-move);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user