102 lines
2.5 KiB
TypeScript
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;
|
|
}
|