UNPKG

@3mo/data-grid

Version:
207 lines (198 loc) 6.98 kB
import { __decorate } from "tslib"; import { component, Component, html, property, css, state } from '@a11d/lit'; import { NotificationComponent } from '@a11d/lit-application'; import { Localizer } from '@3mo/localization'; import { DataGridEditability } from './index.js'; Localizer.dictionaries.add('de', { 'Copied to clipboard': 'In die Zwischenablage kopiert', }); /** * @element mo-data-grid-cell * * @attr value * @attr column * @attr row */ let DataGridCell = class DataGridCell extends Component { constructor() { super(...arguments); this.editing = false; } get dataGrid() { return this.row.dataGrid; } get data() { return this.row.data; } get dataSelector() { return this.column.dataSelector; } get cellIndex() { return this.row.cells.indexOf(this); } get rowIndex() { return this.dataGrid.rows.indexOf(this.row); } get valueTextContent() { return this.renderRoot.textContent?.trim() || ''; } get isEditable() { return this.dataGrid.editability !== DataGridEditability.Never && [undefined, null].includes(this.editContentTemplate) === false && (this.column.editable === true || (typeof this.column.editable === 'function' && this.column.editable(this.data))); } get isEditing() { return this.isEditable && (this.editing || this.dataGrid.editability === DataGridEditability.Always); } handlePointerDown(event) { if (this.isEditing && event.composedPath().includes(this) === false) { this.setEditing(false); } } handleDoubleClick(event) { if (this.dataGrid.editability === DataGridEditability.Cell) { event.preventDefault(); this.setEditing(true); } } async handleKeyDown(event) { switch (event.key) { case 'Enter': event.preventDefault(); event.stopPropagation(); if (this.isEditable) { this.setEditing(true); } else { this.click(); } break; case 'Escape': event.preventDefault(); event.stopPropagation(); this.setEditing(false); await this.updateComplete; this.focusCell(event, this); break; case 'c': if (this.isEditing === false && (event.ctrlKey || event.metaKey)) { event.preventDefault(); await navigator.clipboard.writeText(this.valueTextContent); NotificationComponent.notifySuccess(t('Copied to clipboard')); } break; case 'Tab': case 'ArrowRight': this.focusCell(event, this.row.cells.at(this.cellIndex === this.dataGrid.visibleColumns.length - 1 ? 0 : this.cellIndex + 1)); break; case 'ArrowLeft': this.focusCell(event, this.row.cells.at(this.cellIndex === 0 ? this.dataGrid.visibleColumns.length - 1 : this.cellIndex - 1)); break; case 'ArrowUp': this.focusCell(event, this.dataGrid.rows.at(this.rowIndex === 0 ? this.dataGrid.rows.length - 1 : this.rowIndex - 1)?.cells.at(this.cellIndex)); break; case 'ArrowDown': this.focusCell(event, this.dataGrid.rows.at(this.rowIndex === this.dataGrid.rows.length - 1 ? 0 : this.rowIndex + 1)?.cells.at(this.cellIndex)); break; default: break; } } async setEditing(value) { if (this.editing === value) { return; } this.editing = value; await this.updateComplete; if (value) { this.renderRoot.querySelector('[autofocus]')?.focus(); } } focusCell(event, cell) { if (cell && this.isEditing === false) { event.preventDefault(); cell.focus(); this.setEditing(false); if (this.dataGrid.selectOnClick) { this.dataGrid.selectionController.setSelection(cell.row.data, true, event.shiftKey); } } } static get styles() { return css ` :host { display: inline-grid; align-items: center; position: relative; padding-inline: var(--mo-data-grid-cell-padding); font-size: var(--mo-data-grid-cell-font-size); outline: none; min-height: var(--mo-data-grid-row-height); } :host(:not([isEditing])) div { user-select: none; white-space: nowrap; overflow: hidden !important; text-overflow: ellipsis; } :host(:not([isEditing]):focus) { outline: 2px solid var(--mo-color-accent); } :host([isEditing]) { display: grid; } :host([alignment=start]) { text-align: start; } :host([alignment=center]) { text-align: center; } :host([alignment=end]) { text-align: end; } :host([sticky]) { position: sticky; } :host([sticky]) /*[sticking]*/ { z-index: 2; background: var(--mo-data-grid-sticky-part-color); } `; } get tooltip() { return this.valueTextContent; } get template() { this.title = this.tooltip; this.toggleAttribute('isEditing', this.isEditing); this.setAttribute('alignment', this.column.alignment || 'start'); if (this.isEditing) { this.removeAttribute('tabindex'); } else { this.setAttribute('tabindex', '-1'); } this.toggleAttribute('sticky', this.column.sticky !== undefined); this.toggleAttribute('sticking', this.column.intersecting === false); this.style.insetInline = this.column.stickyColumnInsetInline; return this.isEditing ? this.editContentTemplate : this.contentTemplate; } get contentTemplate() { return html ` <div> ${this.column.getContentTemplate?.(this.value, this.data) ?? html `${this.value}`} </div> `; } // Having focus-controller on every cell can lead to performance issues // in larger data-grids. Therefore defaulting to CSS native outline for now. // protected get focusRingTemplate() { // return !this.focusController.focused ? html.nothing : html`<mo-focus-ring inward visible></mo-focus-ring>` // } get editContentTemplate() { return this.column.getEditContentTemplate?.(this.value, this.data); } }; __decorate([ property({ type: Object }) ], DataGridCell.prototype, "value", void 0); __decorate([ property({ type: Object }) ], DataGridCell.prototype, "column", void 0); __decorate([ property({ type: Object }) ], DataGridCell.prototype, "row", void 0); __decorate([ state() ], DataGridCell.prototype, "editing", void 0); DataGridCell = __decorate([ component('mo-data-grid-cell') ], DataGridCell); export { DataGridCell };