(defaultViewportWidth);
+
+ let isLargeViewport: boolean = viewportWidth > 992;
+
+ useEffect(() => {
+ const handleResize = debounce(() => setViewportWidth(window.innerWidth));
+
+ window.addEventListener("resize", handleResize);
+
+ // Cleanup function
+ return () => {
+ window.removeEventListener("resize", handleResize);
+ };
+ }, []);
+
+ return (
+ <>
+
+ {({ className, style, tokens, getLineProps, getTokenProps }) => (
+
+
+ {tokens.map((line, i) => (
+
+ {line.map((token, key) => (
+
+ ))}
+
+ ))}
+
+
+ )}
+
+
+ {showStackblitzBtn &&
+ filePaths !== undefined &&
+ filePaths?.length > 0 &&
+ projectTitle !== undefined &&
+ projectDescription !== undefined && (
+
+ )}
+ {
+ navigator.clipboard.writeText(code);
+ document
+ .querySelector("#copy-to-clipboard-toast")
+ ?.setVisible();
+ }}
+ >
+
+ {isLargeViewport && "Copy code"}
+
+
+ >
+ );
+};
const ComponentPreview: React.FC = ({
snippets,
@@ -70,6 +126,7 @@ const ComponentPreview: React.FC = ({
centered = true,
style,
state = "none",
+ showStackblitzBtn,
}) => (
Interactive example
@@ -111,7 +168,15 @@ const ComponentPreview: React.FC = ({
{snippets.map((snippet, index) => (
-
+
))}
diff --git a/src/content/static/components/CookiesData/index.tsx b/src/content/static/components/CookiesData/index.tsx
index e0bc43306..345597f28 100644
--- a/src/content/static/components/CookiesData/index.tsx
+++ b/src/content/static/components/CookiesData/index.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from "react";
+import React, { useState, useEffect } from "react";
import { debounce } from "../../../../utils/helpers";
import CookiesCards from "./CookiesCards";
@@ -31,14 +31,18 @@ const CookiesData = ({ headers, data, caption }: CookiesDataProps) => {
const [viewportWidth, setViewportWidth] = useState(defaultViewportWidth);
- React.useEffect(() => {
- window.addEventListener(
- "resize",
- debounce(() => setViewportWidth(window.innerWidth))
- );
+ useEffect(() => {
+ const handleResize = debounce(() => setViewportWidth(window.innerWidth));
+
+ window.addEventListener("resize", handleResize);
+
+ // Cleanup function
+ return () => {
+ window.removeEventListener("resize", handleResize);
+ };
}, []);
- if (viewportWidth > 991) {
+ if (viewportWidth > 992) {
return ;
}
diff --git a/src/content/structured/patterns/components/StackblitzButton/index.tsx b/src/content/structured/patterns/components/StackblitzButton/index.tsx
new file mode 100644
index 000000000..c1c2723cb
--- /dev/null
+++ b/src/content/structured/patterns/components/StackblitzButton/index.tsx
@@ -0,0 +1,152 @@
+import React, { useEffect, useState } from "react";
+import { readFile } from "fs";
+import sdk from "@stackblitz/sdk";
+import kebabCase from "lodash/kebabCase";
+import { StackblitzLogo } from "../../../../../assets/svg";
+import { debounce } from "../../../../../utils/helpers";
+
+export type StackblitzProps = {
+ filePaths: string[];
+ projectTitle: string;
+ projectDescription: string;
+};
+
+const StackblitzButton: React.FC = ({
+ filePaths,
+ projectTitle,
+ projectDescription,
+}) => {
+ let defaultViewportWidth = 0;
+
+ if (typeof window !== "undefined") {
+ defaultViewportWidth = window.innerWidth;
+ }
+
+ const [viewportWidth, setViewportWidth] =
+ useState(defaultViewportWidth);
+
+ let isLargeViewport: boolean = viewportWidth > 992;
+
+ useEffect(() => {
+ const handleResize = debounce(() => setViewportWidth(window.innerWidth));
+
+ window.addEventListener("resize", handleResize);
+
+ // Cleanup function
+ return () => {
+ window.removeEventListener("resize", handleResize);
+ };
+ }, []);
+
+ // Define the package.json content for a React app
+ const packageJson = {
+ name: `icds-${kebabCase(projectTitle)}`,
+ version: "0.0.0",
+ private: true,
+ dependencies: {
+ "@mdi/js": "^7.4.47",
+ "@types/react": "18.2.48",
+ "@types/react-dom": "18.2.18",
+ "@ukic/fonts": "^2.6.0",
+ "@ukic/react": "^2.10.0",
+ // prettier-ignore
+ "react": "18.2.0",
+ "react-dom": "18.2.0",
+ "react-router-dom": "^6.21.3",
+ },
+ scripts: {
+ start: "react-scripts start",
+ build: "react-scripts build",
+ test: "react-scripts test --env=jsdom",
+ eject: "react-scripts eject",
+ },
+ devDependencies: {
+ "react-scripts": "latest",
+ },
+ };
+
+ // Define the index.tsx content for a React app
+ const indexTsx = `import { StrictMode } from 'react';
+ import { createRoot } from 'react-dom/client';
+ import { BrowserRouter } from 'react-router-dom';
+
+ import App from './App';
+
+ const root = createRoot(document.getElementById('app'));
+
+ root.render(
+
+
+
+
+
+ );`;
+
+ const createStackblitzProject = (paths: string[]) => {
+ const files: { [key: string]: string } = {};
+ let isWebComponents = false;
+ let isJSX = false;
+ let ext = isJSX ? "jsx" : "tsx";
+ if (paths.length > 0) {
+ for (const path of paths) {
+ const extension = path.match(/\.([a-z]+)$/i);
+ // Check if path ends in HTML, CSS, TSX or JSX
+ if (extension && ["html", "css", "tsx", "jsx"].includes(extension[1])) {
+ if (extension[1] === "html") {
+ isWebComponents = true;
+ }
+ if (extension[1] === "jsx") {
+ isJSX = true;
+ }
+ // Read the contents of the passed file
+ readFile(path, "utf8", (err, data) => {
+ if (err) {
+ console.error(
+ "Error reading file passed into Stackblitz SDK",
+ err
+ );
+ }
+ files[`index.${extension}`] = data;
+ });
+ } else {
+ console.error(`File type not supported for path: ${path}`);
+ }
+ }
+ }
+
+ // Change file structure for React code examples
+ if (!isWebComponents) {
+ files["package.json"] = JSON.stringify(packageJson, null, 2);
+ files[`app.${ext}`] = files[`index.${ext}`];
+ files[`index.${ext}`] = indexTsx;
+ }
+
+ sdk.embedProject("app", {
+ title: `ICDS ${projectTitle}`,
+ description: `${projectDescription}`,
+ files,
+ template: isWebComponents ? "html" : "create-react-app",
+ tags: ["stackblitz", "sdk"],
+ });
+ };
+
+ return (
+ createStackblitzProject(filePaths)}
+ >
+ {isLargeViewport ? (
+
+
+
+ ) : (
+
+ )}
+ {isLargeViewport && "Stackblitz"}
+
+ );
+};
+
+export default StackblitzButton;