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

400 lines
12 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} />;
default:
2026-02-02 10:53:43 +01:00
throw new Error(`Invalid icon type: ${type satisfies never}`);
2025-08-28 18:27:07 +02:00
}
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
2025-10-10 16:18:43 +02:00
className="flex flex-col items-center rounded-xl bg-muted p-2 hover:opacity-75"
2025-08-29 16:18:32 +02:00
key={icon}
2025-08-28 18:27:07 +02:00
onClick={async () => {
await navigator.clipboard.writeText(icon);
toast("Copiato", { icon: "📋" });
}}
2025-08-29 16:18:32 +02:00
type="button"
2025-08-28 18:27:07 +02:00
>
2025-08-29 16:18:32 +02:00
<IconMatrix className="size-6" type={icon} />
2025-08-28 18:27:07 +02:00
<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
className={className}
2025-08-29 16:18:32 +02:00
fill="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
2025-08-28 18:27:07 +02:00
>
<title>Shield</title>
<path
clipRule="evenodd"
2025-08-29 16:18:32 +02:00
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"
fillRule="evenodd"
2025-08-28 18:27:07 +02:00
/>
</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
className={className}
2025-08-29 16:18:32 +02:00
fill="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
2025-08-28 18:27:07 +02:00
>
<title>QuestionMark</title>
<path
clipRule="evenodd"
2025-08-29 16:18:32 +02:00
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"
fillRule="evenodd"
2025-08-28 18:27:07 +02:00
/>
</svg>
2025-08-04 17:45:44 +02:00
);
export const HomeIcon = ({ className }: { className?: string }) => (
2025-08-28 18:27:07 +02:00
<svg
2025-08-29 16:18:32 +02:00
className={className}
2025-08-28 18:27:07 +02:00
fill="none"
stroke="currentColor"
2025-08-29 16:18:32 +02:00
strokeWidth={1.5}
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
2025-08-28 18:27:07 +02:00
>
<title>Home</title>
<path
2025-08-29 16:18:32 +02:00
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"
2025-08-28 18:27:07 +02:00
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
2025-08-04 17:45:44 +02:00
);
const CheckCircleIcon = ({ className }: { className?: string }) => (
2025-08-28 18:27:07 +02:00
<svg
className={className}
2025-08-29 16:18:32 +02:00
fill="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
2025-08-28 18:27:07 +02:00
>
<title>CheckCircle</title>
<path
clipRule="evenodd"
2025-08-29 16:18:32 +02:00
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"
fillRule="evenodd"
2025-08-28 18:27:07 +02:00
/>
</svg>
2025-08-04 17:45:44 +02:00
);
export const Moon2 = ({ className }: { className?: string }) => (
<svg
className={className}
fill="none"
height="15"
viewBox="0 0 15 15"
width="15"
xmlns="http://www.w3.org/2000/svg"
>
<title>Moon</title>
<path
clipRule="evenodd"
d="M2.89998 0.499976C2.89998 0.279062 2.72089 0.0999756 2.49998 0.0999756C2.27906 0.0999756 2.09998 0.279062 2.09998 0.499976V1.09998H1.49998C1.27906 1.09998 1.09998 1.27906 1.09998 1.49998C1.09998 1.72089 1.27906 1.89998 1.49998 1.89998H2.09998V2.49998C2.09998 2.72089 2.27906 2.89998 2.49998 2.89998C2.72089 2.89998 2.89998 2.72089 2.89998 2.49998V1.89998H3.49998C3.72089 1.89998 3.89998 1.72089 3.89998 1.49998C3.89998 1.27906 3.72089 1.09998 3.49998 1.09998H2.89998V0.499976ZM5.89998 3.49998C5.89998 3.27906 5.72089 3.09998 5.49998 3.09998C5.27906 3.09998 5.09998 3.27906 5.09998 3.49998V4.09998H4.49998C4.27906 4.09998 4.09998 4.27906 4.09998 4.49998C4.09998 4.72089 4.27906 4.89998 4.49998 4.89998H5.09998V5.49998C5.09998 5.72089 5.27906 5.89998 5.49998 5.89998C5.72089 5.89998 5.89998 5.72089 5.89998 5.49998V4.89998H6.49998C6.72089 4.89998 6.89998 4.72089 6.89998 4.49998C6.89998 4.27906 6.72089 4.09998 6.49998 4.09998H5.89998V3.49998ZM1.89998 6.49998C1.89998 6.27906 1.72089 6.09998 1.49998 6.09998C1.27906 6.09998 1.09998 6.27906 1.09998 6.49998V7.09998H0.499976C0.279062 7.09998 0.0999756 7.27906 0.0999756 7.49998C0.0999756 7.72089 0.279062 7.89998 0.499976 7.89998H1.09998V8.49998C1.09998 8.72089 1.27906 8.89997 1.49998 8.89997C1.72089 8.89997 1.89998 8.72089 1.89998 8.49998V7.89998H2.49998C2.72089 7.89998 2.89998 7.72089 2.89998 7.49998C2.89998 7.27906 2.72089 7.09998 2.49998 7.09998H1.89998V6.49998ZM8.54406 0.98184L8.24618 0.941586C8.03275 0.917676 7.90692 1.1655 8.02936 1.34194C8.17013 1.54479 8.29981 1.75592 8.41754 1.97445C8.91878 2.90485 9.20322 3.96932 9.20322 5.10022C9.20322 8.37201 6.82247 11.0878 3.69887 11.6097C3.45736 11.65 3.20988 11.6772 2.96008 11.6906C2.74563 11.702 2.62729 11.9535 2.77721 12.1072C2.84551 12.1773 2.91535 12.2458 2.98667 12.3128L3.05883 12.3795L3.31883 12.6045L3.50684 12.7532L3.62796 12.8433L3.81491 12.9742L3.99079 13.089C4.11175 13.1651 4.23536 13.2375 4.36157 13.3059L4.62496 13.4412L4.88553 13.5607L5.18837 13.6828L5.43169 13.7686C5.56564 13.8128 5.70149 13.8529 5.83857 13.8885C5.94262 13.9155 6.04767 13.9401 6.15405 13.9622C6.27993 13.9883 6.40713 14.0109 6.53544 14.0298L6.85241 14.0685L7.11934 14.0892C7.24637 14.0965 7.37436 14.1002 7.50322 14.1002C11.1483 14.1002 14.1032 11.1453 14.1032 7.50023C14.1032 7.25044 14.0893 7.00389 14.0623 6.76131L14.0255 6.48407C13.991 6.26083 13.9453 6.04129 13.8891 5.82642C13.8213 5.56709 13.7382 5.31398 13.6409 5.06881L13.5279 4.80132L13.4507 4.63542L13.3766 4.48666C13.2178 4.17773 13.0353 3.88295 12.8312 3.60423L12.6782 3.40352L12.4793 3.16432L12.3157 2.98361L12.1961 2.85951L12.0355 2.70246L11.8134 2.50184L11.4925 2.24191L11.2483 2.06498L10.9562 1.87446L10.6346 1.68894L10.3073 1.52378L10.1938 1.47176L9.95488 1.3706L9.67791 1.2669L9.42566 1.1846L9.10075 1.09489L8.83599 1.03486L8.54406 0.98184ZM10.4032 5.30023C10.4032 4.27588 10.2002 3.29829 9.83244 2.40604C11.7623 3.28995 13.1032 5.23862 13.1032 7.50023C13.1032 10.593 10.596 13.1002 7.50322 13.1002C6.63646 13.1002 5.81597 12.9036 5.08355 12.5522C6.5419 12.0941 7.81081 11.2082 8.74322 10.0416C8.87963 10.2284 9.10028 10.3497 9.34928 10.3497C9.76349 10.3497 10.0993 10.0139 10.0993 9.59971C10.0993 9.24256 9.84965 8.94373 9.51535 8.86816C9.57741 8.75165 9.63653 8.63334 9.6926 8.51332C9.88358 8.63163 10.1088 8.69993 10.35 8.69993C11.0403 8.69993 11.6 8.14028 11.6 7.44993C11.6 6.75976 11.0406 6.20024 10.3505 6.19993C10.3853 5.90487 10.4032 5.60464 10.4032 5.30023Z"
fill="currentColor"
fillRule="evenodd"
></path>
</svg>
);