chore: remove Next.js dependencies and update UI components with standard React
This commit is contained in:
18
src/components/ui/CountUpNumber.tsx
Normal file
18
src/components/ui/CountUpNumber.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
'use client'
|
||||
|
||||
import CountUp from 'react-countup'
|
||||
import { SectionHeader } from '@/components/Texts'
|
||||
|
||||
interface CountUpNumberProps {
|
||||
end: number
|
||||
className?: string
|
||||
color?: 'light' | 'primary' | 'secondary'
|
||||
}
|
||||
|
||||
export function CountUpNumber({ end, className, color }: CountUpNumberProps) {
|
||||
return (
|
||||
<SectionHeader color={color} className={className}>
|
||||
<CountUp end={end} duration={2.75} separator="," />
|
||||
</SectionHeader>
|
||||
)
|
||||
}
|
||||
28
src/components/ui/FadeIn.tsx
Normal file
28
src/components/ui/FadeIn.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
'use client'
|
||||
|
||||
import { motion, type Transition } from 'framer-motion'
|
||||
import React from 'react'
|
||||
import { useMediaQuery } from '@/hooks/useMediaQuery'
|
||||
|
||||
type FadeInProps = {
|
||||
children: React.ReactNode
|
||||
transition?: Transition
|
||||
className?: string
|
||||
}
|
||||
|
||||
export function FadeIn({ children, transition, className }: FadeInProps) {
|
||||
const isMobile = useMediaQuery('(max-width: 768px)')
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
className={className}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: false, margin: isMobile ? '0px 0px -50px 0px' : '0px 0px -100px 0px' }}
|
||||
transition={transition || { duration: 0.5 }}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
)
|
||||
}
|
||||
|
||||
47
src/components/ui/Globe2.tsx
Normal file
47
src/components/ui/Globe2.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
import createGlobe from 'cobe'
|
||||
|
||||
export function Globe({ className }: { className?: string }) {
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
let phi = 0
|
||||
|
||||
if (!canvasRef.current) return
|
||||
|
||||
const globe = createGlobe(canvasRef.current, {
|
||||
devicePixelRatio: 2,
|
||||
width: 600 * 2,
|
||||
height: 600 * 2,
|
||||
phi: 0,
|
||||
theta: 0,
|
||||
dark: 0,
|
||||
diffuse: 1.2,
|
||||
mapSamples: 16000,
|
||||
mapBrightness: 6,
|
||||
baseColor: [0.3, 0.3, 0.3],
|
||||
markerColor: [0.1, 0.8, 1],
|
||||
glowColor: [1, 1, 1],
|
||||
markers: [
|
||||
{ location: [37.7595, -122.4367], size: 0.03 },
|
||||
{ location: [40.7128, -74.006], size: 0.1 },
|
||||
],
|
||||
onRender: (state) => {
|
||||
state.phi = phi
|
||||
phi += 0.01
|
||||
},
|
||||
})
|
||||
|
||||
return () => {
|
||||
globe.destroy()
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className={className}
|
||||
style={{ width: '100%', height: '100%', maxWidth: '100%', aspectRatio: 1 }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import { CT, CP } from "@/components/Texts";
|
||||
import Image from 'next/image';
|
||||
import React from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
@@ -55,11 +54,9 @@ export const BentoGridItem = React.forwardRef<HTMLDivElement, BentoGridItemProps
|
||||
className="w-full h-full object-cover opacity-90 group-hover/bento:opacity-100 transition-opacity duration-300"
|
||||
/>
|
||||
) : img ? (
|
||||
<Image
|
||||
<img
|
||||
src={img}
|
||||
alt={title as string}
|
||||
width={300}
|
||||
height={300}
|
||||
className="w-full h-full object-cover opacity-90 group-hover/bento:opacity-100 transition-opacity duration-300"
|
||||
/>
|
||||
) : null}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { motion, AnimatePresence } from "motion/react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export const LayoutTextFlip = ({
|
||||
@@ -33,7 +33,7 @@ export const LayoutTextFlip = ({
|
||||
|
||||
<motion.span
|
||||
layout
|
||||
className="relative w-fit overflow-hidden px-2 py-2 font-neuton font-medium italic tracking-tight"
|
||||
className="relative w-fit overflow-hidden px-2 py-2 font-medium italic tracking-tight"
|
||||
>
|
||||
<AnimatePresence mode="popLayout">
|
||||
<motion.span
|
||||
|
||||
@@ -4,8 +4,6 @@ import { useRef } from "react";
|
||||
import { motion } from "motion/react";
|
||||
import DottedMap from "dotted-map";
|
||||
|
||||
import { useTheme } from "next-themes";
|
||||
|
||||
interface MapProps {
|
||||
dots?: Array<{
|
||||
start: { lat: number; lng: number; label?: string };
|
||||
@@ -21,13 +19,11 @@ export default function WorldMap({
|
||||
const svgRef = useRef<SVGSVGElement>(null);
|
||||
const map = new DottedMap({ height: 100, grid: "diagonal" });
|
||||
|
||||
const { theme } = useTheme();
|
||||
|
||||
const svgMap = map.getSVG({
|
||||
radius: 0.22,
|
||||
color: theme === "dark" ? "#FFFFFF40" : "#00000040",
|
||||
color: "#FFFFFF40", // Hardcoded for dark theme
|
||||
shape: "circle",
|
||||
backgroundColor: theme === "dark" ? "black" : "white",
|
||||
backgroundColor: "black", // Hardcoded for dark theme
|
||||
});
|
||||
|
||||
const projectPoint = (lat: number, lng: number) => {
|
||||
|
||||
Reference in New Issue
Block a user