"use client"; import { type MotionValue, motion, useMotionTemplate, useMotionValue, } from "framer-motion"; import Link from "next/link"; import type { ComponentPropsWithoutRef, ComponentType, MouseEvent, } from "react"; import { GridPattern } from "./GridPattern"; import { Heading } from "./Heading"; import { ChatBubbleIcon } from "./icons/ChatBubbleIcon"; import { UsersIcon } from "./icons/UsersIcon"; interface Resource { href: string; name: string; description: string; icon: ComponentType<{ className?: string }>; pattern: Omit< ComponentPropsWithoutRef, "width" | "height" | "x" >; } const resources: Resource[] = [ { href: "/entities", name: "Entities", description: "Learn how Entities work and how to use them to transmit federated data.", icon: ChatBubbleIcon, pattern: { y: 16, squares: [ [0, 1], [1, 3], ], }, }, { href: "/security", name: "Security", description: "Learn how to secure your Lysand implementation and protect your users' data.", icon: UsersIcon, pattern: { y: -6, squares: [ [-1, 2], [1, 3], ], }, }, ]; function ResourceIcon({ icon: Icon }: { icon: Resource["icon"] }) { return (
); } function ResourcePattern({ mouseX, mouseY, ...gridProps }: Resource["pattern"] & { mouseX: MotionValue; mouseY: MotionValue; }) { const maskImage = useMotionTemplate`radial-gradient(180px at ${mouseX}px ${mouseY}px, white, transparent)`; const style = { maskImage, WebkitMaskImage: maskImage }; return (
); } function Resource({ resource }: { resource: Resource }) { const mouseX = useMotionValue(0); const mouseY = useMotionValue(0); function onMouseMove({ currentTarget, clientX, clientY, }: MouseEvent) { const { left, top } = currentTarget.getBoundingClientRect(); mouseX.set(clientX - left); mouseY.set(clientY - top); } return (

{resource.name}

{resource.description}

); } export function Resources() { return (
Resources
{resources.map((resource) => ( ))}
); }