Skip to content

Commit 45b5c70

Browse files
authored
Merge branch 'main' into fix/growth-chart-svg-id-collision
2 parents 238f1e9 + 0c9e059 commit 45b5c70

11 files changed

Lines changed: 799 additions & 389 deletions

File tree

app/compare/page.tsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Suspense } from 'react';
22
import type { Metadata } from 'next';
33
import CompareClient from './CompareClient';
4+
import { Footer } from '../components/Footer';
45

56
export const metadata: Metadata = {
67
title: 'Compare | CommitPulse',
@@ -14,14 +15,19 @@ export const metadata: Metadata = {
1415

1516
export default function ComparePage() {
1617
return (
17-
<Suspense
18-
fallback={
19-
<div className="min-h-screen flex items-center justify-center pt-28 pb-16">
20-
<div className="w-8 h-8 rounded-full border-2 border-emerald-500 border-t-transparent animate-spin"></div>
21-
</div>
22-
}
23-
>
24-
<CompareClient />
25-
</Suspense>
18+
<>
19+
<Suspense
20+
fallback={
21+
<div className="min-h-screen flex items-center justify-center pt-28 pb-16">
22+
<div className="w-8 h-8 rounded-full border-2 border-emerald-500 border-t-transparent animate-spin"></div>
23+
</div>
24+
}
25+
>
26+
<CompareClient />
27+
</Suspense>
28+
<div className="mx-auto max-w-7xl px-6 pb-8">
29+
<Footer />
30+
</div>
31+
</>
2632
);
2733
}

app/components/CopyRepoButton.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'use client';
2+
3+
import { useState } from 'react';
4+
import { Copy } from 'lucide-react';
5+
6+
export default function CopyRepoButton() {
7+
const [copied, setCopied] = useState(false);
8+
9+
const repoUrl = 'https://github.com/JhaSourav07/commitpulse';
10+
11+
const handleCopy = async () => {
12+
await navigator.clipboard.writeText(repoUrl);
13+
14+
setCopied(true);
15+
16+
setTimeout(() => {
17+
setCopied(false);
18+
}, 2000);
19+
};
20+
21+
return (
22+
<button
23+
onClick={handleCopy}
24+
className="inline-flex items-center gap-2 rounded-2xl border border-black/10 bg-white/60 px-8 py-4 font-semibold transition-all duration-300 hover:scale-105 dark:border-white/10 dark:bg-white/5"
25+
>
26+
<Copy className="h-5 w-5" />
27+
{copied ? 'Copied!' : 'Copy URL'}
28+
</button>
29+
);
30+
}

app/contributors/page.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import Link from 'next/link';
22
import { Globe, Sparkles, Users, GitPullRequest, ArrowRight } from 'lucide-react';
3-
43
import BrandParticles from '@/components/BrandParticles';
54
import { Footer } from '@/app/components/Footer';
65
import ContributorsSearch from './ContributorsSearch';
76
import Leaderboard from '@/components/Leaderboard';
7+
import CopyRepoButton from '@/app/components/CopyRepoButton';
88

99
interface Contributor {
1010
id: number;
@@ -231,6 +231,8 @@ export default async function ContributorsPage() {
231231
View Repository
232232
</Link>
233233

234+
<CopyRepoButton />
235+
234236
<Link
235237
href="https://github.com/JhaSourav07/commitpulse/issues"
236238
target="_blank"

app/customize/page.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,32 @@ export default function CustomizePage(): ReactElement {
150150
// - Use a conservative URI whitelist to prevent javascript: URIs
151151
const sanitized = DOMPurify.sanitize(text, {
152152
USE_PROFILES: { svg: true },
153+
ADD_TAGS: ['animate', 'style'],
154+
ADD_ATTR: [
155+
'fill',
156+
'fill-opacity',
157+
'stroke',
158+
'stroke-width',
159+
'stroke-opacity',
160+
'x1',
161+
'y1',
162+
'x2',
163+
'y2',
164+
'stop-color',
165+
'stop-opacity',
166+
'offset',
167+
'transform-origin',
168+
'transform-box',
169+
'transform',
170+
'attributeName',
171+
'from',
172+
'to',
173+
'dur',
174+
'repeatCount',
175+
'id',
176+
'class',
177+
'href',
178+
],
153179
FORBID_TAGS: ['foreignObject', 'iframe', 'object', 'embed', 'script'],
154180
FORBID_ATTR: ['xlink:href'],
155181
ALLOWED_URI_REGEXP: /^(?:(?:https?|mailto|data):|#)/i,

app/page.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use client';
22
import { trackUser } from '@/utils/tracking';
3-
import InteractiveViewer from '@/components/InteractiveViewer';
43
import Link from 'next/link';
54
import { useRef, useState, useEffect } from 'react';
65
import { AnimatePresence, motion } from 'framer-motion';

components/FeatureCards.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ import { useRef, useState, useEffect, type ReactNode } from 'react';
44
import gsap from 'gsap';
55
import { ScrollTrigger } from 'gsap/ScrollTrigger';
66

7-
if (typeof window !== 'undefined') {
8-
gsap.registerPlugin(ScrollTrigger);
9-
}
7+
let gsapRegistered = false;
108

119
/* ─── Types ─── */
1210
interface FeatureCardProps {
@@ -44,7 +42,7 @@ function FloatingParticle({
4442
tl.to(ref.current, {
4543
opacity: 0.6,
4644
y: -60,
47-
x: `random(-30, 30)`,
45+
x: Math.random() * 60 - 30,
4846
duration: duration * 0.4,
4947
ease: 'power2.out',
5048
})
@@ -119,8 +117,6 @@ function AnimatedBorder({ color, isHovered }: { color: string; isHovered: boolea
119117
style={{
120118
opacity: 0,
121119
background: `conic-gradient(from 0deg, transparent, ${color}, transparent, ${color}44, transparent)`,
122-
mask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
123-
maskComposite: 'exclude',
124120
WebkitMaskComposite: 'xor',
125121
padding: '1.5px',
126122
}}
@@ -417,6 +413,13 @@ export function FeatureCard({ icon, title, desc, accent, index, accentColor }: F
417413

418414
/* ─── Section Wrapper (optional heading + background glow) ─── */
419415
export function FeatureCardsSection({ children }: { children: ReactNode }) {
416+
useEffect(() => {
417+
if (!gsapRegistered) {
418+
gsap.registerPlugin(ScrollTrigger);
419+
gsapRegistered = true;
420+
}
421+
}, []);
422+
420423
const sectionRef = useRef<HTMLDivElement>(null);
421424
const headingRef = useRef<HTMLHeadingElement>(null);
422425

0 commit comments

Comments
 (0)