@alaarab/ogrid-angular 2.0.11 → 2.0.13
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/components/base-datagrid-table.component.js +13 -24
- package/dist/esm/components/ogrid-layout.component.js +70 -25
- package/dist/esm/components/sidebar.component.js +22 -22
- package/dist/esm/services/datagrid-state.service.js +1 -1
- package/dist/esm/services/ogrid.service.js +8 -18
- package/dist/types/components/base-datagrid-table.component.d.ts +2 -3
- package/dist/types/services/datagrid-state.service.d.ts +1 -1
- package/dist/types/services/ogrid.service.d.ts +2 -1
- package/dist/types/types/dataGridTypes.d.ts +3 -1
- package/package.json +2 -2
|
@@ -2,7 +2,7 @@ import { signal, computed, effect } from '@angular/core';
|
|
|
2
2
|
import { DataGridStateService } from '../services/datagrid-state.service';
|
|
3
3
|
import { ColumnReorderService } from '../services/column-reorder.service';
|
|
4
4
|
import { VirtualScrollService } from '../services/virtual-scroll.service';
|
|
5
|
-
import { buildHeaderRows, DEFAULT_MIN_COLUMN_WIDTH, CELL_PADDING, CHECKBOX_COLUMN_WIDTH, ROW_NUMBER_COLUMN_WIDTH, } from '@alaarab/ogrid-core';
|
|
5
|
+
import { buildHeaderRows, DEFAULT_MIN_COLUMN_WIDTH, CELL_PADDING, CHECKBOX_COLUMN_WIDTH, ROW_NUMBER_COLUMN_WIDTH, measureColumnContentWidth, } from '@alaarab/ogrid-core';
|
|
6
6
|
import { getHeaderFilterConfig, getCellRenderDescriptor, resolveCellDisplayContent, resolveCellStyle, buildPopoverEditorProps, } from '../utils';
|
|
7
7
|
/**
|
|
8
8
|
* Abstract base class containing all shared TypeScript logic for DataGridTable components.
|
|
@@ -209,7 +209,7 @@ export class BaseDataGridTableComponent {
|
|
|
209
209
|
this.columnReorderService.columns.set(cols);
|
|
210
210
|
this.columnReorderService.columnOrder.set(p.columnOrder);
|
|
211
211
|
this.columnReorderService.onColumnOrderChange.set(p.onColumnOrderChange);
|
|
212
|
-
this.columnReorderService.enabled.set(
|
|
212
|
+
this.columnReorderService.enabled.set(p.columnReorder === true);
|
|
213
213
|
}
|
|
214
214
|
});
|
|
215
215
|
// Wire virtual scroll service inputs
|
|
@@ -428,16 +428,18 @@ export class BaseDataGridTableComponent {
|
|
|
428
428
|
// --- Column sorting methods ---
|
|
429
429
|
onSortAsc(columnId) {
|
|
430
430
|
const props = this.getProps();
|
|
431
|
-
props?.onColumnSort?.(columnId);
|
|
431
|
+
props?.onColumnSort?.(columnId, 'asc');
|
|
432
432
|
}
|
|
433
433
|
onSortDesc(columnId) {
|
|
434
434
|
const props = this.getProps();
|
|
435
|
-
props?.onColumnSort?.(columnId);
|
|
435
|
+
props?.onColumnSort?.(columnId, 'desc');
|
|
436
436
|
}
|
|
437
|
-
onClearSort() {
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
437
|
+
onClearSort(columnId) {
|
|
438
|
+
const props = this.getProps();
|
|
439
|
+
const col = columnId ?? props?.sortBy;
|
|
440
|
+
if (col) {
|
|
441
|
+
props?.onColumnSort?.(col, null);
|
|
442
|
+
}
|
|
441
443
|
}
|
|
442
444
|
getSortState(columnId) {
|
|
443
445
|
const props = this.getProps();
|
|
@@ -451,7 +453,7 @@ export class BaseDataGridTableComponent {
|
|
|
451
453
|
const col = this.visibleCols().find((c) => c.columnId === columnId);
|
|
452
454
|
if (!col)
|
|
453
455
|
return;
|
|
454
|
-
const width = this.
|
|
456
|
+
const width = measureColumnContentWidth(columnId, col.minWidth, this.tableContainerEl() ?? undefined);
|
|
455
457
|
this.state().layout.setColumnSizingOverrides({
|
|
456
458
|
...this.columnSizingOverrides(),
|
|
457
459
|
[columnId]: { widthPx: width },
|
|
@@ -459,9 +461,10 @@ export class BaseDataGridTableComponent {
|
|
|
459
461
|
this.state().layout.onColumnResized?.(columnId, width);
|
|
460
462
|
}
|
|
461
463
|
onAutosizeAllColumns() {
|
|
464
|
+
const tableEl = this.tableContainerEl() ?? undefined;
|
|
462
465
|
const overrides = {};
|
|
463
466
|
for (const col of this.visibleCols()) {
|
|
464
|
-
const width =
|
|
467
|
+
const width = measureColumnContentWidth(col.columnId, col.minWidth, tableEl);
|
|
465
468
|
overrides[col.columnId] = { widthPx: width };
|
|
466
469
|
this.state().layout.onColumnResized?.(col.columnId, width);
|
|
467
470
|
}
|
|
@@ -470,18 +473,4 @@ export class BaseDataGridTableComponent {
|
|
|
470
473
|
...overrides,
|
|
471
474
|
});
|
|
472
475
|
}
|
|
473
|
-
measureColumnContentWidth(columnId) {
|
|
474
|
-
const tableEl = this.tableContainerEl();
|
|
475
|
-
if (!tableEl)
|
|
476
|
-
return DEFAULT_MIN_COLUMN_WIDTH;
|
|
477
|
-
const cells = Array.from(tableEl.querySelectorAll(`[data-column-id="${columnId}"]`));
|
|
478
|
-
if (cells.length === 0)
|
|
479
|
-
return DEFAULT_MIN_COLUMN_WIDTH;
|
|
480
|
-
let maxWidth = DEFAULT_MIN_COLUMN_WIDTH;
|
|
481
|
-
for (const cell of cells) {
|
|
482
|
-
const rect = cell.getBoundingClientRect();
|
|
483
|
-
maxWidth = Math.max(maxWidth, Math.ceil(rect.width) + CELL_PADDING);
|
|
484
|
-
}
|
|
485
|
-
return maxWidth;
|
|
486
|
-
}
|
|
487
476
|
}
|
|
@@ -4,7 +4,7 @@ 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 } from '@angular/core';
|
|
7
|
+
import { Component, Input, ViewEncapsulation } from '@angular/core';
|
|
8
8
|
import { CommonModule } from '@angular/common';
|
|
9
9
|
import { SideBarComponent } from './sidebar.component';
|
|
10
10
|
import { GRID_BORDER_RADIUS } from '@alaarab/ogrid-core';
|
|
@@ -36,32 +36,83 @@ OGridLayoutComponent = __decorate([
|
|
|
36
36
|
Component({
|
|
37
37
|
selector: 'ogrid-layout',
|
|
38
38
|
standalone: true,
|
|
39
|
+
encapsulation: ViewEncapsulation.None,
|
|
39
40
|
imports: [CommonModule, SideBarComponent],
|
|
40
41
|
styles: [`
|
|
42
|
+
/* ─── OGrid Theme Variables ─── */
|
|
43
|
+
:root {
|
|
44
|
+
--ogrid-bg: #ffffff;
|
|
45
|
+
--ogrid-fg: rgba(0, 0, 0, 0.87);
|
|
46
|
+
--ogrid-fg-secondary: rgba(0, 0, 0, 0.6);
|
|
47
|
+
--ogrid-fg-muted: rgba(0, 0, 0, 0.5);
|
|
48
|
+
--ogrid-border: rgba(0, 0, 0, 0.12);
|
|
49
|
+
--ogrid-header-bg: rgba(0, 0, 0, 0.04);
|
|
50
|
+
--ogrid-hover-bg: rgba(0, 0, 0, 0.04);
|
|
51
|
+
--ogrid-selected-row-bg: #e6f0fb;
|
|
52
|
+
--ogrid-active-cell-bg: rgba(0, 0, 0, 0.02);
|
|
53
|
+
--ogrid-range-bg: rgba(33, 115, 70, 0.12);
|
|
54
|
+
--ogrid-accent: #0078d4;
|
|
55
|
+
--ogrid-selection-color: #217346;
|
|
56
|
+
--ogrid-loading-overlay: rgba(255, 255, 255, 0.7);
|
|
57
|
+
}
|
|
58
|
+
@media (prefers-color-scheme: dark) {
|
|
59
|
+
:root:not([data-theme="light"]) {
|
|
60
|
+
--ogrid-bg: #1e1e1e;
|
|
61
|
+
--ogrid-fg: rgba(255, 255, 255, 0.87);
|
|
62
|
+
--ogrid-fg-secondary: rgba(255, 255, 255, 0.6);
|
|
63
|
+
--ogrid-fg-muted: rgba(255, 255, 255, 0.5);
|
|
64
|
+
--ogrid-border: rgba(255, 255, 255, 0.12);
|
|
65
|
+
--ogrid-header-bg: rgba(255, 255, 255, 0.06);
|
|
66
|
+
--ogrid-hover-bg: rgba(255, 255, 255, 0.08);
|
|
67
|
+
--ogrid-selected-row-bg: #1a3a5c;
|
|
68
|
+
--ogrid-active-cell-bg: rgba(255, 255, 255, 0.06);
|
|
69
|
+
--ogrid-range-bg: rgba(46, 160, 67, 0.15);
|
|
70
|
+
--ogrid-accent: #4da6ff;
|
|
71
|
+
--ogrid-selection-color: #2ea043;
|
|
72
|
+
--ogrid-loading-overlay: rgba(0, 0, 0, 0.7);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
[data-theme="dark"] {
|
|
76
|
+
--ogrid-bg: #1e1e1e;
|
|
77
|
+
--ogrid-fg: rgba(255, 255, 255, 0.87);
|
|
78
|
+
--ogrid-fg-secondary: rgba(255, 255, 255, 0.6);
|
|
79
|
+
--ogrid-fg-muted: rgba(255, 255, 255, 0.5);
|
|
80
|
+
--ogrid-border: rgba(255, 255, 255, 0.12);
|
|
81
|
+
--ogrid-header-bg: rgba(255, 255, 255, 0.06);
|
|
82
|
+
--ogrid-hover-bg: rgba(255, 255, 255, 0.08);
|
|
83
|
+
--ogrid-selected-row-bg: #1a3a5c;
|
|
84
|
+
--ogrid-active-cell-bg: rgba(255, 255, 255, 0.06);
|
|
85
|
+
--ogrid-range-bg: rgba(46, 160, 67, 0.15);
|
|
86
|
+
--ogrid-accent: #4da6ff;
|
|
87
|
+
--ogrid-selection-color: #2ea043;
|
|
88
|
+
--ogrid-loading-overlay: rgba(0, 0, 0, 0.7);
|
|
89
|
+
}
|
|
90
|
+
:host { display: block; height: 100%; }
|
|
41
91
|
.ogrid-layout-root { display: flex; flex-direction: column; height: 100%; }
|
|
42
92
|
.ogrid-layout-container {
|
|
43
|
-
border: 1px solid var(--ogrid-border,
|
|
93
|
+
border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
|
|
44
94
|
overflow: hidden; display: flex; flex-direction: column;
|
|
45
|
-
flex: 1; min-height: 0; background: var(--ogrid-bg, #
|
|
95
|
+
flex: 1; min-height: 0; background: var(--ogrid-bg, #ffffff);
|
|
96
|
+
color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
|
|
46
97
|
}
|
|
47
98
|
.ogrid-layout-toolbar {
|
|
48
99
|
display: flex; justify-content: space-between; align-items: center;
|
|
49
|
-
padding: 6px 12px; background: var(--ogrid-header-bg,
|
|
100
|
+
padding: 6px 12px; background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04));
|
|
50
101
|
gap: 8px; flex-wrap: wrap; min-height: 0;
|
|
51
102
|
}
|
|
52
103
|
.ogrid-layout-toolbar--has-below { border-bottom: none; }
|
|
53
|
-
.ogrid-layout-toolbar--no-below { border-bottom: 1px solid var(--ogrid-border,
|
|
104
|
+
.ogrid-layout-toolbar--no-below { border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12)); }
|
|
54
105
|
.ogrid-layout-toolbar-left { display: flex; align-items: center; gap: 8px; }
|
|
55
106
|
.ogrid-layout-toolbar-right { display: flex; align-items: center; gap: 8px; }
|
|
56
107
|
.ogrid-layout-toolbar-below {
|
|
57
|
-
border-bottom: 1px solid var(--ogrid-border,
|
|
58
|
-
padding: 6px 12px; background: var(--ogrid-header-bg,
|
|
108
|
+
border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
|
|
109
|
+
padding: 6px 12px; background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04));
|
|
59
110
|
}
|
|
60
111
|
.ogrid-layout-grid-area { width: 100%; min-width: 0; min-height: 0; flex: 1; display: flex; }
|
|
61
|
-
.ogrid-layout-grid-content { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column;
|
|
112
|
+
.ogrid-layout-grid-content { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
|
|
62
113
|
.ogrid-layout-footer {
|
|
63
|
-
border-top: 1px solid var(--ogrid-border,
|
|
64
|
-
background: var(--ogrid-header-bg,
|
|
114
|
+
border-top: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
|
|
115
|
+
background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)); padding: 6px 12px;
|
|
65
116
|
}
|
|
66
117
|
`],
|
|
67
118
|
template: `
|
|
@@ -90,24 +141,18 @@ OGridLayoutComponent = __decorate([
|
|
|
90
141
|
</div>
|
|
91
142
|
}
|
|
92
143
|
|
|
93
|
-
<!-- Grid area -->
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
<div class="ogrid-layout-grid-content">
|
|
100
|
-
<ng-content></ng-content>
|
|
101
|
-
</div>
|
|
102
|
-
@if (sideBar?.position !== 'left') {
|
|
103
|
-
<ogrid-sidebar [sideBarProps]="sideBar"></ogrid-sidebar>
|
|
104
|
-
}
|
|
105
|
-
</div>
|
|
106
|
-
} @else {
|
|
144
|
+
<!-- Grid area (single ng-content to avoid Angular content projection issues) -->
|
|
145
|
+
<div class="ogrid-layout-grid-area">
|
|
146
|
+
@if (sideBar && sideBar.position === 'left') {
|
|
147
|
+
<ogrid-sidebar [sideBarProps]="sideBar"></ogrid-sidebar>
|
|
148
|
+
}
|
|
107
149
|
<div class="ogrid-layout-grid-content">
|
|
108
150
|
<ng-content></ng-content>
|
|
109
151
|
</div>
|
|
110
|
-
|
|
152
|
+
@if (sideBar && sideBar.position !== 'left') {
|
|
153
|
+
<ogrid-sidebar [sideBarProps]="sideBar"></ogrid-sidebar>
|
|
154
|
+
}
|
|
155
|
+
</div>
|
|
111
156
|
|
|
112
157
|
<!-- Footer strip (pagination) -->
|
|
113
158
|
@if (hasPagination) {
|
|
@@ -106,56 +106,56 @@ SideBarComponent = __decorate([
|
|
|
106
106
|
.ogrid-sidebar-tab-strip {
|
|
107
107
|
display: flex; flex-direction: column;
|
|
108
108
|
width: var(--ogrid-sidebar-tab-size, 36px);
|
|
109
|
-
background: var(--ogrid-header-bg,
|
|
109
|
+
background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04));
|
|
110
110
|
}
|
|
111
|
-
.ogrid-sidebar-tab-strip--left { border-right: 1px solid var(--ogrid-border,
|
|
112
|
-
.ogrid-sidebar-tab-strip--right { border-left: 1px solid var(--ogrid-border,
|
|
111
|
+
.ogrid-sidebar-tab-strip--left { border-right: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12)); }
|
|
112
|
+
.ogrid-sidebar-tab-strip--right { border-left: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12)); }
|
|
113
113
|
.ogrid-sidebar-tab {
|
|
114
114
|
width: var(--ogrid-sidebar-tab-size, 36px);
|
|
115
115
|
height: var(--ogrid-sidebar-tab-size, 36px);
|
|
116
116
|
border: none; cursor: pointer;
|
|
117
|
-
color: var(--ogrid-fg,
|
|
117
|
+
color: var(--ogrid-fg, rgba(0, 0, 0, 0.87)); font-size: 14px;
|
|
118
118
|
display: flex; align-items: center; justify-content: center;
|
|
119
119
|
background: transparent; font-weight: normal;
|
|
120
120
|
}
|
|
121
|
-
.ogrid-sidebar-tab--active { background: var(--ogrid-bg, #
|
|
121
|
+
.ogrid-sidebar-tab--active { background: var(--ogrid-bg, #ffffff); font-weight: bold; }
|
|
122
122
|
.ogrid-sidebar-panel {
|
|
123
123
|
width: var(--ogrid-sidebar-panel-width, 240px);
|
|
124
124
|
display: flex; flex-direction: column; overflow: hidden;
|
|
125
|
-
background: var(--ogrid-bg, #
|
|
125
|
+
background: var(--ogrid-bg, #ffffff); color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
|
|
126
126
|
}
|
|
127
|
-
.ogrid-sidebar-panel--left { border-right: 1px solid var(--ogrid-border,
|
|
128
|
-
.ogrid-sidebar-panel--right { border-left: 1px solid var(--ogrid-border,
|
|
127
|
+
.ogrid-sidebar-panel--left { border-right: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12)); }
|
|
128
|
+
.ogrid-sidebar-panel--right { border-left: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12)); }
|
|
129
129
|
.ogrid-sidebar-panel-header {
|
|
130
130
|
display: flex; justify-content: space-between; align-items: center;
|
|
131
|
-
padding: 8px 12px; border-bottom: 1px solid var(--ogrid-border,
|
|
131
|
+
padding: 8px 12px; border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12)); font-weight: 600;
|
|
132
132
|
}
|
|
133
133
|
.ogrid-sidebar-panel-close {
|
|
134
134
|
border: none; background: transparent; cursor: pointer;
|
|
135
|
-
font-size: 16px; color: var(--ogrid-fg,
|
|
135
|
+
font-size: 16px; color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
|
|
136
136
|
}
|
|
137
137
|
.ogrid-sidebar-panel-body { flex: 1; overflow-y: auto; padding: 8px 12px; }
|
|
138
138
|
.ogrid-sidebar-actions { display: flex; gap: 8px; margin-bottom: 8px; }
|
|
139
139
|
.ogrid-sidebar-action-btn {
|
|
140
140
|
flex: 1; cursor: pointer;
|
|
141
|
-
background: var(--ogrid-bg
|
|
142
|
-
border: 1px solid var(--ogrid-border,
|
|
141
|
+
background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)); color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
|
|
142
|
+
border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12)); border-radius: 4px; padding: 4px 8px;
|
|
143
143
|
}
|
|
144
144
|
.ogrid-sidebar-col-label { display: flex; align-items: center; gap: 6px; padding: 2px 0; cursor: pointer; }
|
|
145
|
-
.ogrid-sidebar-empty { color: var(--ogrid-muted,
|
|
145
|
+
.ogrid-sidebar-empty { color: var(--ogrid-fg-muted, rgba(0, 0, 0, 0.5)); font-style: italic; }
|
|
146
146
|
.ogrid-sidebar-filter-group { margin-bottom: 12px; }
|
|
147
147
|
.ogrid-sidebar-filter-label { font-weight: 500; margin-bottom: 4px; font-size: 13px; }
|
|
148
148
|
.ogrid-sidebar-text-input {
|
|
149
149
|
width: 100%; box-sizing: border-box; padding: 4px 6px;
|
|
150
|
-
background: var(--ogrid-bg, #
|
|
151
|
-
border: 1px solid var(--ogrid-border,
|
|
150
|
+
background: var(--ogrid-bg, #ffffff); color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
|
|
151
|
+
border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12)); border-radius: 4px;
|
|
152
152
|
}
|
|
153
153
|
.ogrid-sidebar-date-row { display: flex; flex-direction: column; gap: 4px; }
|
|
154
154
|
.ogrid-sidebar-date-label { display: flex; align-items: center; gap: 4px; font-size: 12px; }
|
|
155
155
|
.ogrid-sidebar-date-input {
|
|
156
156
|
flex: 1; padding: 2px 4px;
|
|
157
|
-
background: var(--ogrid-bg, #
|
|
158
|
-
border: 1px solid var(--ogrid-border,
|
|
157
|
+
background: var(--ogrid-bg, #ffffff); color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
|
|
158
|
+
border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12)); border-radius: 4px;
|
|
159
159
|
}
|
|
160
160
|
.ogrid-sidebar-multiselect-list { max-height: 120px; overflow-y: auto; }
|
|
161
161
|
.ogrid-sidebar-multiselect-item {
|
|
@@ -220,7 +220,7 @@ SideBarComponent = __decorate([
|
|
|
220
220
|
</div>
|
|
221
221
|
@for (col of sideBarProps?.columns ?? []; track col.columnId) {
|
|
222
222
|
<label class="ogrid-sidebar-col-label">
|
|
223
|
-
<input type="checkbox" [checked]="sideBarProps?.visibleColumns?.has(col.columnId)" (change)="onVisibilityChange(col.columnId, ($event.target
|
|
223
|
+
<input type="checkbox" [checked]="sideBarProps?.visibleColumns?.has(col.columnId)" (change)="onVisibilityChange(col.columnId, $any($event.target).checked)" [disabled]="col.required" />
|
|
224
224
|
<span>{{ col.name }}</span>
|
|
225
225
|
</label>
|
|
226
226
|
}
|
|
@@ -237,7 +237,7 @@ SideBarComponent = __decorate([
|
|
|
237
237
|
type="text"
|
|
238
238
|
class="ogrid-sidebar-text-input"
|
|
239
239
|
[value]="getTextFilterValue(col.filterField)"
|
|
240
|
-
(input)="onTextFilterChange(col.filterField, ($event.target
|
|
240
|
+
(input)="onTextFilterChange(col.filterField, $any($event.target).value)"
|
|
241
241
|
[placeholder]="'Filter ' + col.name + '...'"
|
|
242
242
|
[attr.aria-label]="'Filter ' + col.name"
|
|
243
243
|
/>
|
|
@@ -246,11 +246,11 @@ SideBarComponent = __decorate([
|
|
|
246
246
|
<div class="ogrid-sidebar-date-row">
|
|
247
247
|
<label class="ogrid-sidebar-date-label">
|
|
248
248
|
From:
|
|
249
|
-
<input type="date" class="ogrid-sidebar-date-input" [value]="getDateFrom(col.filterField)" (change)="onDateFromChange(col.filterField, ($event.target
|
|
249
|
+
<input type="date" class="ogrid-sidebar-date-input" [value]="getDateFrom(col.filterField)" (change)="onDateFromChange(col.filterField, $any($event.target).value)" [attr.aria-label]="col.name + ' from date'" />
|
|
250
250
|
</label>
|
|
251
251
|
<label class="ogrid-sidebar-date-label">
|
|
252
252
|
To:
|
|
253
|
-
<input type="date" class="ogrid-sidebar-date-input" [value]="getDateTo(col.filterField)" (change)="onDateToChange(col.filterField, ($event.target
|
|
253
|
+
<input type="date" class="ogrid-sidebar-date-input" [value]="getDateTo(col.filterField)" (change)="onDateToChange(col.filterField, $any($event.target).value)" [attr.aria-label]="col.name + ' to date'" />
|
|
254
254
|
</label>
|
|
255
255
|
</div>
|
|
256
256
|
}
|
|
@@ -258,7 +258,7 @@ SideBarComponent = __decorate([
|
|
|
258
258
|
<div class="ogrid-sidebar-multiselect-list" role="group" [attr.aria-label]="col.name + ' options'">
|
|
259
259
|
@for (opt of getFilterOptions(col.filterField); track opt) {
|
|
260
260
|
<label class="ogrid-sidebar-multiselect-item">
|
|
261
|
-
<input type="checkbox" [checked]="isMultiSelectChecked(col.filterField, opt)" (change)="onMultiSelectChange(col.filterField, opt, ($event.target
|
|
261
|
+
<input type="checkbox" [checked]="isMultiSelectChecked(col.filterField, opt)" (change)="onMultiSelectChange(col.filterField, opt, $any($event.target).checked)" />
|
|
262
262
|
<span>{{ opt }}</span>
|
|
263
263
|
</label>
|
|
264
264
|
}
|
|
@@ -1081,7 +1081,7 @@ let DataGridStateService = class DataGridStateService {
|
|
|
1081
1081
|
headerFilterInput: {
|
|
1082
1082
|
sortBy: p?.sortBy,
|
|
1083
1083
|
sortDirection: p?.sortDirection ?? 'asc',
|
|
1084
|
-
onColumnSort: (columnKey) => p?.onColumnSort(columnKey),
|
|
1084
|
+
onColumnSort: (columnKey, direction) => p?.onColumnSort(columnKey, direction),
|
|
1085
1085
|
filters: p?.filters ?? {},
|
|
1086
1086
|
onFilterChange: (key, value) => p?.onFilterChange(key, value),
|
|
1087
1087
|
filterOptions: p?.filterOptions ?? {},
|
|
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
import { Injectable, signal, computed, effect, DestroyRef, inject } from '@angular/core';
|
|
8
|
-
import { mergeFilter, deriveFilterOptionsFromData, getMultiSelectFilterFields, flattenColumns, processClientSideData, } from '@alaarab/ogrid-core';
|
|
8
|
+
import { mergeFilter, deriveFilterOptionsFromData, getMultiSelectFilterFields, flattenColumns, processClientSideData, computeNextSortState, } from '@alaarab/ogrid-core';
|
|
9
9
|
const DEFAULT_PAGE_SIZE = 25;
|
|
10
10
|
const EMPTY_LOADING_OPTIONS = {};
|
|
11
11
|
const DEFAULT_PANELS = ['columns', 'filters'];
|
|
@@ -67,6 +67,7 @@ let OGridService = class OGridService {
|
|
|
67
67
|
this.onFirstDataRendered = signal(undefined);
|
|
68
68
|
this.onError = signal(undefined);
|
|
69
69
|
this.columnChooserProp = signal(undefined);
|
|
70
|
+
this.columnReorder = signal(undefined);
|
|
70
71
|
this.virtualScroll = signal(undefined);
|
|
71
72
|
this.ariaLabel = signal(undefined);
|
|
72
73
|
this.ariaLabelledBy = signal(undefined);
|
|
@@ -215,7 +216,7 @@ let OGridService = class OGridService {
|
|
|
215
216
|
getRowId: this.getRowId(),
|
|
216
217
|
sortBy: this.sort().field,
|
|
217
218
|
sortDirection: this.sort().direction,
|
|
218
|
-
onColumnSort: (columnKey) => this.handleSort(columnKey),
|
|
219
|
+
onColumnSort: (columnKey, direction) => this.handleSort(columnKey, direction),
|
|
219
220
|
visibleColumns: this.visibleColumns(),
|
|
220
221
|
columnOrder: this.columnOrder(),
|
|
221
222
|
onColumnOrderChange: this.onColumnOrderChange(),
|
|
@@ -246,6 +247,7 @@ let OGridService = class OGridService {
|
|
|
246
247
|
getUserByEmail: this.dataSource()?.getUserByEmail?.bind(this.dataSource()),
|
|
247
248
|
layoutMode: this.layoutMode(),
|
|
248
249
|
suppressHorizontalScroll: this.suppressHorizontalScroll(),
|
|
250
|
+
columnReorder: this.columnReorder(),
|
|
249
251
|
virtualScroll: this.virtualScroll(),
|
|
250
252
|
'aria-label': this.ariaLabel(),
|
|
251
253
|
'aria-labelledby': this.ariaLabelledBy(),
|
|
@@ -401,22 +403,8 @@ let OGridService = class OGridService {
|
|
|
401
403
|
this.internalVisibleColumnsOverride.set(cols);
|
|
402
404
|
this.onVisibleColumnsChange()?.(cols);
|
|
403
405
|
}
|
|
404
|
-
handleSort(columnKey) {
|
|
405
|
-
|
|
406
|
-
if (sort.field === columnKey) {
|
|
407
|
-
// Cycle: asc → desc → clear
|
|
408
|
-
if (sort.direction === 'asc') {
|
|
409
|
-
this.setSort({ field: columnKey, direction: 'desc' });
|
|
410
|
-
}
|
|
411
|
-
else {
|
|
412
|
-
// Clear sort (empty field means no column is sorted)
|
|
413
|
-
this.setSort({ field: '', direction: 'asc' });
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
else {
|
|
417
|
-
// Start new sort
|
|
418
|
-
this.setSort({ field: columnKey, direction: 'asc' });
|
|
419
|
-
}
|
|
406
|
+
handleSort(columnKey, direction) {
|
|
407
|
+
this.setSort(computeNextSortState(this.sort(), columnKey, direction));
|
|
420
408
|
}
|
|
421
409
|
handleFilterChange(key, value) {
|
|
422
410
|
this.setFilters(mergeFilter(this.filters(), key, value));
|
|
@@ -531,6 +519,8 @@ let OGridService = class OGridService {
|
|
|
531
519
|
this.onError.set(props.onError);
|
|
532
520
|
if (props.columnChooser !== undefined)
|
|
533
521
|
this.columnChooserProp.set(props.columnChooser);
|
|
522
|
+
if (props.columnReorder !== undefined)
|
|
523
|
+
this.columnReorder.set(props.columnReorder);
|
|
534
524
|
if (props.virtualScroll !== undefined)
|
|
535
525
|
this.virtualScroll.set(props.virtualScroll);
|
|
536
526
|
if (props.entityLabelPlural !== undefined)
|
|
@@ -87,7 +87,7 @@ export declare abstract class BaseDataGridTableComponent<T = unknown> {
|
|
|
87
87
|
readonly headerFilterInput: import("@angular/core").Signal<{
|
|
88
88
|
sortBy?: string;
|
|
89
89
|
sortDirection: "asc" | "desc";
|
|
90
|
-
onColumnSort: (columnKey: string) => void;
|
|
90
|
+
onColumnSort: (columnKey: string, direction?: "asc" | "desc" | null) => void;
|
|
91
91
|
filters: import("@alaarab/ogrid-core").IFilters;
|
|
92
92
|
onFilterChange: (key: string, value: import("@alaarab/ogrid-core").FilterValue | undefined) => void;
|
|
93
93
|
filterOptions: Record<string, string[]>;
|
|
@@ -187,9 +187,8 @@ export declare abstract class BaseDataGridTableComponent<T = unknown> {
|
|
|
187
187
|
};
|
|
188
188
|
onSortAsc(columnId: string): void;
|
|
189
189
|
onSortDesc(columnId: string): void;
|
|
190
|
-
onClearSort(): void;
|
|
190
|
+
onClearSort(columnId?: string): void;
|
|
191
191
|
getSortState(columnId: string): 'asc' | 'desc' | null;
|
|
192
192
|
onAutosizeColumn(columnId: string): void;
|
|
193
193
|
onAutosizeAllColumns(): void;
|
|
194
|
-
private measureColumnContentWidth;
|
|
195
194
|
}
|
|
@@ -88,7 +88,7 @@ export interface DataGridViewModelState<T> {
|
|
|
88
88
|
headerFilterInput: {
|
|
89
89
|
sortBy?: string;
|
|
90
90
|
sortDirection: 'asc' | 'desc';
|
|
91
|
-
onColumnSort: (columnKey: string) => void;
|
|
91
|
+
onColumnSort: (columnKey: string, direction?: 'asc' | 'desc' | null) => void;
|
|
92
92
|
filters: IFilters;
|
|
93
93
|
onFilterChange: (key: string, value: FilterValue | undefined) => void;
|
|
94
94
|
filterOptions: Record<string, string[]>;
|
|
@@ -101,6 +101,7 @@ export declare class OGridService<T> {
|
|
|
101
101
|
readonly onFirstDataRendered: import("@angular/core").WritableSignal<(() => void) | undefined>;
|
|
102
102
|
readonly onError: import("@angular/core").WritableSignal<((error: unknown) => void) | undefined>;
|
|
103
103
|
readonly columnChooserProp: import("@angular/core").WritableSignal<boolean | "toolbar" | "sidebar" | undefined>;
|
|
104
|
+
readonly columnReorder: import("@angular/core").WritableSignal<boolean | undefined>;
|
|
104
105
|
readonly virtualScroll: import("@angular/core").WritableSignal<IVirtualScrollConfig | undefined>;
|
|
105
106
|
readonly ariaLabel: import("@angular/core").WritableSignal<string | undefined>;
|
|
106
107
|
readonly ariaLabelledBy: import("@angular/core").WritableSignal<string | undefined>;
|
|
@@ -179,7 +180,7 @@ export declare class OGridService<T> {
|
|
|
179
180
|
}): void;
|
|
180
181
|
setFilters(f: IFilters): void;
|
|
181
182
|
setVisibleColumns(cols: Set<string>): void;
|
|
182
|
-
handleSort(columnKey: string): void;
|
|
183
|
+
handleSort(columnKey: string, direction?: 'asc' | 'desc' | null): void;
|
|
183
184
|
handleFilterChange(key: string, value: FilterValue | undefined): void;
|
|
184
185
|
handleVisibilityChange(columnKey: string, isVisible: boolean): void;
|
|
185
186
|
handleSelectionChange(event: IRowSelectionChangeEvent<T>): void;
|
|
@@ -57,6 +57,7 @@ interface IOGridBaseProps<T> {
|
|
|
57
57
|
layoutMode?: 'content' | 'fill';
|
|
58
58
|
suppressHorizontalScroll?: boolean;
|
|
59
59
|
sideBar?: boolean | ISideBarDef;
|
|
60
|
+
columnReorder?: boolean;
|
|
60
61
|
virtualScroll?: IVirtualScrollConfig;
|
|
61
62
|
pageSizeOptions?: number[];
|
|
62
63
|
onFirstDataRendered?: () => void;
|
|
@@ -85,7 +86,7 @@ export interface IOGridDataGridProps<T> {
|
|
|
85
86
|
getRowId: (item: T) => RowId;
|
|
86
87
|
sortBy?: string;
|
|
87
88
|
sortDirection: 'asc' | 'desc';
|
|
88
|
-
onColumnSort: (columnKey: string) => void;
|
|
89
|
+
onColumnSort: (columnKey: string, direction?: 'asc' | 'desc' | null) => void;
|
|
89
90
|
visibleColumns: Set<string>;
|
|
90
91
|
columnOrder?: string[];
|
|
91
92
|
onColumnOrderChange?: (order: string[]) => void;
|
|
@@ -120,6 +121,7 @@ export interface IOGridDataGridProps<T> {
|
|
|
120
121
|
loadingFilterOptions: Record<string, boolean>;
|
|
121
122
|
peopleSearch?: (query: string) => Promise<UserLike[]>;
|
|
122
123
|
getUserByEmail?: (email: string) => Promise<UserLike | undefined>;
|
|
124
|
+
columnReorder?: boolean;
|
|
123
125
|
virtualScroll?: IVirtualScrollConfig;
|
|
124
126
|
emptyState?: {
|
|
125
127
|
onClearAll: () => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alaarab/ogrid-angular",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.13",
|
|
4
4
|
"description": "OGrid Angular – Angular services, signals, and headless components for OGrid data grids.",
|
|
5
5
|
"main": "dist/esm/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"node": ">=18"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@alaarab/ogrid-core": "2.0.
|
|
38
|
+
"@alaarab/ogrid-core": "2.0.13"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"@angular/core": "^21.0.0",
|