import { useEffect, useState, type ReactElement } from "react"; import { Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Input, Label, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@arronqzy/ui"; import type { BlueprintLibraryListItem } from "../library/types"; import type { LifecycleNodeOption } from "../hooks/useBlueprintDebugSession"; import { type PageLifecyclePhase } from "@arronqzy/blueprint-dsl"; import { useI18n } from "@arronqzy/i18n/react"; import { getLifecyclePhaseLabel } from "../graph/document"; export type BlueprintRenameDialogProps = { open: boolean; initialName: string; onOpenChange: (open: boolean) => void; onConfirm: (name: string) => void; }; export function BlueprintRenameDialog({ open, initialName, onOpenChange, onConfirm, }: BlueprintRenameDialogProps) { const { t } = useI18n(); const [name, setName] = useState(initialName); useEffect(() => { if (!open) return; setName(initialName); }, [initialName, open]); const handleConfirm = () => { const next = name.trim(); if (!next) return; onConfirm(next); onOpenChange(false); }; return ( {t("blueprint.dialog.renameTitle")} {t("blueprint.dialog.renameDescription")}
setName(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") handleConfirm(); }} autoFocus />
); } function IconSave() { return ( ); } function IconSync() { return ( ); } function IconPencil() { return ( ); } function IconTrash() { return ( ); } function IconChevronDown() { return ( ); } export type BlueprintDeleteDialogProps = { open: boolean; blueprintName: string; onOpenChange: (open: boolean) => void; onConfirm: () => void; }; export function BlueprintDeleteDialog({ open, blueprintName, onOpenChange, onConfirm, }: BlueprintDeleteDialogProps) { const { t } = useI18n(); return ( {t("blueprint.dialog.deleteTitle")} {t("blueprint.dialog.deleteDescription", { name: blueprintName })} ); } function IconLog({ className }: { className?: string }) { return ( ); } /** 快进:双三角,表示走完全流程 */ function IconRunAll({ className }: { className?: string }) { return ( ); } /** 单三角播放:表示单步执行下一步 */ function IconStepNext({ className }: { className?: string }) { return ( ); } /** 左向三角:回到上一步 */ function IconStepBack({ className }: { className?: string }) { return ( ); } /** 回到开始:竖线 + 左向三角 */ function IconResetToStart({ className }: { className?: string }) { return ( ); } export type BlueprintDebugToolbarProps = { lifecycleNodes: LifecycleNodeOption[]; selectedLifecycleNodeId: string | null; onSelectLifecycleNode: (id: string | null) => void; onRunAll: () => void; onResetToStart: () => void; onStepBack: () => void; onStepNext: () => void; canResetToStart?: boolean; canStepBack?: boolean; canStepNext?: boolean; chainComplete?: boolean; falseSignalHalt?: boolean; logPanelOpen: boolean; onToggleLogPanel: () => void; running?: boolean; }; export type BlueprintPanelToolbarProps = { items: BlueprintLibraryListItem[]; activeId: string | null; /** 未选中库蓝图时,下拉触发器展示的工作区蓝图名称 */ currentBlueprintLabel?: string; onSelectItem: (id: string) => void; onRenameItem: (id: string, name: string) => void; onDeleteItem: (id: string) => void; onSave: () => void; onSync?: () => void; canSync?: boolean; debug?: BlueprintDebugToolbarProps; }; function groupItems(items: BlueprintLibraryListItem[]) { return { saved: items.filter((item) => item.source === "saved"), imported: items.filter((item) => item.source === "imported"), }; } function ToolbarTooltip({ content, children, }: { content: string; children: ReactElement; }) { return ( {children} {content} ); } function ToolbarTooltipButton({ content, disabled, className, ...props }: React.ComponentProps & { content: string }) { const button = ( ); return (
{active ? ( {nameButton} ) : ( nameButton )}
); } export function BlueprintPanelToolbar({ items, activeId, currentBlueprintLabel, onSelectItem, onRenameItem, onDeleteItem, onSave, onSync, canSync = false, debug, }: BlueprintPanelToolbarProps) { const { t } = useI18n(); const [menuOpen, setMenuOpen] = useState(false); const [renameTarget, setRenameTarget] = useState( null ); const [deleteTarget, setDeleteTarget] = useState( null ); const activeItem = items.find((item) => item.id === activeId) ?? null; const { saved, imported } = groupItems(items); const triggerLabel = activeItem?.name ?? (currentBlueprintLabel?.trim() || (items.length > 0 ? t("blueprint.toolbar.library") : t("blueprint.toolbar.libraryEmpty"))); const handleRenameConfirm = (name: string) => { if (!renameTarget) return; onRenameItem(renameTarget.id, name); setRenameTarget(null); }; return ( <>
{menuOpen && items.length > 0 ? ( <>
setMenuOpen(false)} aria-hidden="true" />
{saved.length > 0 ? (
{t("blueprint.toolbar.saved")}
{saved.map((item) => ( { onSelectItem(item.id); setMenuOpen(false); }} onRename={() => setRenameTarget(item)} onDelete={() => setDeleteTarget(item)} /> ))}
) : null} {imported.length > 0 ? (
{t("blueprint.toolbar.imported")}
{imported.map((item) => ( { onSelectItem(item.id); setMenuOpen(false); }} onRename={() => setRenameTarget(item)} onDelete={() => setDeleteTarget(item)} /> ))}
) : null}
) : null}
{onSync ? ( ) : null} {debug && debug.lifecycleNodes.length > 0 ? ( <> void debug.onRunAll()} > void debug.onResetToStart()} > void debug.onStepBack()} > void debug.onStepNext()} > ) : null}
{ if (!open) setRenameTarget(null); }} onConfirm={handleRenameConfirm} /> { if (!open) setDeleteTarget(null); }} onConfirm={() => { if (!deleteTarget) return; onDeleteItem(deleteTarget.id); setDeleteTarget(null); }} /> ); }