'use client' import { Fragment, useEffect, useId, useRef, useState } from 'react' import { Tab, TabGroup, TabList, TabPanel, TabPanels } from '@headlessui/react' import clsx from 'clsx' import { type MotionProps, type Variant, type Variants, AnimatePresence, motion, } from 'framer-motion' import { useDebouncedCallback } from 'use-debounce' import { AppScreen } from '@/components/AppScreen' import { CircleBackground } from '@/components/CircleBackground' import { Container } from '@/components/Container' import { PhoneFrame } from '@/components/PhoneFrame' import { DiageoLogo, LaravelLogo, MirageLogo, ReversableLogo, StatamicLogo, StaticKitLogo, TransistorLogo, TupleLogo, } from '@/components/StockLogos' const MotionAppScreenHeader = motion(AppScreen.Header) const MotionAppScreenBody = motion(AppScreen.Body) interface CustomAnimationProps { isForwards: boolean changeCount: number } const features = [ { name: 'Decentralized Nodes', description: "Mycelium operates through a network of decentralized nodes, similar to how nature's mycelium forms a decentralized network of threads. Each node acts as a connection point in the overall digital ecosystem.", icon: DeviceUserIcon, screen: InviteScreen, }, { name: 'Efficient Data Routing', description: 'Mycelium optimizes data routing by choosing the most efficient path for communication. Data travels along the shortest path in terms of latency, ensuring that information reaches its destination swiftly.', icon: DeviceNotificationIcon, screen: StocksScreen, }, { name: 'End-to-End Encryption', description: 'Each node in the system is identified by a unique key pair. Data between nodes is encrypted using secret keys derived from these pairs. This ensures that data remains confidential, enhancing the privacy of the network.', icon: DeviceTouchIcon, screen: InvestScreen, }, ] function DeviceUserIcon(props: React.ComponentPropsWithoutRef<'svg'>) { return ( ) } function DeviceNotificationIcon(props: React.ComponentPropsWithoutRef<'svg'>) { return ( ) } function DeviceTouchIcon(props: React.ComponentPropsWithoutRef<'svg'>) { let id = useId() return ( ) } const headerAnimation: Variants = { initial: { opacity: 0, transition: { duration: 0.3 } }, animate: { opacity: 1, transition: { duration: 0.3, delay: 0.3 } }, exit: { opacity: 0, transition: { duration: 0.3 } }, } const maxZIndex = 2147483647 const bodyVariantBackwards: Variant = { opacity: 0.4, scale: 0.8, zIndex: 0, filter: 'blur(4px)', transition: { duration: 0.4 }, } const bodyVariantForwards: Variant = (custom: CustomAnimationProps) => ({ y: '100%', zIndex: maxZIndex - custom.changeCount, transition: { duration: 0.4 }, }) const bodyAnimation: MotionProps = { initial: 'initial', animate: 'animate', exit: 'exit', variants: { initial: (custom: CustomAnimationProps, ...props) => custom.isForwards ? bodyVariantForwards(custom, ...props) : bodyVariantBackwards, animate: (custom: CustomAnimationProps) => ({ y: '0%', opacity: 1, scale: 1, zIndex: maxZIndex / 2 - custom.changeCount, filter: 'blur(0px)', transition: { duration: 0.4 }, }), exit: (custom: CustomAnimationProps, ...props) => custom.isForwards ? bodyVariantBackwards : bodyVariantForwards(custom, ...props), }, } type ScreenProps = | { animated: true custom: CustomAnimationProps } | { animated?: false } function InviteScreen(props: ScreenProps) { return ( Invite people Get tips 5s sooner for every invite.
{[ { label: 'Full name', value: 'Albert H. Wiggin' }, { label: 'Email address', value: 'awiggin@chase.com' }, ].map((field) => (
{field.label}
{field.value}
))}
Invite person
) } function StocksScreen(props: ScreenProps) { return ( Stocks March 9, 2022
{[ { name: 'Laravel', price: '4,098.01', change: '+4.98%', color: '#F9322C', logo: LaravelLogo, }, { name: 'Tuple', price: '5,451.10', change: '-3.38%', color: '#5A67D8', logo: TupleLogo, }, { name: 'Transistor', price: '4,098.41', change: '+6.25%', color: '#2A5B94', logo: TransistorLogo, }, { name: 'Diageo', price: '250.65', change: '+1.25%', color: '#3320A7', logo: DiageoLogo, }, { name: 'StaticKit', price: '250.65', change: '-3.38%', color: '#2A3034', logo: StaticKitLogo, }, { name: 'Statamic', price: '5,040.85', change: '-3.11%', color: '#0EA5E9', logo: StatamicLogo, }, { name: 'Mirage', price: '140.44', change: '+9.09%', color: '#16A34A', logo: MirageLogo, }, { name: 'Reversable', price: '550.60', change: '-1.25%', color: '#8D8D8D', logo: ReversableLogo, }, ].map((stock) => (
{stock.name}
{stock.price}
{stock.change}
))}
) } function InvestScreen(props: ScreenProps) { return ( Buy $LA $34.28 per share
{[ { label: 'Number of shares', value: '100' }, { label: 'Current market price', value: (
$34.28
), }, { label: 'Estimated cost', value: '$3,428.00' }, ].map((item) => (
{item.label}
{item.value}
))}
Buy shares
) } function usePrevious(value: T) { let ref = useRef() useEffect(() => { ref.current = value }, [value]) return ref.current } function FeaturesDesktop() { let [changeCount, setChangeCount] = useState(0) let [selectedIndex, setSelectedIndex] = useState(0) let prevIndex = usePrevious(selectedIndex) let isForwards = prevIndex === undefined ? true : selectedIndex > prevIndex let onChange = useDebouncedCallback( (selectedIndex) => { setSelectedIndex(selectedIndex) setChangeCount((changeCount) => changeCount + 1) }, 100, { leading: true }, ) return ( {features.map((feature, featureIndex) => (
{featureIndex === selectedIndex && ( )}

{feature.name}

{feature.description}

))}
{features.map((feature, featureIndex) => selectedIndex === featureIndex ? ( ) : null, )}
) } function FeaturesMobile() { let [activeIndex, setActiveIndex] = useState(0) let slideContainerRef = useRef>(null) let slideRefs = useRef>>([]) useEffect(() => { let observer = new window.IntersectionObserver( (entries) => { for (let entry of entries) { if (entry.isIntersecting && entry.target instanceof HTMLDivElement) { setActiveIndex(slideRefs.current.indexOf(entry.target)) break } } }, { root: slideContainerRef.current, threshold: 0.6, }, ) for (let slide of slideRefs.current) { if (slide) { observer.observe(slide) } } return () => { observer.disconnect() } }, [slideContainerRef, slideRefs]) return ( <>
{features.map((feature, featureIndex) => (
ref && (slideRefs.current[featureIndex] = ref)} className="w-full flex-none snap-center px-4 sm:px-6" >

{feature.name}

{feature.description}

))}
{features.map((_, featureIndex) => ( ))}
) } export function PrimaryFeatures() { return (

How Mycelium Operates

Mycelium, like its natural namesake, thrives on decentralization, efficiency, and security, making it a truly powerful force in the world of decentralized networks.

) }