feat: initialize drainage network frontend
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
"use client";
|
||||
|
||||
import type { LucideIcon } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger
|
||||
} from "@/shared/ui/tooltip";
|
||||
import {
|
||||
MAP_CONTROL_HOVER_CLASS_NAME,
|
||||
MAP_CONTROL_RADIUS_CLASS_NAME,
|
||||
MAP_ICON_CELL_RADIUS_CLASS_NAME,
|
||||
MAP_CONTROL_SURFACE_CLASS_NAME
|
||||
} from "./map-control-styles";
|
||||
|
||||
export type MapToolbarItem = {
|
||||
id: string;
|
||||
label: string;
|
||||
description?: string;
|
||||
icon: LucideIcon;
|
||||
active?: boolean;
|
||||
disabled?: boolean;
|
||||
badge?: string | number;
|
||||
onClick?: () => void;
|
||||
};
|
||||
|
||||
type MapToolbarProps = {
|
||||
items: MapToolbarItem[];
|
||||
label?: string;
|
||||
orientation?: "vertical" | "horizontal";
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export function MapToolbar({
|
||||
items,
|
||||
label = "地图工具",
|
||||
orientation = "vertical",
|
||||
className = ""
|
||||
}: MapToolbarProps) {
|
||||
const isVertical = orientation === "vertical";
|
||||
|
||||
return (
|
||||
<TooltipProvider delayDuration={180}>
|
||||
<nav
|
||||
aria-label={label}
|
||||
className={cn(
|
||||
"pointer-events-auto p-[3px]",
|
||||
MAP_CONTROL_RADIUS_CLASS_NAME,
|
||||
MAP_CONTROL_SURFACE_CLASS_NAME,
|
||||
isVertical ? "flex w-[46px] flex-col" : "inline-flex",
|
||||
className
|
||||
)}
|
||||
>
|
||||
{items.map((tool, index) => {
|
||||
const Icon = tool.icon;
|
||||
const title = tool.description ? `${tool.label}:${tool.description}` : tool.label;
|
||||
|
||||
return (
|
||||
<div key={tool.id} className={cn(isVertical ? "contents" : "flex items-center")}>
|
||||
{index > 0 ? <ToolbarDivider vertical={isVertical} /> : null}
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
aria-label={title}
|
||||
aria-pressed={tool.active}
|
||||
disabled={tool.disabled}
|
||||
onClick={tool.onClick}
|
||||
className={cn(
|
||||
"relative grid h-[38px] w-[38px] shrink-0 place-items-center text-slate-700 transition duration-150",
|
||||
MAP_ICON_CELL_RADIUS_CLASS_NAME,
|
||||
"focus-visible:z-10 focus-visible:outline focus-visible:outline-2 focus-visible:outline-slate-900 focus-visible:outline-offset-2",
|
||||
tool.active
|
||||
? "bg-blue-50 text-blue-800 ring-1 ring-blue-300/70 hover:bg-blue-100 hover:text-blue-900"
|
||||
: MAP_CONTROL_HOVER_CLASS_NAME,
|
||||
tool.disabled && "cursor-not-allowed text-slate-400 opacity-60 hover:bg-transparent hover:text-slate-400 hover:ring-0 active:bg-transparent"
|
||||
)}
|
||||
>
|
||||
<Icon size={20} strokeWidth={2.15} aria-hidden="true" />
|
||||
<span className="sr-only">{tool.label}</span>
|
||||
{tool.badge ? (
|
||||
<span className="absolute -right-1 -top-1 grid min-w-4 place-items-center rounded-full bg-red-500 px-1 text-xs font-semibold leading-4 text-white ring-2 ring-white">
|
||||
{tool.badge}
|
||||
</span>
|
||||
) : null}
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
side={isVertical ? "left" : "top"}
|
||||
sideOffset={8}
|
||||
className="border border-slate-200 bg-white px-2.5 py-1.5 text-xs font-medium text-slate-800 shadow-lg"
|
||||
>
|
||||
{title}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
</TooltipProvider>
|
||||
);
|
||||
}
|
||||
|
||||
function ToolbarDivider({ vertical }: { vertical: boolean }) {
|
||||
if (vertical) {
|
||||
return (
|
||||
<div
|
||||
className="my-0.5 flex h-px w-full items-center justify-center"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<span className="block h-px w-3.5 bg-slate-300/70" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="mx-0.5 flex h-full w-px items-center justify-center"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<span className="block h-3.5 w-px bg-slate-300/70" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user