<!DOCTYPE html>
<html>

<head>
  <title>pure web playground</title>
  <script src="https://cdn.tailwindcss.com"></script>
</head>

<body class="bg-rose-700">
  <main class="min-h-screen bg-black text-emerald-400 grid place-items-center [perspective:100vw]">
    <article class="grid gap-4 p-4 outline-dashed outline-1 outline-emerald-300 transition-all duration-1000 ease-in-out" style="transform:rotateX(90deg);">
      <section>
        <p>TODO list 
          <span class="text-sm italic text-sky-300">and more</span>
        </p>
        <p>instruction: <span class="text-sky-300 bg-sky-700 p-1">-</span> to add a new item</p>
        <p class="text-sm italic text-right text-sky-300">tested by: Chuck Norris before was created</p>
      </section>
      <pre id="monitor"></pre>
      <form action="">
        <input
          name="todo"
          type="text"
          class="
            bg-zinc-800
            text-zinc-300
            border-none
            outline-none
            py-1
            px-4
            focus:outline-1
            focus:outline-zinc-300
            focus:outline-dashed

          "
          maxlength="777"
        >
      </form>
      <section>
        <button class="bg-emerald-950 p-1 my-2 px-4 rounded" onclick="start()">start</button>
        <button class="bg-emerald-950 p-1 my-2 px-4 rounded" onclick="stop()">stop</button>
        <button class="bg-emerald-950 p-1 my-2 px-4 rounded" onclick="stop();z.counter = 42;rotate(0)">reset</button>
        <button class="bg-emerald-950 p-1 my-2 px-4 rounded" onclick="rotate(Math.random()*90|0)">rotate</button>
      </section>
    </article>
  </main>
</body>

<script>
  /** @type {<T>(watcher:function) => (state:T) => T} */
  const signal =
    (watcher=()=>{}) =>
      (state) =>
        new Proxy(state, {
          get: (base, target) => base[target],
          set: (base, target, value) => {
            base[target] = value;
            watcher(base, target, value);
            return true;
          },
        });

  const elMonitor = document.getElementById('monitor');
  const monitor = base => elMonitor.innerText = JSON.stringify(base, null, 2);
  let z = signal(monitor)({ pure: 'web', counter: 42 });

  let bum
  const stop = () => clearInterval(bum)
  const start = () => {stop(); bum = setInterval(() => z.counter++)}

  const textInput = document.querySelector('[name="todo"]');
  textInput.addEventListener('input', e => {
    z.todo = e.target.value.split('-');
    z.length = z.todo.length;
    rotate(Math.random()*90|0)
  });

  const rotate = amount => setTimeout(() => {
    document.querySelector('article').style.transform = `rotateX(${amount}deg)`
  }, 200);

  rotate(0)

</script>

</html>

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.