191 lines
4.9 KiB
TypeScript
191 lines
4.9 KiB
TypeScript
import { ReactNode } from "react";
|
|
import Checkbox from "../../form/input/Checkbox";
|
|
|
|
interface ListProps {
|
|
children: ReactNode;
|
|
variant?: "unordered" | "ordered" | "horizontal" | "button" | "icon" | "checkbox" | "radio";
|
|
className?: string;
|
|
}
|
|
|
|
export const List: React.FC<ListProps> = ({
|
|
children,
|
|
variant = "unordered",
|
|
className = "",
|
|
}) => {
|
|
const baseClasses = "rounded-lg border border-gray-200 bg-white dark:border-gray-800 dark:bg-white/[0.03] sm:w-fit";
|
|
|
|
if (variant === "ordered") {
|
|
return (
|
|
<ol className={`flex flex-col list-decimal ${baseClasses} ${className}`}>
|
|
{children}
|
|
</ol>
|
|
);
|
|
}
|
|
|
|
if (variant === "horizontal") {
|
|
return (
|
|
<ul className={`flex flex-col md:flex-row ${baseClasses} ${className}`}>
|
|
{children}
|
|
</ul>
|
|
);
|
|
}
|
|
|
|
if (variant === "button") {
|
|
return (
|
|
<ul className={`w-full overflow-hidden rounded-lg border border-gray-200 bg-white dark:border-gray-800 dark:bg-white/[0.03] sm:w-[228px] flex flex-col ${className}`}>
|
|
{children}
|
|
</ul>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<ul className={`flex flex-col ${baseClasses} ${className}`}>
|
|
{children}
|
|
</ul>
|
|
);
|
|
};
|
|
|
|
interface ListItemProps {
|
|
children: ReactNode;
|
|
variant?: "unordered" | "ordered" | "horizontal" | "button" | "icon" | "checkbox" | "radio";
|
|
onClick?: () => void;
|
|
disabled?: boolean;
|
|
className?: string;
|
|
}
|
|
|
|
export const ListItem: React.FC<ListItemProps> = ({
|
|
children,
|
|
variant = "unordered",
|
|
onClick,
|
|
disabled = false,
|
|
className = "",
|
|
}) => {
|
|
if (variant === "button") {
|
|
return (
|
|
<li className={`border-b border-gray-200 last:border-b-0 dark:border-gray-800 ${className}`}>
|
|
<button
|
|
className={`flex w-full items-center gap-3 px-3 py-2.5 text-sm font-medium text-gray-500 hover:bg-brand-50 hover:text-brand-500 dark:text-gray-400 dark:hover:bg-brand-500/[0.12] dark:hover:text-brand-400 ${disabled ? "disabled:opacity-50" : ""}`}
|
|
onClick={onClick}
|
|
disabled={disabled}
|
|
type="button"
|
|
>
|
|
{children}
|
|
</button>
|
|
</li>
|
|
);
|
|
}
|
|
|
|
if (variant === "horizontal") {
|
|
return (
|
|
<li className={`flex items-center gap-2 border-b border-gray-200 px-3 py-2.5 text-sm text-gray-500 last:border-0 dark:border-gray-800 dark:text-gray-400 md:border-b-0 md:border-r ${className}`}>
|
|
{children}
|
|
</li>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<li className={`flex items-center gap-2 border-b border-gray-200 px-3 py-2.5 text-sm text-gray-500 last:border-b-0 dark:border-gray-800 dark:text-gray-400 ${className}`}>
|
|
{children}
|
|
</li>
|
|
);
|
|
};
|
|
|
|
interface ListDotProps {
|
|
className?: string;
|
|
}
|
|
|
|
export const ListDot: React.FC<ListDotProps> = ({ className = "" }) => {
|
|
return (
|
|
<span className={`ml-2 block h-[3px] w-[3px] rounded-full bg-gray-500 dark:bg-gray-400 ${className}`}></span>
|
|
);
|
|
};
|
|
|
|
interface ListIconProps {
|
|
children: ReactNode;
|
|
className?: string;
|
|
}
|
|
|
|
export const ListIcon: React.FC<ListIconProps> = ({
|
|
children,
|
|
className = "",
|
|
}) => {
|
|
return (
|
|
<span className={`text-brand-500 dark:text-brand-400 ${className}`}>
|
|
{children}
|
|
</span>
|
|
);
|
|
};
|
|
|
|
interface ListCheckboxItemProps {
|
|
id: string;
|
|
label: string;
|
|
checked?: boolean;
|
|
disabled?: boolean;
|
|
onChange?: (checked: boolean) => void;
|
|
className?: string;
|
|
}
|
|
|
|
export const ListCheckboxItem: React.FC<ListCheckboxItemProps> = ({
|
|
id,
|
|
label,
|
|
checked = false,
|
|
disabled = false,
|
|
onChange,
|
|
className = "",
|
|
}) => {
|
|
return (
|
|
<li className={`border-b border-gray-200 px-3 py-2.5 last:border-b-0 dark:border-gray-800 ${className}`}>
|
|
<Checkbox
|
|
id={id}
|
|
label={label}
|
|
checked={checked}
|
|
disabled={disabled}
|
|
onChange={(val) => onChange?.(val)}
|
|
/>
|
|
</li>
|
|
);
|
|
};
|
|
|
|
interface ListRadioItemProps {
|
|
id: string;
|
|
name: string;
|
|
value: string;
|
|
label: string;
|
|
checked?: boolean;
|
|
onChange?: (value: string) => void;
|
|
className?: string;
|
|
}
|
|
|
|
export const ListRadioItem: React.FC<ListRadioItemProps> = ({
|
|
id,
|
|
name,
|
|
value,
|
|
label,
|
|
checked = false,
|
|
onChange,
|
|
className = "",
|
|
}) => {
|
|
return (
|
|
<li className={`border-b border-gray-200 px-3 py-2.5 last:border-b-0 dark:border-gray-800 ${className}`}>
|
|
<label htmlFor={id} className="flex cursor-pointer select-none items-center text-sm text-gray-500 dark:text-gray-400">
|
|
<span className="relative">
|
|
<input
|
|
id={id}
|
|
className="sr-only"
|
|
type="radio"
|
|
value={value}
|
|
name={name}
|
|
checked={checked}
|
|
onChange={(e) => onChange?.(e.target.value)}
|
|
/>
|
|
<span className={`mr-2 flex h-4 w-4 items-center justify-center rounded-full border ${checked ? "border-brand-500 bg-brand-500" : "bg-transparent border-gray-300 dark:border-gray-700"}`}>
|
|
<span className="h-1.5 w-1.5 rounded-full bg-white dark:bg-gray-800"></span>
|
|
</span>
|
|
</span>
|
|
{label}
|
|
</label>
|
|
</li>
|
|
);
|
|
};
|
|
|