106 lines
2.5 KiB
TypeScript
106 lines
2.5 KiB
TypeScript
"use client";
|
|
|
|
import type { CSSProperties } from "react";
|
|
import {
|
|
ReferenceIcon,
|
|
type ReferenceIconName,
|
|
} from "@/components/lovart/reference-icon";
|
|
import type { LucideIcon } from "lucide-react";
|
|
import type { CanvasToolbarItemConfig } from "@/lib/canvas-toolbar-config";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
type CanvasToolbarIconProps = {
|
|
item?: CanvasToolbarItemConfig | null;
|
|
iconUrl?: string | null;
|
|
fallback: LucideIcon;
|
|
className?: string;
|
|
style?: CSSProperties;
|
|
active?: boolean;
|
|
referenceName?: ReferenceIconName;
|
|
referenceSize?: number;
|
|
};
|
|
|
|
function isSvgIconUrl(url: string) {
|
|
return /^data:image\/svg\+xml/i.test(url) || /\.svg(?:[?#].*)?$/i.test(url);
|
|
}
|
|
|
|
function stripImageFilterClasses(className?: string) {
|
|
return String(className || "")
|
|
.split(/\s+/)
|
|
.filter(
|
|
(token) =>
|
|
token &&
|
|
token !== "brightness-0" &&
|
|
token !== "invert" &&
|
|
token !== "dark:invert" &&
|
|
token !== "dark:invert-0"
|
|
)
|
|
.join(" ");
|
|
}
|
|
|
|
export function CanvasToolbarIcon({
|
|
item,
|
|
iconUrl,
|
|
fallback: FallbackIcon,
|
|
className,
|
|
style,
|
|
active = false,
|
|
referenceName,
|
|
referenceSize = 18,
|
|
}: CanvasToolbarIconProps) {
|
|
const resolvedIconUrl = String(iconUrl || item?.iconUrl || "").trim();
|
|
|
|
if (resolvedIconUrl) {
|
|
if (isSvgIconUrl(resolvedIconUrl)) {
|
|
return (
|
|
<span
|
|
aria-hidden="true"
|
|
className={cn(
|
|
"inline-block shrink-0 bg-current",
|
|
stripImageFilterClasses(className)
|
|
)}
|
|
style={{
|
|
WebkitMaskImage: `url("${resolvedIconUrl}")`,
|
|
maskImage: `url("${resolvedIconUrl}")`,
|
|
WebkitMaskRepeat: "no-repeat",
|
|
maskRepeat: "no-repeat",
|
|
WebkitMaskPosition: "center",
|
|
maskPosition: "center",
|
|
WebkitMaskSize: "contain",
|
|
maskSize: "contain",
|
|
...style,
|
|
}}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<img
|
|
alt=""
|
|
aria-hidden="true"
|
|
className={cn(
|
|
"object-contain",
|
|
active
|
|
? "brightness-0 invert opacity-95"
|
|
: "brightness-0 opacity-80 dark:invert",
|
|
className
|
|
)}
|
|
src={resolvedIconUrl}
|
|
style={style}
|
|
/>
|
|
);
|
|
}
|
|
|
|
if (referenceName) {
|
|
return (
|
|
<ReferenceIcon
|
|
name={referenceName}
|
|
size={referenceSize}
|
|
className={className}
|
|
style={style}
|
|
/>
|
|
);
|
|
}
|
|
return <FallbackIcon className={className} style={style} />;
|
|
}
|