@alaarab/ogrid-angular 2.6.0 → 2.6.1
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/dist/esm/components/base-column-chooser.component.js +77 -0
- package/dist/esm/components/base-column-header-filter.component.js +267 -0
- package/dist/esm/components/base-column-header-menu.component.js +80 -0
- package/dist/esm/components/base-datagrid-table.component.js +768 -0
- package/dist/esm/components/base-inline-cell-editor.component.js +380 -0
- package/dist/esm/components/base-ogrid.component.js +36 -0
- package/dist/esm/components/base-pagination-controls.component.js +68 -0
- package/dist/esm/components/base-popover-cell-editor.component.js +122 -0
- package/dist/esm/components/empty-state.component.js +68 -0
- package/dist/esm/components/formula-bar.component.js +99 -0
- package/dist/esm/components/formula-ref-overlay.component.js +115 -0
- package/dist/esm/components/grid-context-menu.component.js +197 -0
- package/dist/esm/components/inline-cell-editor-template.js +134 -0
- package/dist/esm/components/marching-ants-overlay.component.js +177 -0
- package/dist/esm/components/ogrid-layout.component.js +302 -0
- package/dist/esm/components/sheet-tabs.component.js +83 -0
- package/dist/esm/components/sidebar.component.js +431 -0
- package/dist/esm/components/status-bar.component.js +92 -0
- package/dist/esm/index.js +39 -819
- package/dist/esm/services/column-reorder.service.js +176 -0
- package/dist/esm/services/datagrid-editing.service.js +59 -0
- package/dist/esm/services/datagrid-interaction.service.js +744 -0
- package/dist/esm/services/datagrid-layout.service.js +157 -0
- package/dist/esm/services/datagrid-state.service.js +636 -0
- package/dist/esm/services/formula-engine.service.js +223 -0
- package/dist/esm/services/ogrid.service.js +1094 -0
- package/dist/esm/services/virtual-scroll.service.js +114 -0
- package/dist/esm/styles/ogrid-theme-vars.js +112 -0
- package/dist/esm/types/columnTypes.js +1 -0
- package/dist/esm/types/dataGridTypes.js +1 -0
- package/dist/esm/types/index.js +1 -0
- package/dist/esm/utils/dataGridViewModel.js +6 -0
- package/dist/esm/utils/debounce.js +68 -0
- package/dist/esm/utils/index.js +8 -0
- package/dist/esm/utils/latestRef.js +41 -0
- package/dist/types/components/base-column-chooser.component.d.ts +3 -0
- package/dist/types/components/base-column-header-filter.component.d.ts +3 -0
- package/dist/types/components/base-column-header-menu.component.d.ts +3 -0
- package/dist/types/components/base-datagrid-table.component.d.ts +4 -19
- package/dist/types/components/base-inline-cell-editor.component.d.ts +7 -0
- package/dist/types/components/base-ogrid.component.d.ts +3 -0
- package/dist/types/components/base-pagination-controls.component.d.ts +3 -0
- package/dist/types/components/base-popover-cell-editor.component.d.ts +3 -0
- package/dist/types/components/empty-state.component.d.ts +3 -0
- package/dist/types/components/formula-bar.component.d.ts +3 -8
- package/dist/types/components/formula-ref-overlay.component.d.ts +3 -6
- package/dist/types/components/grid-context-menu.component.d.ts +3 -0
- package/dist/types/components/inline-cell-editor-template.d.ts +2 -2
- package/dist/types/components/marching-ants-overlay.component.d.ts +3 -0
- package/dist/types/components/ogrid-layout.component.d.ts +3 -0
- package/dist/types/components/sheet-tabs.component.d.ts +3 -8
- package/dist/types/components/sidebar.component.d.ts +3 -0
- package/dist/types/components/status-bar.component.d.ts +3 -0
- package/dist/types/index.d.ts +0 -2
- package/dist/types/services/column-reorder.service.d.ts +3 -0
- package/dist/types/services/datagrid-interaction.service.d.ts +1 -0
- package/dist/types/services/datagrid-state.service.d.ts +5 -0
- package/dist/types/services/formula-engine.service.d.ts +3 -9
- package/dist/types/services/ogrid.service.d.ts +8 -11
- package/dist/types/services/virtual-scroll.service.d.ts +3 -0
- package/dist/types/types/dataGridTypes.d.ts +0 -4
- package/package.json +4 -3
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Directive, signal, computed, Input, Output, EventEmitter } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* Abstract base class containing all shared TypeScript logic for ColumnChooser components.
|
|
5
|
+
* Framework-specific UI packages extend this with their templates and style overrides.
|
|
6
|
+
*
|
|
7
|
+
* Subclasses must:
|
|
8
|
+
* 1. Provide a @Component decorator with template and styles
|
|
9
|
+
* 2. Handle their own click-outside behavior (host binding or effect)
|
|
10
|
+
*/
|
|
11
|
+
export class BaseColumnChooserComponent {
|
|
12
|
+
constructor() {
|
|
13
|
+
this._columns = signal([], ...(ngDevMode ? [{ debugName: "_columns" }] : []));
|
|
14
|
+
this._visibleColumns = signal(new Set(), ...(ngDevMode ? [{ debugName: "_visibleColumns" }] : []));
|
|
15
|
+
this.visibilityChange = new EventEmitter();
|
|
16
|
+
// Dropdown state
|
|
17
|
+
this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
18
|
+
// Computed counts (signal-backed so computed() tracks changes)
|
|
19
|
+
this.visibleCount = computed(() => this._visibleColumns().size, ...(ngDevMode ? [{ debugName: "visibleCount" }] : []));
|
|
20
|
+
this.totalCount = computed(() => this._columns().length, ...(ngDevMode ? [{ debugName: "totalCount" }] : []));
|
|
21
|
+
}
|
|
22
|
+
set columns(v) { this._columns.set(v); }
|
|
23
|
+
get columns() { return this._columns(); }
|
|
24
|
+
set visibleColumns(v) { this._visibleColumns.set(v); }
|
|
25
|
+
get visibleColumns() { return this._visibleColumns(); }
|
|
26
|
+
toggle() {
|
|
27
|
+
this.isOpen.update((v) => !v);
|
|
28
|
+
}
|
|
29
|
+
onCheckboxChange(columnKey, event) {
|
|
30
|
+
const checked = event.target.checked;
|
|
31
|
+
this.visibilityChange.emit({ columnKey, visible: checked });
|
|
32
|
+
}
|
|
33
|
+
onToggle(columnKey, checked) {
|
|
34
|
+
this.visibilityChange.emit({ columnKey, visible: checked });
|
|
35
|
+
}
|
|
36
|
+
selectAll() {
|
|
37
|
+
for (const col of this.columns) {
|
|
38
|
+
if (!this.visibleColumns.has(col.columnId)) {
|
|
39
|
+
this.visibilityChange.emit({ columnKey: col.columnId, visible: true });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
clearAll() {
|
|
44
|
+
for (const col of this.columns) {
|
|
45
|
+
if (this.visibleColumns.has(col.columnId)) {
|
|
46
|
+
this.visibilityChange.emit({ columnKey: col.columnId, visible: false });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
onClearAll() {
|
|
51
|
+
for (const col of this.columns) {
|
|
52
|
+
if (col.required !== true && this.visibleColumns.has(col.columnId)) {
|
|
53
|
+
this.visibilityChange.emit({ columnKey: col.columnId, visible: false });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
onSelectAll() {
|
|
58
|
+
for (const col of this.columns) {
|
|
59
|
+
if (!this.visibleColumns.has(col.columnId)) {
|
|
60
|
+
this.visibilityChange.emit({ columnKey: col.columnId, visible: true });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
static { this.ɵfac = function BaseColumnChooserComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || BaseColumnChooserComponent)(); }; }
|
|
65
|
+
static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: BaseColumnChooserComponent, inputs: { columns: "columns", visibleColumns: "visibleColumns" }, outputs: { visibilityChange: "visibilityChange" } }); }
|
|
66
|
+
}
|
|
67
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(BaseColumnChooserComponent, [{
|
|
68
|
+
type: Directive
|
|
69
|
+
}], null, { columns: [{
|
|
70
|
+
type: Input,
|
|
71
|
+
args: [{ required: true }]
|
|
72
|
+
}], visibleColumns: [{
|
|
73
|
+
type: Input,
|
|
74
|
+
args: [{ required: true }]
|
|
75
|
+
}], visibilityChange: [{
|
|
76
|
+
type: Output
|
|
77
|
+
}] }); })();
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { Directive, signal, computed, Input } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* Abstract base class containing all shared TypeScript logic for ColumnHeaderFilter components.
|
|
5
|
+
* Framework-specific UI packages extend this with their templates and style overrides.
|
|
6
|
+
*
|
|
7
|
+
* Subclasses must:
|
|
8
|
+
* 1. Provide a @Component decorator with template and styles
|
|
9
|
+
* 2. Implement abstract accessor for headerEl (ViewChild reference)
|
|
10
|
+
*/
|
|
11
|
+
export class BaseColumnHeaderFilterComponent {
|
|
12
|
+
constructor() {
|
|
13
|
+
// Signal-backed inputs used by computed() - plain @Input properties aren't tracked by computed()
|
|
14
|
+
this._filterType = signal('none', ...(ngDevMode ? [{ debugName: "_filterType" }] : []));
|
|
15
|
+
this._selectedValues = signal(undefined, ...(ngDevMode ? [{ debugName: "_selectedValues" }] : []));
|
|
16
|
+
this._options = signal(undefined, ...(ngDevMode ? [{ debugName: "_options" }] : []));
|
|
17
|
+
this._textValue = signal('', ...(ngDevMode ? [{ debugName: "_textValue" }] : []));
|
|
18
|
+
this._selectedUser = signal(undefined, ...(ngDevMode ? [{ debugName: "_selectedUser" }] : []));
|
|
19
|
+
this._dateValue = signal(undefined, ...(ngDevMode ? [{ debugName: "_dateValue" }] : []));
|
|
20
|
+
// Plain inputs (not used in computed() - no signal wrapper needed)
|
|
21
|
+
this.isSorted = false;
|
|
22
|
+
this.isSortedDescending = false;
|
|
23
|
+
this.onSort = undefined;
|
|
24
|
+
this.onFilterChange = undefined;
|
|
25
|
+
this.isLoadingOptions = false;
|
|
26
|
+
this.onTextChange = undefined;
|
|
27
|
+
this.onUserChange = undefined;
|
|
28
|
+
this.peopleSearch = undefined;
|
|
29
|
+
this.onDateChange = undefined;
|
|
30
|
+
// Internal state signals
|
|
31
|
+
this.isFilterOpen = signal(false, ...(ngDevMode ? [{ debugName: "isFilterOpen" }] : []));
|
|
32
|
+
this.tempTextValue = signal('', ...(ngDevMode ? [{ debugName: "tempTextValue" }] : []));
|
|
33
|
+
this.searchText = signal('', ...(ngDevMode ? [{ debugName: "searchText" }] : []));
|
|
34
|
+
this.tempSelected = signal(new Set(), ...(ngDevMode ? [{ debugName: "tempSelected" }] : []));
|
|
35
|
+
this.peopleSearchText = signal('', ...(ngDevMode ? [{ debugName: "peopleSearchText" }] : []));
|
|
36
|
+
this.peopleSuggestions = signal([], ...(ngDevMode ? [{ debugName: "peopleSuggestions" }] : []));
|
|
37
|
+
this.isPeopleLoading = signal(false, ...(ngDevMode ? [{ debugName: "isPeopleLoading" }] : []));
|
|
38
|
+
this.tempDateFrom = signal('', ...(ngDevMode ? [{ debugName: "tempDateFrom" }] : []));
|
|
39
|
+
this.tempDateTo = signal('', ...(ngDevMode ? [{ debugName: "tempDateTo" }] : []));
|
|
40
|
+
// Popover position
|
|
41
|
+
this.popoverTop = signal(0, ...(ngDevMode ? [{ debugName: "popoverTop" }] : []));
|
|
42
|
+
this.popoverLeft = signal(0, ...(ngDevMode ? [{ debugName: "popoverLeft" }] : []));
|
|
43
|
+
this.peopleDebounceTimer = null;
|
|
44
|
+
// Computed signals
|
|
45
|
+
this.hasActiveFilter = computed(() => {
|
|
46
|
+
const ft = this._filterType();
|
|
47
|
+
if (ft === 'text')
|
|
48
|
+
return !!this._textValue();
|
|
49
|
+
if (ft === 'multiSelect')
|
|
50
|
+
return (this._selectedValues()?.length ?? 0) > 0;
|
|
51
|
+
if (ft === 'people')
|
|
52
|
+
return this._selectedUser() != null;
|
|
53
|
+
if (ft === 'date')
|
|
54
|
+
return this._dateValue() != null;
|
|
55
|
+
return false;
|
|
56
|
+
}, ...(ngDevMode ? [{ debugName: "hasActiveFilter" }] : []));
|
|
57
|
+
this.filteredOptions = computed(() => {
|
|
58
|
+
const opts = this._options() ?? [];
|
|
59
|
+
const search = this.searchText().toLowerCase().trim();
|
|
60
|
+
if (!search)
|
|
61
|
+
return opts;
|
|
62
|
+
return opts.filter((o) => o.toLowerCase().includes(search));
|
|
63
|
+
}, ...(ngDevMode ? [{ debugName: "filteredOptions" }] : []));
|
|
64
|
+
}
|
|
65
|
+
set filterType(v) { this._filterType.set(v); }
|
|
66
|
+
get filterType() { return this._filterType(); }
|
|
67
|
+
set selectedValues(v) { this._selectedValues.set(v); }
|
|
68
|
+
get selectedValues() { return this._selectedValues(); }
|
|
69
|
+
set options(v) { this._options.set(v); }
|
|
70
|
+
get options() { return this._options(); }
|
|
71
|
+
set textValue(v) { this._textValue.set(v); }
|
|
72
|
+
get textValue() { return this._textValue(); }
|
|
73
|
+
set selectedUser(v) { this._selectedUser.set(v); }
|
|
74
|
+
get selectedUser() { return this._selectedUser(); }
|
|
75
|
+
set dateValue(v) { this._dateValue.set(v); }
|
|
76
|
+
get dateValue() { return this._dateValue(); }
|
|
77
|
+
// Utility methods
|
|
78
|
+
asInputValue(event) {
|
|
79
|
+
return event.target.value;
|
|
80
|
+
}
|
|
81
|
+
toggleFilter(event) {
|
|
82
|
+
event.stopPropagation();
|
|
83
|
+
if (this.isFilterOpen()) {
|
|
84
|
+
this.isFilterOpen.set(false);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// Initialize temp state from current values
|
|
88
|
+
this.tempTextValue.set(this.textValue);
|
|
89
|
+
this.tempSelected.set(new Set(this.selectedValues ?? []));
|
|
90
|
+
this.searchText.set('');
|
|
91
|
+
this.peopleSearchText.set('');
|
|
92
|
+
this.peopleSuggestions.set([]);
|
|
93
|
+
const dv = this.dateValue;
|
|
94
|
+
this.tempDateFrom.set(dv?.from ?? '');
|
|
95
|
+
this.tempDateTo.set(dv?.to ?? '');
|
|
96
|
+
// Compute popover position
|
|
97
|
+
const el = this.getHeaderEl()?.nativeElement;
|
|
98
|
+
if (el) {
|
|
99
|
+
const rect = el.getBoundingClientRect();
|
|
100
|
+
this.popoverTop.set(rect.bottom + 4);
|
|
101
|
+
this.popoverLeft.set(rect.left);
|
|
102
|
+
}
|
|
103
|
+
this.isFilterOpen.set(true);
|
|
104
|
+
}
|
|
105
|
+
// --- Text filter handlers ---
|
|
106
|
+
onTextKeydown(event) {
|
|
107
|
+
event.stopPropagation();
|
|
108
|
+
if (event.key === 'Enter') {
|
|
109
|
+
event.preventDefault();
|
|
110
|
+
this.handleTextApply();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
handleTextApply() {
|
|
114
|
+
if (this.onTextChange)
|
|
115
|
+
this.onTextChange(this.tempTextValue());
|
|
116
|
+
this.isFilterOpen.set(false);
|
|
117
|
+
}
|
|
118
|
+
handleTextClear() {
|
|
119
|
+
this.tempTextValue.set('');
|
|
120
|
+
if (this.onTextChange)
|
|
121
|
+
this.onTextChange('');
|
|
122
|
+
this.isFilterOpen.set(false);
|
|
123
|
+
}
|
|
124
|
+
// --- MultiSelect filter handlers ---
|
|
125
|
+
handleCheckboxChange(option, event) {
|
|
126
|
+
const checked = event.target.checked;
|
|
127
|
+
this.tempSelected.update((s) => {
|
|
128
|
+
const next = new Set(s);
|
|
129
|
+
if (checked)
|
|
130
|
+
next.add(option);
|
|
131
|
+
else
|
|
132
|
+
next.delete(option);
|
|
133
|
+
return next;
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
handleSelectAllFiltered() {
|
|
137
|
+
this.tempSelected.update((s) => {
|
|
138
|
+
const next = new Set(s);
|
|
139
|
+
for (const opt of this.filteredOptions())
|
|
140
|
+
next.add(opt);
|
|
141
|
+
return next;
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
handleClearSelection() {
|
|
145
|
+
this.tempSelected.set(new Set());
|
|
146
|
+
}
|
|
147
|
+
handleApplyMultiSelect() {
|
|
148
|
+
if (this.onFilterChange)
|
|
149
|
+
this.onFilterChange(Array.from(this.tempSelected()));
|
|
150
|
+
this.isFilterOpen.set(false);
|
|
151
|
+
}
|
|
152
|
+
// --- People filter handlers ---
|
|
153
|
+
onPeopleSearchInput(event) {
|
|
154
|
+
const value = event.target.value;
|
|
155
|
+
this.peopleSearchText.set(value);
|
|
156
|
+
if (this.peopleDebounceTimer)
|
|
157
|
+
clearTimeout(this.peopleDebounceTimer);
|
|
158
|
+
const query = value.trim();
|
|
159
|
+
if (!query) {
|
|
160
|
+
this.peopleSuggestions.set([]);
|
|
161
|
+
this.isPeopleLoading.set(false);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
this.isPeopleLoading.set(true);
|
|
165
|
+
this.peopleDebounceTimer = setTimeout(() => {
|
|
166
|
+
const fn = this.peopleSearch;
|
|
167
|
+
if (!fn)
|
|
168
|
+
return;
|
|
169
|
+
fn(query)
|
|
170
|
+
.then((results) => {
|
|
171
|
+
this.peopleSuggestions.set(results);
|
|
172
|
+
this.isPeopleLoading.set(false);
|
|
173
|
+
})
|
|
174
|
+
.catch(() => {
|
|
175
|
+
this.peopleSuggestions.set([]);
|
|
176
|
+
this.isPeopleLoading.set(false);
|
|
177
|
+
});
|
|
178
|
+
}, 300);
|
|
179
|
+
}
|
|
180
|
+
handleUserSelect(user) {
|
|
181
|
+
if (this.onUserChange)
|
|
182
|
+
this.onUserChange(user);
|
|
183
|
+
this.isFilterOpen.set(false);
|
|
184
|
+
}
|
|
185
|
+
handleClearUser() {
|
|
186
|
+
if (this.onUserChange)
|
|
187
|
+
this.onUserChange(undefined);
|
|
188
|
+
this.isFilterOpen.set(false);
|
|
189
|
+
}
|
|
190
|
+
// --- Date filter handlers ---
|
|
191
|
+
handleDateApply() {
|
|
192
|
+
const from = this.tempDateFrom();
|
|
193
|
+
const to = this.tempDateTo();
|
|
194
|
+
if (this.onDateChange) {
|
|
195
|
+
if (!from && !to) {
|
|
196
|
+
this.onDateChange(undefined);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
this.onDateChange({ from: from || undefined, to: to || undefined });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
this.isFilterOpen.set(false);
|
|
203
|
+
}
|
|
204
|
+
handleDateClear() {
|
|
205
|
+
this.tempDateFrom.set('');
|
|
206
|
+
this.tempDateTo.set('');
|
|
207
|
+
if (this.onDateChange)
|
|
208
|
+
this.onDateChange(undefined);
|
|
209
|
+
this.isFilterOpen.set(false);
|
|
210
|
+
}
|
|
211
|
+
/** Clean up debounce timer on destroy. */
|
|
212
|
+
ngOnDestroy() {
|
|
213
|
+
if (this.peopleDebounceTimer) {
|
|
214
|
+
clearTimeout(this.peopleDebounceTimer);
|
|
215
|
+
this.peopleDebounceTimer = null;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// --- Document click handler (for click-outside to close) ---
|
|
219
|
+
onDocumentClick(event, selectorName) {
|
|
220
|
+
const el = event.target;
|
|
221
|
+
if (!el.closest(selectorName) && !el.closest('.ogrid-header-filter__popover')) {
|
|
222
|
+
this.isFilterOpen.set(false);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
static { this.ɵfac = function BaseColumnHeaderFilterComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || BaseColumnHeaderFilterComponent)(); }; }
|
|
226
|
+
static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: BaseColumnHeaderFilterComponent, inputs: { columnKey: "columnKey", columnName: "columnName", filterType: "filterType", selectedValues: "selectedValues", options: "options", textValue: "textValue", selectedUser: "selectedUser", dateValue: "dateValue", isSorted: "isSorted", isSortedDescending: "isSortedDescending", onSort: "onSort", onFilterChange: "onFilterChange", isLoadingOptions: "isLoadingOptions", onTextChange: "onTextChange", onUserChange: "onUserChange", peopleSearch: "peopleSearch", onDateChange: "onDateChange" } }); }
|
|
227
|
+
}
|
|
228
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(BaseColumnHeaderFilterComponent, [{
|
|
229
|
+
type: Directive
|
|
230
|
+
}], null, { columnKey: [{
|
|
231
|
+
type: Input,
|
|
232
|
+
args: [{ required: true }]
|
|
233
|
+
}], columnName: [{
|
|
234
|
+
type: Input,
|
|
235
|
+
args: [{ required: true }]
|
|
236
|
+
}], filterType: [{
|
|
237
|
+
type: Input,
|
|
238
|
+
args: [{ required: true }]
|
|
239
|
+
}], selectedValues: [{
|
|
240
|
+
type: Input
|
|
241
|
+
}], options: [{
|
|
242
|
+
type: Input
|
|
243
|
+
}], textValue: [{
|
|
244
|
+
type: Input
|
|
245
|
+
}], selectedUser: [{
|
|
246
|
+
type: Input
|
|
247
|
+
}], dateValue: [{
|
|
248
|
+
type: Input
|
|
249
|
+
}], isSorted: [{
|
|
250
|
+
type: Input
|
|
251
|
+
}], isSortedDescending: [{
|
|
252
|
+
type: Input
|
|
253
|
+
}], onSort: [{
|
|
254
|
+
type: Input
|
|
255
|
+
}], onFilterChange: [{
|
|
256
|
+
type: Input
|
|
257
|
+
}], isLoadingOptions: [{
|
|
258
|
+
type: Input
|
|
259
|
+
}], onTextChange: [{
|
|
260
|
+
type: Input
|
|
261
|
+
}], onUserChange: [{
|
|
262
|
+
type: Input
|
|
263
|
+
}], peopleSearch: [{
|
|
264
|
+
type: Input
|
|
265
|
+
}], onDateChange: [{
|
|
266
|
+
type: Input
|
|
267
|
+
}] }); })();
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Directive, signal, computed, Input } from '@angular/core';
|
|
2
|
+
import { getColumnHeaderMenuItems, } from '@alaarab/ogrid-core';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Abstract base class containing all shared TypeScript logic for ColumnHeaderMenu components.
|
|
6
|
+
* Framework-specific UI packages extend this with their templates and style overrides.
|
|
7
|
+
*
|
|
8
|
+
* Uses signal-backed @Input setters so that computed() tracks input changes reactively
|
|
9
|
+
* (plain @Input properties are not reactive in Angular signals).
|
|
10
|
+
*
|
|
11
|
+
* Subclasses must:
|
|
12
|
+
* 1. Provide a @Component decorator with template and styles
|
|
13
|
+
* 2. Implement their own menu open/close mechanism (mat-menu, p-menu, or native dropdown)
|
|
14
|
+
*/
|
|
15
|
+
export class BaseColumnHeaderMenuComponent {
|
|
16
|
+
constructor() {
|
|
17
|
+
// Signal-backed inputs so computed() tracks changes reactively
|
|
18
|
+
this._canPinLeft = signal(true, ...(ngDevMode ? [{ debugName: "_canPinLeft" }] : []));
|
|
19
|
+
this._canPinRight = signal(true, ...(ngDevMode ? [{ debugName: "_canPinRight" }] : []));
|
|
20
|
+
this._canUnpin = signal(false, ...(ngDevMode ? [{ debugName: "_canUnpin" }] : []));
|
|
21
|
+
this._currentSort = signal(null, ...(ngDevMode ? [{ debugName: "_currentSort" }] : []));
|
|
22
|
+
this._isSortable = signal(true, ...(ngDevMode ? [{ debugName: "_isSortable" }] : []));
|
|
23
|
+
this._isResizable = signal(true, ...(ngDevMode ? [{ debugName: "_isResizable" }] : []));
|
|
24
|
+
this.handlers = {};
|
|
25
|
+
this.menuItems = computed(() => getColumnHeaderMenuItems({
|
|
26
|
+
canPinLeft: this._canPinLeft(),
|
|
27
|
+
canPinRight: this._canPinRight(),
|
|
28
|
+
canUnpin: this._canUnpin(),
|
|
29
|
+
currentSort: this._currentSort(),
|
|
30
|
+
isSortable: this._isSortable(),
|
|
31
|
+
isResizable: this._isResizable(),
|
|
32
|
+
}), ...(ngDevMode ? [{ debugName: "menuItems" }] : []));
|
|
33
|
+
}
|
|
34
|
+
set canPinLeft(v) { this._canPinLeft.set(v); }
|
|
35
|
+
set canPinRight(v) { this._canPinRight.set(v); }
|
|
36
|
+
set canUnpin(v) { this._canUnpin.set(v); }
|
|
37
|
+
set currentSort(v) { this._currentSort.set(v); }
|
|
38
|
+
set isSortable(v) { this._isSortable.set(v); }
|
|
39
|
+
set isResizable(v) { this._isResizable.set(v); }
|
|
40
|
+
handleMenuItemClick(itemId) {
|
|
41
|
+
const h = this.handlers;
|
|
42
|
+
const actionMap = {
|
|
43
|
+
pinLeft: h.onPinLeft,
|
|
44
|
+
pinRight: h.onPinRight,
|
|
45
|
+
unpin: h.onUnpin,
|
|
46
|
+
sortAsc: h.onSortAsc,
|
|
47
|
+
sortDesc: h.onSortDesc,
|
|
48
|
+
clearSort: h.onClearSort,
|
|
49
|
+
autosizeThis: h.onAutosizeThis,
|
|
50
|
+
autosizeAll: h.onAutosizeAll,
|
|
51
|
+
};
|
|
52
|
+
const action = actionMap[itemId];
|
|
53
|
+
if (action) {
|
|
54
|
+
action();
|
|
55
|
+
h.onClose?.();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
static { this.ɵfac = function BaseColumnHeaderMenuComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || BaseColumnHeaderMenuComponent)(); }; }
|
|
59
|
+
static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: BaseColumnHeaderMenuComponent, inputs: { columnId: "columnId", canPinLeft: "canPinLeft", canPinRight: "canPinRight", canUnpin: "canUnpin", currentSort: "currentSort", isSortable: "isSortable", isResizable: "isResizable", handlers: "handlers" } }); }
|
|
60
|
+
}
|
|
61
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(BaseColumnHeaderMenuComponent, [{
|
|
62
|
+
type: Directive
|
|
63
|
+
}], null, { columnId: [{
|
|
64
|
+
type: Input,
|
|
65
|
+
args: [{ required: true }]
|
|
66
|
+
}], canPinLeft: [{
|
|
67
|
+
type: Input
|
|
68
|
+
}], canPinRight: [{
|
|
69
|
+
type: Input
|
|
70
|
+
}], canUnpin: [{
|
|
71
|
+
type: Input
|
|
72
|
+
}], currentSort: [{
|
|
73
|
+
type: Input
|
|
74
|
+
}], isSortable: [{
|
|
75
|
+
type: Input
|
|
76
|
+
}], isResizable: [{
|
|
77
|
+
type: Input
|
|
78
|
+
}], handlers: [{
|
|
79
|
+
type: Input
|
|
80
|
+
}] }); })();
|