@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
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# @alaarab/ogrid-angular-radix
|
|
2
|
+
|
|
3
|
+
Lightweight Angular data grid with sorting, filtering, pagination, column chooser, and CSV export. Built with Angular CDK for overlays.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @alaarab/ogrid-angular-radix
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- ✅ **Lightweight**: Uses Angular CDK only - no heavy UI framework dependency
|
|
14
|
+
- ✅ **Full-featured**: Sorting, filtering, pagination, column management
|
|
15
|
+
- ✅ **Cell Selection**: Excel-like spreadsheet selection and editing
|
|
16
|
+
- ✅ **Keyboard Navigation**: Arrow keys, Enter, Escape, Tab
|
|
17
|
+
- ✅ **Copy/Paste**: Clipboard integration with Excel-compatible formats
|
|
18
|
+
- ✅ **Fill Handle**: Drag to fill cells like Excel
|
|
19
|
+
- ✅ **Undo/Redo**: Full edit history support
|
|
20
|
+
- ✅ **Context Menu**: Right-click menu for common operations
|
|
21
|
+
- ✅ **Column Resize**: Drag column borders to resize
|
|
22
|
+
- ✅ **Column Reorder**: Drag column headers to reorder
|
|
23
|
+
- ✅ **Customizable**: CSS variables for theming
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { Component } from '@angular/core';
|
|
29
|
+
import { OGridComponent } from '@alaarab/ogrid-angular-radix';
|
|
30
|
+
|
|
31
|
+
interface Employee {
|
|
32
|
+
id: number;
|
|
33
|
+
name: string;
|
|
34
|
+
department: string;
|
|
35
|
+
salary: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@Component({
|
|
39
|
+
selector: 'app-root',
|
|
40
|
+
standalone: true,
|
|
41
|
+
imports: [OGridComponent],
|
|
42
|
+
template: `
|
|
43
|
+
<ogrid
|
|
44
|
+
[props]="{
|
|
45
|
+
columns: columns,
|
|
46
|
+
data: data,
|
|
47
|
+
cellSelection: true,
|
|
48
|
+
editable: true,
|
|
49
|
+
statusBar: true
|
|
50
|
+
}"
|
|
51
|
+
/>
|
|
52
|
+
`
|
|
53
|
+
})
|
|
54
|
+
export class AppComponent {
|
|
55
|
+
columns = [
|
|
56
|
+
{ columnId: 'id', name: 'ID', type: 'numeric' as const },
|
|
57
|
+
{ columnId: 'name', name: 'Name', type: 'text' as const },
|
|
58
|
+
{ columnId: 'department', name: 'Department', type: 'text' as const, filterable: { type: 'multiSelect' as const } },
|
|
59
|
+
{ columnId: 'salary', name: 'Salary', type: 'numeric' as const, editable: true }
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
data: Employee[] = [
|
|
63
|
+
{ id: 1, name: 'Alice', department: 'Engineering', salary: 120000 },
|
|
64
|
+
{ id: 2, name: 'Bob', department: 'Marketing', salary: 90000 },
|
|
65
|
+
{ id: 3, name: 'Carol', department: 'Engineering', salary: 115000 }
|
|
66
|
+
];
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Documentation
|
|
71
|
+
|
|
72
|
+
Full documentation available at: https://alaarab.github.io/ogrid
|
|
73
|
+
|
|
74
|
+
## License
|
|
75
|
+
|
|
76
|
+
MIT © Ala Arab
|
|
@@ -0,0 +1,199 @@
|
|
|
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, signal, computed, ChangeDetectionStrategy } from '@angular/core';
|
|
8
|
+
/**
|
|
9
|
+
* Column visibility chooser dropdown for Angular Radix (lightweight styling).
|
|
10
|
+
* Standalone component with inline template and CSS variables for theming.
|
|
11
|
+
*/
|
|
12
|
+
let ColumnChooserComponent = class ColumnChooserComponent {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.columns = input.required();
|
|
15
|
+
this.visibleColumns = input.required();
|
|
16
|
+
this.visibilityChange = output();
|
|
17
|
+
this.isOpen = signal(false);
|
|
18
|
+
this.visibleCount = computed(() => this.visibleColumns().size);
|
|
19
|
+
this.totalCount = computed(() => this.columns().length);
|
|
20
|
+
}
|
|
21
|
+
toggle() {
|
|
22
|
+
this.isOpen.update((v) => !v);
|
|
23
|
+
}
|
|
24
|
+
onCheckboxChange(columnKey, event) {
|
|
25
|
+
const checked = event.target.checked;
|
|
26
|
+
this.visibilityChange.emit({ columnKey, visible: checked });
|
|
27
|
+
}
|
|
28
|
+
selectAll() {
|
|
29
|
+
for (const col of this.columns()) {
|
|
30
|
+
if (!this.visibleColumns().has(col.columnId)) {
|
|
31
|
+
this.visibilityChange.emit({ columnKey: col.columnId, visible: true });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
clearAll() {
|
|
36
|
+
for (const col of this.columns()) {
|
|
37
|
+
if (this.visibleColumns().has(col.columnId)) {
|
|
38
|
+
this.visibilityChange.emit({ columnKey: col.columnId, visible: false });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
onDocumentClick(event) {
|
|
43
|
+
// Close dropdown when clicking outside
|
|
44
|
+
const el = event.target;
|
|
45
|
+
if (!el.closest('ogrid-column-chooser')) {
|
|
46
|
+
this.isOpen.set(false);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
ColumnChooserComponent = __decorate([
|
|
51
|
+
Component({
|
|
52
|
+
selector: 'ogrid-column-chooser',
|
|
53
|
+
standalone: true,
|
|
54
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
55
|
+
template: `
|
|
56
|
+
<div class="ogrid-column-chooser">
|
|
57
|
+
<button
|
|
58
|
+
class="ogrid-column-chooser__trigger"
|
|
59
|
+
(click)="toggle()"
|
|
60
|
+
[attr.aria-expanded]="isOpen()"
|
|
61
|
+
aria-haspopup="listbox"
|
|
62
|
+
>
|
|
63
|
+
☰ Columns ({{ visibleCount() }}/{{ totalCount() }})
|
|
64
|
+
<span class="ogrid-column-chooser__caret">{{ isOpen() ? '▲' : '▼' }}</span>
|
|
65
|
+
</button>
|
|
66
|
+
|
|
67
|
+
@if (isOpen()) {
|
|
68
|
+
<div class="ogrid-column-chooser__dropdown" (click)="$event.stopPropagation()">
|
|
69
|
+
<div class="ogrid-column-chooser__header">
|
|
70
|
+
Select Columns ({{ visibleCount() }} of {{ totalCount() }})
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<div class="ogrid-column-chooser__list">
|
|
74
|
+
@for (col of columns(); track col.columnId) {
|
|
75
|
+
<label class="ogrid-column-chooser__item">
|
|
76
|
+
<input
|
|
77
|
+
type="checkbox"
|
|
78
|
+
[checked]="visibleColumns().has(col.columnId)"
|
|
79
|
+
(change)="onCheckboxChange(col.columnId, $event)"
|
|
80
|
+
/>
|
|
81
|
+
<span>{{ col.name }}</span>
|
|
82
|
+
</label>
|
|
83
|
+
}
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<div class="ogrid-column-chooser__footer">
|
|
87
|
+
<button class="ogrid-column-chooser__btn" (click)="clearAll()">Clear All</button>
|
|
88
|
+
<button class="ogrid-column-chooser__btn ogrid-column-chooser__btn--primary" (click)="selectAll()">Select All</button>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
}
|
|
92
|
+
</div>
|
|
93
|
+
`,
|
|
94
|
+
styles: [`
|
|
95
|
+
:host { display: inline-flex; position: relative; }
|
|
96
|
+
.ogrid-column-chooser { position: relative; }
|
|
97
|
+
.ogrid-column-chooser__trigger {
|
|
98
|
+
display: inline-flex;
|
|
99
|
+
align-items: center;
|
|
100
|
+
gap: 6px;
|
|
101
|
+
padding: 6px 12px;
|
|
102
|
+
border: 1px solid var(--ogrid-border, #e0e0e0);
|
|
103
|
+
border-radius: 4px;
|
|
104
|
+
background: var(--ogrid-bg, #ffffff);
|
|
105
|
+
color: var(--ogrid-fg, #242424);
|
|
106
|
+
cursor: pointer;
|
|
107
|
+
font-size: 14px;
|
|
108
|
+
font-weight: 600;
|
|
109
|
+
text-transform: none;
|
|
110
|
+
white-space: nowrap;
|
|
111
|
+
transition: all 0.15s ease;
|
|
112
|
+
}
|
|
113
|
+
.ogrid-column-chooser__trigger:hover {
|
|
114
|
+
background: var(--ogrid-hover-bg, #f0f0f0);
|
|
115
|
+
border-color: var(--ogrid-active-border, #0078d4);
|
|
116
|
+
}
|
|
117
|
+
.ogrid-column-chooser__caret {
|
|
118
|
+
font-size: 10px;
|
|
119
|
+
opacity: 0.7;
|
|
120
|
+
}
|
|
121
|
+
.ogrid-column-chooser__dropdown {
|
|
122
|
+
position: absolute;
|
|
123
|
+
top: 100%;
|
|
124
|
+
right: 0;
|
|
125
|
+
z-index: 1000;
|
|
126
|
+
min-width: 220px;
|
|
127
|
+
margin-top: 4px;
|
|
128
|
+
background: var(--ogrid-bg, #ffffff);
|
|
129
|
+
border: 1px solid var(--ogrid-border, #e0e0e0);
|
|
130
|
+
border-radius: 4px;
|
|
131
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
132
|
+
}
|
|
133
|
+
.ogrid-column-chooser__header {
|
|
134
|
+
padding: 8px 12px;
|
|
135
|
+
font-size: 14px;
|
|
136
|
+
font-weight: 600;
|
|
137
|
+
color: var(--ogrid-fg, #242424);
|
|
138
|
+
border-bottom: 1px solid var(--ogrid-border, #e0e0e0);
|
|
139
|
+
background: var(--ogrid-header-bg, #f5f5f5);
|
|
140
|
+
}
|
|
141
|
+
.ogrid-column-chooser__list {
|
|
142
|
+
max-height: 320px;
|
|
143
|
+
overflow-y: auto;
|
|
144
|
+
padding: 4px 0;
|
|
145
|
+
}
|
|
146
|
+
.ogrid-column-chooser__item {
|
|
147
|
+
display: flex;
|
|
148
|
+
align-items: center;
|
|
149
|
+
gap: 8px;
|
|
150
|
+
padding: 6px 12px;
|
|
151
|
+
min-height: 32px;
|
|
152
|
+
cursor: pointer;
|
|
153
|
+
font-size: 14px;
|
|
154
|
+
color: var(--ogrid-fg, #242424);
|
|
155
|
+
transition: background 0.15s ease;
|
|
156
|
+
}
|
|
157
|
+
.ogrid-column-chooser__item:hover {
|
|
158
|
+
background: var(--ogrid-hover-bg, #f0f0f0);
|
|
159
|
+
}
|
|
160
|
+
.ogrid-column-chooser__item input[type="checkbox"] {
|
|
161
|
+
cursor: pointer;
|
|
162
|
+
}
|
|
163
|
+
.ogrid-column-chooser__footer {
|
|
164
|
+
display: flex;
|
|
165
|
+
justify-content: flex-end;
|
|
166
|
+
gap: 8px;
|
|
167
|
+
padding: 8px 12px;
|
|
168
|
+
border-top: 1px solid var(--ogrid-border, #e0e0e0);
|
|
169
|
+
background: var(--ogrid-header-bg, #f5f5f5);
|
|
170
|
+
}
|
|
171
|
+
.ogrid-column-chooser__btn {
|
|
172
|
+
padding: 6px 12px;
|
|
173
|
+
border: 1px solid var(--ogrid-border, #e0e0e0);
|
|
174
|
+
border-radius: 4px;
|
|
175
|
+
background: var(--ogrid-bg, #ffffff);
|
|
176
|
+
color: var(--ogrid-fg, #242424);
|
|
177
|
+
cursor: pointer;
|
|
178
|
+
font-size: 13px;
|
|
179
|
+
text-transform: none;
|
|
180
|
+
transition: all 0.15s ease;
|
|
181
|
+
}
|
|
182
|
+
.ogrid-column-chooser__btn:hover {
|
|
183
|
+
background: var(--ogrid-hover-bg, #f0f0f0);
|
|
184
|
+
}
|
|
185
|
+
.ogrid-column-chooser__btn--primary {
|
|
186
|
+
background: var(--ogrid-active-border, #0078d4);
|
|
187
|
+
color: #ffffff;
|
|
188
|
+
border-color: var(--ogrid-active-border, #0078d4);
|
|
189
|
+
}
|
|
190
|
+
.ogrid-column-chooser__btn--primary:hover {
|
|
191
|
+
opacity: 0.9;
|
|
192
|
+
}
|
|
193
|
+
`],
|
|
194
|
+
host: {
|
|
195
|
+
'(document:click)': 'onDocumentClick($event)',
|
|
196
|
+
},
|
|
197
|
+
})
|
|
198
|
+
], ColumnChooserComponent);
|
|
199
|
+
export { ColumnChooserComponent };
|