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>