JSFiddle - React, Tailwind, and code Playground

author(s): Tao Xin

HTML

<script src="https://cdn.jsdelivr.net/gh/vanjs-org/van/public/van-0.12.4.nomodule.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>

CSS

body { max-width: 960px; }

.row {
  display: flex;
  flex-flow: wrap;
}

.left {
  width: 60px;
  text-align: right;
}

.run {
  display: none;
  margin: 9px;
}

@media (max-width: 450px), (pointer:none), (pointer:coarse) {
  .break { width: 100%; }
  .run { display: unset; }
}

.right { flex-grow: 1; }

.right textarea, .right table {
  margin: 11px;
  border-width: 1px;
  box-sizing: border-box;
  font: 15px monospace;
  width: 100%;
}

.right pre, .right .chart { margin: 12px; }

a { cursor: pointer ;}

table { border-collapse: collapse; }

th, td { border: 1px solid black; }

.err { color: red; }

JavaScript

const {button, code, div, li, p, pre, span, tbody, td, textarea, th, thead, tr, ul} = van.tags

const toDataArray = data => {
  const hasPrimitive = !data.every(r => typeof r === "object")
  const keys = [...new Set(
    data.flatMap(r => typeof r === "object" ? Object.keys(r) : []))]
  return [
    (hasPrimitive ? ["Value"] : []).concat(keys),
    ...data.map(r =>
      (typeof r === "object" ? (hasPrimitive ? [""] : []) : [r]).concat(
        keys.map(k => r[k] ?? "")
      )),
  ]
}

const table = data => {
  const dataArray = toDataArray(data)
  return van.tags.table(
    thead(tr(th("(index)"), dataArray[0].map(k => th(k)))),
    tbody(dataArray.slice(1).map((r, i) => tr(td(i), r.map(c => td(c))))),
  )
}

const plot = (data, chartType, options) => {
  if (data[0].constructor === Object) data = toDataArray(data)
  else if (typeof data[0] === "number")
    data = [["", "Value"], ...data.map((d, i) => [i + 1, d])]
  const dom = div({class: "chart"})
  setTimeout(() => new google.visualization[chartType](dom).draw(
    google.visualization.arrayToDataTable(data), options))
  return dom
}

const Tree = ({obj, indent = ""}) =>
  (indent ? div : pre)(Object.entries(obj).map(([k, v]) => {
    if (v?.constructor !== Object && !Array.isArray(v))
      return div(indent + "🟰 ", van.tags.b(k + ": "), v)
    const icon = van.state("âž• ")
    const suffix = van.state(" {…}")
    const show = () => {
      const treeDom = result.appendChild(Tree({obj: v, indent: indent + "  "}))
      icon.val = "âž– "
      suffix.val = ""
      onclick.val = () => {
        treeDom.remove()
        onclick.val = show
        icon.val = "âž• "
        suffix.val = " {…}"
      }
    }
    const onclick = van.state(show)
    const result = div(indent, van.tags.a({onclick}, icon, van.tags.b(k + ":"), suffix))
    return result
  }))

const ValueView = expr => {
  try {
    const value = eval(`(${expr})`)
    if (value instanceof Element) return value
    if (value?.constructor === Object ||...