@alaarab/ogrid-angular-material 2.0.3 → 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.
@@ -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,9 +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, ColumnReorderService, VirtualScrollService, buildHeaderRows, CHECKBOX_COLUMN_WIDTH, DEFAULT_MIN_COLUMN_WIDTH, getHeaderFilterConfig, getCellRenderDescriptor, resolveCellDisplayContent, resolveCellStyle, } from '@alaarab/ogrid-angular';
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
+ import { ColumnHeaderMenuComponent } from '../column-header-menu/column-header-menu.component';
10
11
  /**
11
12
  * DataGridTable component using native HTML table with Material Design-inspired styling.
12
13
  * Standalone component — this is the workhorse of the grid.
@@ -20,6 +21,7 @@ let DataGridTableComponent = class DataGridTableComponent {
20
21
  this.columnReorderService = new ColumnReorderService();
21
22
  this.virtualScrollService = new VirtualScrollService();
22
23
  this.lastMouseShift = false;
24
+ this.columnSizingVersion = signal(0);
23
25
  // --- Delegated state ---
24
26
  this.state = computed(() => this.stateService.getState());
25
27
  this.items = computed(() => this.propsInput()?.items ?? []);
@@ -32,9 +34,13 @@ let DataGridTableComponent = class DataGridTableComponent {
32
34
  this.ariaLabel = computed(() => this.propsInput()?.['aria-label'] ?? 'Data grid');
33
35
  this.ariaLabelledBy = computed(() => this.propsInput()?.['aria-labelledby']);
34
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);
35
40
  // State service outputs
36
41
  this.visibleCols = computed(() => this.state().layout.visibleCols);
37
42
  this.hasCheckboxCol = computed(() => this.state().layout.hasCheckboxCol);
43
+ this.hasRowNumbersCol = computed(() => this.state().layout.hasRowNumbersCol);
38
44
  this.colOffset = computed(() => this.state().layout.colOffset);
39
45
  this.containerWidth = computed(() => this.state().layout.containerWidth);
40
46
  this.minTableWidth = computed(() => this.state().layout.minTableWidth);
@@ -84,10 +90,13 @@ let DataGridTableComponent = class DataGridTableComponent {
84
90
  this.columnLayouts = computed(() => {
85
91
  const cols = this.visibleCols();
86
92
  const fc = this.freezeCols();
93
+ const props = this.propsInput();
94
+ const pinnedCols = props?.pinnedColumns ?? {};
87
95
  return cols.map((col, colIdx) => {
88
96
  const isFreezeCol = fc != null && fc >= 1 && colIdx < fc;
89
- const pinnedLeft = col.pinned === 'left' || (isFreezeCol && colIdx === 0);
90
- const pinnedRight = col.pinned === 'right';
97
+ const runtimePinned = pinnedCols[col.columnId];
98
+ const pinnedLeft = runtimePinned === 'left' || (isFreezeCol && colIdx === 0);
99
+ const pinnedRight = runtimePinned === 'right';
91
100
  const w = this.getColumnWidth(col);
92
101
  return {
93
102
  col,
@@ -203,6 +212,7 @@ let DataGridTableComponent = class DataGridTableComponent {
203
212
  const newWidth = Math.max(minWidth, startWidth + delta);
204
213
  const overrides = { ...this.columnSizingOverrides(), [col.columnId]: { widthPx: newWidth } };
205
214
  this.state().layout.setColumnSizingOverrides(overrides);
215
+ this.columnSizingVersion.update(v => v + 1);
206
216
  };
207
217
  const onUp = () => {
208
218
  window.removeEventListener('mousemove', onMove);
@@ -269,12 +279,33 @@ let DataGridTableComponent = class DataGridTableComponent {
269
279
  onHeaderMouseDown(columnId, event) {
270
280
  this.columnReorderService.handleHeaderMouseDown(columnId, event);
271
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
+ }
272
303
  };
273
304
  DataGridTableComponent = __decorate([
274
305
  Component({
275
306
  selector: 'ogrid-datagrid-table',
276
307
  standalone: true,
277
- imports: [ColumnHeaderFilterComponent],
308
+ imports: [ColumnHeaderFilterComponent, ColumnHeaderMenuComponent, MarchingAntsOverlayComponent],
278
309
  providers: [DataGridStateService],
279
310
  changeDetection: ChangeDetectionStrategy.OnPush,
280
311
  template: `
@@ -319,6 +350,14 @@ DataGridTableComponent = __decorate([
319
350
  @if (rowIdx === 0 && rowIdx < headerRows().length - 1 && hasCheckboxCol()) {
320
351
  <th [attr.rowSpan]="headerRows().length - 1" class="ogrid-datagrid-th" style="width: 48px; min-width: 48px; padding: 0;"></th>
321
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
+ }
322
361
  @for (cell of row; track $index; let cellIdx = $index) {
323
362
  @if (cell.isGroup) {
324
363
  <th [attr.colSpan]="cell.colSpan" scope="colgroup" class="ogrid-datagrid-th ogrid-datagrid-group-header">
@@ -329,10 +368,13 @@ DataGridTableComponent = __decorate([
329
368
  @let colIdx = visibleColIndex(col);
330
369
  @let isFreezeCol = freezeCols() != null && (freezeCols() ?? 0) >= 1 && colIdx < (freezeCols() ?? 0);
331
370
  @let colW = getColumnWidth(col);
371
+ @let pinned = isPinned(col.columnId);
372
+ @let pinnedLeft = pinned === 'left' || (isFreezeCol && colIdx === 0);
373
+ @let pinnedRight = pinned === 'right';
332
374
  <th scope="col"
333
375
  class="ogrid-datagrid-th"
334
- [class.ogrid-datagrid-th--pinned-left]="col.pinned === 'left' || (isFreezeCol && colIdx === 0)"
335
- [class.ogrid-datagrid-th--pinned-right]="col.pinned === 'right'"
376
+ [class.ogrid-datagrid-th--pinned-left]="pinnedLeft"
377
+ [class.ogrid-datagrid-th--pinned-right]="pinnedRight"
336
378
  [attr.rowSpan]="headerRows().length > 1 ? headerRows().length - rowIdx : null"
337
379
  [attr.data-column-id]="col.columnId"
338
380
  [style.minWidth.px]="col.minWidth ?? 80"
@@ -341,25 +383,37 @@ DataGridTableComponent = __decorate([
341
383
  [style.cursor]="columnReorderService.isDragging() ? 'grabbing' : 'grab'"
342
384
  (mousedown)="onHeaderMouseDown(col.columnId, $event)"
343
385
  >
344
- <ogrid-column-header-filter
345
- [columnKey]="col.columnId"
346
- [columnName]="col.name"
347
- [filterType]="getFilterConfig(col).filterType"
348
- [isSorted]="getFilterConfig(col).isSorted"
349
- [isSortedDescending]="getFilterConfig(col).isSortedDescending"
350
- [onSort]="getFilterConfig(col).onSort"
351
- [selectedValues]="getFilterConfig(col).selectedValues"
352
- [onFilterChange]="getFilterConfig(col).onFilterChange"
353
- [options]="getFilterConfig(col).options"
354
- [isLoadingOptions]="getFilterConfig(col).isLoadingOptions ?? false"
355
- [textValue]="getFilterConfig(col).textValue ?? ''"
356
- [onTextChange]="getFilterConfig(col).onTextChange"
357
- [selectedUser]="getFilterConfig(col).selectedUser"
358
- [onUserChange]="getFilterConfig(col).onUserChange"
359
- [peopleSearch]="getFilterConfig(col).peopleSearch"
360
- [dateValue]="getFilterConfig(col).dateValue"
361
- [onDateChange]="getFilterConfig(col).onDateChange"
362
- />
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>
363
417
  <div class="ogrid-datagrid-resize-handle" (mousedown)="onResizeStart($event, col)"></div>
364
418
  </th>
365
419
  }
@@ -395,6 +449,13 @@ DataGridTableComponent = __decorate([
395
449
  </div>
396
450
  </td>
397
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
+ }
398
459
  @for (colLayout of columnLayouts(); track colLayout.col.columnId; let colIdx = $index) {
399
460
  <td
400
461
  class="ogrid-datagrid-td"
@@ -487,6 +548,15 @@ DataGridTableComponent = __decorate([
487
548
  }
488
549
  </table>
489
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
+
490
560
  @if (showEmptyInGrid() && emptyState()) {
491
561
  <div class="ogrid-datagrid-empty">
492
562
  <div class="ogrid-datagrid-empty__title">No results found</div>
@@ -583,9 +653,11 @@ DataGridTableComponent = __decorate([
583
653
  }
584
654
  .ogrid-datagrid-th--pinned-left {
585
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);
586
657
  }
587
658
  .ogrid-datagrid-th--pinned-right {
588
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);
589
661
  }
590
662
  .ogrid-datagrid-group-header {
591
663
  text-align: center; font-weight: 600; border-bottom: 2px solid rgba(0,0,0,0.12); padding: 6px;
@@ -595,15 +667,28 @@ DataGridTableComponent = __decorate([
595
667
  max-width: ${CHECKBOX_COLUMN_WIDTH}px; text-align: center;
596
668
  }
597
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
+ }
598
681
  .ogrid-datagrid-row { }
599
682
  .ogrid-datagrid-row:hover { background: rgba(0,0,0,0.04); }
600
683
  .ogrid-datagrid-row--selected { background: rgba(25,118,210,0.08); }
601
684
  .ogrid-datagrid-td { position: relative; padding: 0; height: 1px; border-bottom: 1px solid rgba(0,0,0,0.06); }
602
685
  .ogrid-datagrid-td--pinned-left {
603
686
  position: sticky; left: 0; z-index: 6; background: #fff; will-change: transform;
687
+ border-left: 2px solid var(--mat-sys-primary, #1976d2);
604
688
  }
605
689
  .ogrid-datagrid-td--pinned-right {
606
690
  position: sticky; right: 0; z-index: 6; background: #fff; will-change: transform;
691
+ border-right: 2px solid var(--mat-sys-primary, #1976d2);
607
692
  }
608
693
  .ogrid-datagrid-cell {
609
694
  width: 100%; height: 100%; display: flex; align-items: center; min-width: 0;
@@ -623,7 +708,10 @@ DataGridTableComponent = __decorate([
623
708
  .ogrid-datagrid-cell--editing { padding: 0; }
624
709
  .ogrid-datagrid-editor-input {
625
710
  width: 100%; height: 100%; padding: 6px 10px; border: 2px solid var(--ogrid-selection, #217346);
626
- 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;
627
715
  }
628
716
  .ogrid-datagrid-editor-select {
629
717
  width: 100%; height: 100%; padding: 4px 8px; border: 2px solid var(--ogrid-selection, #217346);
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
+ }
@@ -12,6 +12,7 @@ export declare class DataGridTableComponent<T> {
12
12
  readonly columnReorderService: ColumnReorderService<T>;
13
13
  readonly virtualScrollService: VirtualScrollService;
14
14
  private lastMouseShift;
15
+ private columnSizingVersion;
15
16
  constructor();
16
17
  private readonly state;
17
18
  readonly items: import("@angular/core").Signal<T[]>;
@@ -29,8 +30,12 @@ export declare class DataGridTableComponent<T> {
29
30
  message?: string;
30
31
  render?: import("@angular/core").TemplateRef<unknown>;
31
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>;
32
36
  readonly visibleCols: import("@angular/core").Signal<IColumnDef<T>[]>;
33
37
  readonly hasCheckboxCol: import("@angular/core").Signal<boolean>;
38
+ readonly hasRowNumbersCol: import("@angular/core").Signal<boolean>;
34
39
  readonly colOffset: import("@angular/core").Signal<number>;
35
40
  readonly containerWidth: import("@angular/core").Signal<number>;
36
41
  readonly minTableWidth: import("@angular/core").Signal<number>;
@@ -46,11 +51,11 @@ export declare class DataGridTableComponent<T> {
46
51
  columnId: string;
47
52
  } | null>;
48
53
  readonly pendingEditorValue: import("@angular/core").Signal<unknown>;
49
- readonly activeCell: import("@angular/core").Signal<import("@alaarab/ogrid-angular").IActiveCell | null>;
50
- readonly selectionRange: import("@angular/core").Signal<import("@alaarab/ogrid-angular").ISelectionRange | null>;
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>;
51
56
  readonly hasCellSelection: import("@angular/core").Signal<boolean>;
52
- readonly cutRange: import("@angular/core").Signal<import("@alaarab/ogrid-angular").ISelectionRange | null>;
53
- readonly copyRange: import("@angular/core").Signal<import("@alaarab/ogrid-angular").ISelectionRange | null>;
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>;
54
59
  readonly canUndo: import("@angular/core").Signal<boolean>;
55
60
  readonly canRedo: import("@angular/core").Signal<boolean>;
56
61
  readonly isDragging: import("@angular/core").Signal<boolean>;
@@ -58,37 +63,37 @@ export declare class DataGridTableComponent<T> {
58
63
  x: number;
59
64
  y: number;
60
65
  } | null>;
61
- readonly statusBarConfig: import("@angular/core").Signal<import("@alaarab/ogrid-angular").IStatusBarProps | null>;
66
+ readonly statusBarConfig: import("@angular/core").Signal<import("@alaarab/ogrid-core").IStatusBarProps | null>;
62
67
  readonly showEmptyInGrid: import("@angular/core").Signal<boolean>;
63
68
  readonly headerFilterInput: import("@angular/core").Signal<{
64
69
  sortBy?: string;
65
70
  sortDirection: "asc" | "desc";
66
71
  onColumnSort: (columnKey: string) => void;
67
- filters: import("@alaarab/ogrid-angular").IFilters;
68
- onFilterChange: (key: string, value: import("@alaarab/ogrid-angular").FilterValue | undefined) => void;
72
+ filters: import("@alaarab/ogrid-core").IFilters;
73
+ onFilterChange: (key: string, value: import("@alaarab/ogrid-core").FilterValue | undefined) => void;
69
74
  filterOptions: Record<string, string[]>;
70
75
  loadingFilterOptions: Record<string, boolean>;
71
- peopleSearch?: (query: string) => Promise<import("@alaarab/ogrid-angular").UserLike[]>;
76
+ peopleSearch?: (query: string) => Promise<import("@alaarab/ogrid-core").UserLike[]>;
72
77
  }>;
73
78
  readonly cellDescriptorInput: import("@angular/core").Signal<{
74
79
  editingCell: {
75
80
  rowId: RowId;
76
81
  columnId: string;
77
82
  } | null;
78
- activeCell: import("@alaarab/ogrid-angular").IActiveCell | null;
79
- selectionRange: import("@alaarab/ogrid-angular").ISelectionRange | null;
80
- cutRange: import("@alaarab/ogrid-angular").ISelectionRange | null;
81
- copyRange: import("@alaarab/ogrid-angular").ISelectionRange | null;
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;
82
87
  colOffset: number;
83
88
  itemsLength: number;
84
89
  getRowId: (item: T) => RowId;
85
90
  editable?: boolean;
86
- onCellValueChanged?: ((event: import("@alaarab/ogrid-angular").ICellValueChangedEvent<T>) => void) | undefined;
91
+ onCellValueChanged?: ((event: import("@alaarab/ogrid-core").ICellValueChangedEvent<T>) => void) | undefined;
87
92
  isDragging: boolean;
88
93
  }>;
89
94
  readonly allowOverflowX: import("@angular/core").Signal<boolean>;
90
95
  readonly selectionCellCount: import("@angular/core").Signal<number | undefined>;
91
- readonly headerRows: import("@angular/core").Signal<import("@alaarab/ogrid-angular").HeaderRow<T>[]>;
96
+ readonly headerRows: import("@angular/core").Signal<import("@alaarab/ogrid-core").HeaderRow<T>[]>;
92
97
  readonly columnLayouts: import("@angular/core").Signal<{
93
98
  col: IColumnDef<T>;
94
99
  pinnedLeft: boolean;
@@ -127,4 +132,12 @@ export declare class DataGridTableComponent<T> {
127
132
  onUndo(): void;
128
133
  onRedo(): void;
129
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
+ };
130
143
  }
@@ -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-angular").PaginationViewModel | null>;
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",
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.3"
25
+ "@alaarab/ogrid-angular": "2.0.4"
26
26
  },
27
27
  "peerDependencies": {
28
28
  "@angular/core": "^21.0.0",