JSFiddle - React, Tailwind, and code Playground

by Josh Pullen

HTML

<script src="https://unpkg.com/[email protected]/lib/jailed.js"></script>

JavaScript

import { html, render, useState, useEffect, useMemo } from "https://unpkg.com/[email protected]/preact/standalone.module.js";

const code = `
	const { count, setCount } = props;
	return html\`
  	<button onClick=$\{() => { setCount(count + 1) }}>
      $\{count} clicks
    </button>
  \`;
`;

function App() {
	const [count, setCount] = useState(0);
	return html`<${StringComponent} code=${code} props=${{ count }} />`;
}

function StringComponent({ code, props }) {
	const plugin = useMemo(() => {
      let fullCode = `
        application.setInterface({ Component });

        function Component(props, cb) {
        	for (const [key, value] of Object.entries(application.remote)) {
          	self[key] = value;
          }
          
          function html(...args) {
          	return args;
          }

					const result = (() => {
            ${code}
          })();
          
          console.log(props);
          console.log("Result:", result);
          cb(result);
        }
      `;

      const plugin = new jailed.DynamicPlugin(fullCode, {});
      return plugin;
  }, [code]);
  
  const [result, setResult] = useState(html`Loading...`);
  
  useEffect(() => {
  	if (plugin) {
    	let cancelled = false;

			plugin.whenConnected(() => {
      	console.log(plugin.remote.Component);
      	plugin.remote.Component(props, newResult => {
            console.log(newResult, cancelled);
            if (!cancelled) setResult(html(...newResult));
          });
      });

      return () => {
        cancelled = true;
      }
    }
  }, [props, plugin]);

  return result;
}

render(html`<${App} />`, document.body);