Files
qapi/src/codec-components/common/ListItem.tsx
2024-11-08 23:17:25 +07:00

86 lines
2.3 KiB
TypeScript

import { ExpandBtn } from "@/components/Expand"
import { useStateObservable } from "@react-rxjs/core"
import { Dot, Trash2 } from "lucide-react"
import { twMerge as clsx, twMerge } from "tailwind-merge"
import { Marker } from "./Markers"
import {
isActive$,
isCollapsed$,
setHovered,
toggleCollapsed,
} from "./paths.state"
import { ReactNode } from "react"
export const ListItem: React.FC<{
idx: number
children: React.ReactNode
path: string[]
onDelete?: () => void
actions?: ReactNode
inline?: boolean
}> = ({ idx, onDelete, children, path, actions, inline }) => {
const pathStr = path.join(".")
const isActive = useStateObservable(isActive$(pathStr))
const isCollapsed = useStateObservable(isCollapsed$(pathStr))
const title = inline ? (
<div className="flex items-center">
<Marker id={path} />
<span className="flex items-center py-1 gap-1 mr-2">
<Dot size={16} />
Item {idx + 1}.
</span>
<div className="flex-1">{children}</div>
{onDelete ? (
<button
className="cursor-pointer text-foreground/80 ml-2 hover:text-primary"
onClick={() => onDelete()}
>
<Trash2 size={16} />
</button>
) : null}
{actions}
</div>
) : (
<div className="flex items-center">
<Marker id={path} />
<span
className="cursor-pointer flex items-center py-1 gap-1"
onClick={() => toggleCollapsed(pathStr)}
>
<ExpandBtn expanded={!isCollapsed} />
Item {idx + 1}.
</span>
{onDelete ? (
<button
className="cursor-pointer text-foreground/80 ml-2 hover:text-primary"
onClick={() => onDelete()}
>
<Trash2 size={16} />
</button>
) : null}
{actions}
</div>
)
return (
<li
className={twMerge("flex flex-col mb-1", isActive && "bg-secondary/80")}
onMouseEnter={() => setHovered({ id: pathStr, hover: true })}
onMouseLeave={() => setHovered({ id: pathStr, hover: false })}
>
{title}
{inline ? null : (
<div
className={clsx(
"flex-row p-2 items-center border border-border",
isCollapsed ? "hidden" : "",
)}
>
{children}
</div>
)}
</li>
)
}