infoalloggi-monorepo/apps/infoalloggi/src/components/IconComponents.tsx

379 lines
8.8 KiB
TypeScript
Raw Normal View History

2025-08-04 17:45:44 +02:00
import {
2025-08-28 18:27:07 +02:00
Accessibility,
ArrowLeft,
ArrowRight,
Baby,
BellRing,
Building,
Building2,
CircleDot,
CircleParking,
CirclePlus,
CircleX,
Cog,
Contact,
Cross,
Dot,
Euro,
FerrisWheel,
Film,
GraduationCap,
Heart,
Heater,
House,
Info,
LayoutDashboard,
type LucideProps,
Mail,
MessageSquareText,
MessagesSquare,
Milestone,
Paperclip,
Pointer,
Search,
ShoppingCart,
SlidersHorizontal,
Sofa,
Star,
Target,
ThermometerSun,
ThumbsUp,
Trees,
TriangleAlert,
User,
Users,
Wifi,
2025-08-04 17:45:44 +02:00
} from "lucide-react";
import type {
2025-08-28 18:27:07 +02:00
ComponentPropsWithoutRef,
ForwardRefExoticComponent,
RefAttributes,
2025-08-04 17:45:44 +02:00
} from "react";
2025-08-28 18:27:07 +02:00
import toast from "react-hot-toast";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "~/components/ui/tooltip";
2025-08-04 17:45:44 +02:00
const iconOptions = [
2025-08-28 18:27:07 +02:00
"heater",
"error",
"warning",
"sofa",
"building",
"building2",
"wifi",
"accessibility",
"baby",
"thermometer-sun",
"circle-plus",
"circle-dot",
"dot",
"cog",
"check",
"search",
"contact",
"euro",
"dashboard",
"settings",
"user",
"users",
"messages",
"message",
"arrowR",
"arrowL",
"attachment",
"cart",
"star",
"house",
"heart",
"info",
"mail",
"school",
"cross",
"park",
"parking",
"film",
"milestone",
"entertainment",
"circle-help",
"bell",
"target",
"thumbs-up",
2025-08-04 17:45:44 +02:00
] as const;
export type IconType = (typeof iconOptions)[number];
type LucidePropsType = ForwardRefExoticComponent<
2025-08-28 18:27:07 +02:00
Omit<LucideProps, "ref"> & RefAttributes<SVGSVGElement>
2025-08-04 17:45:44 +02:00
>;
interface IconMatrixProps extends ComponentPropsWithoutRef<LucidePropsType> {
2025-08-28 18:27:07 +02:00
type: IconType;
2025-08-04 17:45:44 +02:00
}
export const IconMatrix = ({ type, ...rest }: IconMatrixProps) => {
2025-08-28 18:27:07 +02:00
switch (type) {
case "heater":
return <Heater {...rest} />;
case "error":
return <CircleX {...rest} />;
case "warning":
return <TriangleAlert {...rest} />;
case "sofa":
return <Sofa {...rest} />;
case "building":
return <Building {...rest} />;
case "building2":
return <Building2 {...rest} />;
case "wifi":
return <Wifi {...rest} />;
case "accessibility":
return <Accessibility {...rest} />;
case "baby":
return <Baby {...rest} />;
case "thermometer-sun":
return <ThermometerSun {...rest} />;
case "circle-plus":
return <CirclePlus {...rest} />;
case "circle-dot":
return <CircleDot {...rest} />;
case "dot":
return <Dot {...rest} />;
case "cog":
return <Cog {...rest} />;
case "check":
return <CheckCircleIcon {...rest} />;
case "search":
return <Search {...rest} />;
case "contact":
return <Contact {...rest} />;
case "euro":
return <Euro {...rest} />;
case "dashboard":
return <LayoutDashboard {...rest} />;
case "settings":
return <SlidersHorizontal {...rest} />;
case "user":
return <User {...rest} />;
case "users":
return <Users {...rest} />;
case "messages":
return <MessagesSquare {...rest} />;
case "message":
return <MessageSquareText {...rest} />;
case "arrowR":
return <ArrowRight {...rest} />;
case "arrowL":
return <ArrowLeft {...rest} />;
case "attachment":
return <Paperclip {...rest} />;
case "cart":
return <ShoppingCart {...rest} />;
case "star":
return <Star {...rest} />;
case "house":
return <House {...rest} />;
case "heart":
return <Heart {...rest} />;
case "info":
return <Info {...rest} />;
case "mail":
return <Mail {...rest} />;
case "school":
return <GraduationCap {...rest} />;
case "cross":
return <Cross {...rest} />;
case "park":
return <Trees {...rest} />;
case "parking":
return <CircleParking {...rest} />;
case "film":
return <Film {...rest} />;
case "milestone":
return <Milestone {...rest} />;
case "entertainment":
return <FerrisWheel {...rest} />;
case "circle-help":
return <QuestionMarkCircleIcon {...rest} />;
case "bell":
return <BellRing {...rest} />;
case "target":
return <Target {...rest} />;
case "thumbs-up":
return <ThumbsUp {...rest} />;
}
2025-08-04 17:45:44 +02:00
};
export const IconMatrixTooltip = () => {
2025-08-28 18:27:07 +02:00
return (
<TooltipProvider delayDuration={300}>
<Tooltip>
<TooltipTrigger className="flex flex-row gap-1" type="button">
Lista Icone <Pointer className="size-4" />
</TooltipTrigger>
<TooltipContent>
<div className="grid grid-cols-4 gap-2">
{iconOptions.map((icon) => (
<button
type="button"
onClick={async () => {
await navigator.clipboard.writeText(icon);
toast("Copiato", { icon: "📋" });
}}
key={icon}
className="bg-muted flex flex-col items-center rounded-xl p-2 hover:opacity-75"
>
<IconMatrix type={icon} className="size-6" />
<span className="text-sm">{icon}</span>
</button>
))}
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
2025-08-04 17:45:44 +02:00
};
/*
type IRP_readOnly = {
readOnly: true;
value: number;
setValue?: never;
};
type IRP_dynamic = {
readOnly?: false;
value: number;
setValue: (value: number) => void;
};
type IconRatingProps = {
maxRating?: number;
icon: IconType;
outline?: boolean;
zeroable?: boolean;
iconClassName?: string;
} & (IRP_readOnly | IRP_dynamic);
export const IconRatingComonent = ({
maxRating = 5,
value,
setValue,
icon,
outline = false,
zeroable = false,
iconClassName,
readOnly = false,
}: IconRatingProps) => {
return (
<div
className={cn(
"flex justify-center",
!readOnly &&
(outline
? "[&>*:has(~*:hover)]:stroke-yellow-500 [&>*:hover]:stroke-yellow-500"
: "[&>*:has(~*:hover)]:fill-yellow-500 [&>*:hover]:fill-yellow-500"),
)}
>
{Array.from({ length: maxRating }, (_, i) => (
<IconMatrix
type={icon}
key={i}
className={cn(
"size-10 px-1",
iconClassName,
outline ? "fill-none stroke-neutral-300" : "fill-neutral-300 stroke-none",
i < value
? outline
? "stroke-yellow-500"
: "fill-yellow-500"
: "",
)}
{...(!readOnly &&
setValue != undefined && {
onClick: () => {
if (zeroable && value == 1 && i == 0) {
setValue(0);
} else {
setValue(i + 1);
}
},
})}
/>
))}
</div>
);
};
*/
export const ShieldExclamationIcon = ({
2025-08-28 18:27:07 +02:00
className,
2025-08-04 17:45:44 +02:00
}: {
2025-08-28 18:27:07 +02:00
className?: string;
2025-08-04 17:45:44 +02:00
}) => (
2025-08-28 18:27:07 +02:00
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className={className}
>
<title>Shield</title>
<path
fillRule="evenodd"
d="M11.484 2.17a.75.75 0 0 1 1.032 0 11.209 11.209 0 0 0 7.877 3.08.75.75 0 0 1 .722.515 12.74 12.74 0 0 1 .635 3.985c0 5.942-4.064 10.933-9.563 12.348a.749.749 0 0 1-.374 0C6.314 20.683 2.25 15.692 2.25 9.75c0-1.39.223-2.73.635-3.985a.75.75 0 0 1 .722-.516l.143.001c2.996 0 5.718-1.17 7.734-3.08ZM12 8.25a.75.75 0 0 1 .75.75v3.75a.75.75 0 0 1-1.5 0V9a.75.75 0 0 1 .75-.75ZM12 15a.75.75 0 0 0-.75.75v.008c0 .414.336.75.75.75h.008a.75.75 0 0 0 .75-.75v-.008a.75.75 0 0 0-.75-.75H12Z"
clipRule="evenodd"
/>
</svg>
2025-08-04 17:45:44 +02:00
);
export const QuestionMarkCircleIcon = ({
2025-08-28 18:27:07 +02:00
className,
2025-08-04 17:45:44 +02:00
}: {
2025-08-28 18:27:07 +02:00
className?: string;
2025-08-04 17:45:44 +02:00
}) => (
2025-08-28 18:27:07 +02:00
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className={className}
>
<title>QuestionMark</title>
<path
fillRule="evenodd"
d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm11.378-3.917c-.89-.777-2.366-.777-3.255 0a.75.75 0 0 1-.988-1.129c1.454-1.272 3.776-1.272 5.23 0 1.513 1.324 1.513 3.518 0 4.842a3.75 3.75 0 0 1-.837.552c-.676.328-1.028.774-1.028 1.152v.75a.75.75 0 0 1-1.5 0v-.75c0-1.279 1.06-2.107 1.875-2.502.182-.088.351-.199.503-.331.83-.727.83-1.857 0-2.584ZM12 18a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Z"
clipRule="evenodd"
/>
</svg>
2025-08-04 17:45:44 +02:00
);
export const HomeIcon = ({ className }: { className?: string }) => (
2025-08-28 18:27:07 +02:00
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className={className}
>
<title>Home</title>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"
/>
</svg>
2025-08-04 17:45:44 +02:00
);
const CheckCircleIcon = ({ className }: { className?: string }) => (
2025-08-28 18:27:07 +02:00
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className={className}
>
<title>CheckCircle</title>
<path
fillRule="evenodd"
d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm13.36-1.814a.75.75 0 1 0-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 0 0-1.06 1.06l2.25 2.25a.75.75 0 0 0 1.14-.094l3.75-5.25Z"
clipRule="evenodd"
/>
</svg>
2025-08-04 17:45:44 +02:00
);