1import type { EnvironmentMachineKind } from "@t3tools/contracts";
2import { CloudIcon, LaptopIcon, MonitorIcon, ServerIcon, type LucideProps } from "lucide-react";
3import type { FunctionComponent, SVGProps } from "react";
4import { LinuxIcon } from "./Icons";
5
6// Lucide has no Apple desktops, so these two are drawn to its grammar (24
7// unit grid, 2 unit stroke, round joins) and share its prop surface so callers
8// can swap freely.
9function LucideLike(props: SVGProps<SVGSVGElement>) {
10 return (
11 <svg
12 xmlns="http://www.w3.org/2000/svg"
13 width="24"
14 height="24"
15 viewBox="0 0 24 24"
16 fill="none"
17 stroke="currentColor"
18 strokeWidth="2"
19 strokeLinecap="round"
20 strokeLinejoin="round"
21 {...props}
22 />
23 );
24}
25
26/** A Mac mini: squat rounded slab with a front-edge LED. */
27function MacMiniIcon(props: SVGProps<SVGSVGElement>) {
28 return (
29 <LucideLike {...props}>
30 <rect width="20" height="8" x="2" y="8" rx="2" />
31 <path d="M6 12h.01" />
32 </LucideLike>
33 );
34}
35
36/** A Mac Studio: the same slab twice as tall, ports along the front foot. */
37function MacStudioIcon(props: SVGProps<SVGSVGElement>) {
38 return (
39 <LucideLike {...props}>
40 <rect width="18" height="14" x="3" y="5" rx="2" />
41 <path d="M7 15h.01M11 15h.01M15 15h.01" />
42 </LucideLike>
43 );
44}
45
46const ICON_BY_KIND: Record<EnvironmentMachineKind, FunctionComponent<LucideProps>> = {
47 server: ServerIcon,
48 cloud: CloudIcon,
49 linux: LinuxIcon,
50 desktop: MonitorIcon,
51 laptop: LaptopIcon,
52 "mac-mini": MacMiniIcon,
53 "mac-studio": MacStudioIcon,
54};
55
56export const ENVIRONMENT_MACHINE_KIND_LABELS: Record<EnvironmentMachineKind, string> = {
57 server: "Server",
58 cloud: "Cloud VM",
59 linux: "Linux/WSL",
60 desktop: "Desktop",
61 laptop: "Laptop",
62 "mac-mini": "Mini PC",
63 "mac-studio": "Workstation",
64};
65
66export function environmentMachineIcon(
67 kind: EnvironmentMachineKind,
68): FunctionComponent<LucideProps> {
69 return ICON_BY_KIND[kind];
70}
71
72export function EnvironmentMachineIcon({
73 kind,
74 ...props
75}: LucideProps & { readonly kind: EnvironmentMachineKind }) {
76 const Icon = ICON_BY_KIND[kind];
77 return <Icon {...props} />;
78}