2
2
3
3
import { Select , Tooltip , useThemeMode } from "flowbite-react" ;
4
4
import type { ComponentProps , PropsWithChildren } from "react" ;
5
- import { useEffect , useState } from "react" ;
5
+ import { useEffect , useRef , useState } from "react" ;
6
6
import type { IconType } from "react-icons" ;
7
7
import { FaCopy } from "react-icons/fa" ;
8
8
import { HiMoon , HiSun } from "react-icons/hi" ;
@@ -12,10 +12,18 @@ import { TfiMobile } from "react-icons/tfi";
12
12
import { twMerge } from "tailwind-merge" ;
13
13
import { CodeHighlight , type Language } from "./code-highlight" ;
14
14
15
+ type IFrameData = number | IFrameOptions ;
16
+
17
+ interface IFrameOptions {
18
+ height : number ;
19
+ noPadding ?: boolean ;
20
+ }
21
+
15
22
interface BaseCodeData < T extends "single" | "variant" > {
16
23
type : T ;
17
24
githubSlug : string ;
18
25
component : React . ReactNode ;
26
+ iframe ?: IFrameData ;
19
27
}
20
28
21
29
interface VariantCodeData < V extends Variant > extends BaseCodeData < "variant" > {
@@ -135,8 +143,8 @@ export function CodeDemo({ data }: CodeDemoProps) {
135
143
</ div >
136
144
</ div >
137
145
</ div >
138
- < CodePreview view = { view } isRTL = { isRTL } isDarkMode = { isDarkMode } >
139
- { data . component }
146
+ < CodePreview view = { view } isRTL = { isRTL } isDarkMode = { isDarkMode } iframe = { data . iframe } >
147
+ { data . iframe ? < IFrame data = { data } isRTL = { isRTL } isDarkMode = { isDarkMode } /> : data . component }
140
148
</ CodePreview >
141
149
< div className = "code-syntax-wrapper" >
142
150
< div
@@ -173,6 +181,40 @@ export function CodeDemo({ data }: CodeDemoProps) {
173
181
) ;
174
182
}
175
183
184
+ function IFrame ( { data, isRTL, isDarkMode } : { data : CodeData ; isRTL : boolean ; isDarkMode : boolean | null } ) {
185
+ const ref = useRef < HTMLIFrameElement > ( null ) ;
186
+
187
+ useEffect ( ( ) => {
188
+ const document = ref . current ?. contentDocument ;
189
+
190
+ if ( ! document ) return ;
191
+
192
+ document . documentElement . setAttribute ( "dir" , isRTL ? "rtl" : "ltr" ) ;
193
+
194
+ if ( isDarkMode ) {
195
+ document . documentElement . classList . add ( "dark" ) ;
196
+ } else {
197
+ document . documentElement . classList . remove ( "dark" ) ;
198
+ }
199
+ } , [ isRTL , isDarkMode ] ) ;
200
+
201
+ function getSrc ( ) {
202
+ const base = "/examples" ;
203
+ const target = data . githubSlug . split ( "/" ) [ 1 ] . replace ( ".tsx" , "" ) ;
204
+ const noPadding = typeof data . iframe === "object" && data . iframe . noPadding ? `?noPadding` : "" ;
205
+
206
+ return `${ base } /${ target } ${ noPadding } ` ;
207
+ }
208
+
209
+ function getHeight ( ) : number {
210
+ const payload = data . iframe ! ;
211
+
212
+ return typeof payload === "number" ? payload : payload . height ;
213
+ }
214
+
215
+ return < iframe ref = { ref } src = { getSrc ( ) } height = { getHeight ( ) } className = "w-full" /> ;
216
+ }
217
+
176
218
function Tabs ( { tabIndex, items, onSelect } : { tabIndex : number ; items : CodeItem [ ] ; onSelect ( index : number ) : void } ) {
177
219
return (
178
220
< ul className = "flex flex-1 text-center text-sm font-medium text-gray-500 dark:text-gray-400" >
@@ -198,20 +240,22 @@ function CodePreview({
198
240
view,
199
241
isRTL,
200
242
isDarkMode,
243
+ iframe,
201
244
children,
202
- } : PropsWithChildren < { view : View ; isRTL : boolean ; isDarkMode : boolean | null } > ) {
245
+ } : PropsWithChildren < { view : View ; isRTL : boolean ; isDarkMode : boolean | null ; iframe ?: IFrameData } > ) {
203
246
return (
204
247
< div
205
248
{ ...( isRTL && { dir : "rtl" } ) }
206
249
className = { twMerge ( "code-preview-wrapper" , isDarkMode !== null && ( isDarkMode ? "dark" : "light" ) ) }
207
250
>
208
- < div className = "code-preview flex border-x border-gray-200 bg-white bg-gradient-to-r p-0 dark:border-gray-600 dark:bg-gray-900" >
251
+ < div className = "flex border-x border-gray-200 bg-white bg-gradient-to-r p-0 dark:border-gray-600 dark:bg-gray-900" >
209
252
< div className = "code-responsive-wrapper w-full" >
210
253
< div
211
254
className = { twMerge (
212
- "mx-auto w-full bg-white bg-gradient-to-r p-5 dark:bg-gray-900" ,
255
+ "mx-auto w-full bg-white bg-gradient-to-r dark:bg-gray-900" ,
213
256
view === "tablet" && "max-w-lg" ,
214
257
view === "mobile" && "max-w-sm" ,
258
+ ! iframe && "p-5" ,
215
259
) }
216
260
>
217
261
{ children }
0 commit comments