@alaarab/ogrid-angular-material 2.0.2 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/column-header-menu/column-header-menu.component.js +122 -0
- package/dist/esm/datagrid-table/datagrid-table.component.js +153 -135
- package/dist/esm/index.js +1 -0
- package/dist/types/column-header-menu/column-header-menu.component.d.ts +20 -0
- package/dist/types/datagrid-table/datagrid-table.component.d.ts +32 -50
- package/dist/types/index.d.ts +1 -0
- package/dist/types/pagination-controls/pagination-controls.component.d.ts +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';
|
|
8
|
+
import { MatMenuModule, MatMenuTrigger } from '@angular/material/menu';
|
|
9
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
10
|
+
import { MatIconModule } from '@angular/material/icon';
|
|
11
|
+
import { COLUMN_HEADER_MENU_ITEMS } from '@alaarab/ogrid-core';
|
|
12
|
+
/**
|
|
13
|
+
* Column header dropdown menu for pin/unpin actions.
|
|
14
|
+
* Uses Angular Material MatMenu.
|
|
15
|
+
*/
|
|
16
|
+
let ColumnHeaderMenuComponent = class ColumnHeaderMenuComponent {
|
|
17
|
+
constructor() {
|
|
18
|
+
this.canPinLeft = true;
|
|
19
|
+
this.canPinRight = true;
|
|
20
|
+
this.canUnpin = false;
|
|
21
|
+
this.pinLeft = new EventEmitter();
|
|
22
|
+
this.pinRight = new EventEmitter();
|
|
23
|
+
this.unpin = new EventEmitter();
|
|
24
|
+
this.menuItems = COLUMN_HEADER_MENU_ITEMS;
|
|
25
|
+
}
|
|
26
|
+
handlePinLeft() {
|
|
27
|
+
if (this.canPinLeft) {
|
|
28
|
+
this.pinLeft.emit();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
handlePinRight() {
|
|
32
|
+
if (this.canPinRight) {
|
|
33
|
+
this.pinRight.emit();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
handleUnpin() {
|
|
37
|
+
if (this.canUnpin) {
|
|
38
|
+
this.unpin.emit();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
__decorate([
|
|
43
|
+
Input()
|
|
44
|
+
], ColumnHeaderMenuComponent.prototype, "columnId", void 0);
|
|
45
|
+
__decorate([
|
|
46
|
+
Input()
|
|
47
|
+
], ColumnHeaderMenuComponent.prototype, "canPinLeft", void 0);
|
|
48
|
+
__decorate([
|
|
49
|
+
Input()
|
|
50
|
+
], ColumnHeaderMenuComponent.prototype, "canPinRight", void 0);
|
|
51
|
+
__decorate([
|
|
52
|
+
Input()
|
|
53
|
+
], ColumnHeaderMenuComponent.prototype, "canUnpin", void 0);
|
|
54
|
+
__decorate([
|
|
55
|
+
Output()
|
|
56
|
+
], ColumnHeaderMenuComponent.prototype, "pinLeft", void 0);
|
|
57
|
+
__decorate([
|
|
58
|
+
Output()
|
|
59
|
+
], ColumnHeaderMenuComponent.prototype, "pinRight", void 0);
|
|
60
|
+
__decorate([
|
|
61
|
+
Output()
|
|
62
|
+
], ColumnHeaderMenuComponent.prototype, "unpin", void 0);
|
|
63
|
+
__decorate([
|
|
64
|
+
ViewChild(MatMenuTrigger)
|
|
65
|
+
], ColumnHeaderMenuComponent.prototype, "menuTrigger", void 0);
|
|
66
|
+
ColumnHeaderMenuComponent = __decorate([
|
|
67
|
+
Component({
|
|
68
|
+
selector: 'column-header-menu',
|
|
69
|
+
standalone: true,
|
|
70
|
+
imports: [MatMenuModule, MatButtonModule, MatIconModule],
|
|
71
|
+
template: `
|
|
72
|
+
<button
|
|
73
|
+
mat-icon-button
|
|
74
|
+
[matMenuTriggerFor]="menu"
|
|
75
|
+
class="column-header-menu-trigger"
|
|
76
|
+
[attr.aria-label]="'Column options for ' + columnId"
|
|
77
|
+
>
|
|
78
|
+
<mat-icon>more_vert</mat-icon>
|
|
79
|
+
</button>
|
|
80
|
+
|
|
81
|
+
<mat-menu #menu="matMenu">
|
|
82
|
+
<button
|
|
83
|
+
mat-menu-item
|
|
84
|
+
[disabled]="!canPinLeft"
|
|
85
|
+
(click)="handlePinLeft()"
|
|
86
|
+
>
|
|
87
|
+
{{ menuItems[0].label }}
|
|
88
|
+
</button>
|
|
89
|
+
<button
|
|
90
|
+
mat-menu-item
|
|
91
|
+
[disabled]="!canPinRight"
|
|
92
|
+
(click)="handlePinRight()"
|
|
93
|
+
>
|
|
94
|
+
{{ menuItems[1].label }}
|
|
95
|
+
</button>
|
|
96
|
+
<button
|
|
97
|
+
mat-menu-item
|
|
98
|
+
[disabled]="!canUnpin"
|
|
99
|
+
(click)="handleUnpin()"
|
|
100
|
+
>
|
|
101
|
+
{{ menuItems[2].label }}
|
|
102
|
+
</button>
|
|
103
|
+
</mat-menu>
|
|
104
|
+
`,
|
|
105
|
+
styles: [`
|
|
106
|
+
.column-header-menu-trigger {
|
|
107
|
+
opacity: 0;
|
|
108
|
+
transition: opacity 0.15s;
|
|
109
|
+
width: 24px;
|
|
110
|
+
height: 24px;
|
|
111
|
+
line-height: 24px;
|
|
112
|
+
padding: 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
:host:hover .column-header-menu-trigger,
|
|
116
|
+
.column-header-menu-trigger:focus {
|
|
117
|
+
opacity: 1;
|
|
118
|
+
}
|
|
119
|
+
`],
|
|
120
|
+
})
|
|
121
|
+
], ColumnHeaderMenuComponent);
|
|
122
|
+
export { ColumnHeaderMenuComponent };
|
|
@@ -4,116 +4,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { Component, input, computed, effect, ChangeDetectionStrategy, viewChild, } from '@angular/core';
|
|
8
|
-
import { DataGridStateService,
|
|
7
|
+
import { Component, input, signal, computed, effect, ChangeDetectionStrategy, viewChild, } from '@angular/core';
|
|
8
|
+
import { DataGridStateService, ColumnReorderService, VirtualScrollService, MarchingAntsOverlayComponent, buildHeaderRows, CHECKBOX_COLUMN_WIDTH, ROW_NUMBER_COLUMN_WIDTH, DEFAULT_MIN_COLUMN_WIDTH, getHeaderFilterConfig, getCellRenderDescriptor, resolveCellDisplayContent, resolveCellStyle, } from '@alaarab/ogrid-angular';
|
|
9
9
|
import { ColumnHeaderFilterComponent } from '../column-header-filter/column-header-filter.component';
|
|
10
|
-
|
|
11
|
-
const filterable = col.filterable && typeof col.filterable === 'object' ? col.filterable : null;
|
|
12
|
-
const filterType = (filterable?.type ?? 'none');
|
|
13
|
-
const filterField = filterable?.filterField ?? col.columnId;
|
|
14
|
-
const sortable = col.sortable !== false;
|
|
15
|
-
const filterValue = input.filters[filterField];
|
|
16
|
-
const base = {
|
|
17
|
-
columnKey: col.columnId,
|
|
18
|
-
columnName: col.name,
|
|
19
|
-
filterType,
|
|
20
|
-
isSorted: input.sortBy === col.columnId,
|
|
21
|
-
isSortedDescending: input.sortBy === col.columnId && input.sortDirection === 'desc',
|
|
22
|
-
onSort: sortable ? () => input.onColumnSort(col.columnId) : undefined,
|
|
23
|
-
};
|
|
24
|
-
if (filterType === 'text') {
|
|
25
|
-
return {
|
|
26
|
-
...base,
|
|
27
|
-
textValue: filterValue?.type === 'text' ? filterValue.value : '',
|
|
28
|
-
onTextChange: (v) => input.onFilterChange(filterField, v.trim() ? { type: 'text', value: v } : undefined),
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
if (filterType === 'people') {
|
|
32
|
-
return {
|
|
33
|
-
...base,
|
|
34
|
-
selectedUser: filterValue?.type === 'people' ? filterValue.value : undefined,
|
|
35
|
-
onUserChange: (u) => input.onFilterChange(filterField, u ? { type: 'people', value: u } : undefined),
|
|
36
|
-
peopleSearch: input.peopleSearch,
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
if (filterType === 'multiSelect') {
|
|
40
|
-
return {
|
|
41
|
-
...base,
|
|
42
|
-
options: input.filterOptions[filterField] ?? [],
|
|
43
|
-
isLoadingOptions: input.loadingFilterOptions[filterField] ?? false,
|
|
44
|
-
selectedValues: filterValue?.type === 'multiSelect' ? filterValue.value : [],
|
|
45
|
-
onFilterChange: (values) => input.onFilterChange(filterField, values.length ? { type: 'multiSelect', value: values } : undefined),
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
if (filterType === 'date') {
|
|
49
|
-
return {
|
|
50
|
-
...base,
|
|
51
|
-
dateValue: filterValue?.type === 'date' ? filterValue.value : undefined,
|
|
52
|
-
onDateChange: (v) => input.onFilterChange(filterField, v ? { type: 'date', value: v } : undefined),
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
return base;
|
|
56
|
-
}
|
|
57
|
-
function getCellRenderDescriptor(item, col, rowIndex, colIdx, input) {
|
|
58
|
-
const rowId = input.getRowId(item);
|
|
59
|
-
const globalColIndex = colIdx + input.colOffset;
|
|
60
|
-
const colEditable = col.editable === true || (typeof col.editable === 'function' && col.editable(item));
|
|
61
|
-
const canEditInline = input.editable !== false && !!colEditable && !!input.onCellValueChanged && typeof col.cellEditor !== 'function';
|
|
62
|
-
const canEditPopup = input.editable !== false && !!colEditable && !!input.onCellValueChanged && typeof col.cellEditor === 'function';
|
|
63
|
-
const canEditAny = canEditInline || canEditPopup;
|
|
64
|
-
const isEditing = input.editingCell?.rowId === rowId && input.editingCell?.columnId === col.columnId;
|
|
65
|
-
const isActive = input.activeCell?.rowIndex === rowIndex && input.activeCell?.columnIndex === globalColIndex;
|
|
66
|
-
const inRange = input.selectionRange != null && isInSelectionRange(input.selectionRange, rowIndex, colIdx);
|
|
67
|
-
const isInCutRange = input.cutRange != null && isInSelectionRange(input.cutRange, rowIndex, colIdx);
|
|
68
|
-
const isSelectionEndCell = !input.isDragging && input.copyRange == null && input.cutRange == null &&
|
|
69
|
-
input.selectionRange != null && rowIndex === input.selectionRange.endRow && colIdx === input.selectionRange.endCol;
|
|
70
|
-
let mode = 'display';
|
|
71
|
-
let editorType;
|
|
72
|
-
const value = getCellValue(item, col);
|
|
73
|
-
if (isEditing && canEditInline) {
|
|
74
|
-
mode = 'editing-inline';
|
|
75
|
-
if (col.cellEditor === 'text' || col.cellEditor === 'select' || col.cellEditor === 'checkbox' || col.cellEditor === 'richSelect' || col.cellEditor === 'date') {
|
|
76
|
-
editorType = col.cellEditor;
|
|
77
|
-
}
|
|
78
|
-
else if (col.type === 'date')
|
|
79
|
-
editorType = 'date';
|
|
80
|
-
else if (col.type === 'boolean')
|
|
81
|
-
editorType = 'checkbox';
|
|
82
|
-
else
|
|
83
|
-
editorType = 'text';
|
|
84
|
-
}
|
|
85
|
-
else if (isEditing && canEditPopup) {
|
|
86
|
-
mode = 'editing-popover';
|
|
87
|
-
}
|
|
88
|
-
return {
|
|
89
|
-
mode, editorType, value,
|
|
90
|
-
isActive, isInRange: inRange, isInCutRange, isSelectionEndCell,
|
|
91
|
-
canEditAny, globalColIndex, rowId, rowIndex, displayValue: value,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
function resolveCellDisplayContent(col, item, displayValue) {
|
|
95
|
-
if (col.renderCell && typeof col.renderCell === 'function') {
|
|
96
|
-
const result = col.renderCell(item);
|
|
97
|
-
return result != null ? String(result) : '';
|
|
98
|
-
}
|
|
99
|
-
if (col.valueFormatter)
|
|
100
|
-
return String(col.valueFormatter(displayValue, item) ?? '');
|
|
101
|
-
if (displayValue == null)
|
|
102
|
-
return '';
|
|
103
|
-
if (col.type === 'date') {
|
|
104
|
-
const d = new Date(String(displayValue));
|
|
105
|
-
if (!Number.isNaN(d.getTime()))
|
|
106
|
-
return d.toLocaleDateString();
|
|
107
|
-
}
|
|
108
|
-
if (col.type === 'boolean')
|
|
109
|
-
return displayValue ? 'True' : 'False';
|
|
110
|
-
return String(displayValue);
|
|
111
|
-
}
|
|
112
|
-
function resolveCellStyle(col, item) {
|
|
113
|
-
if (!col.cellStyle)
|
|
114
|
-
return undefined;
|
|
115
|
-
return typeof col.cellStyle === 'function' ? col.cellStyle(item) : col.cellStyle;
|
|
116
|
-
}
|
|
10
|
+
import { ColumnHeaderMenuComponent } from '../column-header-menu/column-header-menu.component';
|
|
117
11
|
/**
|
|
118
12
|
* DataGridTable component using native HTML table with Material Design-inspired styling.
|
|
119
13
|
* Standalone component — this is the workhorse of the grid.
|
|
@@ -124,7 +18,10 @@ let DataGridTableComponent = class DataGridTableComponent {
|
|
|
124
18
|
this.wrapperRef = viewChild('wrapperEl');
|
|
125
19
|
this.tableContainerRef = viewChild('tableContainerEl');
|
|
126
20
|
this.stateService = new DataGridStateService();
|
|
21
|
+
this.columnReorderService = new ColumnReorderService();
|
|
22
|
+
this.virtualScrollService = new VirtualScrollService();
|
|
127
23
|
this.lastMouseShift = false;
|
|
24
|
+
this.columnSizingVersion = signal(0);
|
|
128
25
|
// --- Delegated state ---
|
|
129
26
|
this.state = computed(() => this.stateService.getState());
|
|
130
27
|
this.items = computed(() => this.propsInput()?.items ?? []);
|
|
@@ -137,9 +34,13 @@ let DataGridTableComponent = class DataGridTableComponent {
|
|
|
137
34
|
this.ariaLabel = computed(() => this.propsInput()?.['aria-label'] ?? 'Data grid');
|
|
138
35
|
this.ariaLabelledBy = computed(() => this.propsInput()?.['aria-labelledby']);
|
|
139
36
|
this.emptyState = computed(() => this.propsInput()?.emptyState);
|
|
37
|
+
this.currentPage = computed(() => this.propsInput()?.currentPage ?? 1);
|
|
38
|
+
this.pageSize = computed(() => this.propsInput()?.pageSize ?? 25);
|
|
39
|
+
this.rowNumberOffset = computed(() => this.hasRowNumbersCol() ? (this.currentPage() - 1) * this.pageSize() : 0);
|
|
140
40
|
// State service outputs
|
|
141
41
|
this.visibleCols = computed(() => this.state().layout.visibleCols);
|
|
142
42
|
this.hasCheckboxCol = computed(() => this.state().layout.hasCheckboxCol);
|
|
43
|
+
this.hasRowNumbersCol = computed(() => this.state().layout.hasRowNumbersCol);
|
|
143
44
|
this.colOffset = computed(() => this.state().layout.colOffset);
|
|
144
45
|
this.containerWidth = computed(() => this.state().layout.containerWidth);
|
|
145
46
|
this.minTableWidth = computed(() => this.state().layout.minTableWidth);
|
|
@@ -189,10 +90,13 @@ let DataGridTableComponent = class DataGridTableComponent {
|
|
|
189
90
|
this.columnLayouts = computed(() => {
|
|
190
91
|
const cols = this.visibleCols();
|
|
191
92
|
const fc = this.freezeCols();
|
|
93
|
+
const props = this.propsInput();
|
|
94
|
+
const pinnedCols = props?.pinnedColumns ?? {};
|
|
192
95
|
return cols.map((col, colIdx) => {
|
|
193
96
|
const isFreezeCol = fc != null && fc >= 1 && colIdx < fc;
|
|
194
|
-
const
|
|
195
|
-
const
|
|
97
|
+
const runtimePinned = pinnedCols[col.columnId];
|
|
98
|
+
const pinnedLeft = runtimePinned === 'left' || (isFreezeCol && colIdx === 0);
|
|
99
|
+
const pinnedRight = runtimePinned === 'right';
|
|
196
100
|
const w = this.getColumnWidth(col);
|
|
197
101
|
return {
|
|
198
102
|
col,
|
|
@@ -211,8 +115,28 @@ let DataGridTableComponent = class DataGridTableComponent {
|
|
|
211
115
|
});
|
|
212
116
|
effect(() => {
|
|
213
117
|
const el = this.wrapperRef()?.nativeElement;
|
|
214
|
-
if (el)
|
|
118
|
+
if (el) {
|
|
215
119
|
this.stateService.wrapperEl.set(el);
|
|
120
|
+
this.columnReorderService.wrapperEl.set(el);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
// Wire column reorder service inputs
|
|
124
|
+
effect(() => {
|
|
125
|
+
const p = this.propsInput();
|
|
126
|
+
if (p) {
|
|
127
|
+
const cols = this.visibleCols();
|
|
128
|
+
this.columnReorderService.columns.set(cols);
|
|
129
|
+
this.columnReorderService.columnOrder.set(p.columnOrder);
|
|
130
|
+
this.columnReorderService.onColumnOrderChange.set(p.onColumnOrderChange);
|
|
131
|
+
this.columnReorderService.enabled.set(!!p.onColumnOrderChange);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
// Wire virtual scroll service inputs
|
|
135
|
+
effect(() => {
|
|
136
|
+
const p = this.propsInput();
|
|
137
|
+
if (p) {
|
|
138
|
+
this.virtualScrollService.totalRows.set(p.items.length);
|
|
139
|
+
}
|
|
216
140
|
});
|
|
217
141
|
}
|
|
218
142
|
// --- Helper methods ---
|
|
@@ -288,6 +212,7 @@ let DataGridTableComponent = class DataGridTableComponent {
|
|
|
288
212
|
const newWidth = Math.max(minWidth, startWidth + delta);
|
|
289
213
|
const overrides = { ...this.columnSizingOverrides(), [col.columnId]: { widthPx: newWidth } };
|
|
290
214
|
this.state().layout.setColumnSizingOverrides(overrides);
|
|
215
|
+
this.columnSizingVersion.update(v => v + 1);
|
|
291
216
|
};
|
|
292
217
|
const onUp = () => {
|
|
293
218
|
window.removeEventListener('mousemove', onMove);
|
|
@@ -351,12 +276,36 @@ let DataGridTableComponent = class DataGridTableComponent {
|
|
|
351
276
|
onRedo() {
|
|
352
277
|
this.state().interaction.onRedo?.();
|
|
353
278
|
}
|
|
279
|
+
onHeaderMouseDown(columnId, event) {
|
|
280
|
+
this.columnReorderService.handleHeaderMouseDown(columnId, event);
|
|
281
|
+
}
|
|
282
|
+
// --- Column pinning methods ---
|
|
283
|
+
onPinColumn(columnId, side) {
|
|
284
|
+
const props = this.propsInput();
|
|
285
|
+
props?.onColumnPinned?.(columnId, side);
|
|
286
|
+
}
|
|
287
|
+
onUnpinColumn(columnId) {
|
|
288
|
+
const props = this.propsInput();
|
|
289
|
+
props?.onColumnPinned?.(columnId, null);
|
|
290
|
+
}
|
|
291
|
+
isPinned(columnId) {
|
|
292
|
+
const props = this.propsInput();
|
|
293
|
+
return props?.pinnedColumns?.[columnId];
|
|
294
|
+
}
|
|
295
|
+
getPinState(columnId) {
|
|
296
|
+
const pinned = this.isPinned(columnId);
|
|
297
|
+
return {
|
|
298
|
+
canPinLeft: pinned !== 'left',
|
|
299
|
+
canPinRight: pinned !== 'right',
|
|
300
|
+
canUnpin: !!pinned,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
354
303
|
};
|
|
355
304
|
DataGridTableComponent = __decorate([
|
|
356
305
|
Component({
|
|
357
306
|
selector: 'ogrid-datagrid-table',
|
|
358
307
|
standalone: true,
|
|
359
|
-
imports: [ColumnHeaderFilterComponent],
|
|
308
|
+
imports: [ColumnHeaderFilterComponent, ColumnHeaderMenuComponent, MarchingAntsOverlayComponent],
|
|
360
309
|
providers: [DataGridStateService],
|
|
361
310
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
362
311
|
template: `
|
|
@@ -401,6 +350,14 @@ DataGridTableComponent = __decorate([
|
|
|
401
350
|
@if (rowIdx === 0 && rowIdx < headerRows().length - 1 && hasCheckboxCol()) {
|
|
402
351
|
<th [attr.rowSpan]="headerRows().length - 1" class="ogrid-datagrid-th" style="width: 48px; min-width: 48px; padding: 0;"></th>
|
|
403
352
|
}
|
|
353
|
+
@if (rowIdx === headerRows().length - 1 && hasRowNumbersCol()) {
|
|
354
|
+
<th class="ogrid-datagrid-th ogrid-row-number-header" [attr.rowSpan]="headerRows().length > 1 ? 1 : null">
|
|
355
|
+
<div class="ogrid-row-number-header-content">#</div>
|
|
356
|
+
</th>
|
|
357
|
+
}
|
|
358
|
+
@if (rowIdx === 0 && rowIdx < headerRows().length - 1 && hasRowNumbersCol()) {
|
|
359
|
+
<th [attr.rowSpan]="headerRows().length - 1" class="ogrid-datagrid-th" [style.width.px]="50" [style.min-width.px]="50" style="padding: 0;"></th>
|
|
360
|
+
}
|
|
404
361
|
@for (cell of row; track $index; let cellIdx = $index) {
|
|
405
362
|
@if (cell.isGroup) {
|
|
406
363
|
<th [attr.colSpan]="cell.colSpan" scope="colgroup" class="ogrid-datagrid-th ogrid-datagrid-group-header">
|
|
@@ -411,34 +368,52 @@ DataGridTableComponent = __decorate([
|
|
|
411
368
|
@let colIdx = visibleColIndex(col);
|
|
412
369
|
@let isFreezeCol = freezeCols() != null && (freezeCols() ?? 0) >= 1 && colIdx < (freezeCols() ?? 0);
|
|
413
370
|
@let colW = getColumnWidth(col);
|
|
371
|
+
@let pinned = isPinned(col.columnId);
|
|
372
|
+
@let pinnedLeft = pinned === 'left' || (isFreezeCol && colIdx === 0);
|
|
373
|
+
@let pinnedRight = pinned === 'right';
|
|
414
374
|
<th scope="col"
|
|
415
375
|
class="ogrid-datagrid-th"
|
|
416
|
-
[class.ogrid-datagrid-th--pinned-left]="
|
|
417
|
-
[class.ogrid-datagrid-th--pinned-right]="
|
|
376
|
+
[class.ogrid-datagrid-th--pinned-left]="pinnedLeft"
|
|
377
|
+
[class.ogrid-datagrid-th--pinned-right]="pinnedRight"
|
|
418
378
|
[attr.rowSpan]="headerRows().length > 1 ? headerRows().length - rowIdx : null"
|
|
379
|
+
[attr.data-column-id]="col.columnId"
|
|
419
380
|
[style.minWidth.px]="col.minWidth ?? 80"
|
|
420
381
|
[style.width.px]="colW"
|
|
421
382
|
[style.maxWidth.px]="colW"
|
|
383
|
+
[style.cursor]="columnReorderService.isDragging() ? 'grabbing' : 'grab'"
|
|
384
|
+
(mousedown)="onHeaderMouseDown(col.columnId, $event)"
|
|
422
385
|
>
|
|
423
|
-
<
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
386
|
+
<div style="display:flex;align-items:center;gap:4px;">
|
|
387
|
+
<ogrid-column-header-filter
|
|
388
|
+
[columnKey]="col.columnId"
|
|
389
|
+
[columnName]="col.name"
|
|
390
|
+
[filterType]="getFilterConfig(col).filterType"
|
|
391
|
+
[isSorted]="getFilterConfig(col).isSorted"
|
|
392
|
+
[isSortedDescending]="getFilterConfig(col).isSortedDescending"
|
|
393
|
+
[onSort]="getFilterConfig(col).onSort"
|
|
394
|
+
[selectedValues]="getFilterConfig(col).selectedValues"
|
|
395
|
+
[onFilterChange]="getFilterConfig(col).onFilterChange"
|
|
396
|
+
[options]="getFilterConfig(col).options"
|
|
397
|
+
[isLoadingOptions]="getFilterConfig(col).isLoadingOptions ?? false"
|
|
398
|
+
[textValue]="getFilterConfig(col).textValue ?? ''"
|
|
399
|
+
[onTextChange]="getFilterConfig(col).onTextChange"
|
|
400
|
+
[selectedUser]="getFilterConfig(col).selectedUser"
|
|
401
|
+
[onUserChange]="getFilterConfig(col).onUserChange"
|
|
402
|
+
[peopleSearch]="getFilterConfig(col).peopleSearch"
|
|
403
|
+
[dateValue]="getFilterConfig(col).dateValue"
|
|
404
|
+
[onDateChange]="getFilterConfig(col).onDateChange"
|
|
405
|
+
/>
|
|
406
|
+
@let pinState = getPinState(col.columnId);
|
|
407
|
+
<column-header-menu
|
|
408
|
+
[columnId]="col.columnId"
|
|
409
|
+
[onPinLeft]="() => onPinColumn(col.columnId, 'left')"
|
|
410
|
+
[onPinRight]="() => onPinColumn(col.columnId, 'right')"
|
|
411
|
+
[onUnpin]="() => onUnpinColumn(col.columnId)"
|
|
412
|
+
[canPinLeft]="pinState.canPinLeft"
|
|
413
|
+
[canPinRight]="pinState.canPinRight"
|
|
414
|
+
[canUnpin]="pinState.canUnpin"
|
|
415
|
+
/>
|
|
416
|
+
</div>
|
|
442
417
|
<div class="ogrid-datagrid-resize-handle" (mousedown)="onResizeStart($event, col)"></div>
|
|
443
418
|
</th>
|
|
444
419
|
}
|
|
@@ -474,6 +449,13 @@ DataGridTableComponent = __decorate([
|
|
|
474
449
|
</div>
|
|
475
450
|
</td>
|
|
476
451
|
}
|
|
452
|
+
@if (hasRowNumbersCol()) {
|
|
453
|
+
<td class="ogrid-datagrid-td ogrid-row-number-cell">
|
|
454
|
+
<div class="ogrid-row-number-cell-content">
|
|
455
|
+
{{ rowNumberOffset() + rowIndex + 1 }}
|
|
456
|
+
</div>
|
|
457
|
+
</td>
|
|
458
|
+
}
|
|
477
459
|
@for (colLayout of columnLayouts(); track colLayout.col.columnId; let colIdx = $index) {
|
|
478
460
|
<td
|
|
479
461
|
class="ogrid-datagrid-td"
|
|
@@ -566,6 +548,15 @@ DataGridTableComponent = __decorate([
|
|
|
566
548
|
}
|
|
567
549
|
</table>
|
|
568
550
|
|
|
551
|
+
<ogrid-marching-ants-overlay
|
|
552
|
+
[containerEl]="tableContainerEl()"
|
|
553
|
+
[selectionRange]="state().interaction.selectionRange"
|
|
554
|
+
[copyRange]="state().interaction.copyRange"
|
|
555
|
+
[cutRange]="state().interaction.cutRange"
|
|
556
|
+
[colOffset]="state().layout.colOffset"
|
|
557
|
+
[columnSizingVersion]="columnSizingVersion()"
|
|
558
|
+
></ogrid-marching-ants-overlay>
|
|
559
|
+
|
|
569
560
|
@if (showEmptyInGrid() && emptyState()) {
|
|
570
561
|
<div class="ogrid-datagrid-empty">
|
|
571
562
|
<div class="ogrid-datagrid-empty__title">No results found</div>
|
|
@@ -586,6 +577,10 @@ DataGridTableComponent = __decorate([
|
|
|
586
577
|
</div>
|
|
587
578
|
</div>
|
|
588
579
|
|
|
580
|
+
@if (columnReorderService.isDragging() && columnReorderService.dropIndicatorX() !== null) {
|
|
581
|
+
<div class="ogrid-datagrid-drop-indicator" [style.left.px]="columnReorderService.dropIndicatorX()"></div>
|
|
582
|
+
}
|
|
583
|
+
|
|
589
584
|
@if (menuPosition()) {
|
|
590
585
|
<div
|
|
591
586
|
class="ogrid-datagrid-context-menu-overlay"
|
|
@@ -658,9 +653,11 @@ DataGridTableComponent = __decorate([
|
|
|
658
653
|
}
|
|
659
654
|
.ogrid-datagrid-th--pinned-left {
|
|
660
655
|
position: sticky; left: 0; z-index: 9; background: rgba(0,0,0,0.04); will-change: transform;
|
|
656
|
+
border-left: 2px solid var(--mat-sys-primary, #1976d2);
|
|
661
657
|
}
|
|
662
658
|
.ogrid-datagrid-th--pinned-right {
|
|
663
659
|
position: sticky; right: 0; z-index: 9; background: rgba(0,0,0,0.04); will-change: transform;
|
|
660
|
+
border-right: 2px solid var(--mat-sys-primary, #1976d2);
|
|
664
661
|
}
|
|
665
662
|
.ogrid-datagrid-group-header {
|
|
666
663
|
text-align: center; font-weight: 600; border-bottom: 2px solid rgba(0,0,0,0.12); padding: 6px;
|
|
@@ -670,15 +667,28 @@ DataGridTableComponent = __decorate([
|
|
|
670
667
|
max-width: ${CHECKBOX_COLUMN_WIDTH}px; text-align: center;
|
|
671
668
|
}
|
|
672
669
|
.ogrid-datagrid-checkbox-wrapper { display: flex; align-items: center; justify-content: center; }
|
|
670
|
+
.ogrid-row-number-header, .ogrid-row-number-cell {
|
|
671
|
+
width: ${ROW_NUMBER_COLUMN_WIDTH}px; min-width: ${ROW_NUMBER_COLUMN_WIDTH}px;
|
|
672
|
+
max-width: ${ROW_NUMBER_COLUMN_WIDTH}px; text-align: center;
|
|
673
|
+
background: rgba(0,0,0,0.04); font-weight: 600;
|
|
674
|
+
font-variant-numeric: tabular-nums; color: rgba(0,0,0,0.6);
|
|
675
|
+
position: sticky; left: 0; z-index: 3;
|
|
676
|
+
}
|
|
677
|
+
.ogrid-row-number-header { z-index: 4; }
|
|
678
|
+
.ogrid-row-number-header-content, .ogrid-row-number-cell-content {
|
|
679
|
+
display: flex; align-items: center; justify-content: center;
|
|
680
|
+
}
|
|
673
681
|
.ogrid-datagrid-row { }
|
|
674
682
|
.ogrid-datagrid-row:hover { background: rgba(0,0,0,0.04); }
|
|
675
683
|
.ogrid-datagrid-row--selected { background: rgba(25,118,210,0.08); }
|
|
676
684
|
.ogrid-datagrid-td { position: relative; padding: 0; height: 1px; border-bottom: 1px solid rgba(0,0,0,0.06); }
|
|
677
685
|
.ogrid-datagrid-td--pinned-left {
|
|
678
686
|
position: sticky; left: 0; z-index: 6; background: #fff; will-change: transform;
|
|
687
|
+
border-left: 2px solid var(--mat-sys-primary, #1976d2);
|
|
679
688
|
}
|
|
680
689
|
.ogrid-datagrid-td--pinned-right {
|
|
681
690
|
position: sticky; right: 0; z-index: 6; background: #fff; will-change: transform;
|
|
691
|
+
border-right: 2px solid var(--mat-sys-primary, #1976d2);
|
|
682
692
|
}
|
|
683
693
|
.ogrid-datagrid-cell {
|
|
684
694
|
width: 100%; height: 100%; display: flex; align-items: center; min-width: 0;
|
|
@@ -698,7 +708,10 @@ DataGridTableComponent = __decorate([
|
|
|
698
708
|
.ogrid-datagrid-cell--editing { padding: 0; }
|
|
699
709
|
.ogrid-datagrid-editor-input {
|
|
700
710
|
width: 100%; height: 100%; padding: 6px 10px; border: 2px solid var(--ogrid-selection, #217346);
|
|
701
|
-
box-sizing: border-box; font-size: 14px; outline: none;
|
|
711
|
+
box-sizing: border-box; font-size: 14px; outline: none; font-family: inherit; line-height: inherit;
|
|
712
|
+
}
|
|
713
|
+
.ogrid-datagrid-cell--numeric .ogrid-datagrid-editor-input {
|
|
714
|
+
text-align: right;
|
|
702
715
|
}
|
|
703
716
|
.ogrid-datagrid-editor-select {
|
|
704
717
|
width: 100%; height: 100%; padding: 4px 8px; border: 2px solid var(--ogrid-selection, #217346);
|
|
@@ -744,6 +757,11 @@ DataGridTableComponent = __decorate([
|
|
|
744
757
|
border-radius: 50%; animation: ogrid-spin 0.8s linear infinite;
|
|
745
758
|
}
|
|
746
759
|
@keyframes ogrid-spin { to { transform: rotate(360deg); } }
|
|
760
|
+
.ogrid-datagrid-drop-indicator {
|
|
761
|
+
position: absolute; top: 0; bottom: 0; width: 3px;
|
|
762
|
+
background: var(--ogrid-primary, #217346);
|
|
763
|
+
pointer-events: none; z-index: 100; transition: left 0.05s;
|
|
764
|
+
}
|
|
747
765
|
.ogrid-datagrid-context-menu-overlay {
|
|
748
766
|
position: fixed; inset: 0; z-index: 1000;
|
|
749
767
|
}
|
package/dist/esm/index.js
CHANGED
|
@@ -6,3 +6,4 @@ export { DataGridTableComponent } from './datagrid-table/datagrid-table.componen
|
|
|
6
6
|
export { ColumnHeaderFilterComponent } from './column-header-filter/column-header-filter.component';
|
|
7
7
|
export { ColumnChooserComponent } from './column-chooser/column-chooser.component';
|
|
8
8
|
export { PaginationControlsComponent } from './pagination-controls/pagination-controls.component';
|
|
9
|
+
export { ColumnHeaderMenuComponent } from './column-header-menu/column-header-menu.component';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { EventEmitter } from '@angular/core';
|
|
2
|
+
import { MatMenuTrigger } from '@angular/material/menu';
|
|
3
|
+
/**
|
|
4
|
+
* Column header dropdown menu for pin/unpin actions.
|
|
5
|
+
* Uses Angular Material MatMenu.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ColumnHeaderMenuComponent {
|
|
8
|
+
columnId: string;
|
|
9
|
+
canPinLeft: boolean;
|
|
10
|
+
canPinRight: boolean;
|
|
11
|
+
canUnpin: boolean;
|
|
12
|
+
pinLeft: EventEmitter<void>;
|
|
13
|
+
pinRight: EventEmitter<void>;
|
|
14
|
+
unpin: EventEmitter<void>;
|
|
15
|
+
menuTrigger?: MatMenuTrigger;
|
|
16
|
+
readonly menuItems: import("@alaarab/ogrid-core").IColumnHeaderMenuItem[];
|
|
17
|
+
handlePinLeft(): void;
|
|
18
|
+
handlePinRight(): void;
|
|
19
|
+
handleUnpin(): void;
|
|
20
|
+
}
|
|
@@ -1,38 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
type
|
|
3
|
-
interface CellRenderDescriptor {
|
|
4
|
-
mode: CellRenderMode;
|
|
5
|
-
editorType?: 'text' | 'select' | 'checkbox' | 'richSelect' | 'date';
|
|
6
|
-
value?: unknown;
|
|
7
|
-
isActive: boolean;
|
|
8
|
-
isInRange: boolean;
|
|
9
|
-
isInCutRange: boolean;
|
|
10
|
-
isSelectionEndCell: boolean;
|
|
11
|
-
canEditAny: boolean;
|
|
12
|
-
globalColIndex: number;
|
|
13
|
-
rowId: RowId;
|
|
14
|
-
rowIndex: number;
|
|
15
|
-
displayValue?: unknown;
|
|
16
|
-
}
|
|
17
|
-
interface HeaderFilterConfig {
|
|
18
|
-
columnKey: string;
|
|
19
|
-
columnName: string;
|
|
20
|
-
filterType: ColumnFilterType;
|
|
21
|
-
isSorted: boolean;
|
|
22
|
-
isSortedDescending: boolean;
|
|
23
|
-
onSort: (() => void) | undefined;
|
|
24
|
-
selectedValues?: string[];
|
|
25
|
-
onFilterChange?: (values: string[]) => void;
|
|
26
|
-
options?: string[];
|
|
27
|
-
isLoadingOptions?: boolean;
|
|
28
|
-
textValue?: string;
|
|
29
|
-
onTextChange?: (value: string) => void;
|
|
30
|
-
selectedUser?: UserLike;
|
|
31
|
-
onUserChange?: (user: UserLike | undefined) => void;
|
|
32
|
-
peopleSearch?: (query: string) => Promise<UserLike[]>;
|
|
33
|
-
dateValue?: IDateFilterValue;
|
|
34
|
-
onDateChange?: (value: IDateFilterValue | undefined) => void;
|
|
35
|
-
}
|
|
1
|
+
import { ColumnReorderService, VirtualScrollService } from '@alaarab/ogrid-angular';
|
|
2
|
+
import type { IOGridDataGridProps, IColumnDef, RowId, CellRenderDescriptor, HeaderFilterConfig } from '@alaarab/ogrid-angular';
|
|
36
3
|
/**
|
|
37
4
|
* DataGridTable component using native HTML table with Material Design-inspired styling.
|
|
38
5
|
* Standalone component — this is the workhorse of the grid.
|
|
@@ -42,7 +9,10 @@ export declare class DataGridTableComponent<T> {
|
|
|
42
9
|
private readonly wrapperRef;
|
|
43
10
|
private readonly tableContainerRef;
|
|
44
11
|
private readonly stateService;
|
|
12
|
+
readonly columnReorderService: ColumnReorderService<T>;
|
|
13
|
+
readonly virtualScrollService: VirtualScrollService;
|
|
45
14
|
private lastMouseShift;
|
|
15
|
+
private columnSizingVersion;
|
|
46
16
|
constructor();
|
|
47
17
|
private readonly state;
|
|
48
18
|
readonly items: import("@angular/core").Signal<T[]>;
|
|
@@ -60,8 +30,12 @@ export declare class DataGridTableComponent<T> {
|
|
|
60
30
|
message?: string;
|
|
61
31
|
render?: import("@angular/core").TemplateRef<unknown>;
|
|
62
32
|
} | undefined>;
|
|
33
|
+
readonly currentPage: import("@angular/core").Signal<number>;
|
|
34
|
+
readonly pageSize: import("@angular/core").Signal<number>;
|
|
35
|
+
readonly rowNumberOffset: import("@angular/core").Signal<number>;
|
|
63
36
|
readonly visibleCols: import("@angular/core").Signal<IColumnDef<T>[]>;
|
|
64
37
|
readonly hasCheckboxCol: import("@angular/core").Signal<boolean>;
|
|
38
|
+
readonly hasRowNumbersCol: import("@angular/core").Signal<boolean>;
|
|
65
39
|
readonly colOffset: import("@angular/core").Signal<number>;
|
|
66
40
|
readonly containerWidth: import("@angular/core").Signal<number>;
|
|
67
41
|
readonly minTableWidth: import("@angular/core").Signal<number>;
|
|
@@ -77,11 +51,11 @@ export declare class DataGridTableComponent<T> {
|
|
|
77
51
|
columnId: string;
|
|
78
52
|
} | null>;
|
|
79
53
|
readonly pendingEditorValue: import("@angular/core").Signal<unknown>;
|
|
80
|
-
readonly activeCell: import("@angular/core").Signal<import("@alaarab/ogrid-
|
|
81
|
-
readonly selectionRange: import("@angular/core").Signal<import("@alaarab/ogrid-
|
|
54
|
+
readonly activeCell: import("@angular/core").Signal<import("@alaarab/ogrid-core").IActiveCell | null>;
|
|
55
|
+
readonly selectionRange: import("@angular/core").Signal<import("@alaarab/ogrid-core").ISelectionRange | null>;
|
|
82
56
|
readonly hasCellSelection: import("@angular/core").Signal<boolean>;
|
|
83
|
-
readonly cutRange: import("@angular/core").Signal<import("@alaarab/ogrid-
|
|
84
|
-
readonly copyRange: import("@angular/core").Signal<import("@alaarab/ogrid-
|
|
57
|
+
readonly cutRange: import("@angular/core").Signal<import("@alaarab/ogrid-core").ISelectionRange | null>;
|
|
58
|
+
readonly copyRange: import("@angular/core").Signal<import("@alaarab/ogrid-core").ISelectionRange | null>;
|
|
85
59
|
readonly canUndo: import("@angular/core").Signal<boolean>;
|
|
86
60
|
readonly canRedo: import("@angular/core").Signal<boolean>;
|
|
87
61
|
readonly isDragging: import("@angular/core").Signal<boolean>;
|
|
@@ -89,37 +63,37 @@ export declare class DataGridTableComponent<T> {
|
|
|
89
63
|
x: number;
|
|
90
64
|
y: number;
|
|
91
65
|
} | null>;
|
|
92
|
-
readonly statusBarConfig: import("@angular/core").Signal<import("@alaarab/ogrid-
|
|
66
|
+
readonly statusBarConfig: import("@angular/core").Signal<import("@alaarab/ogrid-core").IStatusBarProps | null>;
|
|
93
67
|
readonly showEmptyInGrid: import("@angular/core").Signal<boolean>;
|
|
94
68
|
readonly headerFilterInput: import("@angular/core").Signal<{
|
|
95
69
|
sortBy?: string;
|
|
96
70
|
sortDirection: "asc" | "desc";
|
|
97
71
|
onColumnSort: (columnKey: string) => void;
|
|
98
|
-
filters: IFilters;
|
|
99
|
-
onFilterChange: (key: string, value: FilterValue | undefined) => void;
|
|
72
|
+
filters: import("@alaarab/ogrid-core").IFilters;
|
|
73
|
+
onFilterChange: (key: string, value: import("@alaarab/ogrid-core").FilterValue | undefined) => void;
|
|
100
74
|
filterOptions: Record<string, string[]>;
|
|
101
75
|
loadingFilterOptions: Record<string, boolean>;
|
|
102
|
-
peopleSearch?: (query: string) => Promise<UserLike[]>;
|
|
76
|
+
peopleSearch?: (query: string) => Promise<import("@alaarab/ogrid-core").UserLike[]>;
|
|
103
77
|
}>;
|
|
104
78
|
readonly cellDescriptorInput: import("@angular/core").Signal<{
|
|
105
79
|
editingCell: {
|
|
106
80
|
rowId: RowId;
|
|
107
81
|
columnId: string;
|
|
108
82
|
} | null;
|
|
109
|
-
activeCell: import("@alaarab/ogrid-
|
|
110
|
-
selectionRange: import("@alaarab/ogrid-
|
|
111
|
-
cutRange: import("@alaarab/ogrid-
|
|
112
|
-
copyRange: import("@alaarab/ogrid-
|
|
83
|
+
activeCell: import("@alaarab/ogrid-core").IActiveCell | null;
|
|
84
|
+
selectionRange: import("@alaarab/ogrid-core").ISelectionRange | null;
|
|
85
|
+
cutRange: import("@alaarab/ogrid-core").ISelectionRange | null;
|
|
86
|
+
copyRange: import("@alaarab/ogrid-core").ISelectionRange | null;
|
|
113
87
|
colOffset: number;
|
|
114
88
|
itemsLength: number;
|
|
115
89
|
getRowId: (item: T) => RowId;
|
|
116
90
|
editable?: boolean;
|
|
117
|
-
onCellValueChanged?: ((event: import("@alaarab/ogrid-
|
|
91
|
+
onCellValueChanged?: ((event: import("@alaarab/ogrid-core").ICellValueChangedEvent<T>) => void) | undefined;
|
|
118
92
|
isDragging: boolean;
|
|
119
93
|
}>;
|
|
120
94
|
readonly allowOverflowX: import("@angular/core").Signal<boolean>;
|
|
121
95
|
readonly selectionCellCount: import("@angular/core").Signal<number | undefined>;
|
|
122
|
-
readonly headerRows: import("@angular/core").Signal<import("@alaarab/ogrid-
|
|
96
|
+
readonly headerRows: import("@angular/core").Signal<import("@alaarab/ogrid-core").HeaderRow<T>[]>;
|
|
123
97
|
readonly columnLayouts: import("@angular/core").Signal<{
|
|
124
98
|
col: IColumnDef<T>;
|
|
125
99
|
pinnedLeft: boolean;
|
|
@@ -157,5 +131,13 @@ export declare class DataGridTableComponent<T> {
|
|
|
157
131
|
handleSelectAllCells(): void;
|
|
158
132
|
onUndo(): void;
|
|
159
133
|
onRedo(): void;
|
|
134
|
+
onHeaderMouseDown(columnId: string, event: MouseEvent): void;
|
|
135
|
+
onPinColumn(columnId: string, side: 'left' | 'right'): void;
|
|
136
|
+
onUnpinColumn(columnId: string): void;
|
|
137
|
+
isPinned(columnId: string): 'left' | 'right' | undefined;
|
|
138
|
+
getPinState(columnId: string): {
|
|
139
|
+
canPinLeft: boolean;
|
|
140
|
+
canPinRight: boolean;
|
|
141
|
+
canUnpin: boolean;
|
|
142
|
+
};
|
|
160
143
|
}
|
|
161
|
-
export {};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -6,3 +6,4 @@ export type { IColumnHeaderFilterProps } from './column-header-filter/column-hea
|
|
|
6
6
|
export { ColumnChooserComponent } from './column-chooser/column-chooser.component';
|
|
7
7
|
export type { IColumnChooserProps } from './column-chooser/column-chooser.component';
|
|
8
8
|
export { PaginationControlsComponent } from './pagination-controls/pagination-controls.component';
|
|
9
|
+
export { ColumnHeaderMenuComponent } from './column-header-menu/column-header-menu.component';
|
|
@@ -10,6 +10,6 @@ export declare class PaginationControlsComponent {
|
|
|
10
10
|
readonly entityLabelPlural: import("@angular/core").InputSignal<string>;
|
|
11
11
|
readonly pageChange: import("@angular/core").OutputEmitterRef<number>;
|
|
12
12
|
readonly pageSizeChange: import("@angular/core").OutputEmitterRef<number>;
|
|
13
|
-
readonly vm: import("@angular/core").Signal<import("@alaarab/ogrid-
|
|
13
|
+
readonly vm: import("@angular/core").Signal<import("@alaarab/ogrid-core").PaginationViewModel | null>;
|
|
14
14
|
onPageSizeSelect(event: Event): void;
|
|
15
15
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alaarab/ogrid-angular-material",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "OGrid Angular Material – MatTable-based data grid with sorting, filtering, pagination, column chooser, and CSV export.",
|
|
5
5
|
"main": "dist/esm/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"files": ["dist", "README.md", "LICENSE"],
|
|
23
23
|
"engines": { "node": ">=18" },
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@alaarab/ogrid-angular": "2.0.
|
|
25
|
+
"@alaarab/ogrid-angular": "2.0.4"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"@angular/core": "^21.0.0",
|