feat: initialize drainage network frontend
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
"use client";
|
||||
|
||||
import type { LucideIcon } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger
|
||||
} from "@/shared/ui/tooltip";
|
||||
import {
|
||||
MAP_COMPACT_RADIUS_CLASS_NAME,
|
||||
MAP_CONTROL_SURFACE_CLASS_NAME,
|
||||
MAP_ICON_CELL_RADIUS_CLASS_NAME,
|
||||
MAP_READABLE_SURFACE_CLASS_NAME
|
||||
} from "./map-control-styles";
|
||||
|
||||
export type MapDrawTool = {
|
||||
id: string;
|
||||
label: string;
|
||||
icon: LucideIcon;
|
||||
active?: boolean;
|
||||
disabled?: boolean;
|
||||
tone?: "default" | "danger";
|
||||
onClick?: () => void;
|
||||
};
|
||||
|
||||
export type MapDrawToolbarProps = {
|
||||
items: MapDrawTool[];
|
||||
label?: string;
|
||||
className?: string;
|
||||
variant?: "compact" | "panel";
|
||||
};
|
||||
|
||||
export function MapDrawToolbar({ items, label = "绘制工具", className = "", variant = "compact" }: MapDrawToolbarProps) {
|
||||
if (variant === "panel") {
|
||||
return (
|
||||
<div
|
||||
role="toolbar"
|
||||
aria-label={label}
|
||||
className={cn("pointer-events-auto grid grid-cols-2 gap-1.5", className)}
|
||||
>
|
||||
{items.map((item) => {
|
||||
const Icon = item.icon;
|
||||
const isDanger = item.tone === "danger";
|
||||
|
||||
return (
|
||||
<button
|
||||
key={item.id}
|
||||
type="button"
|
||||
aria-pressed={item.active}
|
||||
disabled={item.disabled}
|
||||
onClick={item.onClick}
|
||||
className={cn(
|
||||
"flex min-h-10 items-center gap-2 border px-2.5 py-2 text-left text-xs font-semibold transition duration-150",
|
||||
MAP_COMPACT_RADIUS_CLASS_NAME,
|
||||
item.active
|
||||
? "border-blue-600 bg-blue-600 text-white shadow-md shadow-blue-600/20"
|
||||
: "text-slate-700 hover:border-blue-100 hover:bg-white hover:text-blue-700",
|
||||
!item.active && MAP_READABLE_SURFACE_CLASS_NAME,
|
||||
isDanger && "hover:border-red-100 hover:text-red-700",
|
||||
item.disabled &&
|
||||
"cursor-not-allowed opacity-55 hover:border-white/70 hover:bg-white/95 hover:text-slate-700"
|
||||
)}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
"grid h-7 w-7 shrink-0 place-items-center",
|
||||
MAP_ICON_CELL_RADIUS_CLASS_NAME,
|
||||
item.active ? "bg-white/16 text-white" : "bg-slate-100 text-slate-500",
|
||||
isDanger && "bg-red-50 text-red-600"
|
||||
)}
|
||||
>
|
||||
<Icon size={15} aria-hidden="true" />
|
||||
</span>
|
||||
<span className="min-w-0 truncate">{item.label}</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<TooltipProvider delayDuration={180}>
|
||||
<div
|
||||
role="toolbar"
|
||||
aria-label={label}
|
||||
className={cn(
|
||||
"pointer-events-auto inline-flex p-1",
|
||||
MAP_COMPACT_RADIUS_CLASS_NAME,
|
||||
MAP_CONTROL_SURFACE_CLASS_NAME,
|
||||
className
|
||||
)}
|
||||
>
|
||||
{items.map((item) => {
|
||||
const Icon = item.icon;
|
||||
const isDanger = item.tone === "danger";
|
||||
|
||||
return (
|
||||
<Tooltip key={item.id}>
|
||||
<TooltipTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
aria-label={item.label}
|
||||
aria-pressed={item.active}
|
||||
disabled={item.disabled}
|
||||
onClick={item.onClick}
|
||||
className={cn(
|
||||
"grid h-8 w-8 shrink-0 place-items-center text-slate-600 transition duration-150",
|
||||
MAP_ICON_CELL_RADIUS_CLASS_NAME,
|
||||
"focus-visible:outline focus-visible:outline-2 focus-visible:outline-slate-900 focus-visible:outline-offset-2",
|
||||
item.active
|
||||
? "bg-blue-600 text-white shadow-sm"
|
||||
: "hover:bg-blue-50 hover:text-blue-700",
|
||||
isDanger && "hover:bg-red-50 hover:text-red-700",
|
||||
item.disabled && "cursor-not-allowed opacity-45 hover:bg-transparent hover:text-slate-600"
|
||||
)}
|
||||
>
|
||||
<Icon size={16} aria-hidden="true" />
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
side="top"
|
||||
sideOffset={7}
|
||||
className="border border-slate-200 bg-white px-2.5 py-1.5 text-xs font-medium text-slate-800 shadow-lg"
|
||||
>
|
||||
{item.label}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</TooltipProvider>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user