@alaarab/ogrid-angular 2.1.0 → 2.1.2

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.
@@ -54,6 +54,7 @@ export class BaseDataGridTableComponent {
54
54
  });
55
55
  this.ariaLabel = computed(() => this.getProps()?.['aria-label'] ?? 'Data grid');
56
56
  this.ariaLabelledBy = computed(() => this.getProps()?.['aria-labelledby']);
57
+ this.stickyHeader = computed(() => this.getProps()?.stickyHeader ?? true);
57
58
  this.emptyState = computed(() => this.getProps()?.emptyState);
58
59
  this.currentPage = computed(() => this.getProps()?.currentPage ?? 1);
59
60
  this.pageSize = computed(() => this.getProps()?.pageSize ?? 25);
@@ -25,7 +25,7 @@ export class BaseOGridComponent {
25
25
  });
26
26
  }
27
27
  get showToolbar() {
28
- return this.ogridService.columnChooserPlacement() === 'toolbar' || this.ogridService.toolbar() != null;
28
+ return this.ogridService.columnChooserPlacement() === 'toolbar' || this.ogridService.toolbar() != null || this.ogridService.fullScreen();
29
29
  }
30
30
  onPageSizeChange(size) {
31
31
  this.ogridService.pagination().setPageSize(size);
@@ -14,7 +14,35 @@ let OGridLayoutComponent = class OGridLayoutComponent {
14
14
  this.hasToolbarBelow = false;
15
15
  this.hasPagination = false;
16
16
  this.sideBar = null;
17
+ this.fullScreen = false;
18
+ this.isFullScreen = false;
17
19
  this.borderRadius = GRID_BORDER_RADIUS;
20
+ this.escListener = null;
21
+ }
22
+ get rootClass() {
23
+ const base = (this.className ?? '') + ' ogrid-layout-root';
24
+ return this.isFullScreen ? base + ' ogrid-layout-root--fullscreen' : base;
25
+ }
26
+ toggleFullScreen() {
27
+ this.isFullScreen = !this.isFullScreen;
28
+ if (this.isFullScreen) {
29
+ this.escListener = (e) => {
30
+ if (e.key === 'Escape') {
31
+ this.isFullScreen = false;
32
+ this.removeEscListener();
33
+ }
34
+ };
35
+ document.addEventListener('keydown', this.escListener);
36
+ }
37
+ else {
38
+ this.removeEscListener();
39
+ }
40
+ }
41
+ removeEscListener() {
42
+ if (this.escListener) {
43
+ document.removeEventListener('keydown', this.escListener);
44
+ this.escListener = null;
45
+ }
18
46
  }
19
47
  };
20
48
  __decorate([
@@ -32,6 +60,9 @@ __decorate([
32
60
  __decorate([
33
61
  Input()
34
62
  ], OGridLayoutComponent.prototype, "sideBar", void 0);
63
+ __decorate([
64
+ Input()
65
+ ], OGridLayoutComponent.prototype, "fullScreen", void 0);
35
66
  OGridLayoutComponent = __decorate([
36
67
  Component({
37
68
  selector: 'ogrid-layout',
@@ -42,12 +73,19 @@ OGridLayoutComponent = __decorate([
42
73
  styles: [OGRID_THEME_VARS_CSS, `
43
74
  :host { display: block; height: 100%; }
44
75
  .ogrid-layout-root { display: flex; flex-direction: column; height: 100%; }
76
+ .ogrid-layout-root--fullscreen {
77
+ position: fixed; inset: 0; z-index: 9999;
78
+ background: var(--ogrid-bg, #ffffff);
79
+ }
45
80
  .ogrid-layout-container {
46
81
  border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
47
82
  overflow: hidden; display: flex; flex-direction: column;
48
83
  flex: 1; min-height: 0; background: var(--ogrid-bg, #ffffff);
49
84
  color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
50
85
  }
86
+ .ogrid-layout-root--fullscreen .ogrid-layout-container {
87
+ border: none; border-radius: 0 !important;
88
+ }
51
89
  .ogrid-layout-toolbar {
52
90
  display: flex; justify-content: space-between; align-items: center;
53
91
  padding: 6px 12px; background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04));
@@ -62,17 +100,24 @@ OGridLayoutComponent = __decorate([
62
100
  padding: 6px 12px; background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04));
63
101
  }
64
102
  .ogrid-layout-grid-area { width: 100%; min-width: 0; min-height: 0; flex: 1; display: flex; }
65
- .ogrid-layout-grid-content { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
103
+ .ogrid-layout-grid-content { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
66
104
  .ogrid-layout-footer {
67
105
  border-top: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
68
106
  background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)); padding: 6px 12px;
69
107
  }
108
+ .ogrid-fullscreen-btn {
109
+ background: none; border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
110
+ border-radius: 4px; padding: 4px 6px; cursor: pointer;
111
+ display: flex; align-items: center; justify-content: center;
112
+ color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
113
+ }
114
+ .ogrid-fullscreen-btn:hover { background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)); }
70
115
  `],
71
116
  template: `
72
- <div [class]="(className ?? '') + ' ogrid-layout-root'">
117
+ <div [class]="rootClass">
73
118
  <div class="ogrid-layout-container" [style.border-radius.px]="borderRadius">
74
119
  <!-- Toolbar strip -->
75
- @if (hasToolbar) {
120
+ @if (hasToolbar || fullScreen) {
76
121
  <div
77
122
  class="ogrid-layout-toolbar"
78
123
  [class.ogrid-layout-toolbar--has-below]="hasToolbarBelow"
@@ -83,6 +128,28 @@ OGridLayoutComponent = __decorate([
83
128
  </div>
84
129
  <div class="ogrid-layout-toolbar-right">
85
130
  <ng-content select="[toolbarEnd]"></ng-content>
131
+ @if (fullScreen) {
132
+ <button type="button" class="ogrid-fullscreen-btn"
133
+ [attr.title]="isFullScreen ? 'Exit fullscreen' : 'Fullscreen'"
134
+ [attr.aria-label]="isFullScreen ? 'Exit fullscreen' : 'Fullscreen'"
135
+ (click)="toggleFullScreen()">
136
+ @if (isFullScreen) {
137
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
138
+ <polyline points="4 10 0 10 0 14"></polyline>
139
+ <polyline points="12 6 16 6 16 2"></polyline>
140
+ <line x1="0" y1="10" x2="4" y2="6"></line>
141
+ <line x1="16" y1="6" x2="12" y2="10"></line>
142
+ </svg>
143
+ } @else {
144
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
145
+ <polyline points="10 2 14 2 14 6"></polyline>
146
+ <polyline points="6 14 2 14 2 10"></polyline>
147
+ <line x1="14" y1="2" x2="10" y2="6"></line>
148
+ <line x1="2" y1="14" x2="6" y2="10"></line>
149
+ </svg>
150
+ }
151
+ </button>
152
+ }
86
153
  </div>
87
154
  </div>
88
155
  }
@@ -94,7 +161,7 @@ OGridLayoutComponent = __decorate([
94
161
  </div>
95
162
  }
96
163
 
97
- <!-- Grid area (single ng-content to avoid Angular content projection issues) -->
164
+ <!-- Grid area -->
98
165
  <div class="ogrid-layout-grid-area">
99
166
  @if (sideBar && sideBar.position === 'left') {
100
167
  <ogrid-sidebar [sideBarProps]="sideBar"></ogrid-sidebar>
@@ -49,6 +49,8 @@ let OGridService = class OGridService {
49
49
  this.className = signal(undefined);
50
50
  this.layoutMode = signal('fill');
51
51
  this.suppressHorizontalScroll = signal(undefined);
52
+ this.stickyHeader = signal(true);
53
+ this.fullScreen = signal(false);
52
54
  this.editable = signal(undefined);
53
55
  this.cellSelection = signal(undefined);
54
56
  this.density = signal('normal');
@@ -261,6 +263,7 @@ let OGridService = class OGridService {
261
263
  getUserByEmail: this.dataSource()?.getUserByEmail?.bind(this.dataSource()),
262
264
  layoutMode: this.layoutMode(),
263
265
  suppressHorizontalScroll: this.suppressHorizontalScroll(),
266
+ stickyHeader: this.stickyHeader(),
264
267
  columnReorder: this.columnReorder(),
265
268
  virtualScroll: this.virtualScroll(),
266
269
  'aria-label': this.ariaLabel(),
@@ -593,6 +596,10 @@ let OGridService = class OGridService {
593
596
  this.layoutMode.set(props.layoutMode);
594
597
  if (props.suppressHorizontalScroll !== undefined)
595
598
  this.suppressHorizontalScroll.set(props.suppressHorizontalScroll);
599
+ if (props.stickyHeader !== undefined)
600
+ this.stickyHeader.set(props.stickyHeader);
601
+ if (props.fullScreen !== undefined)
602
+ this.fullScreen.set(props.fullScreen);
596
603
  if (props['aria-label'] !== undefined)
597
604
  this.ariaLabel.set(props['aria-label']);
598
605
  if (props['aria-labelledby'] !== undefined)
@@ -57,6 +57,7 @@ export declare abstract class BaseDataGridTableComponent<T = unknown> {
57
57
  readonly rowHeightCssVar: import("@angular/core").Signal<string | null>;
58
58
  readonly ariaLabel: import("@angular/core").Signal<string>;
59
59
  readonly ariaLabelledBy: import("@angular/core").Signal<string | undefined>;
60
+ readonly stickyHeader: import("@angular/core").Signal<boolean>;
60
61
  readonly emptyState: import("@angular/core").Signal<{
61
62
  onClearAll: () => void;
62
63
  hasActiveFilters: boolean;
@@ -5,5 +5,11 @@ export declare class OGridLayoutComponent {
5
5
  hasToolbarBelow: boolean;
6
6
  hasPagination: boolean;
7
7
  sideBar: SideBarProps | null;
8
+ fullScreen: boolean;
9
+ isFullScreen: boolean;
8
10
  readonly borderRadius = 6;
11
+ private escListener;
12
+ get rootClass(): string;
13
+ toggleFullScreen(): void;
14
+ private removeEscListener;
9
15
  }
@@ -84,6 +84,8 @@ export declare class OGridService<T> {
84
84
  readonly className: import("@angular/core").WritableSignal<string | undefined>;
85
85
  readonly layoutMode: import("@angular/core").WritableSignal<"content" | "fill">;
86
86
  readonly suppressHorizontalScroll: import("@angular/core").WritableSignal<boolean | undefined>;
87
+ readonly stickyHeader: import("@angular/core").WritableSignal<boolean>;
88
+ readonly fullScreen: import("@angular/core").WritableSignal<boolean>;
87
89
  readonly editable: import("@angular/core").WritableSignal<boolean | undefined>;
88
90
  readonly cellSelection: import("@angular/core").WritableSignal<boolean | undefined>;
89
91
  readonly density: import("@angular/core").WritableSignal<"compact" | "normal" | "comfortable">;
@@ -56,6 +56,10 @@ interface IOGridBaseProps<T> {
56
56
  columnChooser?: boolean | 'toolbar' | 'sidebar';
57
57
  layoutMode?: 'content' | 'fill';
58
58
  suppressHorizontalScroll?: boolean;
59
+ /** When true (default), header row sticks to the top of the scroll container. */
60
+ stickyHeader?: boolean;
61
+ /** When true, shows a fullscreen toggle button in the toolbar. Default: false. */
62
+ fullScreen?: boolean;
59
63
  sideBar?: boolean | ISideBarDef;
60
64
  columnReorder?: boolean;
61
65
  virtualScroll?: IVirtualScrollConfig;
@@ -101,6 +105,8 @@ export interface IOGridDataGridProps<T> {
101
105
  initialColumnWidths?: Record<string, number>;
102
106
  layoutMode?: 'content' | 'fill';
103
107
  suppressHorizontalScroll?: boolean;
108
+ /** When true (default), header row sticks to the top of the scroll container. */
109
+ stickyHeader?: boolean;
104
110
  isLoading?: boolean;
105
111
  loadingMessage?: string;
106
112
  editable?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alaarab/ogrid-angular",
3
- "version": "2.1.0",
3
+ "version": "2.1.2",
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.1.0"
38
+ "@alaarab/ogrid-core": "2.1.2"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "@angular/core": "^21.0.0",