"use client"; import * as React from "react"; import { Copy, Folder, Pencil, Play, Star, Trash2 } from "lucide-react"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { ProviderIcon } from "@/components/brand/provider-icon"; import { RowMenu } from "@/components/projects/row-menu"; import { useApp } from "@/components/app/store"; import { useIsMobile, useLongPress } from "@/lib/client/hooks"; import { formatRelative, truncate, cn } from "@/lib/utils"; import type { PublicPrompt } from "@/lib/client/types"; import type { ActionSheetItem } from "@/components/ui/sheet"; import { PROMPT_KIND_META } from "./prompt-kind"; export interface PromptCardActions { onUse: (p: PublicPrompt) => void; onEdit: (p: PublicPrompt) => void; onDuplicate?: (p: PublicPrompt) => void; onToggleFavorite: (p: PublicPrompt) => void; onDelete: (p: PublicPrompt) => void; } /** Prompt card (grid) or compact row (`compact`, used on project pages). Long-press on phones opens the actions. */ export function PromptCard({ prompt: p, actions, compact, className }: { prompt: PublicPrompt; actions: PromptCardActions; compact?: boolean; className?: string }) { const { modelsByKey } = useApp(); const isMobile = useIsMobile(); const [menu, setMenu] = React.useState(false); const press = useLongPress({ onLongPress: () => setMenu(true), disabled: !isMobile }); const meta = PROMPT_KIND_META[p.kind]; const model = p.defaultModelKey ? modelsByKey.get(p.defaultModelKey) : null; const items: (ActionSheetItem | "separator")[] = [ { key: "use", label: "Use in chat", icon: , onSelect: () => actions.onUse(p) }, { key: "edit", label: "Edit", icon: , onSelect: () => actions.onEdit(p) }, ...(actions.onDuplicate ? [{ key: "dup", label: "Duplicate", icon: , onSelect: () => actions.onDuplicate!(p) } as ActionSheetItem] : []), { key: "fav", label: p.favorite ? "Remove from favourites" : "Add to favourites", icon: , onSelect: () => actions.onToggleFavorite(p) }, "separator", { key: "delete", label: "Delete", icon: , destructive: true, onSelect: () => actions.onDelete(p) }, ]; if (compact) { return (
  • {meta.icon}
  • ); } return (
  • {meta.icon}

    {p.name}

    {p.description ?

    {p.description}

    : null}
    {meta.short} {p.variables.slice(0, 3).map((v) => ( {`{{${v.name}}}`} ))} {p.variables.length > 3 ? +{p.variables.length - 3} : null} {model ? ( {model.displayName} ) : null} {p.folder ? ( {p.folder} ) : null} {p.tags.slice(0, 3).map((t) => ( #{t} ))}
    {p.uses ? `Used ${p.uses}× · ` : ""}Updated {formatRelative(p.updatedAt)}
  • ); }