@alaarab/ogrid-angular-radix 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.
Files changed (33) hide show
  1. package/README.md +76 -0
  2. package/dist/esm/column-chooser/column-chooser.component.js +199 -0
  3. package/dist/esm/column-header-filter/column-header-filter.component.js +497 -0
  4. package/dist/esm/datagrid-table/datagrid-table.component.js +573 -0
  5. package/dist/esm/index.js +14 -0
  6. package/dist/esm/ogrid/ogrid.component.js +77 -0
  7. package/dist/esm/pagination-controls/pagination-controls.component.js +189 -0
  8. package/dist/types/column-chooser/column-chooser.component.d.ts +26 -0
  9. package/dist/types/column-header-filter/column-header-filter.component.d.ts +67 -0
  10. package/dist/types/datagrid-table/datagrid-table.component.d.ts +131 -0
  11. package/dist/types/index.d.ts +12 -0
  12. package/dist/types/ogrid/ogrid.component.d.ts +14 -0
  13. package/dist/types/pagination-controls/pagination-controls.component.d.ts +15 -0
  14. package/jest-mocks/angular-cdk-overlay.cjs.js +38 -0
  15. package/jest-mocks/style-mock.js +1 -0
  16. package/jest.config.js +43 -0
  17. package/package.json +37 -0
  18. package/scripts/compile-styles.js +53 -0
  19. package/src/__tests__/column-chooser.component.spec.ts.skip +195 -0
  20. package/src/__tests__/column-header-filter.component.spec.ts.skip +401 -0
  21. package/src/__tests__/datagrid-table.component.spec.ts.skip +417 -0
  22. package/src/__tests__/exports.test.ts +54 -0
  23. package/src/__tests__/ogrid.component.spec.ts.skip +236 -0
  24. package/src/__tests__/pagination-controls.component.spec.ts.skip +190 -0
  25. package/src/column-chooser/column-chooser.component.ts +204 -0
  26. package/src/column-header-filter/column-header-filter.component.ts +528 -0
  27. package/src/datagrid-table/datagrid-table.component.scss +289 -0
  28. package/src/datagrid-table/datagrid-table.component.ts +636 -0
  29. package/src/index.ts +16 -0
  30. package/src/ogrid/ogrid.component.ts +78 -0
  31. package/src/pagination-controls/pagination-controls.component.ts +187 -0
  32. package/tsconfig.build.json +9 -0
  33. package/tsconfig.json +21 -0
@@ -0,0 +1,78 @@
1
+ import { Component, input, computed, ChangeDetectionStrategy } from '@angular/core';
2
+ import {
3
+ OGridService,
4
+ OGridLayoutComponent,
5
+ } from '@alaarab/ogrid-angular';
6
+ import type { IOGridProps, IOGridDataGridProps } from '@alaarab/ogrid-angular';
7
+ import { DataGridTableComponent } from '../datagrid-table/datagrid-table.component';
8
+ import { ColumnChooserComponent } from '../column-chooser/column-chooser.component';
9
+ import { PaginationControlsComponent } from '../pagination-controls/pagination-controls.component';
10
+
11
+ /**
12
+ * Top-level OGrid component for Angular Radix (lightweight Angular CDK-based implementation).
13
+ * This is the recommended default option for Angular developers.
14
+ * Standalone component — provides OGridService and renders OGridLayout with all sub-components.
15
+ */
16
+ @Component({
17
+ selector: 'ogrid',
18
+ standalone: true,
19
+ imports: [
20
+ OGridLayoutComponent,
21
+ DataGridTableComponent,
22
+ ColumnChooserComponent,
23
+ PaginationControlsComponent,
24
+ ],
25
+ providers: [OGridService],
26
+ changeDetection: ChangeDetectionStrategy.OnPush,
27
+ template: `
28
+ <ogrid-layout
29
+ [className]="ogridService.className()"
30
+ [sideBar]="ogridService.sideBarProps()"
31
+ [toolbar]="ogridService.toolbar()"
32
+ [toolbarBelow]="ogridService.toolbarBelow()"
33
+ >
34
+ <ng-container toolbar-end>
35
+ @if (ogridService.columnChooserPlacement() === 'toolbar') {
36
+ <ogrid-column-chooser
37
+ [columns]="ogridService.columnChooser().columns"
38
+ [visibleColumns]="ogridService.columnChooser().visibleColumns"
39
+ (visibilityChange)="ogridService.columnChooser().onVisibilityChange($event.columnKey, $event.visible)"
40
+ />
41
+ }
42
+ </ng-container>
43
+
44
+ <ogrid-datagrid-table [props]="dataGridProps()" />
45
+
46
+ <ng-container pagination>
47
+ <ogrid-pagination-controls
48
+ [currentPage]="ogridService.pagination().page"
49
+ [pageSize]="ogridService.pagination().pageSize"
50
+ [totalCount]="ogridService.pagination().displayTotalCount"
51
+ [pageSizeOptions]="ogridService.pagination().pageSizeOptions"
52
+ [entityLabelPlural]="ogridService.pagination().entityLabelPlural"
53
+ (pageChange)="ogridService.pagination().setPage($event)"
54
+ (pageSizeChange)="onPageSizeChange($event)"
55
+ />
56
+ </ng-container>
57
+ </ogrid-layout>
58
+ `,
59
+ })
60
+ export class OGridComponent<T> {
61
+ readonly props = input.required<IOGridProps<T>>();
62
+
63
+ readonly ogridService: OGridService<T>;
64
+
65
+ readonly dataGridProps = computed<IOGridDataGridProps<T>>(() => {
66
+ this.ogridService.configure(this.props());
67
+ return this.ogridService.dataGridProps();
68
+ });
69
+
70
+ constructor() {
71
+ this.ogridService = new OGridService<T>();
72
+ }
73
+
74
+ onPageSizeChange(size: number): void {
75
+ this.ogridService.pagination().setPageSize(size);
76
+ this.ogridService.pagination().setPage(1);
77
+ }
78
+ }
@@ -0,0 +1,187 @@
1
+ import { Component, input, output, computed, ChangeDetectionStrategy } from '@angular/core';
2
+ import { getPaginationViewModel } from '@alaarab/ogrid-angular';
3
+
4
+ /**
5
+ * Pagination controls component for Angular Radix (lightweight styling).
6
+ * Standalone component with inline template and CSS variables for theming.
7
+ */
8
+ @Component({
9
+ selector: 'ogrid-pagination-controls',
10
+ standalone: true,
11
+ changeDetection: ChangeDetectionStrategy.OnPush,
12
+ template: `
13
+ @if (vm(); as vm) {
14
+ <nav class="ogrid-pagination" role="navigation" aria-label="Pagination">
15
+ <span class="ogrid-pagination__info">
16
+ Showing {{ vm.startItem }} to {{ vm.endItem }} of {{ totalCount().toLocaleString() }} {{ entityLabelPlural() }}
17
+ </span>
18
+
19
+ <span class="ogrid-pagination__pages">
20
+ <button
21
+ class="ogrid-pagination__btn"
22
+ [disabled]="currentPage() === 1"
23
+ (click)="pageChange.emit(1)"
24
+ aria-label="First page"
25
+ >⏮</button>
26
+ <button
27
+ class="ogrid-pagination__btn"
28
+ [disabled]="currentPage() === 1"
29
+ (click)="pageChange.emit(currentPage() - 1)"
30
+ aria-label="Previous page"
31
+ >◀</button>
32
+
33
+ @if (vm.showStartEllipsis) {
34
+ <button class="ogrid-pagination__btn" (click)="pageChange.emit(1)" aria-label="Page 1">1</button>
35
+ <span class="ogrid-pagination__ellipsis" aria-hidden="true">…</span>
36
+ }
37
+
38
+ @for (pageNum of vm.pageNumbers; track pageNum) {
39
+ <button
40
+ class="ogrid-pagination__btn"
41
+ [class.ogrid-pagination__btn--active]="currentPage() === pageNum"
42
+ (click)="pageChange.emit(pageNum)"
43
+ [attr.aria-label]="'Page ' + pageNum"
44
+ [attr.aria-current]="currentPage() === pageNum ? 'page' : null"
45
+ >{{ pageNum }}</button>
46
+ }
47
+
48
+ @if (vm.showEndEllipsis) {
49
+ <span class="ogrid-pagination__ellipsis" aria-hidden="true">…</span>
50
+ <button
51
+ class="ogrid-pagination__btn"
52
+ (click)="pageChange.emit(vm.totalPages)"
53
+ [attr.aria-label]="'Page ' + vm.totalPages"
54
+ >{{ vm.totalPages }}</button>
55
+ }
56
+
57
+ <button
58
+ class="ogrid-pagination__btn"
59
+ [disabled]="currentPage() >= vm.totalPages"
60
+ (click)="pageChange.emit(currentPage() + 1)"
61
+ aria-label="Next page"
62
+ >▶</button>
63
+ <button
64
+ class="ogrid-pagination__btn"
65
+ [disabled]="currentPage() >= vm.totalPages"
66
+ (click)="pageChange.emit(vm.totalPages)"
67
+ aria-label="Last page"
68
+ >⏭</button>
69
+ </span>
70
+
71
+ <span class="ogrid-pagination__size">
72
+ <label>Rows
73
+ <select
74
+ [value]="pageSize()"
75
+ (change)="onPageSizeSelect($event)"
76
+ aria-label="Rows per page"
77
+ >
78
+ @for (n of vm.pageSizeOptions; track n) {
79
+ <option [value]="n" [selected]="pageSize() === n">{{ n }}</option>
80
+ }
81
+ </select>
82
+ </label>
83
+ </span>
84
+ </nav>
85
+ }
86
+ `,
87
+ styles: [`
88
+ :host { display: block; }
89
+ .ogrid-pagination {
90
+ display: flex;
91
+ align-items: center;
92
+ justify-content: space-between;
93
+ flex-wrap: wrap;
94
+ gap: 8px;
95
+ padding: 6px 12px;
96
+ font-size: 14px;
97
+ background: var(--ogrid-bg, #ffffff);
98
+ }
99
+ .ogrid-pagination__info {
100
+ color: var(--ogrid-fg, #242424);
101
+ opacity: 0.7;
102
+ }
103
+ .ogrid-pagination__pages {
104
+ display: flex;
105
+ align-items: center;
106
+ gap: 4px;
107
+ }
108
+ .ogrid-pagination__btn {
109
+ min-width: 32px;
110
+ height: 32px;
111
+ padding: 0 8px;
112
+ border: 1px solid var(--ogrid-border, #e0e0e0);
113
+ border-radius: 4px;
114
+ background: var(--ogrid-bg, #ffffff);
115
+ color: var(--ogrid-fg, #242424);
116
+ cursor: pointer;
117
+ font-size: 14px;
118
+ transition: all 0.15s ease;
119
+ }
120
+ .ogrid-pagination__btn:hover:not(:disabled) {
121
+ background: var(--ogrid-hover-bg, #f0f0f0);
122
+ border-color: var(--ogrid-active-border, #0078d4);
123
+ }
124
+ .ogrid-pagination__btn:disabled {
125
+ opacity: 0.4;
126
+ cursor: not-allowed;
127
+ }
128
+ .ogrid-pagination__btn--active {
129
+ background: var(--ogrid-active-border, #0078d4);
130
+ color: #ffffff;
131
+ border-color: var(--ogrid-active-border, #0078d4);
132
+ font-weight: 600;
133
+ }
134
+ .ogrid-pagination__ellipsis {
135
+ margin: 0 4px;
136
+ color: var(--ogrid-fg, #242424);
137
+ opacity: 0.6;
138
+ }
139
+ .ogrid-pagination__size {
140
+ display: flex;
141
+ align-items: center;
142
+ gap: 8px;
143
+ color: var(--ogrid-fg, #242424);
144
+ }
145
+ .ogrid-pagination__size select {
146
+ min-width: 60px;
147
+ height: 32px;
148
+ padding: 4px 8px;
149
+ border: 1px solid var(--ogrid-border, #e0e0e0);
150
+ border-radius: 4px;
151
+ background: var(--ogrid-bg, #ffffff);
152
+ color: var(--ogrid-fg, #242424);
153
+ font-size: 14px;
154
+ margin-left: 8px;
155
+ cursor: pointer;
156
+ }
157
+ .ogrid-pagination__size select:focus {
158
+ outline: 2px solid var(--ogrid-active-border, #0078d4);
159
+ outline-offset: 1px;
160
+ }
161
+ `],
162
+ })
163
+ export class PaginationControlsComponent {
164
+ readonly currentPage = input.required<number>();
165
+ readonly pageSize = input.required<number>();
166
+ readonly totalCount = input.required<number>();
167
+ readonly pageSizeOptions = input<number[] | undefined>(undefined);
168
+ readonly entityLabelPlural = input<string>('items');
169
+
170
+ readonly pageChange = output<number>();
171
+ readonly pageSizeChange = output<number>();
172
+
173
+ readonly vm = computed(() => {
174
+ const opts = this.pageSizeOptions();
175
+ return getPaginationViewModel(
176
+ this.currentPage(),
177
+ this.pageSize(),
178
+ this.totalCount(),
179
+ opts ? { pageSizeOptions: opts } : undefined,
180
+ );
181
+ });
182
+
183
+ onPageSizeSelect(event: Event): void {
184
+ const value = Number((event.target as HTMLSelectElement).value);
185
+ this.pageSizeChange.emit(value);
186
+ }
187
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist/esm",
5
+ "declaration": true,
6
+ "declarationDir": "./dist/types"
7
+ },
8
+ "exclude": ["src/**/__tests__/**", "src/**/*.spec.ts"]
9
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "outDir": "./dist/esm",
4
+ "rootDir": "./src",
5
+ "declaration": true,
6
+ "declarationDir": "./dist/types",
7
+ "module": "ES2022",
8
+ "target": "ES2022",
9
+ "lib": ["ES2022", "DOM"],
10
+ "moduleResolution": "bundler",
11
+ "strict": true,
12
+ "esModuleInterop": true,
13
+ "skipLibCheck": true,
14
+ "experimentalDecorators": true,
15
+ "useDefineForClassFields": false,
16
+ "resolveJsonModule": true,
17
+ "allowSyntheticDefaultImports": true
18
+ },
19
+ "include": ["src/**/*"],
20
+ "exclude": ["node_modules", "dist", "**/*.spec.ts", "**/__tests__/**"]
21
+ }