170 lines
4.7 KiB
TypeScript
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>
|
|
);
|
|
}
|