@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.
- package/dist/esm/index.js +4606 -30
- package/dist/types/components/base-datagrid-table.component.d.ts +8 -8
- package/package.json +4 -4
- package/dist/esm/components/base-column-chooser.component.js +0 -78
- package/dist/esm/components/base-column-header-filter.component.js +0 -281
- package/dist/esm/components/base-datagrid-table.component.js +0 -648
- package/dist/esm/components/base-inline-cell-editor.component.js +0 -253
- package/dist/esm/components/base-ogrid.component.js +0 -36
- package/dist/esm/components/base-pagination-controls.component.js +0 -72
- package/dist/esm/components/base-popover-cell-editor.component.js +0 -114
- package/dist/esm/components/empty-state.component.js +0 -58
- package/dist/esm/components/grid-context-menu.component.js +0 -153
- package/dist/esm/components/inline-cell-editor-template.js +0 -107
- package/dist/esm/components/marching-ants-overlay.component.js +0 -164
- package/dist/esm/components/ogrid-layout.component.js +0 -188
- package/dist/esm/components/sidebar.component.js +0 -274
- package/dist/esm/components/status-bar.component.js +0 -71
- package/dist/esm/services/column-reorder.service.js +0 -180
- package/dist/esm/services/datagrid-editing.service.js +0 -52
- package/dist/esm/services/datagrid-interaction.service.js +0 -667
- package/dist/esm/services/datagrid-layout.service.js +0 -151
- package/dist/esm/services/datagrid-state.service.js +0 -591
- package/dist/esm/services/ogrid.service.js +0 -746
- package/dist/esm/services/virtual-scroll.service.js +0 -91
- package/dist/esm/styles/ogrid-theme-vars.js +0 -53
- package/dist/esm/types/columnTypes.js +0 -1
- package/dist/esm/types/dataGridTypes.js +0 -1
- package/dist/esm/types/index.js +0 -1
- package/dist/esm/utils/dataGridViewModel.js +0 -6
- package/dist/esm/utils/debounce.js +0 -68
- package/dist/esm/utils/index.js +0 -8
- package/dist/esm/utils/latestRef.js +0 -41
|
@@ -1,253 +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 { Input, Output, EventEmitter, signal, computed, ViewChild } from '@angular/core';
|
|
8
|
-
/**
|
|
9
|
-
* Abstract base class for Angular inline cell editors.
|
|
10
|
-
* Contains all shared signals, lifecycle hooks, keyboard handlers,
|
|
11
|
-
* dropdown positioning, and display logic.
|
|
12
|
-
*
|
|
13
|
-
* Subclasses only need a @Component decorator with selector + template.
|
|
14
|
-
*/
|
|
15
|
-
export class BaseInlineCellEditorComponent {
|
|
16
|
-
constructor() {
|
|
17
|
-
this.commit = new EventEmitter();
|
|
18
|
-
this.cancel = new EventEmitter();
|
|
19
|
-
this.localValue = signal('');
|
|
20
|
-
this.highlightedIndex = signal(0);
|
|
21
|
-
this.selectOptions = signal([]);
|
|
22
|
-
this.searchText = signal('');
|
|
23
|
-
this.filteredOptions = computed(() => {
|
|
24
|
-
const options = this.selectOptions();
|
|
25
|
-
const search = this.searchText().trim().toLowerCase();
|
|
26
|
-
if (!search)
|
|
27
|
-
return options;
|
|
28
|
-
return options.filter((v) => this.getDisplayText(v).toLowerCase().includes(search));
|
|
29
|
-
});
|
|
30
|
-
this._initialized = false;
|
|
31
|
-
}
|
|
32
|
-
ngOnInit() {
|
|
33
|
-
this._initialized = true;
|
|
34
|
-
this.syncFromInputs();
|
|
35
|
-
}
|
|
36
|
-
ngOnChanges() {
|
|
37
|
-
if (this._initialized) {
|
|
38
|
-
this.syncFromInputs();
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
syncFromInputs() {
|
|
42
|
-
const v = this.value;
|
|
43
|
-
this.localValue.set(v != null ? String(v) : '');
|
|
44
|
-
const col = this.column;
|
|
45
|
-
if (col?.cellEditorParams?.values) {
|
|
46
|
-
const vals = col.cellEditorParams.values;
|
|
47
|
-
this.selectOptions.set(vals);
|
|
48
|
-
const initialIdx = vals.findIndex((opt) => String(opt) === String(v));
|
|
49
|
-
this.highlightedIndex.set(Math.max(initialIdx, 0));
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
ngAfterViewInit() {
|
|
53
|
-
setTimeout(() => {
|
|
54
|
-
const richSelectInput = this.richSelectInput?.nativeElement;
|
|
55
|
-
if (richSelectInput) {
|
|
56
|
-
richSelectInput.focus();
|
|
57
|
-
richSelectInput.select();
|
|
58
|
-
this.positionFixedDropdown(this.richSelectWrapper, this.richSelectDropdown);
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
const selectWrap = this.selectWrapper?.nativeElement;
|
|
62
|
-
if (selectWrap) {
|
|
63
|
-
selectWrap.focus();
|
|
64
|
-
this.positionFixedDropdown(this.selectWrapper, this.selectDropdown);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
const el = this.inputEl?.nativeElement;
|
|
68
|
-
if (el) {
|
|
69
|
-
el.focus();
|
|
70
|
-
if (el instanceof HTMLInputElement && el.type === 'text') {
|
|
71
|
-
el.select();
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
commitValue(value) {
|
|
77
|
-
this.commit.emit(value);
|
|
78
|
-
}
|
|
79
|
-
onTextKeyDown(e) {
|
|
80
|
-
if (e.key === 'Enter') {
|
|
81
|
-
e.preventDefault();
|
|
82
|
-
this.commitValue(this.localValue());
|
|
83
|
-
}
|
|
84
|
-
else if (e.key === 'Escape') {
|
|
85
|
-
e.preventDefault();
|
|
86
|
-
this.cancel.emit();
|
|
87
|
-
}
|
|
88
|
-
else if (e.key === 'Tab') {
|
|
89
|
-
e.preventDefault();
|
|
90
|
-
this.commitValue(this.localValue());
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
getDisplayText(value) {
|
|
94
|
-
const formatValue = this.column?.cellEditorParams?.formatValue;
|
|
95
|
-
if (formatValue)
|
|
96
|
-
return formatValue(value);
|
|
97
|
-
return value != null ? String(value) : '';
|
|
98
|
-
}
|
|
99
|
-
onCustomSelectKeyDown(e) {
|
|
100
|
-
const options = this.selectOptions();
|
|
101
|
-
switch (e.key) {
|
|
102
|
-
case 'ArrowDown':
|
|
103
|
-
e.preventDefault();
|
|
104
|
-
this.highlightedIndex.set(Math.min(this.highlightedIndex() + 1, options.length - 1));
|
|
105
|
-
this.scrollOptionIntoView(this.selectDropdown);
|
|
106
|
-
break;
|
|
107
|
-
case 'ArrowUp':
|
|
108
|
-
e.preventDefault();
|
|
109
|
-
this.highlightedIndex.set(Math.max(this.highlightedIndex() - 1, 0));
|
|
110
|
-
this.scrollOptionIntoView(this.selectDropdown);
|
|
111
|
-
break;
|
|
112
|
-
case 'Enter':
|
|
113
|
-
e.preventDefault();
|
|
114
|
-
e.stopPropagation();
|
|
115
|
-
if (options.length > 0 && this.highlightedIndex() < options.length) {
|
|
116
|
-
this.commitValue(options[this.highlightedIndex()]);
|
|
117
|
-
}
|
|
118
|
-
break;
|
|
119
|
-
case 'Tab':
|
|
120
|
-
e.preventDefault();
|
|
121
|
-
if (options.length > 0 && this.highlightedIndex() < options.length) {
|
|
122
|
-
this.commitValue(options[this.highlightedIndex()]);
|
|
123
|
-
}
|
|
124
|
-
break;
|
|
125
|
-
case 'Escape':
|
|
126
|
-
e.preventDefault();
|
|
127
|
-
e.stopPropagation();
|
|
128
|
-
this.cancel.emit();
|
|
129
|
-
break;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
onRichSelectSearch(text) {
|
|
133
|
-
this.searchText.set(text);
|
|
134
|
-
this.highlightedIndex.set(0);
|
|
135
|
-
}
|
|
136
|
-
onRichSelectKeyDown(e) {
|
|
137
|
-
const options = this.filteredOptions();
|
|
138
|
-
switch (e.key) {
|
|
139
|
-
case 'ArrowDown':
|
|
140
|
-
e.preventDefault();
|
|
141
|
-
this.highlightedIndex.set(Math.min(this.highlightedIndex() + 1, options.length - 1));
|
|
142
|
-
this.scrollOptionIntoView(this.richSelectDropdown);
|
|
143
|
-
break;
|
|
144
|
-
case 'ArrowUp':
|
|
145
|
-
e.preventDefault();
|
|
146
|
-
this.highlightedIndex.set(Math.max(this.highlightedIndex() - 1, 0));
|
|
147
|
-
this.scrollOptionIntoView(this.richSelectDropdown);
|
|
148
|
-
break;
|
|
149
|
-
case 'Enter':
|
|
150
|
-
e.preventDefault();
|
|
151
|
-
e.stopPropagation();
|
|
152
|
-
if (options.length > 0 && this.highlightedIndex() < options.length) {
|
|
153
|
-
this.commitValue(options[this.highlightedIndex()]);
|
|
154
|
-
}
|
|
155
|
-
break;
|
|
156
|
-
case 'Escape':
|
|
157
|
-
e.preventDefault();
|
|
158
|
-
e.stopPropagation();
|
|
159
|
-
this.cancel.emit();
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
onCheckboxKeyDown(e) {
|
|
164
|
-
if (e.key === 'Escape') {
|
|
165
|
-
e.preventDefault();
|
|
166
|
-
this.cancel.emit();
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
onTextBlur() {
|
|
170
|
-
this.commitValue(this.localValue());
|
|
171
|
-
}
|
|
172
|
-
getInputStyle() {
|
|
173
|
-
const baseStyle = 'width:100%;box-sizing:border-box;padding:6px 10px;border:none;outline:none;font:inherit;background:transparent;color:inherit;';
|
|
174
|
-
const col = this.column;
|
|
175
|
-
if (col.type === 'numeric') {
|
|
176
|
-
return baseStyle + 'text-align:right;';
|
|
177
|
-
}
|
|
178
|
-
return baseStyle;
|
|
179
|
-
}
|
|
180
|
-
/** Position a dropdown using fixed positioning to escape overflow clipping. */
|
|
181
|
-
positionFixedDropdown(wrapperRef, dropdownRef) {
|
|
182
|
-
const wrapper = wrapperRef?.nativeElement;
|
|
183
|
-
const dropdown = dropdownRef?.nativeElement;
|
|
184
|
-
if (!wrapper || !dropdown)
|
|
185
|
-
return;
|
|
186
|
-
const rect = wrapper.getBoundingClientRect();
|
|
187
|
-
const maxH = 200;
|
|
188
|
-
const spaceBelow = window.innerHeight - rect.bottom;
|
|
189
|
-
const flipUp = spaceBelow < maxH && rect.top > spaceBelow;
|
|
190
|
-
dropdown.style.position = 'fixed';
|
|
191
|
-
dropdown.style.left = `${rect.left}px`;
|
|
192
|
-
dropdown.style.width = `${rect.width}px`;
|
|
193
|
-
dropdown.style.maxHeight = `${maxH}px`;
|
|
194
|
-
dropdown.style.zIndex = '9999';
|
|
195
|
-
dropdown.style.right = 'auto';
|
|
196
|
-
if (flipUp) {
|
|
197
|
-
dropdown.style.top = 'auto';
|
|
198
|
-
dropdown.style.bottom = `${window.innerHeight - rect.top}px`;
|
|
199
|
-
}
|
|
200
|
-
else {
|
|
201
|
-
dropdown.style.top = `${rect.bottom}px`;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
/** Scroll the highlighted option into view within a dropdown element. */
|
|
205
|
-
scrollOptionIntoView(dropdownRef) {
|
|
206
|
-
setTimeout(() => {
|
|
207
|
-
const dropdown = dropdownRef?.nativeElement;
|
|
208
|
-
if (!dropdown)
|
|
209
|
-
return;
|
|
210
|
-
const highlighted = dropdown.children[this.highlightedIndex()];
|
|
211
|
-
highlighted?.scrollIntoView({ block: 'nearest' });
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
__decorate([
|
|
216
|
-
Input({ required: true })
|
|
217
|
-
], BaseInlineCellEditorComponent.prototype, "value", void 0);
|
|
218
|
-
__decorate([
|
|
219
|
-
Input({ required: true })
|
|
220
|
-
], BaseInlineCellEditorComponent.prototype, "item", void 0);
|
|
221
|
-
__decorate([
|
|
222
|
-
Input({ required: true })
|
|
223
|
-
], BaseInlineCellEditorComponent.prototype, "column", void 0);
|
|
224
|
-
__decorate([
|
|
225
|
-
Input({ required: true })
|
|
226
|
-
], BaseInlineCellEditorComponent.prototype, "rowIndex", void 0);
|
|
227
|
-
__decorate([
|
|
228
|
-
Input({ required: true })
|
|
229
|
-
], BaseInlineCellEditorComponent.prototype, "editorType", void 0);
|
|
230
|
-
__decorate([
|
|
231
|
-
Output()
|
|
232
|
-
], BaseInlineCellEditorComponent.prototype, "commit", void 0);
|
|
233
|
-
__decorate([
|
|
234
|
-
Output()
|
|
235
|
-
], BaseInlineCellEditorComponent.prototype, "cancel", void 0);
|
|
236
|
-
__decorate([
|
|
237
|
-
ViewChild('inputEl')
|
|
238
|
-
], BaseInlineCellEditorComponent.prototype, "inputEl", void 0);
|
|
239
|
-
__decorate([
|
|
240
|
-
ViewChild('selectWrapper')
|
|
241
|
-
], BaseInlineCellEditorComponent.prototype, "selectWrapper", void 0);
|
|
242
|
-
__decorate([
|
|
243
|
-
ViewChild('selectDropdown')
|
|
244
|
-
], BaseInlineCellEditorComponent.prototype, "selectDropdown", void 0);
|
|
245
|
-
__decorate([
|
|
246
|
-
ViewChild('richSelectWrapper')
|
|
247
|
-
], BaseInlineCellEditorComponent.prototype, "richSelectWrapper", void 0);
|
|
248
|
-
__decorate([
|
|
249
|
-
ViewChild('richSelectInput')
|
|
250
|
-
], BaseInlineCellEditorComponent.prototype, "richSelectInput", void 0);
|
|
251
|
-
__decorate([
|
|
252
|
-
ViewChild('richSelectDropdown')
|
|
253
|
-
], BaseInlineCellEditorComponent.prototype, "richSelectDropdown", void 0);
|
|
@@ -1,36 +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
|
-
/**
|
|
8
|
-
* Base class for OGrid top-level components (Material, Radix).
|
|
9
|
-
* Contains all shared TypeScript logic. Subclasses provide a @Component
|
|
10
|
-
* decorator with their own selector, template, and imports.
|
|
11
|
-
*/
|
|
12
|
-
import { Input, signal, effect, inject } from '@angular/core';
|
|
13
|
-
import { OGridService } from '../services/ogrid.service';
|
|
14
|
-
export class BaseOGridComponent {
|
|
15
|
-
set props(value) {
|
|
16
|
-
this.propsSignal.set(value);
|
|
17
|
-
}
|
|
18
|
-
constructor() {
|
|
19
|
-
this.propsSignal = signal(undefined);
|
|
20
|
-
this.ogridService = inject(OGridService);
|
|
21
|
-
effect(() => {
|
|
22
|
-
const p = this.propsSignal();
|
|
23
|
-
if (p)
|
|
24
|
-
this.ogridService.configure(p);
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
get showToolbar() {
|
|
28
|
-
return this.ogridService.columnChooserPlacement() === 'toolbar' || this.ogridService.toolbar() != null || this.ogridService.fullScreen();
|
|
29
|
-
}
|
|
30
|
-
onPageSizeChange(size) {
|
|
31
|
-
this.ogridService.pagination().setPageSize(size);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
__decorate([
|
|
35
|
-
Input({ required: true })
|
|
36
|
-
], BaseOGridComponent.prototype, "props", null);
|
|
@@ -1,72 +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
|
-
import { getPaginationViewModel } from '@alaarab/ogrid-core';
|
|
9
|
-
/**
|
|
10
|
-
* Abstract base class containing all shared TypeScript logic for PaginationControls components.
|
|
11
|
-
* Framework-specific UI packages extend this with their templates and style overrides.
|
|
12
|
-
*
|
|
13
|
-
* Subclasses must:
|
|
14
|
-
* 1. Provide a @Component decorator with template and styles
|
|
15
|
-
*
|
|
16
|
-
* Uses @Input setter + signal pattern so computed() can track dependencies.
|
|
17
|
-
* (Plain @Input properties are NOT tracked by computed() — only signals are.)
|
|
18
|
-
*/
|
|
19
|
-
export class BasePaginationControlsComponent {
|
|
20
|
-
constructor() {
|
|
21
|
-
this._currentPage = signal(1);
|
|
22
|
-
this._pageSize = signal(25);
|
|
23
|
-
this._totalCount = signal(0);
|
|
24
|
-
this._pageSizeOptions = signal(undefined);
|
|
25
|
-
this._entityLabelPlural = signal('items');
|
|
26
|
-
this.pageChange = new EventEmitter();
|
|
27
|
-
this.pageSizeChange = new EventEmitter();
|
|
28
|
-
this.labelPlural = computed(() => this._entityLabelPlural() ?? 'items');
|
|
29
|
-
this.vm = computed(() => {
|
|
30
|
-
const opts = this._pageSizeOptions();
|
|
31
|
-
return getPaginationViewModel(this._currentPage(), this._pageSize(), this._totalCount(), opts ? { pageSizeOptions: opts } : undefined);
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
set currentPage(v) { this._currentPage.set(v); }
|
|
35
|
-
get currentPage() { return this._currentPage(); }
|
|
36
|
-
set pageSize(v) { this._pageSize.set(v); }
|
|
37
|
-
get pageSize() { return this._pageSize(); }
|
|
38
|
-
set totalCount(v) { this._totalCount.set(v); }
|
|
39
|
-
get totalCount() { return this._totalCount(); }
|
|
40
|
-
set pageSizeOptions(v) { this._pageSizeOptions.set(v); }
|
|
41
|
-
get pageSizeOptions() { return this._pageSizeOptions(); }
|
|
42
|
-
set entityLabelPlural(v) { this._entityLabelPlural.set(v); }
|
|
43
|
-
get entityLabelPlural() { return this._entityLabelPlural(); }
|
|
44
|
-
onPageSizeSelect(event) {
|
|
45
|
-
const value = Number(event.target.value);
|
|
46
|
-
this.pageSizeChange.emit(value);
|
|
47
|
-
}
|
|
48
|
-
onPageSizeChange(value) {
|
|
49
|
-
this.pageSizeChange.emit(Number(value));
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
__decorate([
|
|
53
|
-
Input({ required: true })
|
|
54
|
-
], BasePaginationControlsComponent.prototype, "currentPage", null);
|
|
55
|
-
__decorate([
|
|
56
|
-
Input({ required: true })
|
|
57
|
-
], BasePaginationControlsComponent.prototype, "pageSize", null);
|
|
58
|
-
__decorate([
|
|
59
|
-
Input({ required: true })
|
|
60
|
-
], BasePaginationControlsComponent.prototype, "totalCount", null);
|
|
61
|
-
__decorate([
|
|
62
|
-
Input()
|
|
63
|
-
], BasePaginationControlsComponent.prototype, "pageSizeOptions", null);
|
|
64
|
-
__decorate([
|
|
65
|
-
Input()
|
|
66
|
-
], BasePaginationControlsComponent.prototype, "entityLabelPlural", null);
|
|
67
|
-
__decorate([
|
|
68
|
-
Output()
|
|
69
|
-
], BasePaginationControlsComponent.prototype, "pageChange", void 0);
|
|
70
|
-
__decorate([
|
|
71
|
-
Output()
|
|
72
|
-
], BasePaginationControlsComponent.prototype, "pageSizeChange", void 0);
|
|
@@ -1,114 +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 { Input, ViewChild, Injector, EnvironmentInjector, inject, signal, effect, createComponent } from '@angular/core';
|
|
8
|
-
/**
|
|
9
|
-
* Shared popover cell editor template used by all Angular UI packages.
|
|
10
|
-
*/
|
|
11
|
-
export const POPOVER_CELL_EDITOR_TEMPLATE = `
|
|
12
|
-
<div #anchorEl
|
|
13
|
-
class="ogrid-popover-anchor"
|
|
14
|
-
[attr.data-row-index]="rowIndex"
|
|
15
|
-
[attr.data-col-index]="globalColIndex"
|
|
16
|
-
>
|
|
17
|
-
{{ displayValue }}
|
|
18
|
-
</div>
|
|
19
|
-
@if (showEditor()) {
|
|
20
|
-
<div class="ogrid-popover-editor-overlay" (click)="handleOverlayClick()">
|
|
21
|
-
<div class="ogrid-popover-editor-content" #editorContainer></div>
|
|
22
|
-
</div>
|
|
23
|
-
}
|
|
24
|
-
`;
|
|
25
|
-
/**
|
|
26
|
-
* Shared overlay + content styles for popover cell editors.
|
|
27
|
-
* Subclasses provide their own .ogrid-popover-anchor styles.
|
|
28
|
-
*/
|
|
29
|
-
export const POPOVER_CELL_EDITOR_OVERLAY_STYLES = `
|
|
30
|
-
:host { display: contents; }
|
|
31
|
-
.ogrid-popover-editor-overlay {
|
|
32
|
-
position: fixed; inset: 0; z-index: 1000;
|
|
33
|
-
background: rgba(0,0,0,0.3);
|
|
34
|
-
display: flex; align-items: center; justify-content: center;
|
|
35
|
-
}
|
|
36
|
-
.ogrid-popover-editor-content {
|
|
37
|
-
background: var(--ogrid-bg, #ffffff); border-radius: 4px; padding: 16px;
|
|
38
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
39
|
-
max-width: 90vw; max-height: 90vh; overflow: auto;
|
|
40
|
-
color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
|
|
41
|
-
}
|
|
42
|
-
`;
|
|
43
|
-
/**
|
|
44
|
-
* Abstract base class for Angular popover cell editors.
|
|
45
|
-
* Contains all shared inputs, ViewChild refs, effects, and overlay click handling.
|
|
46
|
-
*
|
|
47
|
-
* Subclasses only need a @Component decorator with selector, template, and
|
|
48
|
-
* framework-specific .ogrid-popover-anchor CSS styles.
|
|
49
|
-
*/
|
|
50
|
-
export class BasePopoverCellEditorComponent {
|
|
51
|
-
constructor() {
|
|
52
|
-
this.injector = inject(Injector);
|
|
53
|
-
this.envInjector = inject(EnvironmentInjector);
|
|
54
|
-
this.showEditor = signal(false);
|
|
55
|
-
// Show editor after anchor is rendered
|
|
56
|
-
effect(() => {
|
|
57
|
-
const anchor = this.anchorRef;
|
|
58
|
-
if (anchor) {
|
|
59
|
-
setTimeout(() => this.showEditor.set(true), 0);
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
// Render custom editor component when container is available.
|
|
63
|
-
// Angular's effect() ignores return values — use onCleanup() for cleanup.
|
|
64
|
-
effect((onCleanup) => {
|
|
65
|
-
const container = this.editorContainerRef;
|
|
66
|
-
const props = this.editorProps;
|
|
67
|
-
const col = this.column;
|
|
68
|
-
if (!container || !this.showEditor() || typeof col.cellEditor !== 'function')
|
|
69
|
-
return;
|
|
70
|
-
const EditorComponent = col.cellEditor;
|
|
71
|
-
const componentRef = createComponent(EditorComponent, {
|
|
72
|
-
environmentInjector: this.envInjector,
|
|
73
|
-
elementInjector: this.injector,
|
|
74
|
-
});
|
|
75
|
-
// Pass props to component instance
|
|
76
|
-
Object.assign(componentRef.instance, props);
|
|
77
|
-
componentRef.changeDetectorRef.detectChanges();
|
|
78
|
-
// Append to DOM
|
|
79
|
-
container.nativeElement.appendChild(componentRef.location.nativeElement);
|
|
80
|
-
// Cleanup when effect re-runs or component is destroyed
|
|
81
|
-
onCleanup(() => componentRef.destroy());
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
handleOverlayClick() {
|
|
85
|
-
this.onCancel();
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
__decorate([
|
|
89
|
-
Input({ required: true })
|
|
90
|
-
], BasePopoverCellEditorComponent.prototype, "item", void 0);
|
|
91
|
-
__decorate([
|
|
92
|
-
Input({ required: true })
|
|
93
|
-
], BasePopoverCellEditorComponent.prototype, "column", void 0);
|
|
94
|
-
__decorate([
|
|
95
|
-
Input({ required: true })
|
|
96
|
-
], BasePopoverCellEditorComponent.prototype, "rowIndex", void 0);
|
|
97
|
-
__decorate([
|
|
98
|
-
Input({ required: true })
|
|
99
|
-
], BasePopoverCellEditorComponent.prototype, "globalColIndex", void 0);
|
|
100
|
-
__decorate([
|
|
101
|
-
Input({ required: true })
|
|
102
|
-
], BasePopoverCellEditorComponent.prototype, "displayValue", void 0);
|
|
103
|
-
__decorate([
|
|
104
|
-
Input({ required: true })
|
|
105
|
-
], BasePopoverCellEditorComponent.prototype, "editorProps", void 0);
|
|
106
|
-
__decorate([
|
|
107
|
-
Input({ required: true })
|
|
108
|
-
], BasePopoverCellEditorComponent.prototype, "onCancel", void 0);
|
|
109
|
-
__decorate([
|
|
110
|
-
ViewChild('anchorEl')
|
|
111
|
-
], BasePopoverCellEditorComponent.prototype, "anchorRef", void 0);
|
|
112
|
-
__decorate([
|
|
113
|
-
ViewChild('editorContainer')
|
|
114
|
-
], BasePopoverCellEditorComponent.prototype, "editorContainerRef", void 0);
|
|
@@ -1,58 +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 { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
|
|
8
|
-
import { NgTemplateOutlet } from '@angular/common';
|
|
9
|
-
let EmptyStateComponent = class EmptyStateComponent {
|
|
10
|
-
constructor() {
|
|
11
|
-
this.message = undefined;
|
|
12
|
-
this.hasActiveFilters = false;
|
|
13
|
-
this.render = undefined;
|
|
14
|
-
this.clearAll = new EventEmitter();
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
__decorate([
|
|
18
|
-
Input()
|
|
19
|
-
], EmptyStateComponent.prototype, "message", void 0);
|
|
20
|
-
__decorate([
|
|
21
|
-
Input()
|
|
22
|
-
], EmptyStateComponent.prototype, "hasActiveFilters", void 0);
|
|
23
|
-
__decorate([
|
|
24
|
-
Input()
|
|
25
|
-
], EmptyStateComponent.prototype, "render", void 0);
|
|
26
|
-
__decorate([
|
|
27
|
-
Output()
|
|
28
|
-
], EmptyStateComponent.prototype, "clearAll", void 0);
|
|
29
|
-
EmptyStateComponent = __decorate([
|
|
30
|
-
Component({
|
|
31
|
-
selector: 'ogrid-empty-state',
|
|
32
|
-
standalone: true,
|
|
33
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
34
|
-
imports: [NgTemplateOutlet],
|
|
35
|
-
styles: [`
|
|
36
|
-
.ogrid-empty-state-clear-btn {
|
|
37
|
-
background: none; border: none; color: inherit;
|
|
38
|
-
text-decoration: underline; cursor: pointer; padding: 0; font: inherit;
|
|
39
|
-
}
|
|
40
|
-
`],
|
|
41
|
-
template: `
|
|
42
|
-
@if (render) {
|
|
43
|
-
<ng-container [ngTemplateOutlet]="render"></ng-container>
|
|
44
|
-
} @else if (message) {
|
|
45
|
-
{{ message }}
|
|
46
|
-
} @else if (hasActiveFilters) {
|
|
47
|
-
No items match your current filters. Try adjusting your search or
|
|
48
|
-
<button type="button" (click)="clearAll.emit()" class="ogrid-empty-state-clear-btn">
|
|
49
|
-
clear all filters
|
|
50
|
-
</button>
|
|
51
|
-
to see all items.
|
|
52
|
-
} @else {
|
|
53
|
-
There are no items available at this time.
|
|
54
|
-
}
|
|
55
|
-
`,
|
|
56
|
-
})
|
|
57
|
-
], EmptyStateComponent);
|
|
58
|
-
export { EmptyStateComponent };
|
|
@@ -1,153 +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 { Component, Input, Output, EventEmitter, ViewChild, DestroyRef, inject, ChangeDetectionStrategy } from '@angular/core';
|
|
8
|
-
import { GRID_CONTEXT_MENU_ITEMS, formatShortcut } from '@alaarab/ogrid-core';
|
|
9
|
-
let GridContextMenuComponent = class GridContextMenuComponent {
|
|
10
|
-
constructor() {
|
|
11
|
-
this.destroyRef = inject(DestroyRef);
|
|
12
|
-
this.hasSelection = false;
|
|
13
|
-
this.canUndoProp = false;
|
|
14
|
-
this.canRedoProp = false;
|
|
15
|
-
this.classNames = undefined;
|
|
16
|
-
this.copyAction = new EventEmitter();
|
|
17
|
-
this.cutAction = new EventEmitter();
|
|
18
|
-
this.pasteAction = new EventEmitter();
|
|
19
|
-
this.selectAllAction = new EventEmitter();
|
|
20
|
-
this.undoAction = new EventEmitter();
|
|
21
|
-
this.redoAction = new EventEmitter();
|
|
22
|
-
this.closeAction = new EventEmitter();
|
|
23
|
-
this.menuItems = GRID_CONTEXT_MENU_ITEMS;
|
|
24
|
-
this.formatShortcutFn = formatShortcut;
|
|
25
|
-
this.clickOutsideHandler = (e) => {
|
|
26
|
-
const el = this.menuRef?.nativeElement;
|
|
27
|
-
if (el && !el.contains(e.target))
|
|
28
|
-
this.closeAction.emit();
|
|
29
|
-
};
|
|
30
|
-
this.keyDownHandler = (e) => {
|
|
31
|
-
if (e.key === 'Escape')
|
|
32
|
-
this.closeAction.emit();
|
|
33
|
-
};
|
|
34
|
-
// Register listeners once on init (no signal dependencies needed)
|
|
35
|
-
document.addEventListener('mousedown', this.clickOutsideHandler, true);
|
|
36
|
-
document.addEventListener('keydown', this.keyDownHandler, true);
|
|
37
|
-
this.destroyRef.onDestroy(() => {
|
|
38
|
-
document.removeEventListener('mousedown', this.clickOutsideHandler, true);
|
|
39
|
-
document.removeEventListener('keydown', this.keyDownHandler, true);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
isDisabled(item) {
|
|
43
|
-
if (item.disabledWhenNoSelection && !this.hasSelection)
|
|
44
|
-
return true;
|
|
45
|
-
if (item.id === 'undo' && !this.canUndoProp)
|
|
46
|
-
return true;
|
|
47
|
-
if (item.id === 'redo' && !this.canRedoProp)
|
|
48
|
-
return true;
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
onItemClick(id) {
|
|
52
|
-
switch (id) {
|
|
53
|
-
case 'copy':
|
|
54
|
-
this.copyAction.emit();
|
|
55
|
-
break;
|
|
56
|
-
case 'cut':
|
|
57
|
-
this.cutAction.emit();
|
|
58
|
-
break;
|
|
59
|
-
case 'paste':
|
|
60
|
-
this.pasteAction.emit();
|
|
61
|
-
break;
|
|
62
|
-
case 'selectAll':
|
|
63
|
-
this.selectAllAction.emit();
|
|
64
|
-
break;
|
|
65
|
-
case 'undo':
|
|
66
|
-
this.undoAction.emit();
|
|
67
|
-
break;
|
|
68
|
-
case 'redo':
|
|
69
|
-
this.redoAction.emit();
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
this.closeAction.emit();
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
__decorate([
|
|
76
|
-
Input({ required: true })
|
|
77
|
-
], GridContextMenuComponent.prototype, "x", void 0);
|
|
78
|
-
__decorate([
|
|
79
|
-
Input({ required: true })
|
|
80
|
-
], GridContextMenuComponent.prototype, "y", void 0);
|
|
81
|
-
__decorate([
|
|
82
|
-
Input()
|
|
83
|
-
], GridContextMenuComponent.prototype, "hasSelection", void 0);
|
|
84
|
-
__decorate([
|
|
85
|
-
Input()
|
|
86
|
-
], GridContextMenuComponent.prototype, "canUndoProp", void 0);
|
|
87
|
-
__decorate([
|
|
88
|
-
Input()
|
|
89
|
-
], GridContextMenuComponent.prototype, "canRedoProp", void 0);
|
|
90
|
-
__decorate([
|
|
91
|
-
Input()
|
|
92
|
-
], GridContextMenuComponent.prototype, "classNames", void 0);
|
|
93
|
-
__decorate([
|
|
94
|
-
Output()
|
|
95
|
-
], GridContextMenuComponent.prototype, "copyAction", void 0);
|
|
96
|
-
__decorate([
|
|
97
|
-
Output()
|
|
98
|
-
], GridContextMenuComponent.prototype, "cutAction", void 0);
|
|
99
|
-
__decorate([
|
|
100
|
-
Output()
|
|
101
|
-
], GridContextMenuComponent.prototype, "pasteAction", void 0);
|
|
102
|
-
__decorate([
|
|
103
|
-
Output()
|
|
104
|
-
], GridContextMenuComponent.prototype, "selectAllAction", void 0);
|
|
105
|
-
__decorate([
|
|
106
|
-
Output()
|
|
107
|
-
], GridContextMenuComponent.prototype, "undoAction", void 0);
|
|
108
|
-
__decorate([
|
|
109
|
-
Output()
|
|
110
|
-
], GridContextMenuComponent.prototype, "redoAction", void 0);
|
|
111
|
-
__decorate([
|
|
112
|
-
Output()
|
|
113
|
-
], GridContextMenuComponent.prototype, "closeAction", void 0);
|
|
114
|
-
__decorate([
|
|
115
|
-
ViewChild('menuRef')
|
|
116
|
-
], GridContextMenuComponent.prototype, "menuRef", void 0);
|
|
117
|
-
GridContextMenuComponent = __decorate([
|
|
118
|
-
Component({
|
|
119
|
-
selector: 'ogrid-context-menu',
|
|
120
|
-
standalone: true,
|
|
121
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
122
|
-
template: `
|
|
123
|
-
<div
|
|
124
|
-
#menuRef
|
|
125
|
-
[class]="classNames?.contextMenu ?? ''"
|
|
126
|
-
role="menu"
|
|
127
|
-
[style.left.px]="x"
|
|
128
|
-
[style.top.px]="y"
|
|
129
|
-
aria-label="Grid context menu"
|
|
130
|
-
>
|
|
131
|
-
@for (item of menuItems; track item.id) {
|
|
132
|
-
@if (item.dividerBefore) {
|
|
133
|
-
<div [class]="classNames?.contextMenuDivider ?? ''"></div>
|
|
134
|
-
}
|
|
135
|
-
<button
|
|
136
|
-
type="button"
|
|
137
|
-
[class]="classNames?.contextMenuItem ?? ''"
|
|
138
|
-
(click)="onItemClick(item.id)"
|
|
139
|
-
[disabled]="isDisabled(item)"
|
|
140
|
-
>
|
|
141
|
-
<span [class]="classNames?.contextMenuItemLabel ?? ''">{{ item.label }}</span>
|
|
142
|
-
@if (item.shortcut) {
|
|
143
|
-
<span [class]="classNames?.contextMenuItemShortcut ?? ''">
|
|
144
|
-
{{ formatShortcutFn(item.shortcut) }}
|
|
145
|
-
</span>
|
|
146
|
-
}
|
|
147
|
-
</button>
|
|
148
|
-
}
|
|
149
|
-
</div>
|
|
150
|
-
`,
|
|
151
|
-
})
|
|
152
|
-
], GridContextMenuComponent);
|
|
153
|
-
export { GridContextMenuComponent };
|