@3mo/data-grid
Version:
A data grid web component
882 lines (855 loc) • 32.9 kB
JavaScript
var DataGrid_1;
import { __decorate } from "tslib";
import { property, component, Component, html, css, query, ifDefined, event, style, literal, staticHtml, cache, eventOptions, queryAll, repeat, eventListener } from '@a11d/lit';
import { LocalStorage } from '@a11d/local-storage';
import { InstanceofAttributeController } from '@3mo/instanceof-attribute-controller';
import { SlotController } from '@3mo/slot-controller';
import { tooltip } from '@3mo/tooltip';
import { ThemeController } from '@3mo/theme';
import { observeMutation } from '@3mo/mutation-observer';
import { MediaQueryController } from '@3mo/media-query-observer';
import { Localizer } from '@3mo/localization';
import { DataGridColumnsController } from './DataGridColumnsController.js';
import { DataGridSelectionBehaviorOnDataChange, DataGridSelectionController } from './DataGridSelectionController.js';
import { DataGridSortingController } from './DataGridSortingController.js';
import { DataGridDetailsController } from './DataGridDetailsController.js';
import { DataGridCsvController, DataGridSidePanelTab, DataGridContextMenuController } from './index.js';
import { DataRecord } from './DataRecord.js';
Localizer.dictionaries.add('de', {
'No results': 'Kein Ergebnis',
'More Filters': 'Weitere Filter',
});
export var DataGridEditability;
(function (DataGridEditability) {
DataGridEditability["Never"] = "never";
DataGridEditability["Cell"] = "cell";
DataGridEditability["Always"] = "always";
})(DataGridEditability || (DataGridEditability = {}));
/**
* @element mo-data-grid
*
* @attr data - The data to be displayed in the DataGrid. It is an array of objects, where each object represents a row.
* @attr columns - The columns to be displayed in the DataGrid. It is an array of objects, where each object represents a column.
* @attr headerHidden - Whether the header should be hidden.
* @attr preventVerticalContentScroll - Whether the content should be prevented from scrolling vertically.
* @attr page - The current page.
* @attr pagination - The pagination mode. It can be either `auto` or a number.
* @attr sorting - The sorting mode. It is an object with `selector` and `strategy` properties.
* @attr selectability - The selection mode. Default to 'single' if context menus available, 'undefined' otherwise.
* @attr isDataSelectable - Whether data of a given row is selectable.
* @attr selectedData - The selected data.
* @attr selectOnClick - Whether the row should be selected on click.
* @attr selectionBehaviorOnDataChange - The behavior of the selection when the data changes.
* @attr multipleDetails - Whether multiple details can be opened at the same time.
* @attr subDataGridDataSelector - The key path of the sub data grid data.
* @attr hasDataDetail - Whether the data has a detail.
* @attr detailsOnClick - Whether the details should be opened on click.
* @attr primaryContextMenuItemOnDoubleClick - The primary context menu item on double click.
* @attr editability - The editability mode.
* @attr getRowDetailsTemplate - A function which returns a template for the details of a given row.
* @attr getRowContextMenuTemplate - A function which returns a template for the context menu of a given row.
* @attr sidePanelTab - The side panel tab.
* @attr sidePanelHidden - Whether the side panel should be hidden.
* @attr hasAlternatingBackground - Whether the rows should have alternating background.
* @attr preventFabCollapse - Whether the FAB should be prevented from collapsing.
* @attr cellFontSize - The font size of the cells relative to the default font size. Defaults @see DataGrid.cellFontSize 's value which defaults to 0.8.
* @attr rowHeight - The height of the rows in pixels. Defaults to @see DataGrid.rowHeight 's value which defaults to 35.
* @attr exportable - Whether the DataGrid is exportable. This will show an export button in the footer.
*
* @slot - Use this slot only for declarative DataGrid APIs e.g. setting ColumnDefinitions via `mo-data-grid-columns` tag.
* @slot toolbar - The horizontal bar above DataGrid's contents.
* @slot toolbar-action - A slot for action icon-buttons in the toolbar which are displayed on the end.
* @slot filter - A vertical bar for elements which filter DataGrid's data. It is opened through an icon-button in the toolbar.
* @slot sum - A horizontal bar in the DataGrid's footer for showing sums. Calculated sums are also placed here by default.
* @slot settings - A vertical bar for elements which change DataGrid's settings. It is pre-filled with columns' settings and can be opened through an icon-button in the toolbar.
* @slot fab - A wrapper at the bottom right edge, floating right above the footer, expecting Floating Action Button to be placed in.
* @slot error-no-content - A slot for displaying an error message when no data is available.
*
* @cssprop --mo-data-grid-min-visible-rows - The minimum number of visible rows. Default to 2.5.
* @cssprop --mo-data-grid-footer-background - The background of the footer.
* @cssprop --mo-data-grid-cell-padding - The inline padding of the cells. Default to 10px.
* @cssprop --mo-data-grid-column-sub-row-indentation - The indentation of the first column in the sub row. Default to 20px.
*
* @fires dataChange
* @fires selectionChange
* @fires pageChange
* @fires paginationChange
* @fires columnsChange
* @fires sidePanelOpen
* @fires sidePanelClose
* @fires sortingChange
* @fires rowDetailsOpen
* @fires rowDetailsClose
* @fires rowClick
* @fires rowDoubleClick
* @fires rowMiddleClick
* @fires cellEdit
*/
let DataGrid = DataGrid_1 = class DataGrid extends Component {
constructor() {
super(...arguments);
this.data = new Array();
this.columns = new Array();
this.headerHidden = false;
this.preventVerticalContentScroll = false;
this.page = 1;
this.selectedData = new Array();
this.selectOnClick = false;
this.selectionBehaviorOnDataChange = DataGridSelectionBehaviorOnDataChange.Reset;
this.multipleDetails = false;
this.detailsOnClick = false;
this.primaryContextMenuItemOnDoubleClick = false;
this.editability = DataGridEditability.Never;
this.sidePanelHidden = false;
this.hasAlternatingBackground = DataGrid_1.hasAlternatingBackground.value;
this.preventFabCollapse = false;
this.fabSlotCollapsed = false;
this.exportable = false;
this.cellFontSize = DataGrid_1.cellRelativeFontSize.value;
this.rowHeight = DataGrid_1.rowHeight.value;
this.slotController = new SlotController(this, async () => {
this.hasSums;
this.hasFabs;
await new Promise(r => requestIdleCallback(r));
this.style.setProperty('--mo-data-grid-fab-slot-width', `${this.renderRoot?.querySelector('slot[name=fab]')?.getBoundingClientRect().width || 75}px`);
});
this.instanceofAttributeController = new InstanceofAttributeController(this);
this.smallScreenObserverController = new MediaQueryController(this, '(max-width: 768px)');
this.themeController = new ThemeController(this);
this.columnsController = new DataGridColumnsController(this);
this.selectionController = new DataGridSelectionController(this);
this.sortingController = new DataGridSortingController(this);
this.contextMenuController = new DataGridContextMenuController(this);
this.detailsController = new DataGridDetailsController(this);
this.csvController = new DataGridCsvController(this);
this.splitterResizerTemplate = html `
<mo-splitter-resizer-line style='--mo-splitter-resizer-line-thickness: 1px; --mo-splitter-resizer-line-idle-background: var(--mo-color-transparent-gray-3); --mo-splitter-resizer-line-horizontal-transform: scaleX(5);'></mo-splitter-resizer-line>
`;
this.lastScrollElementTop = 0;
}
setPage(page) {
this.page = page;
this.pageChange.dispatch(page);
}
setPagination(pagination) {
this.pagination = pagination;
this.paginationChange.dispatch(pagination);
}
setData(data, selectionBehavior = this.selectionBehaviorOnDataChange) {
this.data = data;
this.selectionController.handleDataChange(selectionBehavior);
this.dataChange.dispatch(data);
}
get hasSelection() {
return this.selectionController.hasSelection;
}
selectAll(...parameters) {
return this.selectionController.selectAll(...parameters);
}
deselectAll(...parameters) {
return this.selectionController.deselectAll(...parameters);
}
select(...parameters) {
return this.selectionController.select(...parameters);
}
isSelectable(...parameters) {
return this.selectionController.isSelectable(...parameters);
}
get hasDetails() {
return this.detailsController.hasDetails;
}
get allRowDetailsOpen() {
return this.detailsController.areAllOpen;
}
openRowDetails(...parameters) {
return this.detailsController.openAll(...parameters);
}
closeRowDetails(...parameters) {
return this.detailsController.closeAll(...parameters);
}
toggleRowDetails(...parameters) {
return this.detailsController.toggleAll(...parameters);
}
getSorting(...parameters) {
return this.sortingController.get(...parameters);
}
sort(...parameters) {
return this.sortingController.set(...parameters);
}
unsort(...parameters) {
return this.sortingController.reset(...parameters);
}
setColumns(...parameters) {
return this.columnsController.setColumns(...parameters);
}
extractColumns(...parameters) {
return this.columnsController.extractColumns(...parameters);
}
generateCsv(...parameters) {
return this.csvController.generateCsv(...parameters);
}
get extractedColumns() {
return this.columnsController.extractedColumns;
}
extractedColumnsUpdated(extractedColumns) {
this.setColumns(extractedColumns);
}
get visibleColumns() {
return this.columnsController.visibleColumns;
}
getRow(data) {
return this.rows.find(r => r.data === data);
}
getCell(data, column) {
const row = this.getRow(data);
return row?.getCell(column);
}
handleEdit(data, column, value) {
const row = this.getRow(data);
const cell = row?.getCell(column);
if (row && cell && value !== undefined && column.dataSelector && cell.value !== value) {
row.requestUpdate();
KeyPath.set(row.data, column.dataSelector, value);
this.cellEdit.dispatch(cell);
}
}
navigateToSidePanelTab(tab) {
this.sidePanelTab = tab;
!tab ? this.sidePanelClose.dispatch() : this.sidePanelOpen.dispatch(tab);
}
get hasContextMenu() {
return this.contextMenuController.hasContextMenu;
}
get toolbarElements() {
return this.slotController.getAssignedElements('toolbar');
}
get hasToolbar() {
return this.toolbarDefaultTemplate !== html.nothing || this.toolbarElements.length > 0;
}
get filterElements() {
return this.slotController.getAssignedElements('filter');
}
get hasFilters() {
return this.filtersDefaultTemplate !== html.nothing || this.filterElements.length > 0;
}
get hasSums() {
const hasSums = !!this.columns.find(c => c.sumHeading) || !!this.querySelector('* [slot="sum"]') || !!this.renderRoot?.querySelector('slot[name="sum"] > *');
this.toggleAttribute('hasSums', hasSums);
return hasSums;
}
get hasFabs() {
const hasFabs = !!this.querySelector('* [slot=fab]') || !!this.renderRoot?.querySelector('#fab *:not(slot[name=fab])');
this.toggleAttribute('hasFabs', hasFabs);
return hasFabs;
}
get hasPagination() {
return this.pagination !== undefined;
}
get supportsDynamicPageSize() {
return this.hasPagination;
}
get pageSize() {
const dynamicPageSize = (pageSize) => this.supportsDynamicPageSize ? pageSize : DataGrid_1.pageSize.value;
if (!this.pagination) {
return dynamicPageSize(this.data.length);
}
if (this.pagination === 'auto') {
const rowsHeight = (this.scroller?.clientHeight ?? 0) - (this.header?.clientHeight ?? 0);
const rowHeight = this.rowHeight;
const pageSize = Math.floor(rowsHeight / rowHeight) || 1;
return dynamicPageSize(pageSize);
}
return this.pagination;
}
get hasFooter() {
const value = this.hasPagination || this.hasSums || this.exportable;
this.toggleAttribute('hasFooter', value);
return value;
}
get dataLength() {
return this.dataRecords.length;
}
get maxPage() {
return this.dataLength === undefined ? undefined : Math.max(Math.ceil(this.dataLength / this.pageSize), 1);
}
get hasNextPage() {
return this.page !== this.maxPage;
}
updated(...parameters) {
this.header?.requestUpdate();
this.sidePanel?.requestUpdate();
this.footer?.requestUpdate();
this.rows.forEach(row => row.requestUpdate());
// @ts-expect-error rowIntersectionObserver is initialized once here
this.rowIntersectionObserver ?? (this.rowIntersectionObserver = new IntersectionObserver(entries => {
entries.forEach(({ target, isIntersecting }) => {
target.isIntersecting = isIntersecting;
});
}, { root: this.scroller, rootMargin: '400px 0px' }));
this.navigateToLastValidPageIfNeeded();
return super.updated(...parameters);
}
navigateToLastValidPageIfNeeded() {
if (this.maxPage && this.page > this.maxPage) {
this.setPage(this.maxPage);
}
}
firstUpdated(props) {
super.firstUpdated(props);
this.cellEdit.subscribe(() => this.requestUpdate());
this.setPage(1);
}
static get styles() {
return css `
:host {
--mo-data-grid-column-details-width: 20px;
--mo-data-grid-column-selection-width: 40px;
--mo-data-grid-column-actions-width: 28px;
--mo-data-grid-cell-padding: 10px;
--mo-data-grid-header-height: 32px;
--mo-data-grid-footer-min-height: 40px;
--mo-data-grid-toolbar-padding: 0px 14px 14px 14px;
--mo-data-grid-border: 1px solid var(--mo-color-transparent-gray-3);
--mo-details-data-grid-start-margin: 26px;
--mo-data-grid-sticky-part-color: var(--mo-color-surface);
--mo-data-grid-alternating-background: color-mix(in srgb, black var(--mo-data-grid-alternating-background-transparency), transparent 0%);
--mo-data-grid-selection-background: color-mix(in srgb, var(--mo-color-accent), transparent 50%);
--_content-min-height-default: calc(var(--mo-data-grid-min-visible-rows, 2.5) * var(--mo-data-grid-row-height) + var(--mo-data-grid-header-height));
display: flex;
flex-direction: column;
height: 100%;
overflow-x: hidden;
}
:not(:has([mo-data-grid-row])) {
--_content-min-height-default: 150px;
}
:host([data-theme=light]) {
--mo-data-grid-alternating-background-transparency : 5%;
}
:host([data-theme=dark]) {
--mo-data-grid-alternating-background-transparency: 20%;
}
:host([preventVerticalContentScroll]) mo-scroller {
overflow-y: hidden;
&::part(container) {
position: relative;
}
}
#content {
width: fit-content;
min-width: 100%;
height: min-content;
min-height: 100%;
}
#toolbar {
position: relative;
padding: var(--mo-data-grid-toolbar-padding);
#actions {
margin-inline-start: auto;
mo-icon-button, ::slotted(mo-icon-button[slot='toolbar-action']) {
color: var(--mo-color-gray);
&[data-selected] {
color: var(--mo-color-accent);
}
}
}
}
#fab {
position: absolute;
inset-inline-end: 16px;
transition: var(--mo-data-grid-fab-transition, 250ms);
z-index: 3;
top: -64px;
}
:host([hasFooter]) #fab {
top: -28px;
}
:host([fabSlotCollapsed][hasFabs]) #fab {
transform: scale(0);
opacity: 0;
}
mo-data-grid-footer {
transition: var(--mo-data-grid-fab-transition, 250ms);
}
:host([hasSums][hasFabs]:not([fabSlotCollapsed])) mo-data-grid-footer {
--mo-data-grid-footer-trailing-padding: calc(var(--mo-data-grid-fab-slot-width, 56px) + 16px);
}
slot[name=fab] {
display: block;
z-index: 1;
}
mo-empty-state, ::slotted(mo-empty-state) {
height: calc(100% - var(--mo-data-grid-header-height) / 2);
margin-block-start: calc(var(--mo-data-grid-header-height) / 2);
position: absolute;
inset: 0;
}
#overlayModeContainer {
position: relative;
height: 100%;
width: 100%;
mo-data-grid-side-panel {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
z-index: 5;
background-color: var(--mo-color-surface);
}
}
`;
}
get template() {
return html `
<slot name='column' hidden ${observeMutation(() => this.requestUpdate())}>${this.columnsTemplate}</slot>
${this.toolbarTemplate}
${this.smallScreenObserverController.matches ? this.overlayModeTemplate : this.splitterModeTemplate}
`;
}
get splitterModeTemplate() {
return html `
<mo-splitter direction='horizontal-reversed' ${style({ height: '100%' })} .resizerTemplate=${this.splitterResizerTemplate}>
${cache(this.sidePanelTab === undefined ? html.nothing : html `
<mo-splitter-item size='min(25%, 300px)' min='max(15%, 250px)' max='clamp(100px, 50%, 750px)'>
${this.sidePanelTemplate}
</mo-splitter-item>
`)}
<mo-splitter-item min='0px' ${style({ position: 'relative' })}>
${this.dataGridTemplate}
</mo-splitter-item>
</mo-splitter>
`;
}
get overlayModeTemplate() {
return html `
<mo-flex id='overlayModeContainer'>
${this.dataGridTemplate}
${this.sidePanelTab === undefined ? html.nothing : this.sidePanelTemplate}
</mo-flex>
`;
}
get sidePanelTemplate() {
return html `
<mo-data-grid-side-panel
.dataGrid=${this}
tab=${ifDefined(this.sidePanelTab)}
>
<slot slot='settings' name='settings'>${this.settingsDefaultTemplate}</slot>
<slot slot='filter' name='filter'>${this.filtersDefaultTemplate}</slot>
</mo-data-grid-side-panel>
`;
}
get settingsDefaultTemplate() {
return html.nothing;
}
get filtersDefaultTemplate() {
return html.nothing;
}
get columnsTemplate() {
return html.nothing;
}
get rowElementTag() {
return DataGrid_1.defaultRowElementTag;
}
get hasDefaultRowElements() {
return this.rowElementTag === DataGrid_1.defaultRowElementTag;
}
get fabTemplate() {
// These also update the respective attributes for now
this.hasSums;
this.hasFabs;
return html `
<slot name='fab' =${() => { this.hasSums; this.hasFabs; }}></slot>
`;
}
get contentTemplate() {
return !this.data.length ? this.noContentTemplate : this.rowsTemplate;
}
get noContentTemplate() {
return html `
<slot name='error-no-content'>
<mo-empty-state icon='youtube_searched_for'>${t('No results')}</mo-empty-state>
</slot>
`;
}
get dataGridTemplate() {
this.toggleAttribute('hasDetails', this.hasDetails);
return html `
<mo-grid rows='* auto' ${style({ position: 'relative', height: '100%' })}>
<mo-scroller
${style({ minHeight: 'var(--mo-data-grid-content-min-height, var(--_content-min-height-default))' })}
=${this.handleScroll}
>
<mo-grid id='content' autoRows='min-content' columns='var(--mo-data-grid-columns)'>
${this.headerTemplate}
${this.contentTemplate}
</mo-grid>
</mo-scroller>
${this.footerTemplate}
</mo-grid>
`;
}
get headerTemplate() {
return this.headerHidden ? html.nothing : html `
<mo-data-grid-header .dataGrid=${this}></mo-data-grid-header>
`;
}
get rowsTemplate() {
// Do not use the data-record or data as the key as it leads to UI flickering
return html `
${this.hiddenSizeAnchorRowTemplate}
${repeat(this.renderDataRecords, record => record.index, (record, index) => this.getRowTemplate(record, index))}
`;
}
/**
* The hidden size anchor row renders the longest content of each column in a hidden row.
* This is used to mitigate the issue of using values with fluctuating lengths
* with a automatic column width e.g. "max-content" or "fit-content" in combination with
* row virtualization, which could lead to a lot of column resizing during scrolling.
*/
get hiddenSizeAnchorRowTemplate() {
const getLength = (template) => [...template.values ?? [], ...template.strings ?? []]
.map(v => {
try {
return `${v}`;
}
catch {
return '';
}
})
.reduce((acc, v) => acc + v.length, 0);
const getLongestContent = (column) => {
return this.dataRecords
.map(dr => column.getContentTemplate?.(KeyPath.get(dr.data, column.dataSelector), dr.data) ?? html.nothing)
.reduce((longest, current) => (getLength(current) > getLength(longest)) || false ? current : longest, html.nothing);
};
return html `
<style>
#size-anchor {
display: grid;
grid-template-columns: subgrid;
grid-column: -1 / 1;
font-size: var(--mo-data-grid-cell-font-size);
height: 0;
visibility: hidden;
opacity: 0;
div {
user-select: none;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding-inline: var(--mo-data-grid-cell-padding);
margin-inline-start: calc(var(--_max-level, 0) * var(--mo-data-grid-column-sub-row-indentation, 20px))
}
}
</style>
<div id='size-anchor'>
${!this.hasDetails ? html.nothing : html `<span></span>`}
${!this.hasSelection ? html.nothing : html `<span></span>`}
${this.visibleColumns.map(column => html `
<div style='--_max-level: ${Math.max(...this.dataRecords.map(dr => dr.level))}'>
${getLongestContent(column)}
</div>
`)}
</div>
`;
}
getRowTemplate(dataRecord, index = 0) {
return staticHtml `
<${this.rowElementTag} part='row'
.dataRecord=${dataRecord}
?data-has-alternating-background=${this.hasAlternatingBackground && index % 2 === 1}
></${this.rowElementTag}>
`;
}
get footerTemplate() {
return html `
<mo-flex ${style({ position: 'relative' })}>
<mo-flex id='fab' direction='vertical-reversed' gap='0.5rem'>
${this.fabTemplate}
</mo-flex>
${this.hasFooter === false ? html.nothing : html `
<mo-data-grid-footer .dataGrid=${this} page=${this.page}>
<slot name='sum' slot='sum'>${this.sumDefaultTemplate}</slot>
</mo-data-grid-footer>
`}
</mo-flex>
`;
}
get sumsTemplate() {
return html `
${this.columns.map(c => c.sumTemplate)}
`;
}
get toolbarTemplate() {
return this.hasToolbar === false ? html.nothing : html `
<mo-flex id='toolbar' direction='horizontal' gap='8px' wrap='wrap' alignItems='center'>
<slot name='toolbar'>${this.toolbarDefaultTemplate}</slot>
<mo-flex id='actions' direction='horizontal' gap='8px' alignContent='center'>
<slot name='toolbar-action'>${this.toolbarActionDefaultTemplate}</slot>
${this.toolbarActionsTemplate}
</mo-flex>
</mo-flex>
`;
}
get toolbarDefaultTemplate() {
return html.nothing;
}
get toolbarActionDefaultTemplate() {
return html.nothing;
}
get sumDefaultTemplate() {
return html.nothing;
}
get toolbarActionsTemplate() {
return html `
${!this.hasFilters ? html.nothing : html `
<mo-icon-button icon='filter_list'
${tooltip(t('More Filters'))}
?data-selected=${this.sidePanelTab === DataGridSidePanelTab.Filters}
=${() => this.navigateToSidePanelTab(this.sidePanelTab === DataGridSidePanelTab.Filters ? undefined : DataGridSidePanelTab.Filters)}
></mo-icon-button>
`}
<mo-icon-button icon='settings'
${tooltip(t('Settings'))}
?data-selected=${this.sidePanelTab === DataGridSidePanelTab.Settings}
=${() => this.navigateToSidePanelTab(this.sidePanelTab === DataGridSidePanelTab.Settings ? undefined : DataGridSidePanelTab.Settings)}
></mo-icon-button>
`;
}
handleScroll(e) {
if (this.preventFabCollapse === false) {
if (!e.composed) {
e.preventDefault();
e.target?.dispatchEvent(new Event('scroll', { composed: true, bubbles: true }));
if (this.hasFabs) {
const targetElement = e.composedPath()[0];
const scrollTop = targetElement.scrollTop;
const isUpScrolling = scrollTop <= this.lastScrollElementTop;
this.fabSlotCollapsed = !isUpScrolling;
this.lastScrollElementTop = scrollTop <= 0 ? 0 : scrollTop;
}
}
}
}
handlePointerDown(event) {
this.rows.forEach(row => row.cells.forEach(cell => cell.handlePointerDown(event)));
}
*getFlattenedData(values = this.data) {
if (!this.subDataGridDataSelector) {
yield* this.sortingController.toSortedBy(values.map((data, index) => new DataRecord(this, { level: 0, index, data })), ({ data }) => data);
return;
}
const flatten = (data, level = 0) => {
const subData = KeyPath.get(data, this.subDataGridDataSelector);
const subDataRecords = !Array.isArray(subData)
? undefined
: this.sortingController
.toSortedBy(subData.map(data => new DataRecord(this, { level, data })), ({ data }) => data)
.flatMap(({ data }) => flatten(data, level + 1));
return [
new DataRecord(this, { data, level, subDataRecords }),
...(subDataRecords ?? [])
];
};
for (const data of this.sortingController.toSorted(values)) {
yield* flatten(data);
}
return;
}
get dataRecords() {
return [...this.getFlattenedData()]
.map((record, index) => {
// @ts-expect-error index is initialized here
record.index = index;
return record;
});
}
get renderDataRecords() {
const rootRecords = this.dataRecords.filter(r => r.level === 0);
if (this.hasPagination === false) {
return rootRecords;
}
const from = this.dataSkip;
const to = this.dataSkip + this.dataTake;
return rootRecords.slice(from, to);
}
get dataSkip() {
return (this.page - 1) * this.pageSize;
}
get dataTake() {
return this.pageSize;
}
async *getCsvData() {
yield 1;
return this.dataRecords;
}
};
DataGrid.rowHeight = new LocalStorage('DataGrid.RowHeight', 35);
DataGrid.cellRelativeFontSize = new LocalStorage('DataGrid.CellRelativeFontSize', 0.8);
DataGrid.pageSize = new LocalStorage('DataGrid.PageSize', 25);
DataGrid.hasAlternatingBackground = new LocalStorage('DataGrid.HasAlternatingBackground', true);
DataGrid.defaultRowElementTag = literal `mo-data-grid-default-row`;
__decorate([
event()
], DataGrid.prototype, "dataChange", void 0);
__decorate([
event()
], DataGrid.prototype, "selectionChange", void 0);
__decorate([
event()
], DataGrid.prototype, "pageChange", void 0);
__decorate([
event()
], DataGrid.prototype, "paginationChange", void 0);
__decorate([
event()
], DataGrid.prototype, "columnsChange", void 0);
__decorate([
event()
], DataGrid.prototype, "sidePanelOpen", void 0);
__decorate([
event()
], DataGrid.prototype, "sidePanelClose", void 0);
__decorate([
event()
], DataGrid.prototype, "sortingChange", void 0);
__decorate([
event()
], DataGrid.prototype, "rowDetailsOpen", void 0);
__decorate([
event()
], DataGrid.prototype, "rowDetailsClose", void 0);
__decorate([
event()
], DataGrid.prototype, "rowClick", void 0);
__decorate([
event()
], DataGrid.prototype, "rowDoubleClick", void 0);
__decorate([
event()
], DataGrid.prototype, "rowMiddleClick", void 0);
__decorate([
event()
], DataGrid.prototype, "cellEdit", void 0);
__decorate([
property({ type: Array })
], DataGrid.prototype, "data", void 0);
__decorate([
property({ type: Array })
], DataGrid.prototype, "columns", void 0);
__decorate([
property({ type: Boolean, reflect: true })
], DataGrid.prototype, "headerHidden", void 0);
__decorate([
property({ type: Boolean, reflect: true })
], DataGrid.prototype, "preventVerticalContentScroll", void 0);
__decorate([
property({ type: Number })
], DataGrid.prototype, "page", void 0);
__decorate([
property({ reflect: true, converter: (value) => value === null || value === undefined ? undefined : Number.isNaN(Number(value)) ? value : Number(value) })
], DataGrid.prototype, "pagination", void 0);
__decorate([
property({ type: Object })
], DataGrid.prototype, "sorting", void 0);
__decorate([
property({ reflect: true })
], DataGrid.prototype, "selectability", void 0);
__decorate([
property({ type: Object })
], DataGrid.prototype, "isDataSelectable", void 0);
__decorate([
property({ type: Array, event: 'selectionChange' })
], DataGrid.prototype, "selectedData", void 0);
__decorate([
property({ type: Boolean })
], DataGrid.prototype, "selectOnClick", void 0);
__decorate([
property()
], DataGrid.prototype, "selectionBehaviorOnDataChange", void 0);
__decorate([
property({ type: Object })
], DataGrid.prototype, "getRowDetailsTemplate", void 0);
__decorate([
property({ type: Boolean })
], DataGrid.prototype, "multipleDetails", void 0);
__decorate([
property()
], DataGrid.prototype, "subDataGridDataSelector", void 0);
__decorate([
property({ type: Object })
], DataGrid.prototype, "hasDataDetail", void 0);
__decorate([
property({ type: Boolean })
], DataGrid.prototype, "detailsOnClick", void 0);
__decorate([
property({ type: Object })
], DataGrid.prototype, "getRowContextMenuTemplate", void 0);
__decorate([
property({ type: Boolean })
], DataGrid.prototype, "primaryContextMenuItemOnDoubleClick", void 0);
__decorate([
property({ reflect: true })
], DataGrid.prototype, "editability", void 0);
__decorate([
property()
], DataGrid.prototype, "sidePanelTab", void 0);
__decorate([
property({ type: Boolean })
], DataGrid.prototype, "sidePanelHidden", void 0);
__decorate([
property({ type: Boolean })
], DataGrid.prototype, "hasAlternatingBackground", void 0);
__decorate([
property({ type: Boolean })
], DataGrid.prototype, "preventFabCollapse", void 0);
__decorate([
property({ type: Boolean, reflect: true })
], DataGrid.prototype, "fabSlotCollapsed", void 0);
__decorate([
property({ type: Boolean })
], DataGrid.prototype, "exportable", void 0);
__decorate([
property({
type: Number,
updated() {
const fontSize = Math.max(0.8, Math.min(1.2, this.cellFontSize));
this.style.setProperty('--mo-data-grid-cell-font-size', `${fontSize}rem`);
}
})
], DataGrid.prototype, "cellFontSize", void 0);
__decorate([
property({
type: Number,
updated() {
const rowHeight = Math.max(30, Math.min(60, this.rowHeight));
this.style.setProperty('--mo-data-grid-row-height', `${rowHeight}px`);
}
})
], DataGrid.prototype, "rowHeight", void 0);
__decorate([
query('mo-data-grid-header')
], DataGrid.prototype, "header", void 0);
__decorate([
query('mo-scroller')
], DataGrid.prototype, "scroller", void 0);
__decorate([
queryAll('[mo-data-grid-row]')
], DataGrid.prototype, "rows", void 0);
__decorate([
query('mo-data-grid-footer')
], DataGrid.prototype, "footer", void 0);
__decorate([
query('mo-data-grid-side-panel')
], DataGrid.prototype, "sidePanel", void 0);
__decorate([
eventOptions({ passive: true })
], DataGrid.prototype, "handleScroll", null);
__decorate([
eventListener({ target: document, type: 'pointerdown' })
], DataGrid.prototype, "handlePointerDown", null);
DataGrid = DataGrid_1 = __decorate([
component('mo-data-grid')
], DataGrid);
export { DataGrid };