diff --git a/apps/docs/components/LogoDownloadModal.js b/apps/docs/components/LogoDownloadModal.js index 1772dcb2..3941890d 100644 --- a/apps/docs/components/LogoDownloadModal.js +++ b/apps/docs/components/LogoDownloadModal.js @@ -16,8 +16,8 @@ const styles = stylex.create({ position: 'fixed', top: 60, left: 20, - padding: '16px', - borderRadius: '8px', + padding: 16, + borderRadius: 8, boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)', maxWidth: '16.25rem', maxHeight: '80vh', @@ -39,12 +39,12 @@ const styles = stylex.create({ color: '#FFFFFF', }, section: { - marginBottom: '16px', + marginBottom: 16, }, sectionTitle: { - fontSize: '14px', + fontSize: 14, fontWeight: 'bold', - marginBottom: '8px', + marginBottom: 8, }, buttonGroup: { display: 'flex', @@ -54,7 +54,8 @@ const styles = stylex.create({ display: 'flex', alignItems: 'center', justifyContent: 'flex-start', - padding: '12px 16px', + paddingBlock: 12, + paddingInline: 16, cursor: 'pointer', backgroundColor: { default: 'var(--ifm-background-color)', @@ -64,17 +65,17 @@ const styles = stylex.create({ default: 'var(--ifm-font-color-base)', ':hover': '#FFFFFF', }, - borderRadius: '4px', - fontSize: '14px', + borderRadius: 4, + fontSize: 14, transition: 'background-color 0.2s, color 0.2s', borderStyle: 'none', width: '100%', - marginBottom: '8px', + marginBottom: 8, }, icon: { - marginRight: '8px', - width: '16px', - height: '16px', + marginRight: 8, + width: 16, + height: 16, fill: 'currentColor', }, }); diff --git a/apps/docs/components/Playground.js b/apps/docs/components/Playground.js index 5dc572b8..b6ffd58f 100644 --- a/apps/docs/components/Playground.js +++ b/apps/docs/components/Playground.js @@ -7,6 +7,7 @@ * @format */ +// Import necessary components and libraries import BrowserOnly from '@docusaurus/BrowserOnly'; import { library } from '@fortawesome/fontawesome-svg-core'; import { faBars, faRotateRight } from '@fortawesome/free-solid-svg-icons'; @@ -18,9 +19,17 @@ import { useEffect, useRef, useState } from 'react'; import { UnControlled as CodeMirror } from 'react-codemirror2'; import 'codemirror/mode/javascript/javascript'; import { files } from './playground-utils/files'; +import useDebounced from './hooks/useDebounced'; +// Add FontAwesome icons to the library library.add(faBars, faRotateRight); +/** + * Function to spawn a command in the WebContainer instance. + * @param {WebContainer} instance - The WebContainer instance. + * @param {...string} args - Command arguments to be executed. + * @returns {Promise} - Promise that resolves when the command execution is successful. + */ async function wcSpawn(instance, ...args) { console.log('Running:', args.join(' ')); const process = await instance.spawn(...args); @@ -41,6 +50,10 @@ async function wcSpawn(instance, ...args) { return process; } +/** + * Function to initialize and configure the WebContainer. + * @returns {Promise} - Promise that resolves with the configured WebContainer instance. + */ async function makeWebcontainer() { console.log('Booting WebContainer...'); const instance = await WebContainer.boot(); @@ -57,17 +70,22 @@ async function makeWebcontainer() { return instance; } +/** + * Main component for the Playground. + * @returns {JSX.Element} - The rendered JSX element. + */ export default function Playground() { const instance = useRef(null); const [url, setUrl] = useState(null); - const debounceTimeout = useRef(null); - const [code, setCode] = useState( + const [code, _setCode] = useState( files.src.directory['App.jsx'].file.contents, ); const [error, setError] = useState(null); - const loadingTimeout = useRef(null); const urlRef = useRef(null); + /** + * Function to build the WebContainer and start the development server. + */ const build = async () => { const containerInstance = instance.current; if (!containerInstance) { @@ -96,32 +114,31 @@ export default function Playground() { }); }; - const updateFiles = async () => { + /** + * Function to update files in the WebContainer. + */ + const updateFiles = async (updatedCode) => { const containerInstance = instance.current; const filePath = './src/App.jsx'; - const updatedCode = code; await containerInstance.fs.writeFile(filePath, updatedCode); }; - const handleCodeChange = (newCode) => { - if (debounceTimeout.current) { - clearTimeout(debounceTimeout.current); - debounceTimeout.current = null; - } + const debouncedUpdateFiles = useDebounced(async (newCode) => { + await updateFiles(newCode); + }, 1000); - debounceTimeout.current = setTimeout(async () => { - setCode(newCode); - if (url) { - try { - await updateFiles(); - console.log('Successfully applied changes.'); - } catch (err) { - console.error(err); - } - } - }, 2000); + /** + * Function to handle code changes in the CodeMirror editor. + * @param {string} newCode - The new code content from the editor. + */ + const handleCodeChange = (newCode) => { + // setCode(newCode); + debouncedUpdateFiles(newCode); }; + /** + * Function to reload the WebContainer preview. + */ const reloadWebContainer = async () => { if (!url) return; const iframe = document.querySelector('iframe'); @@ -130,7 +147,6 @@ export default function Playground() { if (error) { setError(null); } - console.log('Reloading container preview...'); await reloadPreview(iframe); } catch (err) { console.error(`Error reloading preview: ${err.message}`); @@ -140,45 +156,46 @@ export default function Playground() { } }; + // useEffect to initialize the WebContainer and build it useEffect(() => { - require('codemirror/mode/javascript/javascript'); + let loadingTimeout; makeWebcontainer().then((i) => { instance.current = i; build().then(() => { - loadingTimeout.current = setTimeout(() => { - console.log('running loading timeout'); - console.log('instance: ', instance.current); - console.log('url ref: ', urlRef.current); + loadingTimeout = setTimeout(() => { if (!urlRef.current) { console.log('error due to timeout...'); setError( 'WebContainer failed to load. Please try reloading or use a different browser.', ); } + loadingTimeout = null; }, 10000); }); }); - () => { + // Cleanup function to unmount the WebContainer and clear timeouts + return () => { instance.current.unmount(); - if (debounceTimeout.current) { - clearTimeout(debounceTimeout.current); - } - if (loadingTimeout.current) { - clearTimeout(loadingTimeout.current); + if (loadingTimeout != null) { + clearTimeout(loadingTimeout); } }; }, []); + // Render the Playground component return (
- - */} + @@ -189,20 +206,24 @@ export default function Playground() { <> handleCodeChange(newCode)} options={{ mode: 'javascript', theme: 'material-darker', lineNumbers: true, }} value={code} - onChange={(editor, data, newCode) => handleCodeChange(newCode)} /> {error ? ( -
{error}
+
+ {error} +
) : url ? (