Skip to content

Commit 2401325

Browse files
committed
fix: remote component render
Signed-off-by: Innei <[email protected]>
1 parent 28bc85f commit 2401325

File tree

4 files changed

+70
-21
lines changed

4 files changed

+70
-21
lines changed

src/components/modules/shared/BlockLoading.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import { clsxm } from '~/lib/helper'
22

3-
export const BlockLoading: Component = (props) => {
3+
export const BlockLoading: Component<{
4+
style?: React.CSSProperties
5+
}> = (props) => {
46
return (
57
<div
68
className={clsxm(
79
'flex h-[500px] items-center justify-center rounded-lg bg-slate-100 text-sm dark:bg-neutral-800',
810
props.className,
911
)}
12+
style={props.style}
1013
>
1114
{props.children}
1215
</div>

src/components/ui/markdown/customize.md

+16-2
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ $$
396396
````
397397

398398
## React Remote Component Render
399-
399+
<!--
400400
```component
401401
import=http://127.0.0.1:2333/snippets/js/components
402402
name=MyComponents.Card
@@ -407,6 +407,20 @@ name=MyComponents.Card
407407
import=http://127.0.0.1:2333/snippets/js/components
408408
name=MyComponents.Card
409409
```
410+
```` -->
411+
412+
413+
```component
414+
import=https://cdn.jsdelivr.net/npm/@innei/[email protected]/dist/components/Firework.js
415+
name=MDX.Firework
416+
height=25
417+
```
418+
419+
````markdown
420+
```component
421+
import=https://cdn.jsdelivr.net/npm/@innei/[email protected]/dist/components/Firework.js
422+
name=MDX.Firework
423+
height=25
424+
```
410425
````
411426

412-

src/components/ui/markdown/index.demo.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
22
import { ReactComponentRender } from '~/components/ui/react-component-render/ComponentRender'
3-
import { lazy, Suspense, useMemo, useState } from 'react'
3+
import React, { lazy, Suspense, useMemo, useState } from 'react'
4+
import ReactDOM from 'react-dom'
45
import { ToastContainer } from 'react-toastify'
56
import { useIsomorphicLayoutEffect } from 'foxact/use-isomorphic-layout-effect'
67
import { ThemeProvider } from 'next-themes'
@@ -64,6 +65,9 @@ const CodeBlockRender = (props: {
6465
</Suspense>
6566
)
6667
}
68+
declare const window: any
69+
window.React = React
70+
window.ReactDOM = ReactDOM
6771

6872
export const MarkdownCustomize: DocumentComponent = () => {
6973
return (

src/components/ui/react-component-render/ComponentRender.tsx

+45-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Suspense, useState } from 'react'
1+
import { createContext, Suspense, useContext, useMemo, useState } from 'react'
22
import { ErrorBoundary } from 'react-error-boundary'
33
import { useIsomorphicLayoutEffect } from 'framer-motion'
44
import type { FC } from 'react'
@@ -7,64 +7,92 @@ import { BlockLoading } from '~/components/modules/shared/BlockLoading'
77
import { loadScript } from '~/lib/load-script'
88
import { get } from '~/lib/lodash'
99

10+
const StyleContext = createContext<React.CSSProperties>({})
11+
1012
export interface ReactComponentRenderProps {
1113
dls: string
1214
}
15+
1316
/**
1417
* define the render dls of the component
1518
* ```component
1619
* import=http://127.0.0.1:2333/snippets/js/components.js
1720
* name=Components.Card
21+
* height=20 // This is optional
1822
* ```
1923
*
2024
* name will be used to find the component in the import, if in the nested object, use dot to separate
2125
*
2226
*/
2327
export const ReactComponentRender: FC<ReactComponentRenderProps> = (props) => {
2428
const { dls } = props
29+
const dlsProps = parseDlsContent(dls)
30+
const style: React.CSSProperties = useMemo(() => {
31+
if (!dlsProps.height) return {}
32+
const isNumberString = /^\d+$/.test(dlsProps.height)
33+
return {
34+
height: isNumberString ? `${dlsProps.height}px` : dlsProps.height,
35+
}
36+
}, [dlsProps.height])
37+
return (
38+
<ErrorBoundary fallback={<ComponentBlockError style={style} />}>
39+
<StyleContext.Provider value={style}>
40+
<ReactComponentRenderImpl {...dlsProps} />
41+
</StyleContext.Provider>
42+
</ErrorBoundary>
43+
)
44+
}
45+
const ReactComponentRenderImpl: FC<DlsProps> = (dlsProps) => {
2546
const [Component, setComponent] = useState({
2647
component: ComponentBlockLoading,
2748
})
2849

50+
const style = useContext(StyleContext)
2951
useIsomorphicLayoutEffect(() => {
30-
const props = parseDlsContent(dls)
31-
3252
loadScript(
3353
'https://unpkg.com/styled-components/dist/styled-components.min.js',
3454
)
35-
.then(() => loadScript(props.import))
55+
.then(() => loadScript(dlsProps.import))
3656
.then(() => {
37-
const Component = get(window, props.name)
57+
const Component = get(window, dlsProps.name)
3858
console.log('Component', Component)
3959
setComponent({ component: Component })
4060
})
41-
}, [dls])
61+
}, [dlsProps])
4262

4363
return (
44-
<ErrorBoundary FallbackComponent={ComponentBlockError}>
45-
<Suspense fallback={<ComponentBlockLoading />}>
46-
<Component.component />
64+
<ErrorBoundary fallback={<ComponentBlockError style={style} />}>
65+
<Suspense fallback={<ComponentBlockLoading style={style} />}>
66+
<div style={style} className="overflow-hidden">
67+
<Component.component />
68+
</div>
4769
</Suspense>
4870
</ErrorBoundary>
4971
)
5072
}
5173

52-
const ComponentBlockError = () => {
74+
const ComponentBlockError: FC<{
75+
style?: React.CSSProperties
76+
}> = ({ style }) => {
5377
return (
54-
<BlockLoading className="bg-red-300 dark:bg-red-700">
78+
<BlockLoading style={style} className="bg-red-300 dark:bg-red-700">
5579
Component Error
5680
</BlockLoading>
5781
)
5882
}
59-
const ComponentBlockLoading = () => {
60-
return <BlockLoading>Component Loading...</BlockLoading>
83+
const ComponentBlockLoading: FC<{
84+
style?: React.CSSProperties
85+
}> = ({ style }) => {
86+
return <BlockLoading style={style}>Component Loading...</BlockLoading>
6187
}
6288

89+
type DlsProps = {
90+
name: string
91+
import: string
92+
height?: string
93+
}
6394
function parseDlsContent(dls: string) {
64-
const parsedProps = {} as {
65-
name: string
66-
import: string
67-
}
95+
const parsedProps = {} as DlsProps
6896
dls.split('\n').forEach((line) => {
6997
const [key, value] = line.split('=')
7098
;(parsedProps as any)[key] = value

0 commit comments

Comments
 (0)