refactor: use mdx rsc

This commit is contained in:
Timothy Lin
2023-07-08 15:23:25 +08:00
parent 8261ff0ec4
commit 1dfa80e8bd
15 changed files with 223 additions and 152 deletions

View File

@ -0,0 +1,7 @@
'use client'
// dot notation breaks RSC - https://github.com/vercel/next.js/issues/51593
// temporarily workaround to re-export
import { BlogNewsletterForm } from 'pliny/ui/NewsletterForm'
export default BlogNewsletterForm

View File

@ -0,0 +1,13 @@
import { useState } from 'react'
export default function ClientComponent() {
const [count, setCount] = useState(0)
return (
<>
<h1>Client Component</h1>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Inc</button>
</>
)
}

View File

@ -2,7 +2,7 @@
import Link from 'next/link'
import { AnchorHTMLAttributes, DetailedHTMLProps } from 'react'
const CustomLink = ({
const CustomLink = async ({
href,
...rest
}: DetailedHTMLProps<AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>) => {

View File

@ -1,16 +1,17 @@
/* eslint-disable react/display-name */
import React from 'react'
import { MDXLayout, ComponentMap } from 'pliny/mdx-components'
import { useMDXComponent } from 'next-contentlayer/hooks'
import { ComponentMap } from 'pliny/mdx-components'
import { TOCInline } from 'pliny/ui/TOCInline'
import { Pre } from 'pliny/ui/Pre'
import { BlogNewsletterForm } from 'pliny/ui/NewsletterForm'
import Pre from './Pre'
import BlogNewsletterForm from './BlogNewsletterForm'
// import { BlogNewsletterForm } from 'pliny/ui/NewsletterForm'
import Image from './Image'
import CustomLink from './Link'
export const Wrapper = ({ layout, content, ...rest }: MDXLayout) => {
const Layout = require(`../layouts/${layout}`).default
return <Layout content={content} {...rest} />
interface MdxProps {
code: string
[key: string]: any
}
export const MDXComponents: ComponentMap = {
@ -18,6 +19,11 @@ export const MDXComponents: ComponentMap = {
TOCInline,
a: CustomLink,
pre: Pre,
wrapper: Wrapper,
BlogNewsletterForm,
}
export function Mdx({ code, ...rest }: MdxProps) {
const Component = useMDXComponent(code)
return <Component components={{ ...MDXComponents }} {...rest} />
}

72
components/Pre.tsx Normal file
View File

@ -0,0 +1,72 @@
'use client'
import { useState, useRef, ReactNode } from 'react'
const Pre = ({ children }: { children: ReactNode }) => {
const textInput = useRef(null)
const [hovered, setHovered] = useState(false)
const [copied, setCopied] = useState(false)
const onEnter = () => {
setHovered(true)
}
const onExit = () => {
setHovered(false)
setCopied(false)
}
const onCopy = () => {
setCopied(true)
// @ts-ignore
navigator.clipboard.writeText(textInput.current.textContent)
setTimeout(() => {
setCopied(false)
}, 2000)
}
return (
<div ref={textInput} onMouseEnter={onEnter} onMouseLeave={onExit} className="relative">
{hovered && (
<button
aria-label="Copy code"
className={`absolute right-2 top-2 h-8 w-8 rounded border-2 bg-gray-700 p-1 dark:bg-gray-800 ${
copied
? 'border-green-400 focus:border-green-400 focus:outline-none'
: 'border-gray-300'
}`}
onClick={onCopy}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
stroke="currentColor"
fill="none"
className={copied ? 'text-green-400' : 'text-gray-300'}
>
{copied ? (
<>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"
/>
</>
) : (
<>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"
/>
</>
)}
</svg>
</button>
)}
<pre>{children}</pre>
</div>
)
}
export default Pre

View File

@ -1,3 +1,5 @@
'use client'
import siteMetadata from '@/data/siteMetadata'
import { useEffect, useState } from 'react'