asdf
This commit is contained in:
parent
11ad50f3a9
commit
03c2871cbd
8 changed files with 134 additions and 141 deletions
42
app/components/README.tsx
Normal file
42
app/components/README.tsx
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { remark } from 'remark';
|
||||||
|
import html from 'remark-html';
|
||||||
|
import rehypeStringify from 'rehype-stringify'
|
||||||
|
import remarkFrontmatter from 'remark-frontmatter'
|
||||||
|
import remarkGfm from 'remark-gfm'
|
||||||
|
import remarkParse from 'remark-parse'
|
||||||
|
import remarkRehype from 'remark-rehype'
|
||||||
|
|
||||||
|
const readmeUrl = 'https://raw.githubusercontent.com/imnyang/imnyang/refs/heads/main/README.md';
|
||||||
|
|
||||||
|
const markdownToHtml = async (markdown: string) => {
|
||||||
|
const result = await remark()
|
||||||
|
.use(remarkParse)
|
||||||
|
.use(remarkFrontmatter)
|
||||||
|
.use(remarkGfm)
|
||||||
|
.use(remarkRehype)
|
||||||
|
.use(rehypeStringify)
|
||||||
|
.use(html)
|
||||||
|
.process(markdown);
|
||||||
|
return result.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
const README = () => {
|
||||||
|
const [content, setContent] = React.useState<string>('');
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const fetchAndConvertMarkdown = async () => {
|
||||||
|
const response = await fetch(readmeUrl);
|
||||||
|
const markdown = await response.text();
|
||||||
|
const htmlContent = await markdownToHtml(markdown);
|
||||||
|
setContent(htmlContent);
|
||||||
|
};
|
||||||
|
fetchAndConvertMarkdown();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div dangerouslySetInnerHTML={{ __html: content }} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default README;
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
/*
|
|
||||||
All rights reserved to NY0510 (As Known As NY64), 2024
|
|
||||||
https://github.com/NY0510/ny64.kr/blob/main/src/components/ProfileSection.tsx
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { useState, useEffect } from 'react';
|
|
||||||
import { useMotionValue, motion, useMotionTemplate } from "framer-motion";
|
|
||||||
|
|
||||||
const birthday = new Date('2021-11-14');
|
|
||||||
|
|
||||||
export function TimeCounter() {
|
|
||||||
const mouseX = useMotionValue(0);
|
|
||||||
const mouseY = useMotionValue(0);
|
|
||||||
|
|
||||||
const background = useMotionTemplate`radial-gradient(200px circle at ${mouseX}px ${mouseY}px, rgba(38, 38, 38, 0.4), transparent 80%)`;
|
|
||||||
|
|
||||||
const [afterBirth, setAfterBirth] = useState<string>('');
|
|
||||||
const [tenThousands, setTenThousands] = useState<number>(0);
|
|
||||||
const [animate, setAnimate] = useState<boolean>(false);
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const interval = setInterval(() => {
|
|
||||||
const elapsed = new Date().getTime() - birthday.getTime();
|
|
||||||
setAfterBirth(elapsed.toLocaleString());
|
|
||||||
|
|
||||||
const newTenThousands = Math.floor(elapsed / 10000);
|
|
||||||
if (newTenThousands !== tenThousands) {
|
|
||||||
setTenThousands(newTenThousands);
|
|
||||||
setAnimate(true);
|
|
||||||
setTimeout(() => setAnimate(false), 200);
|
|
||||||
}
|
|
||||||
}, 1);
|
|
||||||
|
|
||||||
return () => clearInterval(interval);
|
|
||||||
}, [tenThousands]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
onMouseMove={(e) => {
|
|
||||||
const { left, top } = e.currentTarget.getBoundingClientRect();
|
|
||||||
|
|
||||||
mouseX.set(e.clientX - left);
|
|
||||||
mouseY.set(e.clientY - top);
|
|
||||||
}}
|
|
||||||
className="group relative w-full max-w-[350px] overflow-hidden rounded-xl bg-neutral-950"
|
|
||||||
title='암냥으로 활동한지'
|
|
||||||
>
|
|
||||||
<div className="absolute right-5 top-0 h-px w-80 bg-gradient-to-l from-transparent via-white/30 via-10% to-transparent" />
|
|
||||||
<motion.div
|
|
||||||
className="pointer-events-none absolute -inset-px rounded-xl opacity-0 transition duration-300 group-hover:opacity-100"
|
|
||||||
style={{
|
|
||||||
background: background,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div className="relative flexflex-col gap-3 rounded-xl border border-white/10 px-4 py-5">
|
|
||||||
<div className="space-y-2">
|
|
||||||
<span>암냥 ~ </span>
|
|
||||||
<p className={`text-sm tabular-nums transition duration-200 ease-in-out ${animate ? 'text-neutral-100' : 'text-neutral-400'}`}>
|
|
||||||
{afterBirth} ms
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
return (
|
|
||||||
<div className="group relative w-fit mx-auto grid overflow-hidden rounded-3xl px-6 py-3 shadow-[0_1000px_0_0_hsl(0_0%_20%)_inset] transition-colors duration-200">
|
|
||||||
<span>
|
|
||||||
<span className="spark mask-gradient absolute inset-0 h-[100%] w-[100%] animate-flip overflow-hidden rounded-3xl [mask:linear-gradient(white,_transparent_50%)] before:absolute before:aspect-square before:w-[200%] before:rotate-[-90deg] before:animate-rotate before:bg-[conic-gradient(from_0deg,transparent_0_340deg,white_360deg)] before:content-[''] before:[inset:0_auto_auto_50%] before:[translate:-50%_-15%]" />
|
|
||||||
</span>
|
|
||||||
<span className="backdrop absolute inset-px rounded-3xl bg-neutral-950 transition-colors duration-200" />
|
|
||||||
<span className="z-10 flex flex-col items-center gap-2">
|
|
||||||
<span>암냥으로 활동한지</span>
|
|
||||||
<span className={`tabular-nums transition duration-200 ease-in-out ${animate ? 'text-neutral-100' : 'text-neutral-400'}`}>
|
|
||||||
{afterBirth} ms
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
);*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -182,6 +182,7 @@ export default function TimelineComponents() {
|
||||||
<span className="text-base">{event.description}</span>
|
<span className="text-base">{event.description}</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<p className="tabular-nums text-sm text-gray-500">{event.category}</p>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
20
app/components/Top.tsx
Normal file
20
app/components/Top.tsx
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
export default function Top() {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id="top"
|
||||||
|
className="w-auto text-center flex items-center justify-center flex-col gap-4"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src="https://f.imnya.ng/profile/34b47ba35448cc74a659bcec443c3fbc.webp"
|
||||||
|
alt="imnyang"
|
||||||
|
width={200}
|
||||||
|
height={200}
|
||||||
|
className="rounded-full"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold">암냥</h1>
|
||||||
|
<p className="text-sm text-neutral-400">@imnyang</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
import type { Route } from "./+types/home";
|
import type { Route } from "./+types/home";
|
||||||
import React, { useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Link, useNavigate } from "react-router";
|
import { Link, useNavigate } from "react-router";
|
||||||
|
|
||||||
import { AnimatedTabs } from "~/components/AnimatedTabs";
|
import { AnimatedTabs } from "~/components/AnimatedTabs";
|
||||||
import { TimeCounter } from "~/components/TimeCounter";
|
import Readme from "~/components/README";
|
||||||
|
import TimelineComponents from "~/components/TimelineComponents";
|
||||||
|
import Top from "~/components/Top";
|
||||||
|
|
||||||
export function meta({}: Route.MetaArgs) {
|
export function meta({}: Route.MetaArgs) {
|
||||||
return [
|
return [
|
||||||
|
|
@ -13,16 +15,24 @@ export function meta({}: Route.MetaArgs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
|
const navigate = useNavigate();
|
||||||
const [activeTab, setActiveTab] = useState("Home");
|
const [activeTab, setActiveTab] = useState("Home");
|
||||||
const ref = React.useRef(null);
|
const ref = React.useRef(null);
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
useEffect(() => {
|
||||||
if (activeTab === "Timeline") {
|
if (activeTab === "Home") {
|
||||||
navigate("/timeline");
|
navigate("/");
|
||||||
|
} else if (activeTab === "Timeline") {
|
||||||
|
navigate("/#timeline");
|
||||||
}
|
}
|
||||||
}, [activeTab, navigate]);
|
}, [activeTab, navigate]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (window.location.hash === "#timeline") {
|
||||||
|
setActiveTab("Timeline");
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="flex flex-col w-full items-center">
|
<div ref={ref} className="flex flex-col w-full items-center">
|
||||||
<header className="w-full md:w-2/5 h-auto flex flex-row justify-between p-5">
|
<header className="w-full md:w-2/5 h-auto flex flex-row justify-between p-5">
|
||||||
|
|
@ -33,23 +43,48 @@ export default function Home() {
|
||||||
<AnimatedTabs activeTab={activeTab} setActiveTab={setActiveTab} />
|
<AnimatedTabs activeTab={activeTab} setActiveTab={setActiveTab} />
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div
|
<Top />
|
||||||
id="top"
|
{/* ActivatedTab */}
|
||||||
className="w-auto text-center flex items-center justify-center flex-col gap-4"
|
<div className="w-full md:w-2/5">
|
||||||
>
|
{activeTab === "Home" && (
|
||||||
<img
|
<div className="flex flex-col items-center justify-center">
|
||||||
src="https://f.imnya.ng/profile/34b47ba35448cc74a659bcec443c3fbc.webp"
|
<p className="text-lg text-neutral-400">
|
||||||
alt="imnyang"
|
{/* Read README.md with remark<Readme /> */}
|
||||||
width={200}
|
<br />
|
||||||
height={200}
|
<p>
|
||||||
className="rounded-full"
|
<kbd>
|
||||||
/>
|
<img
|
||||||
<div>
|
src="https://github.com/user-attachments/assets/8ea8ff1d-7e2c-4a2b-b688-38c21647ad8c"
|
||||||
<h1 className="text-2xl font-bold">암냥</h1>
|
alt="암냥 & 남냥"
|
||||||
<p className="text-sm text-neutral-400">@imnyang</p>
|
title=""
|
||||||
</div>
|
width="850"
|
||||||
<TimeCounter />
|
style={{ borderRadius: "10px" }}
|
||||||
<h2 className="text-xl">{`Tab: ${activeTab}`}</h2>
|
/>
|
||||||
|
</kbd>
|
||||||
|
</p>
|
||||||
|
<br />
|
||||||
|
<p>
|
||||||
|
<a href="https://skillicons.dev">
|
||||||
|
<kbd>
|
||||||
|
<img
|
||||||
|
width={850}
|
||||||
|
src="https://skillicons.dev/icons?i=typescript,js,c,cpp,java,kotlin,py,html,css,react,nextjs,tailwind,vite,nodejs,bun,elysia,express,fastapi,firebase,mongodb,postgres,sqlite,docker,nginx,github,githubactions,git,gradle,arduino,raspberrypi,figma,cloudflare,bots"
|
||||||
|
/>
|
||||||
|
</kbd>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</p>
|
||||||
|
<p className="text-white">Normal Student Developer</p>
|
||||||
|
<a href="https://sqlare.com" className="text-white">
|
||||||
|
Team. Sqlare
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{activeTab === "Timeline" && (
|
||||||
|
<div className="flex flex-col items-center justify-center">
|
||||||
|
<TimelineComponents />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,6 @@
|
||||||
import type { Route } from "./+types/home";
|
import type { Route } from "./+types/timeline";
|
||||||
import React, { useState } from "react";
|
import React from "react";
|
||||||
import { Link, useNavigate } from "react-router";
|
import { useNavigate } from "react-router";
|
||||||
|
|
||||||
import { AnimatedTabs } from "~/components/AnimatedTabs";
|
|
||||||
import { TimeCounter } from "~/components/TimeCounter";
|
|
||||||
|
|
||||||
import TimelineComponents from "~/components/TimelineComponents";
|
|
||||||
|
|
||||||
export function meta({}: Route.MetaArgs) {
|
export function meta({}: Route.MetaArgs) {
|
||||||
return [
|
return [
|
||||||
|
|
@ -15,37 +10,13 @@ export function meta({}: Route.MetaArgs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Timeline() {
|
export default function Timeline() {
|
||||||
const [activeTab, setActiveTab] = useState("Timeline");
|
|
||||||
const ref = React.useRef(null);
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (activeTab === "Home") {
|
navigate("/#timeline");
|
||||||
navigate("/");
|
}, [navigate]);
|
||||||
}
|
|
||||||
}, [activeTab, navigate]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="flex flex-col w-full items-center">
|
<h1>Redirecting</h1>
|
||||||
<header className="w-full md:w-2/5 h-auto flex flex-row justify-between p-5">
|
|
||||||
<Link to="/" accessKey="h" title="💕 Alt + H" className="text-2xl">💕</Link>
|
|
||||||
<div className="flex items-center">
|
|
||||||
<AnimatedTabs activeTab={activeTab} setActiveTab={setActiveTab} />
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<div id="top" className="w-auto text-center flex items-center justify-center flex-col gap-4">
|
|
||||||
<img src="https://f.imnya.ng/profile/34b47ba35448cc74a659bcec443c3fbc.webp" alt="imnyang" width={200} height={200} className="rounded-full" />
|
|
||||||
<div>
|
|
||||||
<h1 className="text-2xl font-bold">암냥</h1>
|
|
||||||
<p className="text-sm text-neutral-400">@imnyang</p>
|
|
||||||
</div>
|
|
||||||
<TimeCounter />
|
|
||||||
<br />
|
|
||||||
<h1 className="text-2xl font-bold">Timeline</h1>
|
|
||||||
<br/>
|
|
||||||
<TimelineComponents />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
|
|
@ -18,6 +18,13 @@
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-router": "^7.1.1",
|
"react-router": "^7.1.1",
|
||||||
|
"rehype-stringify": "^10.0.1",
|
||||||
|
"remark": "^15.0.1",
|
||||||
|
"remark-frontmatter": "^5.0.0",
|
||||||
|
"remark-gfm": "^4.0.0",
|
||||||
|
"remark-html": "^16.0.1",
|
||||||
|
"remark-parse": "^11.0.0",
|
||||||
|
"remark-rehype": "^11.1.1",
|
||||||
"tailwind-merge": "^2.6.0"
|
"tailwind-merge": "^2.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue