Skip to content

Latest commit

 

History

History
153 lines (136 loc) · 3.87 KB

json-tree.md

File metadata and controls

153 lines (136 loc) · 3.87 KB

JSON Tree

json-tree.js

export class JsonTree extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({mode: 'open'})
  }

  connectedCallback() {
    const style = document.createElement('style')
    style.textContent = `      
    `
    this.shadowRoot.append(style)
  }

  renderObject(ul, data) {
    ul.replaceChildren(...Object.entries(data).map(([key, value]) => {
      const li = document.createElement('li')
      if (typeof value === 'object' && value !== null) {
        li.innerText = JSON.stringify(key)
        const child = document.createElement('ul')
        li.append(child)
        this.renderObject(child, value)
      } else {
        li.innerText = `${JSON.stringify(key)}: ${JSON.stringify(value)}`
      }
      return li
    }))
  }

  set data(data) {
    const ul = document.createElement('ul')
    this.renderObject(ul, data)
    this.shadowRoot.replaceChildren(ul)
  }
}

app-view.js

export class AppView extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({mode: 'open'})
    this.dataTable = document.createElement('json-tree')
    this.shadowRoot.append(this.dataTable)
    this.dataTable.data = this.data
  }

  connectedCallback() {
    const globalStyle = document.createElement('style')
    globalStyle.textContent = `
      body {
        margin: 0;
        padding: 0;
        color: #ffffffbb;
      }
      html {
        box-sizing: border-box;
      }
      *, *:before, *:after {
        box-sizing: inherit;
      }
    `
    document.head.append(globalStyle)

    const style = document.createElement('style')
    style.textContent = `
    `
    this.shadowRoot.append(style)
  }

  get data() {
    if (!this._data) {
      for (const block of readBlocksWithNames(__source)) {
        if (block.name.endsWith('.json')) {
          return JSON.parse(__source.slice(...block.contentRange))
        }
      }
    }
    return this._data
  }
}

app.js

import {JsonTree} from '/json-tree.js'
import {AppView} from '/app-view.js'

customElements.define('json-tree', JsonTree)
customElements.define('app-view', AppView)

async function setup() {
  const appView = document.createElement('app-view')
  document.body.append(appView)
}

await setup()

thumbnail.svg

<svg viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg" fill="#111">
  <style>
    svg {
      background-color: #000;
    }
    .color1 {
      fill: #78c;
    }
    .color2 {
      fill: #aaa;
    }
  </style>
  <g transform="translate(10, 20)">
    <rect x="20" y="20" width="60" height="20" class="color1" />
    <rect x="90" y="20" width="60" height="20" class="color1" />
    <rect x="160" y="20" width="60" height="20" class="color1" />
  </g>
  <g transform="translate(10, 50)">
    <rect x="20" y="20" width="60" height="20" class="color2" />
    <rect x="90" y="20" width="60" height="20" class="color2" />
    <rect x="160" y="20" width="60" height="20" class="color2" />
  </g>
  <g transform="translate(10, 80)">
    <rect x="20" y="20" width="60" height="20" class="color2" />
    <rect x="90" y="20" width="60" height="20" class="color2" />
    <rect x="160" y="20" width="60" height="20" class="color2" />
  </g>
  <g transform="translate(10, 110)">
    <rect x="20" y="20" width="60" height="20" class="color2" />
    <rect x="90" y="20" width="60" height="20" class="color2" />
    <rect x="160" y="20" width="60" height="20" class="color2" />
  </g>
  <g transform="translate(10, 140)">
    <rect x="20" y="20" width="60" height="20" class="color2" />
    <rect x="90" y="20" width="60" height="20" class="color2" />
    <rect x="160" y="20" width="60" height="20" class="color2" />
  </g>
  <g transform="translate(10, 170)">
    <rect x="20" y="20" width="60" height="20" class="color2" />
    <rect x="90" y="20" width="60" height="20" class="color2" />
    <rect x="160" y="20" width="60" height="20" class="color2" />
  </g>
</svg>