UNPKG

@3mo/data-grid

Version:
117 lines (116 loc) 4.69 kB
import { Controller } from '@a11d/lit'; import { DataGridColumnComponent } from './index.js'; export class DataGridColumnsController extends Controller { constructor(host) { super(host); this.host = host; this.detailsColumnWidthInPixels = 0; this.selectionColumnWidthInPixels = 0; this.actionsColumnWidthInPixels = 0; this._extractedColumns = new Array(); this.initialized = false; } hostUpdate() { this.provideCssColumnsProperties(); } hostUpdated() { if (!this.initialized && !this.host.columns.length) { this.extractColumns(); } this.host.columns.forEach(column => column.dataGrid = this.host); this.initialized = true; } get visibleColumns() { return this.host.columns.filter(c => c.hidden === false); } setColumns(columns) { this.host.columns = columns; this.host.columnsChange.dispatch(columns); this.host.requestUpdate(); } extractColumns() { this._extractedColumns = this.elementExtractedColumns.length > 0 ? this.elementExtractedColumns : this.autoGeneratedColumns; this.host.extractedColumnsUpdated(this._extractedColumns); } get extractedColumns() { return this._extractedColumns; } // The reason for not doing this in the CSS is that we need to trim all the 0px values out of the columns // because the 'grid column gap' renders a gap no matter if the column is 0px or not provideCssColumnsProperties() { const columns = this.columns.map(c => `[${c.name}] ${c.width}`).join(' '); if (this.host.style.getPropertyValue('--mo-data-grid-columns') !== columns) { this.host.style.setProperty('--mo-data-grid-columns', columns); } } get columns() { return [ { name: 'details', width: this.detailsColumnWidth }, { name: 'selection', width: this.selectionColumnWidth }, ...this.dataColumnsWidths.map(width => ({ name: 'data', width })), { name: 'padding', width: '1fr' }, { name: 'actions', width: this.actionsColumnWidth } ].filter(c => c.width !== undefined); } get detailsColumnWidth() { return !this.host.hasDetails ? undefined : window.getComputedStyle(this.host).getPropertyValue('--mo-data-grid-column-details-width'); } get selectionColumnWidth() { return !this.host.hasSelection ? undefined : window.getComputedStyle(this.host).getPropertyValue('--mo-data-grid-column-selection-width'); } get dataColumnsWidths() { return this.visibleColumns .map(c => c.width) .filter((c) => c !== undefined); } get actionsColumnWidth() { return this.host.sidePanelHidden && !this.host.hasContextMenu ? undefined : window.getComputedStyle(this.host).getPropertyValue('--mo-data-grid-column-actions-width'); } get columnsElements() { const slot = this.host.renderRoot?.querySelector('slot[name=column]'); if (!slot) { return []; } const children = [...slot.children]; const assigned = [...slot.assignedElements()]; return [...assigned, ...children] .filter((c) => c instanceof DataGridColumnComponent) .map(c => { c.dataGrid = this.host; return c; }); } get elementExtractedColumns() { return this.columnsElements.map(c => c.column); } get autoGeneratedColumns() { if (!this.host.dataLength) { return []; } const getDefaultColumnElement = (value) => { switch (typeof value) { case 'number': case 'bigint': return 'mo-data-grid-column-number'; case 'boolean': return 'mo-data-grid-column-boolean'; default: return 'mo-data-grid-column-text'; } }; const [sampleData] = this.host.data || []; return Object.keys(sampleData || {}) .filter(key => !key.startsWith('_')) .map(key => { const columnElement = document.createElement(getDefaultColumnElement(KeyPath.get(sampleData, key))); columnElement.heading = key.replace(/([A-Z])/g, ' $1').charAt(0).toUpperCase() + key.replace(/([A-Z])/g, ' $1').slice(1); columnElement.dataSelector = key; columnElement.dataGrid = this.host; const column = columnElement.column; columnElement.remove(); return column; }); } }