UNPKG

rapidoc

Version:

RapiDoc - Open API spec viewer with built in console

146 lines (138 loc) 4.85 kB
import { LitElement, html, css } from 'lit'; import { copyToClipboard } from '~/utils/common-utils'; import FontStyles from '~/styles/font-styles'; import BorderStyles from '~/styles/border-styles'; import InputStyles from '~/styles/input-styles'; import CustomStyles from '~/styles/custom-styles'; export default class JsonTree extends LitElement { static get properties() { return { data: { type: Object }, renderStyle: { type: String, attribute: 'render-style' }, }; } static get styles() { return [ FontStyles, BorderStyles, InputStyles, css` :host{ display:flex; } :where(button, input[type="checkbox"], [tabindex="0"]):focus-visible { box-shadow: var(--focus-shadow); } :where(input[type="text"], input[type="password"], select, textarea):focus-visible { border-color: var(--primary-color); } .json-tree { position: relative; font-family: var(--font-mono); font-size: var(--font-size-small); display:inline-block; overflow:hidden; word-break: break-all; flex:1; line-height: calc(var(--font-size-small) + 6px); min-height: 40px; direction: ltr; text-align: left; } .open-bracket { display:inline-block; padding: 0 20px 0 0; cursor:pointer; border: 1px solid transparent; border-radius:3px; } .close-bracket { border: 1px solid transparent; border-radius:3px; display:inline-block; } .open-bracket:hover { color:var(--primary-color); background-color:var(--hover-color); border: 1px solid var(--border-color); } .open-bracket.expanded:hover ~ .inside-bracket { border-left: 1px solid var(--fg3); } .open-bracket.expanded:hover ~ .close-bracket { color:var(--primary-color); } .inside-bracket { padding-left:12px; overflow: hidden; border-left:1px dotted var(--border-color); } .open-bracket.collapsed + .inside-bracket, .open-bracket.collapsed + .inside-bracket + .close-bracket { display:none; } .string{color:var(--green);} .number{color:var(--blue);} .null{color:var(--red);} .boolean{color:var(--purple);} .object{color:var(--fg)} .toolbar { position: absolute; top:5px; right:6px; display:flex; padding:2px; align-items: center; }`, CustomStyles, ]; } /* eslint-disable indent */ render() { return html` <div class = "json-tree" @click='${(e) => { if (e.target.classList.contains('btn-copy')) { copyToClipboard(JSON.stringify(this.data, null, 2), e); } else { this.toggleExpand(e); } }}'> <div class='toolbar'> <button class="toolbar-btn btn-copy" part="btn btn-fill btn-copy"> Copy </button> </div> ${this.generateTree(this.data, true)} </div> `; } generateTree(data, isLast = false) { if (data === null) { return html`<div class="null" style="display:inline;">null</div>`; } if (typeof data === 'object' && (data instanceof Date === false)) { const detailType = Array.isArray(data) ? 'array' : 'pure_object'; if (Object.keys(data).length === 0) { return html`${(Array.isArray(data) ? '[ ],' : '{ },')}`; } return html` <div class="open-bracket expanded ${detailType === 'array' ? 'array' : 'object'}" > ${detailType === 'array' ? '[' : '{'}</div> <div class="inside-bracket"> ${Object.keys(data).map((key, i, a) => html` <div class="item"> ${detailType === 'pure_object' ? html`"${key}":` : ''} ${this.generateTree(data[key], i === (a.length - 1))} </div>`) } </div> <div class="close-bracket">${detailType === 'array' ? ']' : '}'}${isLast ? '' : ','}</div> `; } return (typeof data === 'string' || data instanceof Date) ? html`<span class="${typeof data}">"${data}"</span>${isLast ? '' : ','}` : html`<span class="${typeof data}">${data}</span>${isLast ? '' : ','}`; } /* eslint-enable indent */ toggleExpand(e) { const openBracketEl = e.target; if (e.target.classList.contains('open-bracket')) { if (openBracketEl.classList.contains('expanded')) { openBracketEl.classList.replace('expanded', 'collapsed'); e.target.innerHTML = e.target.classList.contains('array') ? '[...]' : '{...}'; } else { openBracketEl.classList.replace('collapsed', 'expanded'); e.target.innerHTML = e.target.classList.contains('array') ? '[' : '{'; } } } } // Register the element with the browser customElements.define('json-tree', JsonTree);