Files
cadSet/cad-agent-studio/src/components/embedded-cad-toolbar.tsx
T
2026-07-27 17:24:04 +08:00

170 lines
4.7 KiB
TypeScript

"use client";
import type { ReactNode } from "react";
import {
CircleDot,
CircleDotDashed,
CornerDownRight,
Disc,
Drill,
Focus,
Grid2X2Plus,
LassoSelect,
MousePointerClick,
Orbit,
Radius,
SquareDashed,
SquareSplitHorizontal,
} from "lucide-react";
import { AiSelectionMode, CAD_EDIT_TOOLS } from "@/lib/cad-edit-tools";
const EDIT_TOOL_ICONS = {
add_hole: Drill,
add_counterbore: CircleDot,
add_countersink: CircleDotDashed,
add_slot: SquareSplitHorizontal,
add_pocket: SquareDashed,
add_circular_pocket: Disc,
add_hole_pattern: Grid2X2Plus,
add_chamfer: CornerDownRight,
add_fillet: Radius,
};
function ToolbarButton({
label,
active = false,
disabled = false,
children,
onClick,
}: {
label: string;
active?: boolean;
disabled?: boolean;
children: ReactNode;
onClick?: () => void;
}) {
return (
<button
type="button"
aria-label={label}
aria-pressed={active}
title={label}
disabled={disabled}
onClick={onClick}
className={[
"grid size-7 place-items-center rounded-md border text-[#c9cccf] transition",
active
? "border-[#39434b] bg-[#22272c] text-[#f2f4f4] shadow-[inset_0_0_0_1px_rgba(232,232,227,0.08)]"
: "border-transparent hover:border-[#39434b] hover:bg-[#22272c] hover:text-[#f2f4f4]",
disabled ? "cursor-not-allowed opacity-40 hover:border-transparent hover:bg-transparent" : "",
].join(" ")}
>
{children}
</button>
);
}
function Divider() {
return <span className="mx-0.5 h-5 w-px shrink-0 bg-[#39434b]/80" aria-hidden="true" />;
}
export function EmbeddedCadEditToolbar({
activeToolId,
aiSelectionMode,
disabled = false,
onSelectTool,
onSelectionModeChange,
}: {
activeToolId: string;
aiSelectionMode: AiSelectionMode;
disabled?: boolean;
onSelectTool: (toolId: string) => void;
onSelectionModeChange: (mode: AiSelectionMode) => void;
}) {
return (
<div
data-viewer-interaction-overlay="true"
className="pointer-events-auto absolute left-3 top-3 z-30 inline-flex h-10 max-w-[calc(100vw-1.5rem)] flex-nowrap items-center gap-1 overflow-x-auto rounded-md border border-[#2d3339] bg-[#15181b]/95 p-1.5 text-[#c9cccf] shadow-sm shadow-black/20 backdrop-blur"
role="toolbar"
aria-label="CAD 编辑工具"
onPointerDown={(event) => event.stopPropagation()}
>
<ToolbarButton
label="点选几何"
active={aiSelectionMode === "point"}
disabled={disabled}
onClick={() => {
onSelectTool("");
onSelectionModeChange("point");
}}
>
<MousePointerClick className="size-3.5" strokeWidth={2} aria-hidden="true" />
</ToolbarButton>
<ToolbarButton
label="圈选几何"
active={aiSelectionMode === "lasso"}
disabled={disabled}
onClick={() => {
onSelectTool("");
onSelectionModeChange("lasso");
}}
>
<LassoSelect className="size-3.5" strokeWidth={2} aria-hidden="true" />
</ToolbarButton>
<Divider />
{CAD_EDIT_TOOLS.map((tool) => {
const Icon = EDIT_TOOL_ICONS[tool.id as keyof typeof EDIT_TOOL_ICONS] || Drill;
const active = activeToolId === tool.id;
return (
<ToolbarButton
key={tool.id}
label={tool.label}
active={active}
disabled={disabled}
onClick={() => {
if (active) {
onSelectTool("");
onSelectionModeChange("point");
return;
}
onSelectTool(tool.id);
onSelectionModeChange("none");
}}
>
<Icon className="size-3.5" strokeWidth={2} aria-hidden="true" />
</ToolbarButton>
);
})}
</div>
);
}
export function EmbeddedCadViewToolbar({
disabled = false,
onResetView,
onScreenshot,
}: {
disabled?: boolean;
onResetView: () => void;
onScreenshot?: () => void;
}) {
return (
<div
data-viewer-interaction-overlay="true"
className="pointer-events-auto absolute right-3 top-3 z-30 inline-flex min-h-10 items-center gap-1 rounded-md border border-[#2d3339] bg-[#15181b]/95 p-1.5 text-[#c9cccf] shadow-sm shadow-black/20 backdrop-blur"
role="toolbar"
aria-label="CAD 预览工具"
onPointerDown={(event) => event.stopPropagation()}
>
<ToolbarButton label="Orbit" disabled={disabled} onClick={onResetView}>
<Orbit className="size-3.5" strokeWidth={2} aria-hidden="true" />
</ToolbarButton>
<ToolbarButton label="Copy screenshot" disabled={disabled || !onScreenshot} onClick={onScreenshot}>
<Focus className="size-3.5" strokeWidth={2} aria-hidden="true" />
</ToolbarButton>
</div>
);
}