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` ${col}`); } else { let cellClass = ""; if (minDisplay != "" && minDisplay != undefined) { cellClass = "hidden " + minDisplay + ":table-cell"; } if (this.wideColumn[k]) { cellClass += " wide-column"; } headers.push(html` ${col}`); } }); return html` ${headers} `; } tableBody() { const rows: any = []; this.hasActions = false; this.rows.forEach((row: any, _: any) => { const rowHtml = []; const basicData = !row.hasOwnProperty('caption') && !row.hasOwnProperty('data'); if (basicData) { row["data"] = row; } const actions = row.hasOwnProperty('actions') ? row['actions'] : []; const uri = row.hasOwnProperty('uri') ? row['uri'] : []; const target = row.hasOwnProperty('target') ? row['target'] : []; let caption = row.hasOwnProperty('caption') ? this.columnContent(row['caption']) : ''; const summary = row.hasOwnProperty('summary') ? this.columnContent(row['summary']) : ''; let icon = row.hasOwnProperty('icon') ? row['icon'] : ''; let iconSize = row.hasOwnProperty('iconSize') ? row['iconSize'] : ''; const id: string = row.hasOwnProperty('id') ? row['id'] : ''; const color = row.hasOwnProperty('color') ? row['color'] : ''; const nested: boolean = row.hasOwnProperty('nested') ? row['nested'] === 'true' : false; this.hasActions = this.hasActions || (actions && actions.length > 0); if (uri != "") { caption = html`${caption}`; } if (nested) { icon = "subdirectory_arrow_right"; } let iconHtml = html``; if (icon != '') { iconSize = iconSize ? iconSize : summary == '' ? 20 : 40; iconHtml = html` `; } let actionsHtml = html`
`; if (actions && actions.length > 0) { actionsHtml = html`
`; } if (!basicData && (caption + summary + icon + this.columns[0]) != "") { rowHtml.push(html`
${actionsHtml} ${iconHtml}
${caption}${summary}
`); } if (row.hasOwnProperty('data') && row['data'] != null) { row['data'].forEach((col: any, ck: any) => { const minDisplay = this.columnDisplay[ck + 1]; let cellClass = ""; if (minDisplay != "" && minDisplay != undefined) { cellClass = "hidden " + minDisplay + ":table-cell"; } col = this.columnContent(col); rowHtml.push(html` ${typeof col == 'string' ? unsafeHTML(col) : col}`); }); } rows.push(html` ${rowHtml} `); }); return html` ${rows}`; } columnContent(col: any) { if (typeof col !== 'object' || col === null) { if (this.boolIcons && (col.toString() === 'true' || col.toString() === 'false')) { return html` `; } return col; } if (col.hasOwnProperty('chips')) { const colContent = col['chips'].map((chip: any) => { return html` ${chip['chip']}`; }); col = html` ${colContent}`; } else if (col.hasOwnProperty('chip')) { let chipState = ""; if (col.hasOwnProperty('state')) { chipState = col['state']; } col = html` ${col['chip']}`; } else if (col.hasOwnProperty('href')) { const url = col['href']; const text = col.hasOwnProperty('text') ? col['text'] : url; const target = col.hasOwnProperty('target') ? col['target'] : ''; const gaid = col.hasOwnProperty('gaid') ? col['gaid'] : ''; col = html` ${text}`; } return col; } render() { return html`
${this.tableHead()} ${this.tableBody()}
`; } }