Skip to content

Commit 5ed0df6

Browse files
committed
memo
1 parent 9b49afd commit 5ed0df6

File tree

9 files changed

+90
-101
lines changed

9 files changed

+90
-101
lines changed

website/components/CodeBlock.tsx

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,41 @@
11
import githubDark from '@/lib/config/theme.json';
22
import type { CodeBlockProps } from '@/types';
33
import { Code } from 'bright';
4+
import { memo } from 'react';
45
import { CopyButton } from './CopyButton';
56

67
Code.theme = githubDark as unknown as Record<string, string>;
78

8-
export const CodeBlock = ({ code, keyframes, lang, title, isV2 }: CodeBlockProps) => (
9-
<div className='relative border border-neutral-800'>
10-
<div className='absolute top-4 left-4'>
11-
<p className='text-sm text-neutral-400'>
12-
{title}
13-
{isV2 && (
14-
<span className='ml-2 border border-blue-500 bg-blue-600 px-1 py-0.5 text-xs text-zinc-50'>
15-
v2.0
16-
</span>
17-
)}
18-
</p>
19-
</div>
20-
{keyframes && (
9+
export const CodeBlock = memo(
10+
({ code, keyframes, lang, title, isV2 }: CodeBlockProps) => (
11+
<div className='relative border border-neutral-800'>
12+
<div className='absolute top-4 left-4'>
13+
<p className='text-sm text-neutral-400'>
14+
{title}
15+
{isV2 && (
16+
<span className='ml-2 border border-blue-500 bg-blue-600 px-1 py-0.5 text-xs text-zinc-50'>
17+
v2.0
18+
</span>
19+
)}
20+
</p>
21+
</div>
22+
{keyframes && (
23+
<CopyButton
24+
hasKeyframes={Array.isArray(keyframes)}
25+
variant='quaternary'
26+
code={keyframes || ''}
27+
copyText='Keyframes copied to clipboard!'
28+
/>
29+
)}
2130
<CopyButton
22-
hasKeyframes={Array.isArray(keyframes)}
23-
variant='quaternary'
24-
code={keyframes?.toString() || ''}
25-
copyText='Keyframes copied to clipboard!'
31+
hasKeyframes={false}
32+
variant='secondary'
33+
code={code || ''}
34+
copyText='Code copied to clipboard!'
2635
/>
27-
)}
28-
<CopyButton
29-
hasKeyframes={false}
30-
variant='secondary'
31-
code={code || ''}
32-
copyText='Code copied to clipboard!'
33-
/>
34-
<Code style={{ paddingTop: '20px' }} code={code} lang={lang} />
35-
</div>
36+
<Code style={{ paddingTop: '20px' }} code={code} lang={lang} />
37+
</div>
38+
),
3639
);
40+
41+
CodeBlock.displayName = 'CodeBlock';

website/components/CopyButton.tsx

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,42 @@
33
import { useToast } from '@/hooks/use-toast';
44
import type { CopyButtonProps } from '@/types';
55
import { CheckIcon, CopyIcon } from '@radix-ui/react-icons';
6-
import { useState } from 'react';
6+
import { memo, useState } from 'react';
77
import { TbKeyframe } from 'react-icons/tb';
88
import { Button } from './ui/Button';
99

10-
export const CopyButton = ({
11-
hasKeyframes,
12-
variant,
13-
className,
14-
code,
15-
copyText,
16-
}: CopyButtonProps) => {
17-
const { addToast } = useToast();
18-
const [hasCheckIcon, setHasCheckIcon] = useState(false);
10+
export const CopyButton = memo(
11+
({ hasKeyframes, variant, className, code, copyText }: CopyButtonProps) => {
12+
const { addToast } = useToast();
13+
const [hasCheckIcon, setHasCheckIcon] = useState(false);
1914

20-
const handleMouseDown = () => {
21-
navigator.clipboard.writeText(code.toString());
22-
setHasCheckIcon(true);
23-
addToast(copyText);
24-
setTimeout(() => {
25-
setHasCheckIcon(false);
26-
}, 1000);
27-
};
15+
const handleMouseDown = () => {
16+
navigator.clipboard.writeText(code as string);
17+
setHasCheckIcon(true);
18+
addToast(copyText);
19+
setTimeout(() => {
20+
setHasCheckIcon(false);
21+
}, 1000);
22+
};
2823

29-
return (
30-
<Button
31-
onMouseDown={handleMouseDown}
32-
className={className}
33-
variant={variant}
34-
icon={
35-
hasCheckIcon ? (
36-
<CheckIcon className='size-4 text-neutral-50' />
37-
) : hasKeyframes ? (
38-
<TbKeyframe className='size-4 text-neutral-50' />
39-
) : (
40-
<CopyIcon className='size-4 text-neutral-50' />
41-
)
42-
}
43-
aria-label={hasCheckIcon ? 'Copied!' : 'Copy'}
44-
/>
45-
);
46-
};
24+
return (
25+
<Button
26+
onMouseDown={handleMouseDown}
27+
className={className}
28+
variant={variant}
29+
icon={
30+
hasCheckIcon ? (
31+
<CheckIcon className='size-4 text-neutral-50' />
32+
) : hasKeyframes ? (
33+
<TbKeyframe className='size-4 text-neutral-50' />
34+
) : (
35+
<CopyIcon className='size-4 text-neutral-50' />
36+
)
37+
}
38+
aria-label={hasCheckIcon ? 'Copied!' : 'Copy'}
39+
/>
40+
);
41+
},
42+
);
43+
44+
CopyButton.displayName = 'CopyButton';

website/components/Examples.tsx

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,28 @@ import type { LoaderProps } from '@/types';
22
import { memo, useMemo } from 'react';
33
import { CodeBlock } from './CodeBlock';
44

5-
export const StandardExample = memo(({ name, speed }: Partial<LoaderProps>) => {
5+
export const StandardExample = ({ name, speed }: Partial<LoaderProps>) => {
66
const title = 'Standard CLI Example';
7-
const code = useMemo(
8-
() => `// Import the loader initializer
7+
const code = () => `// Import the loader initializer
98
import { initLoader } from 'cli-loaders';
109
1110
// Start the loader
12-
initLoader('${name}', ${speed});`,
13-
[name, speed],
14-
);
15-
16-
return <CodeBlock lang='ts' title={title} code={code} />;
17-
});
11+
initLoader('${name}', ${speed});`;
12+
return <CodeBlock lang='ts' title={title} code={code()} />;
13+
};
1814

1915
StandardExample.displayName = 'StandardExample';
2016

21-
export const CustomExample = memo(({ keyframes }: Partial<LoaderProps>) => {
17+
export const CustomExample = ({ keyframes }: Partial<LoaderProps>) => {
2218
const title = 'Custom Loader Example';
23-
const code = useMemo(
24-
() => `// Import the custom loader initializer
19+
const code = () => `// Import the custom loader initializer
2520
import { initCliLoader, dots_14 } from 'cli-loaders';
2621
2722
initCliLoader(dots14, YOUR_CUSTOM_SPEED, YOUR_CUSTOM_KEYFRAMES);
28-
// Example: initCliLoader(dots_14, 100, [${keyframes?.map((keyframe) => `"${keyframe}"`).join(', ')}]);`,
29-
[keyframes],
30-
);
23+
// Example: initCliLoader(dots_14, 100, [${keyframes?.map((keyframe) => `"${keyframe}"`).join(', ')}]);`;
3124

32-
return <CodeBlock lang='ts' title={title} code={code} keyframes={keyframes} isV2 />;
33-
});
25+
return <CodeBlock lang='ts' title={title} code={code()} keyframes={keyframes} isV2 />;
26+
};
3427

3528
CustomExample.displayName = 'CustomExample';
3629

website/components/Filter.tsx

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,18 @@
11
'use client';
22

33
import LOADERS from '@/lib/config/loaders';
4-
import { useRouter, useSearchParams } from 'next/navigation';
5-
import { Suspense, useEffect, useState } from 'react';
4+
import { memo, Suspense, useState } from 'react';
65
import { Renderer } from './Renderer';
76
import { Tabs } from './Tabs';
87
import { Card } from './ui/Card';
98

10-
export const Filter = () => {
11-
const router = useRouter();
12-
const params = useSearchParams();
13-
const initialTab = params.get('tab') ?? 'arrows';
9+
export const Filter = memo(() => {
10+
const initialTab = 'arrows';
1411
const [activeTab, setActiveTab] = useState(initialTab);
1512
const filteredLoaders = Object.values(LOADERS).filter(
1613
(loader) => loader.category === activeTab,
1714
);
1815

19-
useEffect(() => {
20-
if (params.get('tab') !== activeTab) {
21-
const query = new URLSearchParams({
22-
...Object.fromEntries(params.entries()),
23-
tab: activeTab,
24-
}).toString();
25-
router.push(`${window.location.pathname}?${query}`);
26-
}
27-
}, [params, router, activeTab]);
28-
2916
return (
3017
<Suspense fallback={<div>Loading...</div>}>
3118
<Tabs activeTab={activeTab} setActiveTab={setActiveTab} />
@@ -44,6 +31,6 @@ export const Filter = () => {
4431
</div>
4532
</Suspense>
4633
);
47-
};
34+
});
4835

4936
Filter.displayName = 'Filter';

website/components/Header.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
import { IconGroup } from '@/components/ui/Icons';
44
import Image from 'next/image';
55
import Link from 'next/link';
6+
import { memo } from 'react';
67

7-
export const Header = () => (
8+
export const Header = memo(() => (
89
<header className='z-50 flex h-16 items-center justify-between p-6'>
910
<Link
1011
href='/'
@@ -24,6 +25,6 @@ export const Header = () => (
2425
</Link>
2526
<IconGroup className='flex space-x-6' />
2627
</header>
27-
);
28+
));
2829

2930
Header.displayName = 'Header';

website/components/Hero.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import type { HeroProps } from '@/types';
2+
import { memo } from 'react';
23

3-
export const Hero = ({ title, description, children }: HeroProps) => (
4+
export const Hero = memo(({ title, description, children }: HeroProps) => (
45
<div className='px-6 py-12'>
56
<h1 className='text-center text-4xl font-semibold text-balance text-neutral-50 md:text-5xl'>
67
{title}
78
</h1>
89
<p className='pt-3 text-center text-neutral-100'>{description}</p>
910
{children}
1011
</div>
11-
);
12+
));
13+
14+
Hero.displayName = 'Hero';

website/components/Tabs.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ export const Tabs = memo(({ setActiveTab }: TabsProps) => {
1717

1818
const handleTabClick = (tab: string) => {
1919
setActiveTab(tab);
20-
window.history.pushState(null, '', `?tab=${tab}`);
2120
};
2221

2322
return (

website/eslint.config.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ const compat = new FlatCompat({
66

77
const eslintConfig = [
88
...compat.extends('next/core-web-vitals', 'next/typescript'),
9+
...compat.plugins('react-compiler'),
910
...compat.config({
1011
extends: ['next/core-web-vitals', 'next/typescript', 'prettier'],
1112
rules: {
1213
'@typescript-eslint/no-explicit-any': 'off',
1314
'@typescript-eslint/no-extra-non-null-assertion': 'off',
15+
'react-compiler/react-compiler': 'error',
1416
},
1517
}),
1618
];

website/next.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const nextConfig: NextConfig = {
2323
'react-icons',
2424
'react-share',
2525
],
26+
reactCompiler: true,
2627
serverSourceMaps: false,
2728
webpackBuildWorker: true,
2829
webpackMemoryOptimizations: true,

0 commit comments

Comments
 (0)