import {classMap} from "lit/directives/class-map.js"; import {type CSSResultGroup, html, unsafeCSS} from 'lit'; import {ifDefined} from "lit/directives/if-defined.js"; import {property} from 'lit/decorators.js'; import {unsafeHTML} from "lit/directives/unsafe-html.js"; import ZincElement from '../../internal/zinc-element'; import styles from './table.scss'; /** * @summary Short summary of the component's intended use. * @documentation https://zinc.style/components/table * @status experimental * @since 1.0 * * @dependency zn-example * * @event zn-event-name - Emitted as an example. * * @slot - The default slot. * @slot example - An example slot. * * @csspart base - The component's base wrapper. * * @cssproperty --example - An example CSS custom property. */ export default class ZnTable extends ZincElement { static styles: CSSResultGroup = unsafeCSS(styles); @property({attribute: 'fixed-first', type: Boolean, reflect: true}) fixedFirst: boolean = false; @property({attribute: 'has-actions', type: Boolean, reflect: true}) hasActions: boolean = false; @property({attribute: 'headless', type: Boolean, reflect: true}) headless: boolean = false; @property({attribute: 'left-align', type: Boolean, reflect: true}) allLeft: boolean = false; @property({attribute: 'data', type: Object, reflect: true}) data: any; @property({attribute: 'bool-icons', type: Boolean}) boolIcons: boolean = false; private columns: any = []; private columnDisplay: any = []; private wideColumn: any = []; private rows: any = []; resizing() { // TODO Resizing event } connectedCallback() { if (this.fixedFirst) { new ResizeObserver((_) => this.resizing).observe(this.parentElement as Element); } if (this.data === null || this.data === undefined) { if (this.childNodes.length > 0 && this.childNodes[0].nodeType === 3) { // merge all nodes into one const nodes = this.childNodes; let text = ''; for (const node of nodes) { text += node.textContent; } // remove all \n text = text.replace(/\n/g, ''); try { this.data = JSON.parse(text); this.innerText = ''; } catch (e) { /* empty */ console.error('Error parsing JSON', e); } } } if (this.data !== null && this.data !== undefined) { if (this.data.hasOwnProperty('header')) { this.data['header'].forEach((col: any) => { if (typeof col == 'string') { col = {name: col}; } this.columns.push(col.hasOwnProperty('name') ? col['name'] : ''); this.columnDisplay.push(col.hasOwnProperty('display') ? col['display'] : ''); this.wideColumn.push(col.hasOwnProperty('wide') ? col['wide'] : ''); }); } if (this.data.hasOwnProperty('items') && this.data['items'] != null) { this.rows = this.data['items']; } if (this.rows.length == 0 && this.columns.length == 0) { this.columns.push(''); for (const row in this.data) { for (const column in this.data[row]) { const colName = column.replace(/([A-Z]+)/g, " $1").replace(/([A-Z][a-z])/g, " $1"); if (!this.columns.includes(colName)) { this.columns.push(colName); } } this.rows.push({data: Object.values(this.data[row])}); } } } return super.connectedCallback(); } _handleMenu(e: any) { e.target.closest('.actions').querySelector('zn-menu').toggleAttribute('hidden'); } menuClick(e: any) { const menu = e.target.closest('.actions').querySelector('zn-menu'); menu.style.top = (e.clientY - this.clientTop) + 'px'; menu.style.left = (e.clientX - this.clientLeft) + 'px'; } tableHead() { if (this.headless) return; const headers: any = []; this.columns.forEach((col: any, k: number) => { if (col === "") { return; } if (col === "_") { col = ""; } const minDisplay = this.columnDisplay[k]; if (k == 0) { headers.push(html`