import React, { AnchorHTMLAttributes, ButtonHTMLAttributes, DetailedHTMLProps, FC, Fragment, ReactNode, useContext, } from "react"; import { RenderLink } from "../types"; import { OpenContext, RenderLinkContext, SelectContext } from "../lib/context"; import { classNames } from "../lib/utils"; export type ListItemType = "Link" | "Action"; function getListItemWrapperStyles(selected: boolean, disabled?: boolean) { return classNames( "command-palette-list-item block w-full text-left px-3.5 py-2.5 rounded-md hover:bg-gray-100 dark:hover:bg-gray-800 focus:ring-1 focus:ring-gray-300 focus:outline-none flex items-center space-x-2.5 justify-between", selected && !disabled ? "bg-gray-200/50 dark:bg-gray-800" : "bg-transparent", disabled ? "cursor-default pointer-events-none opacity-50" : "cursor-pointer" ); } interface ListItemBaseProps { closeOnSelect?: boolean; icon?: any; showType?: boolean; disabled?: boolean; keywords?: string[]; index: number; } export interface LinkProps extends ListItemBaseProps, DetailedHTMLProps< AnchorHTMLAttributes, HTMLAnchorElement > { renderLink?: RenderLink; } export function Link({ renderLink: localRenderLink, closeOnSelect = true, disabled = false, showType = true, className, children, onClick, index, icon, ...rest }: LinkProps) { const { renderLink: globalRenderLink } = useContext(RenderLinkContext); const { onChangeOpen } = useContext(OpenContext); const { selected } = useContext(SelectContext); const renderLink = localRenderLink || globalRenderLink; function renderLinkContent() { return ( {children} ); } const styles = classNames( getListItemWrapperStyles(selected === index, disabled), className ); function clickAndClose(e: React.MouseEvent) { if (rest.href && !disabled) { if (onClick) { onClick(e); } if (closeOnSelect) { onChangeOpen(false); } } } return renderLink ? ( {renderLink({ ...rest, "data-close-on-select": closeOnSelect, children: renderLinkContent(), "aria-disabled": disabled, onClick: clickAndClose, className: styles, })} ) : ( {renderLinkContent()} ); } export interface ButtonProps extends ListItemBaseProps, DetailedHTMLProps< ButtonHTMLAttributes, HTMLButtonElement > {} export function Button({ closeOnSelect = true, showType = true, className, children, onClick, index, icon, ...rest }: ButtonProps) { const { selected } = useContext(SelectContext); const { onChangeOpen } = useContext(OpenContext); function clickAndClose(e: React.MouseEvent) { if (onClick) { onClick(e); if (closeOnSelect) { onChangeOpen(false); } } } return ( ); } interface ListItemContentProps { icon?: FC; children: ReactNode; type?: ListItemType; } function ListItemContent({ icon: ListItemIcon, children, type, }: ListItemContentProps) { return ( <>
{ListItemIcon && } {typeof children === "string" ? ( {children} ) : ( children )}
{type && {type}} ); } export default function ListItem(props: ButtonProps & LinkProps) { const Wrapper = props.href ? Link : Button; return ; }