ConceptPortal-public/rsconcept/frontend/src/components/ui/CheckboxTristate.tsx

87 lines
2.1 KiB
TypeScript
Raw Normal View History

import clsx from 'clsx';
2023-09-07 16:30:43 +03:00
2025-01-28 23:23:42 +03:00
import { CheckboxChecked, CheckboxNull } from '@/components/Icons';
import { CProps } from '@/components/props';
import { globals } from '@/utils/constants';
2023-12-21 00:12:24 +03:00
2023-09-07 16:30:43 +03:00
import { CheckboxProps } from './Checkbox';
export interface CheckboxTristateProps extends Omit<CheckboxProps, 'value' | 'onChange'> {
/** Current value - `null`, `true` or `false`. */
2023-12-28 14:04:44 +03:00
value: boolean | null;
/** Callback to set the `value`. */
onChange?: (newValue: boolean | null) => void;
2023-09-07 16:30:43 +03:00
}
/**
2024-10-30 21:35:55 +03:00
* Component that allows toggling among three states: `true`, `false`, and `null`.
*/
function CheckboxTristate({
disabled,
label,
title,
titleHtml,
2024-03-09 16:40:10 +03:00
hideTitle,
className,
value,
onChange,
...restProps
}: CheckboxTristateProps) {
const cursor = disabled ? 'cursor-arrow' : onChange ? 'cursor-pointer' : '';
function handleClick(event: CProps.EventMouse): void {
2023-09-07 16:30:43 +03:00
event.preventDefault();
2024-05-23 13:36:16 +03:00
event.stopPropagation();
if (disabled || !onChange) {
2023-09-07 16:30:43 +03:00
return;
}
if (value === false) {
onChange(null);
} else if (value === null) {
onChange(true);
2023-09-07 16:30:43 +03:00
} else {
onChange(false);
2023-09-07 16:30:43 +03:00
}
}
return (
2023-12-28 14:04:44 +03:00
<button
type='button'
className={clsx(
'flex items-center gap-2', //
'outline-none',
2024-05-12 13:58:28 +03:00
'focus-frame',
cursor,
className
)}
2023-12-28 14:04:44 +03:00
disabled={disabled}
onClick={handleClick}
data-tooltip-id={!!title || !!titleHtml ? globals.tooltip : undefined}
data-tooltip-html={titleHtml}
2023-12-28 14:04:44 +03:00
data-tooltip-content={title}
2024-03-09 16:40:10 +03:00
data-tooltip-hidden={hideTitle}
2023-12-28 14:04:44 +03:00
{...restProps}
>
<div
className={clsx(
'w-4 h-4', //
2024-12-20 13:36:42 +03:00
'pt-[0.1rem] pl-[0.1rem]',
'border rounded-sm',
2024-12-17 11:38:00 +03:00
'cc-animate-color',
{
2024-12-17 11:38:00 +03:00
'bg-sec-600 text-sec-0': value !== false,
2024-12-17 10:53:01 +03:00
'bg-prim-100': value === false
}
)}
2023-12-28 14:04:44 +03:00
>
2024-12-20 13:36:42 +03:00
{value ? <CheckboxChecked /> : null}
{value == null ? <CheckboxNull /> : null}
2023-12-28 14:04:44 +03:00
</div>
{label ? <span className={clsx('text-start text-sm whitespace-nowrap select-text', cursor)}>{label}</span> : null}
2023-12-28 14:04:44 +03:00
</button>
);
2023-09-07 16:30:43 +03:00
}
export default CheckboxTristate;