@alaarab/ogrid-angular 2.1.2 → 2.1.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 (32) hide show
  1. package/dist/esm/index.js +4606 -30
  2. package/dist/types/components/base-datagrid-table.component.d.ts +8 -8
  3. package/package.json +4 -4
  4. package/dist/esm/components/base-column-chooser.component.js +0 -78
  5. package/dist/esm/components/base-column-header-filter.component.js +0 -281
  6. package/dist/esm/components/base-datagrid-table.component.js +0 -648
  7. package/dist/esm/components/base-inline-cell-editor.component.js +0 -253
  8. package/dist/esm/components/base-ogrid.component.js +0 -36
  9. package/dist/esm/components/base-pagination-controls.component.js +0 -72
  10. package/dist/esm/components/base-popover-cell-editor.component.js +0 -114
  11. package/dist/esm/components/empty-state.component.js +0 -58
  12. package/dist/esm/components/grid-context-menu.component.js +0 -153
  13. package/dist/esm/components/inline-cell-editor-template.js +0 -107
  14. package/dist/esm/components/marching-ants-overlay.component.js +0 -164
  15. package/dist/esm/components/ogrid-layout.component.js +0 -188
  16. package/dist/esm/components/sidebar.component.js +0 -274
  17. package/dist/esm/components/status-bar.component.js +0 -71
  18. package/dist/esm/services/column-reorder.service.js +0 -180
  19. package/dist/esm/services/datagrid-editing.service.js +0 -52
  20. package/dist/esm/services/datagrid-interaction.service.js +0 -667
  21. package/dist/esm/services/datagrid-layout.service.js +0 -151
  22. package/dist/esm/services/datagrid-state.service.js +0 -591
  23. package/dist/esm/services/ogrid.service.js +0 -746
  24. package/dist/esm/services/virtual-scroll.service.js +0 -91
  25. package/dist/esm/styles/ogrid-theme-vars.js +0 -53
  26. package/dist/esm/types/columnTypes.js +0 -1
  27. package/dist/esm/types/dataGridTypes.js +0 -1
  28. package/dist/esm/types/index.js +0 -1
  29. package/dist/esm/utils/dataGridViewModel.js +0 -6
  30. package/dist/esm/utils/debounce.js +0 -68
  31. package/dist/esm/utils/index.js +0 -8
  32. package/dist/esm/utils/latestRef.js +0 -41
@@ -40,14 +40,14 @@ export declare abstract class BaseDataGridTableComponent<T = unknown> {
40
40
  /** Measure actual th widths from the DOM and update the measuredColumnWidths signal.
41
41
  * Only updates the signal when values actually change, to avoid render loops. */
42
42
  private measureColumnWidths;
43
- readonly state: import("@angular/core").Signal<import("../services/datagrid-state.service").DataGridStateResult<T>>;
44
- protected readonly layoutState: import("@angular/core").Signal<import("../services/datagrid-state.service").DataGridLayoutState<T>>;
45
- protected readonly rowSelectionState: import("@angular/core").Signal<import("../services/datagrid-state.service").DataGridRowSelectionState>;
46
- protected readonly editingState: import("@angular/core").Signal<import("../services/datagrid-state.service").DataGridEditingState<T>>;
47
- protected readonly interactionState: import("@angular/core").Signal<import("../services/datagrid-state.service").DataGridCellInteractionState>;
48
- protected readonly contextMenuState: import("@angular/core").Signal<import("../services/datagrid-state.service").DataGridContextMenuState>;
49
- protected readonly viewModelsState: import("@angular/core").Signal<import("../services/datagrid-state.service").DataGridViewModelState<T>>;
50
- protected readonly pinningState: import("@angular/core").Signal<import("../services/datagrid-state.service").DataGridPinningState>;
43
+ readonly state: import("@angular/core").Signal<import("..").DataGridStateResult<T>>;
44
+ protected readonly layoutState: import("@angular/core").Signal<import("..").DataGridLayoutState<T>>;
45
+ protected readonly rowSelectionState: import("@angular/core").Signal<import("..").DataGridRowSelectionState>;
46
+ protected readonly editingState: import("@angular/core").Signal<import("..").DataGridEditingState<T>>;
47
+ protected readonly interactionState: import("@angular/core").Signal<import("..").DataGridCellInteractionState>;
48
+ protected readonly contextMenuState: import("@angular/core").Signal<import("..").DataGridContextMenuState>;
49
+ protected readonly viewModelsState: import("@angular/core").Signal<import("..").DataGridViewModelState<T>>;
50
+ protected readonly pinningState: import("@angular/core").Signal<import("..").DataGridPinningState>;
51
51
  readonly tableContainerEl: import("@angular/core").Signal<HTMLElement | null>;
52
52
  readonly items: import("@angular/core").Signal<T[]>;
53
53
  readonly getRowId: import("@angular/core").Signal<(item: T) => RowId>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alaarab/ogrid-angular",
3
- "version": "2.1.2",
3
+ "version": "2.1.4",
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",
@@ -9,11 +9,11 @@
9
9
  ".": {
10
10
  "types": "./dist/types/index.d.ts",
11
11
  "import": "./dist/esm/index.js",
12
- "require": "./dist/esm/index.js"
12
+ "default": "./dist/esm/index.js"
13
13
  }
14
14
  },
15
15
  "scripts": {
16
- "build": "rimraf dist && tsc -p tsconfig.build.json",
16
+ "build": "rimraf dist && tsup && tsc -p tsconfig.build.json",
17
17
  "test": "jest --passWithNoTests"
18
18
  },
19
19
  "keywords": [
@@ -35,7 +35,7 @@
35
35
  "node": ">=18"
36
36
  },
37
37
  "dependencies": {
38
- "@alaarab/ogrid-core": "2.1.2"
38
+ "@alaarab/ogrid-core": "2.1.4"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "@angular/core": "^21.0.0",
@@ -1,78 +0,0 @@
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 { signal, computed, Input, Output, EventEmitter } from '@angular/core';
8
- /**
9
- * Abstract base class containing all shared TypeScript logic for ColumnChooser components.
10
- * Framework-specific UI packages extend this with their templates and style overrides.
11
- *
12
- * Subclasses must:
13
- * 1. Provide a @Component decorator with template and styles
14
- * 2. Handle their own click-outside behavior (host binding or effect)
15
- */
16
- export class BaseColumnChooserComponent {
17
- constructor() {
18
- this._columns = signal([]);
19
- this._visibleColumns = signal(new Set());
20
- this.visibilityChange = new EventEmitter();
21
- // Dropdown state
22
- this.isOpen = signal(false);
23
- // Computed counts (signal-backed so computed() tracks changes)
24
- this.visibleCount = computed(() => this._visibleColumns().size);
25
- this.totalCount = computed(() => this._columns().length);
26
- }
27
- set columns(v) { this._columns.set(v); }
28
- get columns() { return this._columns(); }
29
- set visibleColumns(v) { this._visibleColumns.set(v); }
30
- get visibleColumns() { return this._visibleColumns(); }
31
- toggle() {
32
- this.isOpen.update((v) => !v);
33
- }
34
- onCheckboxChange(columnKey, event) {
35
- const checked = event.target.checked;
36
- this.visibilityChange.emit({ columnKey, visible: checked });
37
- }
38
- onToggle(columnKey, checked) {
39
- this.visibilityChange.emit({ columnKey, visible: checked });
40
- }
41
- selectAll() {
42
- for (const col of this.columns) {
43
- if (!this.visibleColumns.has(col.columnId)) {
44
- this.visibilityChange.emit({ columnKey: col.columnId, visible: true });
45
- }
46
- }
47
- }
48
- clearAll() {
49
- for (const col of this.columns) {
50
- if (this.visibleColumns.has(col.columnId)) {
51
- this.visibilityChange.emit({ columnKey: col.columnId, visible: false });
52
- }
53
- }
54
- }
55
- onClearAll() {
56
- for (const col of this.columns) {
57
- if (col.required !== true && this.visibleColumns.has(col.columnId)) {
58
- this.visibilityChange.emit({ columnKey: col.columnId, visible: false });
59
- }
60
- }
61
- }
62
- onSelectAll() {
63
- for (const col of this.columns) {
64
- if (!this.visibleColumns.has(col.columnId)) {
65
- this.visibilityChange.emit({ columnKey: col.columnId, visible: true });
66
- }
67
- }
68
- }
69
- }
70
- __decorate([
71
- Input({ required: true })
72
- ], BaseColumnChooserComponent.prototype, "columns", null);
73
- __decorate([
74
- Input({ required: true })
75
- ], BaseColumnChooserComponent.prototype, "visibleColumns", null);
76
- __decorate([
77
- Output()
78
- ], BaseColumnChooserComponent.prototype, "visibilityChange", void 0);
@@ -1,281 +0,0 @@
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 { signal, computed, Input } from '@angular/core';
8
- /**
9
- * Abstract base class containing all shared TypeScript logic for ColumnHeaderFilter components.
10
- * Framework-specific UI packages extend this with their templates and style overrides.
11
- *
12
- * Subclasses must:
13
- * 1. Provide a @Component decorator with template and styles
14
- * 2. Implement abstract accessor for headerEl (ViewChild reference)
15
- */
16
- export class BaseColumnHeaderFilterComponent {
17
- constructor() {
18
- // Signal-backed inputs used by computed() — plain @Input properties aren't tracked by computed()
19
- this._filterType = signal('none');
20
- this._selectedValues = signal(undefined);
21
- this._options = signal(undefined);
22
- this._textValue = signal('');
23
- this._selectedUser = signal(undefined);
24
- this._dateValue = signal(undefined);
25
- // Plain inputs (not used in computed() — no signal wrapper needed)
26
- this.isSorted = false;
27
- this.isSortedDescending = false;
28
- this.onSort = undefined;
29
- this.onFilterChange = undefined;
30
- this.isLoadingOptions = false;
31
- this.onTextChange = undefined;
32
- this.onUserChange = undefined;
33
- this.peopleSearch = undefined;
34
- this.onDateChange = undefined;
35
- // Internal state signals
36
- this.isFilterOpen = signal(false);
37
- this.tempTextValue = signal('');
38
- this.searchText = signal('');
39
- this.tempSelected = signal(new Set());
40
- this.peopleSearchText = signal('');
41
- this.peopleSuggestions = signal([]);
42
- this.isPeopleLoading = signal(false);
43
- this.tempDateFrom = signal('');
44
- this.tempDateTo = signal('');
45
- // Popover position
46
- this.popoverTop = signal(0);
47
- this.popoverLeft = signal(0);
48
- this.peopleDebounceTimer = null;
49
- // Computed signals
50
- this.hasActiveFilter = computed(() => {
51
- const ft = this._filterType();
52
- if (ft === 'text')
53
- return !!this._textValue();
54
- if (ft === 'multiSelect')
55
- return (this._selectedValues()?.length ?? 0) > 0;
56
- if (ft === 'people')
57
- return this._selectedUser() != null;
58
- if (ft === 'date')
59
- return this._dateValue() != null;
60
- return false;
61
- });
62
- this.filteredOptions = computed(() => {
63
- const opts = this._options() ?? [];
64
- const search = this.searchText().toLowerCase().trim();
65
- if (!search)
66
- return opts;
67
- return opts.filter((o) => o.toLowerCase().includes(search));
68
- });
69
- }
70
- set filterType(v) { this._filterType.set(v); }
71
- get filterType() { return this._filterType(); }
72
- set selectedValues(v) { this._selectedValues.set(v); }
73
- get selectedValues() { return this._selectedValues(); }
74
- set options(v) { this._options.set(v); }
75
- get options() { return this._options(); }
76
- set textValue(v) { this._textValue.set(v); }
77
- get textValue() { return this._textValue(); }
78
- set selectedUser(v) { this._selectedUser.set(v); }
79
- get selectedUser() { return this._selectedUser(); }
80
- set dateValue(v) { this._dateValue.set(v); }
81
- get dateValue() { return this._dateValue(); }
82
- // Utility methods
83
- asInputValue(event) {
84
- return event.target.value;
85
- }
86
- toggleFilter(event) {
87
- event.stopPropagation();
88
- if (this.isFilterOpen()) {
89
- this.isFilterOpen.set(false);
90
- return;
91
- }
92
- // Initialize temp state from current values
93
- this.tempTextValue.set(this.textValue);
94
- this.tempSelected.set(new Set(this.selectedValues ?? []));
95
- this.searchText.set('');
96
- this.peopleSearchText.set('');
97
- this.peopleSuggestions.set([]);
98
- const dv = this.dateValue;
99
- this.tempDateFrom.set(dv?.from ?? '');
100
- this.tempDateTo.set(dv?.to ?? '');
101
- // Compute popover position
102
- const el = this.getHeaderEl()?.nativeElement;
103
- if (el) {
104
- const rect = el.getBoundingClientRect();
105
- this.popoverTop.set(rect.bottom + 4);
106
- this.popoverLeft.set(rect.left);
107
- }
108
- this.isFilterOpen.set(true);
109
- }
110
- // --- Text filter handlers ---
111
- onTextKeydown(event) {
112
- event.stopPropagation();
113
- if (event.key === 'Enter') {
114
- event.preventDefault();
115
- this.handleTextApply();
116
- }
117
- }
118
- handleTextApply() {
119
- if (this.onTextChange)
120
- this.onTextChange(this.tempTextValue());
121
- this.isFilterOpen.set(false);
122
- }
123
- handleTextClear() {
124
- this.tempTextValue.set('');
125
- if (this.onTextChange)
126
- this.onTextChange('');
127
- this.isFilterOpen.set(false);
128
- }
129
- // --- MultiSelect filter handlers ---
130
- handleCheckboxChange(option, event) {
131
- const checked = event.target.checked;
132
- this.tempSelected.update((s) => {
133
- const next = new Set(s);
134
- if (checked)
135
- next.add(option);
136
- else
137
- next.delete(option);
138
- return next;
139
- });
140
- }
141
- handleSelectAllFiltered() {
142
- this.tempSelected.update((s) => {
143
- const next = new Set(s);
144
- for (const opt of this.filteredOptions())
145
- next.add(opt);
146
- return next;
147
- });
148
- }
149
- handleClearSelection() {
150
- this.tempSelected.set(new Set());
151
- }
152
- handleApplyMultiSelect() {
153
- if (this.onFilterChange)
154
- this.onFilterChange(Array.from(this.tempSelected()));
155
- this.isFilterOpen.set(false);
156
- }
157
- // --- People filter handlers ---
158
- onPeopleSearchInput(event) {
159
- const value = event.target.value;
160
- this.peopleSearchText.set(value);
161
- if (this.peopleDebounceTimer)
162
- clearTimeout(this.peopleDebounceTimer);
163
- const query = value.trim();
164
- if (!query) {
165
- this.peopleSuggestions.set([]);
166
- this.isPeopleLoading.set(false);
167
- return;
168
- }
169
- this.isPeopleLoading.set(true);
170
- this.peopleDebounceTimer = setTimeout(() => {
171
- const fn = this.peopleSearch;
172
- if (!fn)
173
- return;
174
- fn(query)
175
- .then((results) => {
176
- this.peopleSuggestions.set(results);
177
- this.isPeopleLoading.set(false);
178
- })
179
- .catch(() => {
180
- this.peopleSuggestions.set([]);
181
- this.isPeopleLoading.set(false);
182
- });
183
- }, 300);
184
- }
185
- handleUserSelect(user) {
186
- if (this.onUserChange)
187
- this.onUserChange(user);
188
- this.isFilterOpen.set(false);
189
- }
190
- handleClearUser() {
191
- if (this.onUserChange)
192
- this.onUserChange(undefined);
193
- this.isFilterOpen.set(false);
194
- }
195
- // --- Date filter handlers ---
196
- handleDateApply() {
197
- const from = this.tempDateFrom();
198
- const to = this.tempDateTo();
199
- if (this.onDateChange) {
200
- if (!from && !to) {
201
- this.onDateChange(undefined);
202
- }
203
- else {
204
- this.onDateChange({ from: from || undefined, to: to || undefined });
205
- }
206
- }
207
- this.isFilterOpen.set(false);
208
- }
209
- handleDateClear() {
210
- this.tempDateFrom.set('');
211
- this.tempDateTo.set('');
212
- if (this.onDateChange)
213
- this.onDateChange(undefined);
214
- this.isFilterOpen.set(false);
215
- }
216
- /** Clean up debounce timer on destroy. */
217
- ngOnDestroy() {
218
- if (this.peopleDebounceTimer) {
219
- clearTimeout(this.peopleDebounceTimer);
220
- this.peopleDebounceTimer = null;
221
- }
222
- }
223
- // --- Document click handler (for click-outside to close) ---
224
- onDocumentClick(event, selectorName) {
225
- const el = event.target;
226
- if (!el.closest(selectorName) && !el.closest('.ogrid-header-filter__popover')) {
227
- this.isFilterOpen.set(false);
228
- }
229
- }
230
- }
231
- __decorate([
232
- Input({ required: true })
233
- ], BaseColumnHeaderFilterComponent.prototype, "columnKey", void 0);
234
- __decorate([
235
- Input({ required: true })
236
- ], BaseColumnHeaderFilterComponent.prototype, "columnName", void 0);
237
- __decorate([
238
- Input({ required: true })
239
- ], BaseColumnHeaderFilterComponent.prototype, "filterType", null);
240
- __decorate([
241
- Input()
242
- ], BaseColumnHeaderFilterComponent.prototype, "selectedValues", null);
243
- __decorate([
244
- Input()
245
- ], BaseColumnHeaderFilterComponent.prototype, "options", null);
246
- __decorate([
247
- Input()
248
- ], BaseColumnHeaderFilterComponent.prototype, "textValue", null);
249
- __decorate([
250
- Input()
251
- ], BaseColumnHeaderFilterComponent.prototype, "selectedUser", null);
252
- __decorate([
253
- Input()
254
- ], BaseColumnHeaderFilterComponent.prototype, "dateValue", null);
255
- __decorate([
256
- Input()
257
- ], BaseColumnHeaderFilterComponent.prototype, "isSorted", void 0);
258
- __decorate([
259
- Input()
260
- ], BaseColumnHeaderFilterComponent.prototype, "isSortedDescending", void 0);
261
- __decorate([
262
- Input()
263
- ], BaseColumnHeaderFilterComponent.prototype, "onSort", void 0);
264
- __decorate([
265
- Input()
266
- ], BaseColumnHeaderFilterComponent.prototype, "onFilterChange", void 0);
267
- __decorate([
268
- Input()
269
- ], BaseColumnHeaderFilterComponent.prototype, "isLoadingOptions", void 0);
270
- __decorate([
271
- Input()
272
- ], BaseColumnHeaderFilterComponent.prototype, "onTextChange", void 0);
273
- __decorate([
274
- Input()
275
- ], BaseColumnHeaderFilterComponent.prototype, "onUserChange", void 0);
276
- __decorate([
277
- Input()
278
- ], BaseColumnHeaderFilterComponent.prototype, "peopleSearch", void 0);
279
- __decorate([
280
- Input()
281
- ], BaseColumnHeaderFilterComponent.prototype, "onDateChange", void 0);