@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.
- package/README.md +76 -0
- package/dist/esm/column-chooser/column-chooser.component.js +199 -0
- package/dist/esm/column-header-filter/column-header-filter.component.js +497 -0
- package/dist/esm/datagrid-table/datagrid-table.component.js +573 -0
- package/dist/esm/index.js +14 -0
- package/dist/esm/ogrid/ogrid.component.js +77 -0
- package/dist/esm/pagination-controls/pagination-controls.component.js +189 -0
- package/dist/types/column-chooser/column-chooser.component.d.ts +26 -0
- package/dist/types/column-header-filter/column-header-filter.component.d.ts +67 -0
- package/dist/types/datagrid-table/datagrid-table.component.d.ts +131 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/ogrid/ogrid.component.d.ts +14 -0
- package/dist/types/pagination-controls/pagination-controls.component.d.ts +15 -0
- package/jest-mocks/angular-cdk-overlay.cjs.js +38 -0
- package/jest-mocks/style-mock.js +1 -0
- package/jest.config.js +43 -0
- package/package.json +37 -0
- package/scripts/compile-styles.js +53 -0
- package/src/__tests__/column-chooser.component.spec.ts.skip +195 -0
- package/src/__tests__/column-header-filter.component.spec.ts.skip +401 -0
- package/src/__tests__/datagrid-table.component.spec.ts.skip +417 -0
- package/src/__tests__/exports.test.ts +54 -0
- package/src/__tests__/ogrid.component.spec.ts.skip +236 -0
- package/src/__tests__/pagination-controls.component.spec.ts.skip +190 -0
- package/src/column-chooser/column-chooser.component.ts +204 -0
- package/src/column-header-filter/column-header-filter.component.ts +528 -0
- package/src/datagrid-table/datagrid-table.component.scss +289 -0
- package/src/datagrid-table/datagrid-table.component.ts +636 -0
- package/src/index.ts +16 -0
- package/src/ogrid/ogrid.component.ts +78 -0
- package/src/pagination-controls/pagination-controls.component.ts +187 -0
- package/tsconfig.build.json +9 -0
- 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
|
+
}
|
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
|
+
}
|