feat: 统一图表悬浮展开入口
This commit is contained in:
1 parent
67d561a408
commit
cd4e0df1a3
4 files changed
+67
-15
No files matched your search
@@ -115,6 +115,7 @@ describe("diagram editor canvas surface", () => {
|
||||
test("organizes architecture resources in a searchable category library", () => {
|
||||
expect(source).toContain("ARCHITECTURE_LIBRARY_CATEGORIES");
|
||||
expect(source).toContain('t("diagram.componentLibrary")');
|
||||
expect(source).toContain('onPointerEnter={() => setOpen(true)}');
|
||||
expect(source).toContain('t("diagram.componentSearch")');
|
||||
expect(source).toContain('labelKey: "diagram.componentCategoryExperience"');
|
||||
expect(source).toContain('labelKey: "diagram.componentCategoryServices"');
|
||||
@@ -141,6 +142,16 @@ describe("diagram editor canvas surface", () => {
|
||||
expect(source).not.toContain('className="line-clamp-2"');
|
||||
});
|
||||
|
||||
test("opens every diagram insertion library immediately on pointer hover", () => {
|
||||
expect(source).toContain("const DiagramInsertMenu = ({");
|
||||
expect(source.match(/onPointerEnter=\{\(\) => setOpen\(true\)\}/g)?.length).toBe(2);
|
||||
expect(source).toContain('label={t("diagram.addTopic")}');
|
||||
expect(source).toContain('label: t("diagram.addSiblingTopic")');
|
||||
expect(source).toContain('label={t("diagram.addStep")}');
|
||||
expect(source).toContain('label: t("diagram.addDecision")');
|
||||
expect(source).toContain('label: t("diagram.addTerminator")');
|
||||
});
|
||||
|
||||
test("shows connection handles only on selected flowchart nodes", () => {
|
||||
expect(globalStyles).toContain('.x6-node.edgeever-flow-node-active .edgeever-flow-port-dot');
|
||||
expect(globalStyles).toContain('.x6-port-body:hover .edgeever-flow-port-dot');
|
||||
|
||||
@@ -322,7 +322,9 @@ const ArchitectureComponentLibrary = ({
|
||||
if (!nextOpen) setQuery("");
|
||||
}}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button size="sm" variant="outline"><Boxes className="h-4 w-4" />{t("diagram.componentLibrary")}</Button>
|
||||
<Button size="sm" variant="outline" onPointerEnter={() => setOpen(true)}>
|
||||
<Boxes className="h-4 w-4" />{t("diagram.componentLibrary")}
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start" className="max-h-[min(36rem,calc(100vh-8rem))] w-[min(30rem,calc(100vw-2rem))] overflow-y-auto p-0">
|
||||
<div className="sticky top-0 z-10 border-b border-slate-200 bg-white p-2.5">
|
||||
@@ -385,6 +387,40 @@ const ArchitectureComponentLibrary = ({
|
||||
);
|
||||
};
|
||||
|
||||
const DiagramInsertMenu = ({
|
||||
icon: TriggerIcon,
|
||||
items,
|
||||
label,
|
||||
}: {
|
||||
icon: LucideIcon;
|
||||
items: Array<{ icon: LucideIcon; label: string; onSelect: () => void }>;
|
||||
label: string;
|
||||
}) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
return (
|
||||
<DropdownMenu open={open} onOpenChange={setOpen}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button size="sm" variant="soft" onPointerEnter={() => setOpen(true)}>
|
||||
<TriggerIcon className="h-4 w-4" />
|
||||
{label}
|
||||
<ChevronDown className="h-3.5 w-3.5 text-slate-400" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start">
|
||||
{items.map((item) => {
|
||||
const Icon = item.icon;
|
||||
return (
|
||||
<DropdownMenuItem key={item.label} onSelect={item.onSelect}>
|
||||
<Icon className="h-4 w-4" />
|
||||
{item.label}
|
||||
</DropdownMenuItem>
|
||||
);
|
||||
})}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
};
|
||||
|
||||
const FLOW_ACTIVE_NODE_CLASS = "edgeever-flow-node-active";
|
||||
const FLOW_PORT_HIT_RADIUS = 14;
|
||||
const FLOW_PORT_DOT_RADIUS = 7;
|
||||
@@ -2074,12 +2110,14 @@ export const DiagramEditorPane = ({
|
||||
<div className="flex shrink-0 flex-wrap items-center gap-1 border-b border-slate-200 bg-white px-3 py-2">
|
||||
{!readOnly && (
|
||||
document.kind === "mind-map" ? (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button size="sm" variant="soft" onClick={() => addNode("topic")}><GitBranch className="h-4 w-4" />{t("diagram.addTopic")}</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t("diagram.mindMapShortcuts")}</TooltipContent>
|
||||
</Tooltip>
|
||||
<DiagramInsertMenu
|
||||
icon={GitBranch}
|
||||
label={t("diagram.addTopic")}
|
||||
items={[
|
||||
{ icon: GitBranch, label: t("diagram.addTopic"), onSelect: () => addNode("topic", { relation: "child" }) },
|
||||
{ icon: ListTree, label: t("diagram.addSiblingTopic"), onSelect: () => addNode("topic", { relation: "sibling" }) },
|
||||
]}
|
||||
/>
|
||||
) : document.kind === "architecture" ? (
|
||||
<>
|
||||
<ArchitectureComponentLibrary
|
||||
@@ -2093,14 +2131,15 @@ export const DiagramEditorPane = ({
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button size="sm" variant="soft" onClick={() => addNode("process")}><Box className="h-4 w-4" />{t("diagram.addStep")}</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t("diagram.flowchartShortcuts")}</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip><TooltipTrigger asChild><Button size="sm" variant="ghost" aria-label={t("diagram.addDecision")} onClick={() => addNode("decision")}><Diamond className="h-4 w-4" /></Button></TooltipTrigger><TooltipContent>{t("diagram.addDecision")}</TooltipContent></Tooltip>
|
||||
<Tooltip><TooltipTrigger asChild><Button size="sm" variant="ghost" aria-label={t("diagram.addTerminator")} onClick={() => addNode("terminator")}><Circle className="h-4 w-4" /></Button></TooltipTrigger><TooltipContent>{t("diagram.addTerminator")}</TooltipContent></Tooltip>
|
||||
<DiagramInsertMenu
|
||||
icon={Box}
|
||||
label={t("diagram.addStep")}
|
||||
items={[
|
||||
{ icon: Box, label: t("diagram.addStep"), onSelect: () => addNode("process") },
|
||||
{ icon: Diamond, label: t("diagram.addDecision"), onSelect: () => addNode("decision") },
|
||||
{ icon: Circle, label: t("diagram.addTerminator"), onSelect: () => addNode("terminator") },
|
||||
]}
|
||||
/>
|
||||
<span className="hidden items-center gap-1.5 px-2 text-xs text-slate-500 xl:flex"><Link2 className="h-3.5 w-3.5" />{t("diagram.connectHint")}</span>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -250,6 +250,7 @@ export const enUS = {
|
||||
title: "Diagram title",
|
||||
canvas: "{{type}} canvas",
|
||||
addTopic: "Add child topic",
|
||||
addSiblingTopic: "Add sibling topic",
|
||||
mindMapShortcuts: "Tab adds a child; Enter adds a sibling",
|
||||
addStep: "Add step",
|
||||
flowchartShortcuts: "Tab connects the next node; Enter edits; Cmd/Ctrl+D duplicates; arrow keys nudge",
|
||||
|
||||
@@ -250,6 +250,7 @@ export const zhCN = {
|
||||
title: "图表标题",
|
||||
canvas: "{{type}}画布",
|
||||
addTopic: "添加子主题",
|
||||
addSiblingTopic: "添加同级主题",
|
||||
mindMapShortcuts: "Tab 添加子主题,Enter 添加同级主题",
|
||||
addStep: "添加步骤",
|
||||
flowchartShortcuts: "Tab 连接后续节点,Enter 编辑,⌘/Ctrl+D 复制,方向键微调",
|
||||
|
||||
Reference in new issue
Block a user