Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed:iframe,dynamic import and; improvement:created jsonDataDirector… #3

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 34 additions & 31 deletions app/(components)/[componentName]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
"use client";
import React from "react";
import React, { useEffect } from "react";
import components from "@/constant/components";
import ListComponents from "@/components/sections/list-components";
import { notFound } from "next/navigation";
import Link from "next/link";
import jsonDataDirectory from "@/constant/jsonDataDirectory";
import ReactDOMServer from "react-dom/server";

import { getComponentCode } from "@/utils/getComponentCode";
import dynamic from "next/dynamic";

const Components = ({ params }: { params: { componentName: string } }) => {
const filteredComponents = components.filter((component) =>
Expand All @@ -18,36 +21,36 @@ const Components = ({ params }: { params: { componentName: string } }) => {
return notFound();
}

return (
<div>
{filteredComponents.map((component, index) => (
<div key={index} className="">
{component.style
.filter((style) =>
style.name
.toLowerCase()
.includes(params.componentName.toLowerCase()),
)
.map((style, index) => (
<div key={index}>
<ListComponents
code={getComponentCode(style.componentCode)}
name={style.name}
/>
</div>
))}
</div>
))}
{filteredComponents.length === 0 && (
<p>
Maybe you meant{" "}
<Link href={`/${params.componentName}`}>
<a>{params.componentName}</a>
</Link>
</p>
)}
</div>
);
const componentsDancok = [];

if (jsonDataDirectory && Array.isArray(jsonDataDirectory)) {
const findIndexByName = jsonDataDirectory.findIndex(
(component) => component.name === params.componentName,
);
console.log(findIndexByName);
console.log(findIndexByName);
const countComponents = jsonDataDirectory[findIndexByName].allComponents;
console.log(countComponents);
for (let i = 0; i < countComponents.length; i++) {
const file = jsonDataDirectory[findIndexByName].allComponents[i];
const Component = dynamic(
() => import(`@/ui/${params.componentName}/${file}`),
{
ssr: false,
},
);

componentsDancok.push(
<ListComponents
key={`component-${i + 1}`}
name={file}
code={<Component />}
/>,
);
}
}

return <div>{componentsDancok}</div>;
};

export default Components;
45 changes: 45 additions & 0 deletions components/Iframe/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"use client";
import "@/app/globals.css";
import React, { FC, useEffect, useState } from "react";
import { createPortal } from "react-dom";

interface IFrameProps {
children: React.ReactNode;
scripts?: string[] | undefined;
title?: string;
className?: any;
}

export const IframeComp: FC<IFrameProps> = ({
children,
className,
title,
scripts,
...props
}) => {
const [contentRef, setContentRef] = useState<any>(null);
const mountNode = contentRef?.contentWindow?.document.body;
useEffect(() => {
// Memasang skrip ke dalam iframe setelah komponen dimuat
if (mountNode && scripts.length > 0) {
scripts.forEach((scriptUrl) => {
const script = document.createElement("script");
script.src = scriptUrl;
script.async = true;
mountNode.appendChild(script);
});
}
}, [mountNode, scripts]);
return (
<iframe
width={"100%"}
title={title}
{...props}
height={`100%`}
className={className}
ref={setContentRef}
>
{mountNode && createPortal(children, mountNode)}
</iframe>
);
};
66 changes: 10 additions & 56 deletions components/highlighter/highlighter.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import React, { Suspense, useEffect, useState } from "react";
import Prism from "prismjs";

import ButtonHighliter from "./button-highlighter";
import "prismjs/components/prism-jsx";

import "@/app/customprism.css";
import { IframeComp } from "../Iframe";

interface HighlighterProps {
code?: string;
language?: string;
componentName?: string;
code: React.ReactNode;
}

type SizeKey = "mobile" | "sm" | "md" | "lg" | "full";

const Highlighter = ({ code, language, componentName }: HighlighterProps) => {
const Highlighter = ({ language, componentName, code }: HighlighterProps) => {
const [showPreview, setShowPreview] = useState(true);
const [iframeWidth, setIframeWidth] = useState("100%");
const [loading, setLoading] = useState(true);
Expand All @@ -32,14 +33,6 @@ const Highlighter = ({ code, language, componentName }: HighlighterProps) => {
setIframeWidth(sizes[size] || "100%");
};

useEffect(() => {
Prism.highlightAll();
const iframe = document.querySelector("iframe");
if (code) {
setLoading(false);
}
}, [code, language, showPreview]);

return (
<div>
<div className="p-4">
Expand All @@ -53,7 +46,7 @@ const Highlighter = ({ code, language, componentName }: HighlighterProps) => {
onToggle={togglePreview}
isPreviewing={showPreview}
/>
<ButtonHighliter mode="copy" code={code} />
{/* <ButtonHighliter mode="copy" code={code} /> */}
</div>
<ButtonHighliter
mode="responsiveness"
Expand All @@ -66,55 +59,16 @@ const Highlighter = ({ code, language, componentName }: HighlighterProps) => {
<div>
{showPreview ? (
<div className="mt-10 h-[70vh] overflow-hidden rounded-xl border-2 border-b-4 border-r-4 border-slate-800 bg-sky-500 ">
{loading ? (
<div className="mt-20 flex items-center justify-center font-bold text-white">
Loading...
</div>
) : (
<iframe
key={code?.toString()}
srcDoc={`
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>

</style>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body>
<div class="flex justify-center w-full ">
${code}
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
var links = document.querySelectorAll('a');
links.forEach(function(link) {
link.removeAttribute('href');
link.addEventListener('click', function(e) {
e.preventDefault();
});
});
});
</script>
</body>
</html>
`}
title="Component Preview"
width="100%"
height="100%"
className="w-full border-none"
/>
)}
<IframeComp scripts={["https://cdn.tailwindcss.com"]}>
<div className="flex w-full justify-center ">{code}</div>
</IframeComp>
</div>
) : (
<div className="mt-10">
<pre
className={`language-${language} h-[70vh] max-h-[70vh] overflow-scroll rounded-xl border-2 border-b-4 border-r-4 border-slate-800`}
>
<code className={`language-${language}`}>{`${code}`}</code>
{/* <code className={`language-${language}`}>{`${code}`}</code> */}
</pre>
</div>
)}
Expand Down
8 changes: 7 additions & 1 deletion components/sections/list-components.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import React from "react";
import Highlighter from "../highlighter/highlighter";

const ListComponents = ({ code, name }: { code: string; name: string }) => {
const ListComponents = ({
code,
name,
}: {
code: React.ReactNode;
name: string;
}) => {
return (
<div>
<Highlighter code={code} language="html" componentName={name} />
Expand Down
52 changes: 52 additions & 0 deletions constant/jsonDataDirectory.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const jsonDataDirectory = [
{
"id": "alert",
"name": "alert",
"allComponents": [
"AlertWithAction",
"rounded-alert",
"UiSimpleAlert"
]
},
{
"id": "avatar",
"name": "avatar",
"allComponents": [
"simple-avatar"
]
},
{
"id": "button",
"name": "button",
"allComponents": [
"button-checkbox",
"button-group",
"button-toggle"
]
},
{
"id": "card",
"name": "card",
"allComponents": [
"card-image-full",
"simple-card"
]
},
{
"id": "form",
"name": "form",
"allComponents": [
"form-icon",
"simple-form"
]
},
{
"id": "textareas",
"name": "textareas",
"allComponents": [
"textareas"
]
}
];

export default jsonDataDirectory;
4 changes: 2 additions & 2 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {}
const nextConfig = {};

module.exports = nextConfig
module.exports = nextConfig;
21 changes: 20 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
},
"dependencies": {
"@vercel/analytics": "^1.2.2",
"fs": "^0.0.1-security",
"html": "^1.0.0",
"next": "14.0.3",
"prismjs": "^1.29.0",
"react": "^18",
"react-dom": "^18"
"react-dom": "^18",
"uuid": "^9.0.1"
},
"devDependencies": {
"@types/html": "^1.0.4",
Expand Down
1 change: 1 addition & 0 deletions tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const config: Config = {
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
"./ui/**/*.{js,ts,jsx,tsx,mdx",
],
theme: {
extend: {
Expand Down
2 changes: 1 addition & 1 deletion utils/getComponentCode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ import * as beautify from "html";
export function getComponentCode(component: React.JSX.Element): string {
const rawCode = useClientRenderToString(component);
const codeString = beautify.prettyPrint(`${rawCode}`, { indent_size: 2 });

console.log(codeString);
return codeString;
}
Loading