Files
next-tjwater-drainage-frontend/features/map/core/components/annotation-panel.tsx
T

102 lines
2.5 KiB
TypeScript

import type { LucideIcon } from "lucide-react";
import { Download, ListChecks, MapPinned, Plus, Share2 } from "lucide-react";
import { cn } from "@/lib/utils";
import {
MapActionRow,
MapPanelSection
} from "./control-panel";
import {
MAP_READABLE_RADIUS_CLASS_NAME,
MAP_READABLE_SURFACE_CLASS_NAME
} from "./map-control-styles";
export type MapAnnotationItem = {
id: string;
label: string;
description: string;
icon?: LucideIcon;
status?: string;
selected?: boolean;
muted?: boolean;
onClick?: () => void;
};
export type MapAnnotationShareAction = {
id: string;
label: string;
description: string;
icon?: LucideIcon;
onClick?: () => void;
};
export type MapAnnotationPanelProps = {
annotations: MapAnnotationItem[];
shareActions?: MapAnnotationShareAction[];
emptyText?: string;
};
export function MapAnnotationPanel({
annotations,
shareActions = [],
emptyText = "暂无标注"
}: MapAnnotationPanelProps) {
return (
<div className="space-y-3">
<MapPanelSection title="标注列表">
{annotations.length > 0 ? (
annotations.map((annotation) => (
<MapActionRow
key={annotation.id}
icon={annotation.icon ?? getDefaultAnnotationIcon(annotation.status)}
label={annotation.label}
description={annotation.description}
status={annotation.status}
selected={annotation.selected}
muted={annotation.muted}
onClick={annotation.onClick}
/>
))
) : (
<div className={cn("px-3 py-2 text-xs text-slate-500", MAP_READABLE_RADIUS_CLASS_NAME, MAP_READABLE_SURFACE_CLASS_NAME)}>
{emptyText}
</div>
)}
</MapPanelSection>
{shareActions.length > 0 ? (
<MapPanelSection title="共享">
{shareActions.map((action) => (
<MapActionRow
key={action.id}
icon={action.icon ?? getDefaultShareIcon(action.id)}
label={action.label}
description={action.description}
onClick={action.onClick}
/>
))}
</MapPanelSection>
) : null}
</div>
);
}
function getDefaultAnnotationIcon(status?: string) {
if (status) {
return ListChecks;
}
return MapPinned;
}
function getDefaultShareIcon(actionId: string) {
if (actionId.includes("export") || actionId.includes("download")) {
return Download;
}
if (actionId.includes("share")) {
return Share2;
}
return Plus;
}