@alaarab/ogrid-angular-material 2.6.0 → 2.7.0

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 CHANGED
@@ -1,1183 +1,16 @@
1
- import {INLINE_CELL_EDITOR_STYLES,INLINE_CELL_EDITOR_TEMPLATE,POPOVER_CELL_EDITOR_OVERLAY_STYLES,POPOVER_CELL_EDITOR_TEMPLATE,OGRID_THEME_VARS_CSS,CHECKBOX_COLUMN_WIDTH,DataGridStateService,ColumnReorderService,VirtualScrollService,StatusBarComponent,GridContextMenuComponent,MarchingAntsOverlayComponent,EmptyStateComponent,FormulaRefOverlayComponent,OGridService,OGridLayoutComponent,BaseColumnHeaderFilterComponent,BaseColumnHeaderMenuComponent,BaseInlineCellEditorComponent,BasePopoverCellEditorComponent,BaseDataGridTableComponent,formatCellReference,indexToColumnLetter,ROW_NUMBER_COLUMN_ID,BaseColumnChooserComponent,BasePaginationControlsComponent,BaseOGridComponent}from'@alaarab/ogrid-angular';export{AUTOSIZE_EXTRA_PX,AUTOSIZE_MAX_PX,BaseColumnChooserComponent,BaseColumnHeaderFilterComponent,BaseDataGridTableComponent,BaseInlineCellEditorComponent,BaseOGridComponent,BasePaginationControlsComponent,BasePopoverCellEditorComponent,CELL_PADDING,CHECKBOX_COLUMN_WIDTH,COLUMN_HEADER_MENU_ITEMS,ColumnReorderService,DEFAULT_DEBOUNCE_MS,DEFAULT_MIN_COLUMN_WIDTH,DataGridEditingHelper,DataGridInteractionHelper,DataGridLayoutHelper,DataGridStateService,EmptyStateComponent,GRID_BORDER_RADIUS,GRID_CONTEXT_MENU_ITEMS,GridContextMenuComponent,INLINE_CELL_EDITOR_STYLES,INLINE_CELL_EDITOR_TEMPLATE,MAX_PAGE_BUTTONS,MarchingAntsOverlayComponent,OGRID_THEME_VARS_CSS,OGridLayoutComponent,OGridService,PAGE_SIZE_OPTIONS,PEOPLE_SEARCH_DEBOUNCE_MS,POPOVER_CELL_EDITOR_OVERLAY_STYLES,POPOVER_CELL_EDITOR_TEMPLATE,ROW_NUMBER_COLUMN_WIDTH,SIDEBAR_TRANSITION_MS,SideBarComponent,StatusBarComponent,UndoRedoStack,VirtualScrollService,Z_INDEX,applyCellDeletion,applyCutClear,applyFillValues,applyPastedValues,applyRangeRowSelection,areGridRowPropsEqual,booleanParser,buildCsvHeader,buildCsvRows,buildHeaderRows,buildInlineEditorProps,buildPopoverEditorProps,calculateDropTarget,clampSelectionToBounds,computeAggregations,computeArrowNavigation,computeAutoScrollSpeed,computeNextSortState,computeRowSelectionState,computeTabNavigation,computeTotalHeight,computeVisibleRange,createDebouncedCallback,createDebouncedSignal,createLatestCallback,currencyParser,dateParser,debounce,deriveFilterOptionsFromData,emailParser,escapeCsvValue,exportToCsv,findCtrlArrowTarget,flattenColumns,formatCellValueForTsv,formatSelectionAsTsv,formatShortcut,getCellRenderDescriptor,getCellValue,getColumnHeaderMenuItems,getContextMenuHandlers,getDataGridStatusBarConfig,getFilterField,getHeaderFilterConfig,getMultiSelectFilterFields,getPaginationViewModel,getPinStateForColumn,getScrollTopForRow,getStatusBarParts,injectGlobalStyles,isFilterConfig,isInSelectionRange,isRowInRange,measureColumnContentWidth,measureRange,mergeFilter,normalizeSelectionRange,numberParser,parseTsvClipboard,parseValue,processClientSideData,rangesEqual,reorderColumnArray,resolveCellDisplayContent,resolveCellStyle,toUserLike,triggerCsvDownload,validateColumns,validateRowIds}from'@alaarab/ogrid-angular';import {ViewChild,Component,ChangeDetectionStrategy,Input,ViewEncapsulation,signal,computed,effect}from'@angular/core';import {MatMenuTrigger,MatMenuModule}from'@angular/material/menu';import {MatDividerModule}from'@angular/material/divider';var x=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var e=(t,a,r,d)=>{for(var o=d>1?void 0:d?y(a,r):a,u=t.length-1,h;u>=0;u--)(h=t[u])&&(o=(d?h(a,r,o):h(o))||o);return d&&o&&x(a,r,o),o};var n=class extends BaseColumnHeaderFilterComponent{getHeaderEl(){return this.headerEl}onDocumentClickWrapper(a){this.onDocumentClick(a,"ogrid-column-header-filter");}};e([ViewChild("headerEl")],n.prototype,"headerEl",2),n=e([Component({selector:"ogrid-column-header-filter",standalone:true,changeDetection:ChangeDetectionStrategy.OnPush,template:`
2
- <div class="ogrid-header-filter" #headerEl>
3
- <div class="ogrid-header-filter__label">
4
- <span class="ogrid-header-filter__name" [title]="columnName" data-header-label>
5
- {{ columnName }}
6
- </span>
7
- </div>
8
-
9
- <div class="ogrid-header-filter__actions">
10
- @if (filterType !== 'none') {
11
- <button
12
- class="ogrid-header-filter__filter-btn"
13
- [class.ogrid-header-filter__filter-btn--active]="hasActiveFilter() || isFilterOpen()"
14
- (click)="toggleFilter($event)"
15
- [attr.aria-label]="'Filter ' + columnName"
16
- [attr.aria-expanded]="isFilterOpen()"
17
- aria-haspopup="dialog"
18
- [title]="'Filter ' + columnName"
19
- >
20
- <span class="ogrid-header-filter__funnel"></span>
21
- @if (hasActiveFilter()) {
22
- <span class="ogrid-header-filter__dot"></span>
23
- }
24
- </button>
25
- }
26
- </div>
27
- </div>
28
-
29
- @if (isFilterOpen() && filterType !== 'none') {
30
- <div
31
- class="ogrid-header-filter__popover"
32
- [style.top.px]="popoverTop()"
33
- [style.left.px]="popoverLeft()"
34
- (click)="$event.stopPropagation()"
35
- >
36
- <div class="ogrid-header-filter__popover-header">
37
- Filter: {{ columnName }}
38
- </div>
39
-
40
- @switch (filterType) {
41
- @case ('text') {
42
- <div class="ogrid-header-filter__popover-body" style="width: 260px;">
43
- <div style="padding: 12px;">
44
- <input
45
- type="text"
46
- class="ogrid-header-filter__input"
47
- placeholder="Enter search term..."
48
- [value]="tempTextValue()"
49
- (input)="tempTextValue.set(asInputValue($event))"
50
- (keydown)="onTextKeydown($event)"
51
- autocomplete="off"
52
- />
53
- </div>
54
- <div class="ogrid-header-filter__popover-actions">
55
- <button class="ogrid-header-filter__action-btn" [disabled]="!tempTextValue()" (click)="handleTextClear()">Clear</button>
56
- <button class="ogrid-header-filter__action-btn ogrid-header-filter__action-btn--primary" (click)="handleTextApply()">Apply</button>
57
- </div>
58
- </div>
59
- }
60
- @case ('multiSelect') {
61
- <div class="ogrid-header-filter__popover-body" style="width: 280px;">
62
- <div style="padding: 12px 12px 4px;">
63
- <input
64
- type="text"
65
- class="ogrid-header-filter__input"
66
- placeholder="Search..."
67
- [value]="searchText()"
68
- (input)="searchText.set(asInputValue($event))"
69
- (keydown)="$event.stopPropagation()"
70
- autocomplete="off"
71
- />
72
- <div class="ogrid-header-filter__options-info">
73
- {{ filteredOptions().length }} of {{ (options ?? []).length }} options
74
- </div>
75
- </div>
76
- <div class="ogrid-header-filter__select-actions">
77
- <button class="ogrid-header-filter__action-btn" (click)="handleSelectAllFiltered()">
78
- Select All ({{ filteredOptions().length }})
79
- </button>
80
- <button class="ogrid-header-filter__action-btn" (click)="handleClearSelection()">Clear</button>
81
- </div>
82
- <div class="ogrid-header-filter__options-list">
83
- @if (isLoadingOptions) {
84
- <div class="ogrid-header-filter__loading">Loading...</div>
85
- } @else if (filteredOptions().length === 0) {
86
- <div class="ogrid-header-filter__empty">No options found</div>
87
- } @else {
88
- @for (option of filteredOptions(); track option) {
89
- <label class="ogrid-header-filter__option">
90
- <input
91
- type="checkbox"
92
- [checked]="tempSelected().has(option)"
93
- (change)="handleCheckboxChange(option, $event)"
94
- />
95
- <span>{{ option }}</span>
96
- </label>
97
- }
98
- }
99
- </div>
100
- <div class="ogrid-header-filter__popover-actions" style="border-top: 1px solid rgba(0,0,0,0.12);">
101
- <button class="ogrid-header-filter__action-btn" (click)="handleClearSelection()">Clear</button>
102
- <button class="ogrid-header-filter__action-btn ogrid-header-filter__action-btn--primary" (click)="handleApplyMultiSelect()">Apply</button>
103
- </div>
104
- </div>
105
- }
106
- @case ('people') {
107
- <div class="ogrid-header-filter__popover-body" style="width: 300px;">
108
- @if (selectedUser) {
109
- <div class="ogrid-header-filter__people-selected">
110
- <div class="ogrid-header-filter__people-info-label">Currently filtered by:</div>
111
- <div class="ogrid-header-filter__people-card">
112
- <div class="ogrid-header-filter__people-avatar">{{ selectedUser!.displayName?.[0] ?? '?' }}</div>
113
- <div class="ogrid-header-filter__people-details">
114
- <div>{{ selectedUser!.displayName }}</div>
115
- <div class="ogrid-header-filter__people-email">{{ selectedUser!.email }}</div>
116
- </div>
117
- <button class="ogrid-header-filter__btn" (click)="handleClearUser()" aria-label="Remove filter">&times;</button>
118
- </div>
119
- </div>
120
- }
121
- <div style="padding: 12px 12px 4px;">
122
- <input
123
- type="text"
124
- class="ogrid-header-filter__input"
125
- placeholder="Search for a person..."
126
- [value]="peopleSearchText()"
127
- (input)="onPeopleSearchInput($event)"
128
- (keydown)="$event.stopPropagation()"
129
- autocomplete="off"
130
- />
131
- </div>
132
- <div class="ogrid-header-filter__options-list">
133
- @if (isPeopleLoading() && peopleSearchText().trim()) {
134
- <div class="ogrid-header-filter__loading">Loading...</div>
135
- } @else if (peopleSuggestions().length === 0 && peopleSearchText().trim()) {
136
- <div class="ogrid-header-filter__empty">No results found</div>
137
- } @else if (peopleSearchText().trim()) {
138
- @for (user of peopleSuggestions(); track user.id || user.email || user.displayName) {
139
- <div class="ogrid-header-filter__people-option" (click)="handleUserSelect(user)">
140
- <div class="ogrid-header-filter__people-avatar">{{ user.displayName?.[0] ?? '?' }}</div>
141
- <div class="ogrid-header-filter__people-details">
142
- <div>{{ user.displayName }}</div>
143
- <div class="ogrid-header-filter__people-email">{{ user.email }}</div>
144
- </div>
145
- </div>
146
- }
147
- } @else {
148
- <div class="ogrid-header-filter__empty">Type to search...</div>
149
- }
150
- </div>
151
- @if (selectedUser) {
152
- <div style="padding: 8px 12px; border-top: 1px solid rgba(0,0,0,0.12);">
153
- <button class="ogrid-header-filter__action-btn" style="width: 100%;" (click)="handleClearUser()">Clear Filter</button>
154
- </div>
155
- }
156
- </div>
157
- }
158
- @case ('date') {
159
- <div class="ogrid-header-filter__popover-body" style="padding: 12px; display: flex; flex-direction: column; gap: 8px;">
160
- <div style="display: flex; align-items: center; gap: 8px;">
161
- <span style="min-width: 36px; font-size: 12px;">From:</span>
162
- <input type="date" [value]="tempDateFrom()" (input)="tempDateFrom.set(asInputValue($event))" style="flex: 1; padding: 4px 6px;" />
163
- </div>
164
- <div style="display: flex; align-items: center; gap: 8px;">
165
- <span style="min-width: 36px; font-size: 12px;">To:</span>
166
- <input type="date" [value]="tempDateTo()" (input)="tempDateTo.set(asInputValue($event))" style="flex: 1; padding: 4px 6px;" />
167
- </div>
168
- <div class="ogrid-header-filter__popover-actions" style="margin-top: 4px;">
169
- <button class="ogrid-header-filter__action-btn" [disabled]="!tempDateFrom() && !tempDateTo()" (click)="handleDateClear()">Clear</button>
170
- <button class="ogrid-header-filter__action-btn ogrid-header-filter__action-btn--primary" (click)="handleDateApply()">Apply</button>
171
- </div>
172
- </div>
173
- }
174
- }
175
- </div>
176
- }
177
- `,styles:[`
178
- :host { display: flex; align-items: center; flex: 1; min-width: 0; position: relative; }
179
- .ogrid-header-filter { display: flex; align-items: center; width: 100%; min-width: 0; }
180
- .ogrid-header-filter__label { flex: 1; min-width: 0; overflow: hidden; }
181
- .ogrid-header-filter__name {
182
- display: block; font-weight: 600; font-size: 14px; line-height: 1.4;
183
- white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
184
- }
185
- .ogrid-header-filter__actions { display: flex; align-items: center; margin-left: 4px; flex-shrink: 0; }
186
- .ogrid-header-filter__btn {
187
- width: 24px; height: 24px; padding: 2px; border: none; border-radius: 4px;
188
- background: transparent; cursor: pointer; font-size: 12px; line-height: 1;
189
- display: inline-flex; align-items: center; justify-content: center; position: relative;
190
- color: var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.54));
191
- }
192
- .ogrid-header-filter__btn:hover { background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.08)); }
193
- .ogrid-header-filter__btn--active { color: var(--mat-sys-primary, #1976d2); }
194
- .ogrid-header-filter__filter-btn {
195
- width: 24px; height: 24px; padding: 2px; border: none; border-radius: 4px;
196
- background: transparent; cursor: pointer; line-height: 1;
197
- display: inline-flex; align-items: center; justify-content: center; position: relative;
198
- opacity: 0.6; transition: opacity 0.15s;
199
- }
200
- .ogrid-header-filter:hover .ogrid-header-filter__filter-btn { opacity: 0.8; }
201
- /* :hover and --active must override the parent-hover rule (0,2,0) - double-class raises to 0,3,0 */
202
- .ogrid-header-filter .ogrid-header-filter__filter-btn:hover { background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.08)); opacity: 1; }
203
- .ogrid-header-filter .ogrid-header-filter__filter-btn--active { opacity: 1; }
204
- .ogrid-header-filter__funnel {
205
- display: block; width: 0; height: 0;
206
- border-left: 5px solid transparent; border-right: 5px solid transparent;
207
- border-top: 6px solid var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.65));
208
- position: relative;
209
- }
210
- .ogrid-header-filter__funnel::after {
211
- content: ''; display: block; width: 2px; height: 4px;
212
- background: var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.65)); position: absolute;
213
- top: -1px; left: -1px;
214
- }
215
- .ogrid-header-filter__filter-btn--active .ogrid-header-filter__funnel {
216
- border-top-color: var(--mat-sys-primary, #1976d2);
217
- }
218
- .ogrid-header-filter__filter-btn--active .ogrid-header-filter__funnel::after {
219
- background: var(--mat-sys-primary, #1976d2);
220
- }
221
- .ogrid-header-filter__dot {
222
- position: absolute; top: 2px; right: 2px;
223
- width: 6px; height: 6px; border-radius: 50%;
224
- background: var(--mat-sys-primary, #1976d2);
225
- }
226
- .ogrid-header-filter__popover {
227
- position: fixed; z-index: 1000;
228
- background: var(--ogrid-bg, #ffffff); border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.2));
229
- border-radius: 8px; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2), 0 1px 4px rgba(0, 0, 0, 0.1);
230
- margin-top: 4px; color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
231
- }
232
- .ogrid-header-filter__popover-header {
233
- padding: 8px 12px; font-size: 14px; font-weight: 600;
234
- border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
235
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
236
- }
237
- .ogrid-header-filter__popover-body { }
238
- .ogrid-header-filter__popover-actions {
239
- display: flex; justify-content: flex-end; gap: 8px; padding: 8px 12px;
240
- }
241
- .ogrid-header-filter__input {
242
- width: 100%; padding: 8px 12px; border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.23));
243
- border-radius: 4px; font-size: 14px; box-sizing: border-box;
244
- background: var(--ogrid-bg, #ffffff); color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
245
- }
246
- .ogrid-header-filter__input:focus { outline: 2px solid var(--mat-sys-primary, #1976d2); outline-offset: -1px; }
247
- .ogrid-header-filter__options-info { margin-top: 4px; font-size: 12px; color: var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.6)); }
248
- .ogrid-header-filter__select-actions {
249
- display: flex; justify-content: space-between; padding: 4px 12px;
250
- }
251
- .ogrid-header-filter__options-list { max-height: 240px; overflow-y: auto; padding: 0 4px; }
252
- .ogrid-header-filter__option {
253
- display: flex; align-items: center; gap: 8px;
254
- padding: 4px 8px; cursor: pointer; font-size: 14px;
255
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
256
- }
257
- .ogrid-header-filter__option:hover { background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)); }
258
- .ogrid-header-filter__loading, .ogrid-header-filter__empty {
259
- padding: 16px; text-align: center; font-size: 14px; color: var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.6));
260
- }
261
- .ogrid-header-filter__action-btn {
262
- padding: 4px 12px; border: none; border-radius: 4px;
263
- background: transparent; cursor: pointer; font-size: 13px;
264
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
265
- }
266
- .ogrid-header-filter__action-btn:hover { background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)); }
267
- .ogrid-header-filter__action-btn:disabled { opacity: 0.38; cursor: default; }
268
- .ogrid-header-filter__action-btn--primary {
269
- background: var(--mat-sys-primary, #1976d2); color: #fff;
270
- }
271
- .ogrid-header-filter__action-btn--primary:hover { opacity: 0.9; }
272
- .ogrid-header-filter__people-selected {
273
- padding: 12px; border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
274
- }
275
- .ogrid-header-filter__people-info-label { font-size: 12px; color: var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.6)); }
276
- .ogrid-header-filter__people-card {
277
- display: flex; align-items: center; gap: 8px; margin-top: 4px;
278
- }
279
- .ogrid-header-filter__people-avatar {
280
- width: 32px; height: 32px; border-radius: 50%; background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.08));
281
- display: flex; align-items: center; justify-content: center;
282
- font-size: 14px; font-weight: 600; flex-shrink: 0;
283
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
284
- }
285
- .ogrid-header-filter__people-details { flex: 1; min-width: 0; font-size: 14px; color: var(--ogrid-fg, rgba(0, 0, 0, 0.87)); }
286
- .ogrid-header-filter__people-details > div { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
287
- .ogrid-header-filter__people-email { font-size: 12px; color: var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.6)); }
288
- .ogrid-header-filter__people-option {
289
- display: flex; align-items: center; gap: 8px; padding: 8px 12px; cursor: pointer;
290
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
291
- }
292
- .ogrid-header-filter__people-option:hover { background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)); }
293
- `],host:{"(document:click)":"onDocumentClickWrapper($event)"}})],n);var l=class extends BaseColumnHeaderMenuComponent{};e([ViewChild(MatMenuTrigger)],l.prototype,"menuTrigger",2),l=e([Component({selector:"column-header-menu",standalone:true,changeDetection:ChangeDetectionStrategy.OnPush,imports:[MatMenuModule,MatDividerModule],template:`
294
- <button
295
- [matMenuTriggerFor]="menu"
296
- class="column-header-menu-trigger"
297
- [attr.aria-label]="'Column options for ' + columnId"
298
- >
299
- &#8942;
300
- </button>
301
-
302
- <mat-menu #menu="matMenu">
303
- @for (item of menuItems(); track item.id) {
304
- <button
305
- mat-menu-item
306
- [disabled]="item.disabled"
307
- (click)="handleMenuItemClick(item.id)"
308
- >
309
- {{ item.label }}
310
- </button>
311
- @if (item.divider) {
312
- <mat-divider></mat-divider>
313
- }
314
- }
315
- </mat-menu>
316
- `,styles:[`
317
- :host { flex-shrink: 0; }
318
- .column-header-menu-trigger {
319
- width: 24px;
320
- height: 24px;
321
- padding: 0;
322
- border: none;
323
- border-radius: 4px;
324
- background: transparent;
325
- cursor: pointer;
326
- font-size: 16px;
327
- line-height: 1;
328
- display: inline-flex;
329
- align-items: center;
330
- justify-content: center;
331
- color: var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.54));
332
- }
333
-
334
- /* Always reserve space; hide on hover-capable devices until column is hovered.
335
- The th:hover rule lives in the parent (ViewEncapsulation.None) styles. */
336
- @media (hover: hover) {
337
- .column-header-menu-trigger { visibility: hidden; }
338
- }
339
-
340
- .column-header-menu-trigger:hover {
341
- background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.08));
342
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
343
- }
344
- `]})],l);var s=class extends BaseInlineCellEditorComponent{};s=e([Component({selector:"ogrid-mat-inline-cell-editor",standalone:true,changeDetection:ChangeDetectionStrategy.OnPush,template:INLINE_CELL_EDITOR_TEMPLATE,styles:[INLINE_CELL_EDITOR_STYLES]})],s);var g=class extends BasePopoverCellEditorComponent{};g=e([Component({selector:"ogrid-mat-popover-cell-editor",standalone:true,changeDetection:ChangeDetectionStrategy.OnPush,template:POPOVER_CELL_EDITOR_TEMPLATE,styles:[`
345
- ${POPOVER_CELL_EDITOR_OVERLAY_STYLES}
346
- .ogrid-popover-anchor {
347
- width: 100%; height: 100%; display: flex; align-items: center; min-width: 0;
348
- padding: 6px 10px; box-sizing: border-box; overflow: hidden;
349
- text-overflow: ellipsis; white-space: nowrap; user-select: none;
350
- outline: 2px solid var(--ogrid-selection, #217346); outline-offset: -1px;
351
- z-index: 2; position: relative;
352
- }
353
- `]})],g);var i=class extends BaseDataGridTableComponent{constructor(){super();this.propsSignal=signal(void 0);this.showColumnLetters=computed(()=>!!this.getProps()?.showColumnLetters);this.formulaReferences=computed(()=>this.getProps()?.formulaReferences);this.initBase(),effect(()=>{let d=this.getProps()?.onActiveCellChange;if(!d)return;let o=this.activeCell();if(o){let u=o.columnIndex-this.colOffset(),h=o.rowIndex+1;d(formatCellReference(u,h));}else d(null);});}set propsInput(r){this.propsSignal.set(r);}getProps(){return this.propsSignal()}getWrapperRef(){return this.wrapperRef}getTableContainerRef(){return this.tableContainerRef}getColumnLetter(r){return indexToColumnLetter(r)}onResizeRowNumber(r){r.stopPropagation(),this.onResizeStart(r,{columnId:ROW_NUMBER_COLUMN_ID,name:"#"});}};e([Input({required:true,alias:"props"})],i.prototype,"propsInput",1),e([ViewChild("wrapperEl")],i.prototype,"wrapperRef",2),e([ViewChild("tableContainerElRef")],i.prototype,"tableContainerRef",2),i=e([Component({selector:"ogrid-datagrid-table",standalone:true,changeDetection:ChangeDetectionStrategy.OnPush,encapsulation:ViewEncapsulation.None,imports:[n,l,StatusBarComponent,GridContextMenuComponent,MarchingAntsOverlayComponent,EmptyStateComponent,FormulaRefOverlayComponent,s,g],providers:[DataGridStateService,ColumnReorderService,VirtualScrollService],template:`
354
- <div class="ogrid-datagrid-root">
355
- <div
356
- #wrapperEl
357
- class="ogrid-datagrid-wrapper"
358
- [class.ogrid-datagrid-wrapper--fit]="layoutModeFit()"
359
- [class.ogrid-datagrid-wrapper--loading-empty]="isLoading() && items().length === 0"
360
- [style.--ogrid-row-height]="rowHeightCssVar()"
361
- tabindex="0"
362
- role="region"
363
- [attr.aria-label]="ariaLabel()"
364
- [attr.aria-labelledby]="ariaLabelledBy()"
365
- (pointerdown)="onWrapperMouseDown($event)"
366
- (keydown)="onGridKeyDown($event)"
367
- (scroll)="onWrapperScroll($event)"
368
- (contextmenu)="$event.preventDefault()"
369
- [class.ogrid-datagrid-wrapper--overflow-x]="allowOverflowX()"
370
- [attr.data-overflow-x]="allowOverflowX() ? 'true' : 'false'"
371
- [attr.data-virtual-scroll]="vsEnabled() ? '' : null"
372
- data-ogrid-scroll-container
373
- >
374
- <div class="ogrid-datagrid-scroll-wrapper">
375
- <div [style.minWidth.px]="allowOverflowX() ? minTableWidth() : undefined" style="overflow-x: clip">
376
- <div [class.ogrid-datagrid-table-wrapper--loading]="isLoading() && items().length > 0" #tableContainerElRef>
377
- <table class="ogrid-datagrid-table" role="grid" [style.minWidth.px]="minTableWidth()"
378
- [attr.data-virtual-scroll]="vsEnabled() ? '' : null"
379
- >
380
- <thead [class]="stickyHeader() ? 'ogrid-datagrid-thead ogrid-sticky-header' : 'ogrid-datagrid-thead'">
381
- @if (showColumnLetters()) {
382
- <tr class="ogrid-column-letter-row">
383
- @if (hasCheckboxCol()) {
384
- <th class="ogrid-column-letter-cell"></th>
385
- }
386
- @if (hasRowNumbersCol()) {
387
- <th class="ogrid-column-letter-cell"></th>
388
- }
389
- @for (col of visibleCols(); track col.columnId; let colIdx = $index) {
390
- <th class="ogrid-column-letter-cell">
391
- {{ getColumnLetter(colIdx) }}
392
- </th>
393
- }
394
- </tr>
395
- }
396
- @for (row of headerRows(); track $index; let rowIdx = $index) {
397
- <tr class="ogrid-datagrid-header-row">
398
- @if (rowIdx === headerRows().length - 1 && hasCheckboxCol()) {
399
- <th class="ogrid-datagrid-th ogrid-datagrid-checkbox-col" [attr.rowSpan]="headerRows().length > 1 ? 1 : null">
400
- <div class="ogrid-datagrid-checkbox-wrapper">
401
- <input
402
- type="checkbox"
403
- [checked]="allSelected()"
404
- [indeterminate]="someSelected()"
405
- (change)="onSelectAllChange($event)"
406
- aria-label="Select all rows"
407
- />
408
- </div>
409
- </th>
410
- }
411
- @if (rowIdx === 0 && rowIdx < headerRows().length - 1 && hasCheckboxCol()) {
412
- <th [attr.rowSpan]="headerRows().length - 1" class="ogrid-datagrid-th" style="width: 48px; min-width: 48px; padding: 0;"></th>
413
- }
414
- @if (rowIdx === headerRows().length - 1 && hasRowNumbersCol()) {
415
- <th class="ogrid-datagrid-th ogrid-row-number-header" [attr.rowSpan]="headerRows().length > 1 ? 1 : null"
416
- [style.width.px]="getRowNumberWidth()"
417
- [style.min-width.px]="getRowNumberWidth()"
418
- [style.max-width.px]="getRowNumberWidth()"
419
- >
420
- <div class="ogrid-row-number-header-content">#</div>
421
- <div class="ogrid-datagrid-resize-handle" (pointerdown)="onResizeRowNumber($event)" (dblclick)="$event.stopPropagation()"></div>
422
- </th>
423
- }
424
- @if (rowIdx === 0 && rowIdx < headerRows().length - 1 && hasRowNumbersCol()) {
425
- <th [attr.rowSpan]="headerRows().length - 1" class="ogrid-datagrid-th" [style.width.px]="getRowNumberWidth()" [style.min-width.px]="getRowNumberWidth()" style="padding: 0;"></th>
426
- }
427
- @for (cell of row; track cell.columnDef?.columnId ?? $index; let cellIdx = $index) {
428
- @if (cell.isGroup) {
429
- <th [attr.colSpan]="cell.colSpan" scope="colgroup" class="ogrid-datagrid-th ogrid-datagrid-group-header">
430
- {{ cell.label }}
431
- </th>
432
- } @else {
433
- @let col = asColumnDef(cell.columnDef);
434
- @let colW = getColumnWidth(col);
435
- @let pinned = isPinned(col.columnId);
436
- @let pinnedLeft = pinned === 'left';
437
- @let pinnedRight = pinned === 'right';
438
- @let sortState = getSortState(col.columnId);
439
- @let ariaSort = sortState === 'asc' ? 'ascending' : sortState === 'desc' ? 'descending' : null;
440
- @let config = getFilterConfig(col);
441
- <th scope="col"
442
- class="ogrid-datagrid-th"
443
- [class.ogrid-datagrid-th--pinned-left]="pinnedLeft"
444
- [class.ogrid-datagrid-th--pinned-right]="pinnedRight"
445
- [attr.rowSpan]="headerRows().length > 1 ? headerRows().length - rowIdx : null"
446
- [attr.data-column-id]="col.columnId"
447
- [attr.aria-sort]="ariaSort"
448
- [style.minWidth.px]="getEffectiveMinWidth(col)"
449
- [style.width.px]="colW"
450
- [style.maxWidth.px]="colW"
451
- [style.cursor]="columnReorderService.isDragging() ? 'grabbing' : 'grab'"
452
- [style.left.px]="pinnedLeft ? getPinnedLeftOffset(col.columnId) : null"
453
- [style.right.px]="pinnedRight ? getPinnedRightOffset(col.columnId) : null"
454
- (pointerdown)="onHeaderMouseDown(col.columnId, $event)"
455
- >
456
- <div style="display:flex;align-items:center;gap:4px;">
457
- <ogrid-column-header-filter
458
- [columnKey]="col.columnId"
459
- [columnName]="col.name"
460
- [filterType]="config.filterType"
461
- [isSorted]="config.isSorted"
462
- [isSortedDescending]="config.isSortedDescending"
463
- [onSort]="config.onSort"
464
- [selectedValues]="config.selectedValues"
465
- [onFilterChange]="config.onFilterChange"
466
- [options]="config.options"
467
- [isLoadingOptions]="config.isLoadingOptions ?? false"
468
- [textValue]="config.textValue ?? ''"
469
- [onTextChange]="config.onTextChange"
470
- [selectedUser]="config.selectedUser"
471
- [onUserChange]="config.onUserChange"
472
- [peopleSearch]="config.peopleSearch"
473
- [dateValue]="config.dateValue"
474
- [onDateChange]="config.onDateChange"
475
- />
476
- @let pinState = getPinState(col.columnId);
477
- <column-header-menu
478
- [columnId]="col.columnId"
479
- [canPinLeft]="pinState.canPinLeft"
480
- [canPinRight]="pinState.canPinRight"
481
- [canUnpin]="pinState.canUnpin"
482
- [currentSort]="sortState"
483
- [isSortable]="col.sortable !== false"
484
- [isResizable]="col.resizable !== false"
485
- [handlers]="getColumnMenuHandlersMemoized(col.columnId)"
486
- />
487
- </div>
488
- <div class="ogrid-datagrid-resize-handle" (pointerdown)="onResizeStart($event, col)" (dblclick)="onResizeDoubleClick($event, col)"></div>
489
- </th>
490
- }
491
- }
492
- </tr>
493
- }
494
- </thead>
495
- @if (!showEmptyInGrid()) {
496
- <tbody>
497
- @if (vsEnabled() && vsTopSpacerHeight() > 0) {
498
- <tr class="ogrid-datagrid-vs-spacer" [style.height.px]="vsTopSpacerHeight()"></tr>
499
- }
500
- @for (item of vsVisibleItems(); track trackRow(localIdx, item); let localIdx = $index) {
501
- @if (isRowGroupHeader(item)) {
502
- <tr
503
- class="ogrid-datagrid-row ogrid-datagrid-row--group-header"
504
- style="background: var(--ogrid-bg-row-group, var(--ogrid-bg-hover, #f5f5f5)); font-weight: 500"
505
- >
506
- <td [attr.colspan]="totalColCount()" [style.padding-left.px]="$any(item).group.depth * 16 + 8">
507
- <button
508
- (click)="toggleGroup($any(item).group.groupKey)"
509
- (keydown.enter)="$event.preventDefault(); toggleGroup($any(item).group.groupKey)"
510
- (keydown.space)="$event.preventDefault(); toggleGroup($any(item).group.groupKey)"
511
- tabindex="0"
512
- style="background: none; border: none; cursor: pointer; padding: 2px 6px; font: inherit; display: inline-flex; align-items: center; gap: 6px"
513
- >
514
- <span style="display: inline-block; transition: transform 0.15s; font-size: 12px"
515
- [style.transform]="rowGroupExpandedGroups().has($any(item).group.groupKey) ? 'rotate(90deg)' : 'rotate(0deg)'"
516
- >&#9654;</span>
517
- <span>{{ $any(item).group.displayText }} ({{ $any(item).group.itemCount }})</span>
518
- </button>
519
- </td>
520
- </tr>
521
- } @else {
522
- @let rowIndex = vsStartIndex() + localIdx;
523
- @let rowId = getRowId()(item);
524
- @let isSelected = selectedRowIds().has(rowId);
525
- <tr
526
- class="ogrid-datagrid-row"
527
- [class.ogrid-datagrid-row--selected]="isSelected"
528
- [attr.data-row-id]="rowId"
529
- [attr.aria-selected]="isSelected || null"
530
- (click)="onRowClick($event, rowId)"
531
- >
532
- @if (hasCheckboxCol()) {
533
- <td class="ogrid-datagrid-td ogrid-datagrid-checkbox-col">
534
- <div
535
- class="ogrid-datagrid-checkbox-wrapper"
536
- [attr.data-row-index]="rowIndex"
537
- [attr.data-col-index]="0"
538
- (click)="$event.stopPropagation()"
539
- >
540
- <input
541
- type="checkbox"
542
- [checked]="isSelected"
543
- (change)="onRowCheckboxChange(rowId, $event, rowIndex)"
544
- [attr.aria-label]="'Select row ' + (rowIndex + 1)"
545
- />
546
- </div>
547
- </td>
548
- }
549
- @if (hasRowNumbersCol()) {
550
- <td class="ogrid-datagrid-td ogrid-row-number-cell"
551
- [style.width.px]="getRowNumberWidth()"
552
- [style.min-width.px]="getRowNumberWidth()"
553
- [style.max-width.px]="getRowNumberWidth()"
554
- >
555
- <div class="ogrid-row-number-cell-content">
556
- {{ rowNumberOffset() + rowIndex + 1 }}
557
- </div>
558
- </td>
559
- }
560
- @if (vsColumnsEnabled() && vsLeftSpacerWidth() > 0) {
561
- <td [style.width.px]="vsLeftSpacerWidth()" [style.minWidth.px]="vsLeftSpacerWidth()" [style.maxWidth.px]="vsLeftSpacerWidth()" [style.padding]="'0'"></td>
562
- }
563
- @for (colLayout of vsColumnLayouts(); track colLayout.col.columnId) {
564
- <td
565
- class="ogrid-datagrid-td"
566
- [attr.data-column-id]="colLayout.col.columnId"
567
- [class.ogrid-datagrid-td--pinned-left]="colLayout.pinnedLeft"
568
- [class.ogrid-datagrid-td--pinned-right]="colLayout.pinnedRight"
569
- [style.minWidth.px]="colLayout.minWidth"
570
- [style.width.px]="colLayout.width"
571
- [style.maxWidth.px]="colLayout.width"
572
- [style.left.px]="colLayout.pinnedLeft ? getPinnedLeftOffset(colLayout.col.columnId) : null"
573
- [style.right.px]="colLayout.pinnedRight ? getPinnedRightOffset(colLayout.col.columnId) : null"
574
- >
575
- @let descriptor = getCellDescriptor(item, colLayout.col, rowIndex, getGlobalColIndex(colLayout.col));
576
- @if (descriptor.mode === 'editing-inline') {
577
- <div class="ogrid-editing-cell">
578
- <ogrid-mat-inline-cell-editor
579
- [value]="descriptor.value"
580
- [item]="item"
581
- [column]="colLayout.col"
582
- [rowIndex]="rowIndex"
583
- [editorType]="descriptor.editorType ?? 'text'"
584
- (commit)="commitEdit(item, colLayout.col.columnId, descriptor.value, $event, rowIndex, descriptor.globalColIndex)"
585
- (cancel)="cancelEdit()"
586
- ></ogrid-mat-inline-cell-editor>
587
- </div>
588
- } @else if (descriptor.mode === 'editing-popover') {
589
- @let editorProps = buildPopoverEditorProps(item, colLayout.col, descriptor);
590
- <ogrid-mat-popover-cell-editor
591
- [item]="item"
592
- [column]="colLayout.col"
593
- [rowIndex]="rowIndex"
594
- [globalColIndex]="descriptor.globalColIndex"
595
- [displayValue]="descriptor.displayValue"
596
- [editorProps]="editorProps"
597
- [onCancel]="cancelEdit.bind(this)"
598
- ></ogrid-mat-popover-cell-editor>
599
- } @else {
600
- @let content = resolveCellContent(colLayout.col, item, descriptor.displayValue);
601
- @let cellStyle = resolveCellStyleFn(colLayout.col, item, descriptor.displayValue);
602
- <div
603
- class="ogrid-datagrid-cell"
604
- [class.ogrid-datagrid-cell--active]="descriptor.isActive"
605
- [class.ogrid-datagrid-cell--active-in-range]="descriptor.isActive && descriptor.isInRange"
606
- [class.ogrid-datagrid-cell--in-range]="descriptor.isInRange && !descriptor.isActive"
607
- [class.ogrid-datagrid-cell--in-cut-range]="descriptor.isInCutRange"
608
- [class.ogrid-datagrid-cell--editable]="descriptor.canEditAny"
609
- [class.ogrid-datagrid-cell--numeric]="colLayout.col.type === 'numeric'"
610
- [class.ogrid-datagrid-cell--boolean]="colLayout.col.type === 'boolean'"
611
- [attr.data-row-index]="rowIndex"
612
- [attr.data-col-index]="descriptor.globalColIndex"
613
- [attr.data-in-range]="descriptor.isInRange ? 'true' : null"
614
- [attr.tabindex]="descriptor.isActive ? 0 : -1"
615
- (pointerdown)="onCellMouseDown($event, rowIndex, descriptor.globalColIndex)"
616
- (click)="onCellClick(rowIndex, descriptor.globalColIndex)"
617
- (contextmenu)="onCellContextMenu($event)"
618
- (dblclick)="descriptor.canEditAny ? onCellDblClick(descriptor.rowId, colLayout.col.columnId) : null"
619
- [attr.role]="descriptor.canEditAny ? 'button' : null"
620
- [style]="cellStyle ?? undefined"
621
- >
622
- @if (colLayout.col.type === 'boolean') {
623
- <input type="checkbox" [checked]="!!descriptor.displayValue" [disabled]="!descriptor.canEditAny" (change)="descriptor.canEditAny ? commitBooleanEdit(item, colLayout.col.columnId, !!descriptor.displayValue, rowIndex, descriptor.globalColIndex) : null" (pointerdown)="onBooleanCheckboxPointerDown($event, rowIndex, descriptor.globalColIndex)" (click)="$event.stopPropagation()" style="margin:0;outline:none" [style.cursor]="descriptor.canEditAny ? 'pointer' : 'default'" [attr.aria-label]="descriptor.displayValue ? 'Checked' : 'Unchecked'" />
624
- } @else {
625
- {{ content }}
626
- }
627
- @if (descriptor.canEditAny && descriptor.isSelectionEndCell) {
628
- <div
629
- class="ogrid-datagrid-fill-handle"
630
- (pointerdown)="onFillHandleMouseDown($event)"
631
- aria-label="Fill handle"
632
- ></div>
633
- }
634
- </div>
635
- }
636
- </td>
637
- }
638
- @if (vsColumnsEnabled() && vsRightSpacerWidth() > 0) {
639
- <td [style.width.px]="vsRightSpacerWidth()" [style.minWidth.px]="vsRightSpacerWidth()" [style.maxWidth.px]="vsRightSpacerWidth()" [style.padding]="'0'"></td>
640
- }
641
- </tr>
642
- }
643
- }
644
- @if (vsEnabled() && vsBottomSpacerHeight() > 0) {
645
- <tr class="ogrid-datagrid-vs-spacer" [style.height.px]="vsBottomSpacerHeight()"></tr>
646
- }
647
- </tbody>
648
- }
649
- </table>
650
-
651
- <ogrid-marching-ants-overlay
652
- [containerEl]="tableContainerEl()"
653
- [selectionRange]="state().interaction.selectionRange"
654
- [copyRange]="state().interaction.copyRange"
655
- [cutRange]="state().interaction.cutRange"
656
- [colOffset]="state().layout.colOffset"
657
- [columnSizingVersion]="columnSizingVersion()"
658
- [items]="items()"
659
- [visibleColumns]="propsVisibleColumns()"
660
- [columnOrder]="propsColumnOrder()"
661
- ></ogrid-marching-ants-overlay>
662
-
663
- @if (formulaReferences() && formulaReferences()!.length > 0) {
664
- <ogrid-formula-ref-overlay
665
- [containerEl]="tableContainerEl()"
666
- [references]="formulaReferences()!"
667
- [colOffset]="colOffset()"
668
- />
669
- }
670
-
671
- @if (showEmptyInGrid() && emptyState()) {
672
- <div class="ogrid-datagrid-empty">
673
- <div class="ogrid-datagrid-empty__title">No results found</div>
674
- <div class="ogrid-datagrid-empty__message">
675
- <ogrid-empty-state
676
- [message]="emptyState()?.message"
677
- [hasActiveFilters]="emptyState()?.hasActiveFilters ?? false"
678
- [render]="emptyState()?.render"
679
- (clearAll)="emptyState()?.onClearAll()"
680
- ></ogrid-empty-state>
681
- </div>
682
- </div>
683
- }
684
- </div>
685
- </div>
686
- </div>
687
-
688
- @if (columnReorderService.isDragging() && columnReorderService.dropIndicatorX() !== null) {
689
- <div class="ogrid-datagrid-drop-indicator" [style.left.px]="columnReorderService.dropIndicatorX()"></div>
690
- }
691
-
692
- @if (menuPosition()) {
693
- <div
694
- class="ogrid-datagrid-context-menu-overlay"
695
- (click)="closeContextMenu()"
696
- (contextmenu)="$event.preventDefault(); closeContextMenu()"
697
- >
698
- <ogrid-context-menu
699
- [x]="menuPosition()!.x"
700
- [y]="menuPosition()!.y"
701
- [hasSelection]="hasCellSelection()"
702
- [canUndoProp]="canUndo()"
703
- [canRedoProp]="canRedo()"
704
- (undoAction)="onUndo()"
705
- (redoAction)="onRedo()"
706
- (copyAction)="handleCopy()"
707
- (cutAction)="handleCut()"
708
- (pasteAction)="handlePaste()"
709
- (selectAllAction)="handleSelectAllCells()"
710
- (closeAction)="closeContextMenu()"
711
- />
712
- </div>
713
- }
714
- </div>
715
-
716
- @let sbConfig = statusBarConfig();
717
- @if (sbConfig) {
718
- <ogrid-status-bar
719
- [totalCount]="sbConfig.totalCount"
720
- [filteredCount]="sbConfig.filteredCount"
721
- [selectedCount]="sbConfig.selectedCount ?? selectedRowIds().size"
722
- [selectedCellCount]="selectionCellCount()"
723
- [aggregation]="sbConfig.aggregation"
724
- [suppressRowCount]="sbConfig.suppressRowCount"
725
- />
726
- }
727
-
728
- @if (isLoading()) {
729
- <div class="ogrid-datagrid-loading-overlay">
730
- <div class="ogrid-datagrid-loading-inner">
731
- <div class="ogrid-datagrid-spinner"></div>
732
- <span>{{ loadingMessage() }}</span>
733
- </div>
734
- </div>
735
- }
736
- </div>
737
- `,styles:[OGRID_THEME_VARS_CSS,`
738
- :host { display: block; }
739
- .ogrid-datagrid-root { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; }
740
- .ogrid-datagrid-wrapper {
741
- position: relative; width: 100%; max-width: 100%;
742
- overflow-x: hidden; overflow-y: auto; background: var(--ogrid-bg, #ffffff);
743
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
744
- will-change: scroll-position; outline: none;
745
- }
746
- .ogrid-datagrid-wrapper[data-virtual-scroll] { flex: 1; min-height: 0; }
747
- .ogrid-datagrid-wrapper [data-drag-range] { background: var(--ogrid-range-bg, rgba(33, 115, 70, 0.12)); }
748
- .ogrid-datagrid-cell--active[data-drag-range] { outline: none; }
749
- .ogrid-datagrid-wrapper--fit { width: fit-content; }
750
- .ogrid-datagrid-wrapper--overflow-x { overflow-x: auto; }
751
- .ogrid-datagrid-wrapper--loading-empty { min-height: 200px; }
752
- .ogrid-datagrid-scroll-wrapper { display: flex; flex-direction: column; min-height: 100%; }
753
- .ogrid-datagrid-table-wrapper--loading { position: relative; opacity: 0.6; }
754
- .ogrid-datagrid-table {
755
- width: 100%; min-width: max-content; border-collapse: collapse; table-layout: fixed;
756
- }
757
- .ogrid-datagrid-table tr th:first-child,
758
- .ogrid-datagrid-table tr td:first-child { border-left: none; }
759
- .ogrid-datagrid-table tbody tr { height: var(--ogrid-row-height, auto); }
760
- .ogrid-datagrid-thead {
761
- z-index: 8; background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04));
762
- }
763
- .ogrid-datagrid-thead th { background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)); }
764
- .ogrid-datagrid-header-row { background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)); }
765
- .ogrid-datagrid-th {
766
- font-weight: 600; padding: 6px 10px; text-align: left;
767
- font-size: 14px; border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
768
- background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)); z-index: 8;
769
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
770
- }
771
- .ogrid-sticky-header .ogrid-datagrid-th { position: sticky; top: 0; }
772
- .ogrid-datagrid-th:focus-visible {
773
- outline: 2px solid var(--mat-sys-primary, #1976d2); outline-offset: -2px; z-index: 11;
774
- }
775
- .ogrid-datagrid-th--pinned-left {
776
- position: sticky; top: 0; left: 0; z-index: 10; background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)); will-change: transform;
777
- border-right: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
778
- box-shadow: 2px 0 4px -1px rgba(0, 0, 0, 0.1);
779
- }
780
- .ogrid-datagrid-th--pinned-right {
781
- position: sticky; top: 0; right: 0; z-index: 10; background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)); will-change: transform;
782
- border-left: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
783
- box-shadow: -2px 0 4px -1px rgba(0, 0, 0, 0.1);
784
- }
785
- .ogrid-datagrid-group-header {
786
- text-align: center; font-weight: 600; border-bottom: 2px solid var(--ogrid-border, rgba(0, 0, 0, 0.12)); padding: 6px;
787
- }
788
- .ogrid-datagrid-checkbox-col {
789
- width: ${CHECKBOX_COLUMN_WIDTH}px; min-width: ${CHECKBOX_COLUMN_WIDTH}px;
790
- max-width: ${CHECKBOX_COLUMN_WIDTH}px; text-align: center;
791
- }
792
- .ogrid-datagrid-checkbox-wrapper { display: flex; align-items: center; justify-content: center; }
793
- .ogrid-row-number-header, .ogrid-row-number-cell {
794
- text-align: center;
795
- background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)); font-weight: 600;
796
- font-variant-numeric: tabular-nums; color: var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.6));
797
- position: sticky; left: 0; z-index: 3;
798
- }
799
- .ogrid-row-number-header { z-index: 4; }
800
- .ogrid-row-number-header-content, .ogrid-row-number-cell-content {
801
- display: flex; align-items: center; justify-content: center;
802
- }
803
- .ogrid-datagrid-row { }
804
- .ogrid-datagrid-row:hover { background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)); }
805
- .ogrid-datagrid-row--selected { background: var(--ogrid-selected-row-bg, #e6f0fb); }
806
- .ogrid-datagrid-td { position: relative; padding: 0; height: 1px; border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.06)); }
807
- .ogrid-datagrid-td--pinned-left {
808
- position: sticky; left: 0; z-index: 6; background: var(--ogrid-bg, #ffffff); will-change: transform;
809
- border-right: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
810
- box-shadow: 2px 0 4px -1px rgba(0, 0, 0, 0.1);
811
- }
812
- .ogrid-datagrid-td--pinned-right {
813
- position: sticky; right: 0; z-index: 6; background: var(--ogrid-bg, #ffffff); will-change: transform;
814
- border-left: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
815
- box-shadow: -2px 0 4px -1px rgba(0, 0, 0, 0.1);
816
- }
817
- .ogrid-datagrid-cell {
818
- width: 100%; height: 100%; display: flex; align-items: center; min-width: 0;
819
- padding: var(--ogrid-cell-padding, 6px 10px); box-sizing: border-box; overflow: hidden;
820
- text-overflow: ellipsis; white-space: nowrap; user-select: none; outline: none;
821
- font-size: 14px; color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
822
- }
823
- .ogrid-datagrid-cell:focus-visible {
824
- outline: 2px solid var(--mat-sys-primary, #1976d2); outline-offset: -2px; z-index: 3;
825
- }
826
- .ogrid-datagrid-cell--numeric { justify-content: flex-end; text-align: right; }
827
- .ogrid-datagrid-cell--boolean { justify-content: flex-start; }
828
- .ogrid-datagrid-cell--editable { cursor: cell; }
829
- .ogrid-datagrid-cell--active {
830
- outline: 2px solid var(--ogrid-selection-color, #217346); outline-offset: -1px;
831
- z-index: 2; position: relative; overflow: visible;
832
- }
833
- .ogrid-datagrid-td:has(> .ogrid-datagrid-cell--active),
834
- .ogrid-datagrid-td:has(> .ogrid-editing-cell) { z-index: 2; }
835
- .ogrid-datagrid-cell--active-in-range { outline: none; background: var(--ogrid-bg, #fff); }
836
- .ogrid-datagrid-cell--in-range { background: var(--ogrid-range-bg, rgba(33, 115, 70, 0.12)); }
837
- .ogrid-datagrid-cell--in-cut-range { background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)); opacity: 0.7; }
838
- .ogrid-datagrid-cell--editing { padding: 0; }
839
- .ogrid-editing-cell {
840
- width: 100%; height: 100%; display: flex; align-items: center; box-sizing: border-box;
841
- outline: 2px solid var(--ogrid-selection-color, #217346); outline-offset: -1px;
842
- z-index: 2; position: relative; background: var(--ogrid-bg, #fff); overflow: hidden; padding: 0;
843
- }
844
- .ogrid-datagrid-editor-input {
845
- width: 100%; height: 100%; padding: 6px 10px; border: 2px solid var(--ogrid-selection-color, #217346);
846
- box-sizing: border-box; font-size: 14px; outline: none; font-family: inherit; line-height: inherit;
847
- background: var(--ogrid-bg, #ffffff); color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
848
- }
849
- .ogrid-datagrid-cell--numeric .ogrid-datagrid-editor-input {
850
- text-align: right;
851
- }
852
- .ogrid-datagrid-editor-select {
853
- width: 100%; height: 100%; padding: 4px 8px; border: 2px solid var(--ogrid-selection-color, #217346);
854
- box-sizing: border-box; font-size: 14px;
855
- background: var(--ogrid-bg, #ffffff); color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
856
- }
857
- .ogrid-datagrid-fill-handle {
858
- position: absolute; right: -3px; bottom: -3px; width: 7px; height: 7px;
859
- background: var(--ogrid-selection-color, #217346);
860
- border: 1px solid var(--ogrid-bg, #ffffff); border-radius: 1px;
861
- cursor: crosshair; pointer-events: auto; touch-action: none; z-index: 3;
862
- }
863
- @media (pointer: coarse) {
864
- .ogrid-datagrid-fill-handle { width: 14px; height: 14px; right: -7px; bottom: -7px; border-radius: 2px; }
865
- }
866
- .ogrid-datagrid-resize-handle {
867
- position: absolute; top: 0; right: -3px; bottom: 0; width: 8px;
868
- cursor: col-resize; user-select: none; touch-action: none;
869
- }
870
- @media (pointer: coarse) {
871
- .ogrid-datagrid-resize-handle { width: 16px; right: -8px; }
872
- }
873
- .ogrid-datagrid-resize-handle::after {
874
- content: ''; position: absolute; top: 4px; right: 3px; bottom: 4px; width: 2px;
875
- background: var(--ogrid-border, rgba(0, 0, 0, 0.12)); border-radius: 1px; transition: background 0.15s;
876
- }
877
- .ogrid-datagrid-resize-handle:hover::after { background: var(--ogrid-fg-muted, rgba(0, 0, 0, 0.4)); }
878
- .ogrid-datagrid-resize-handle:active::after { background: var(--mat-sys-primary, #1976d2); }
879
- .ogrid-datagrid-empty {
880
- padding: 32px 16px; text-align: center; border-top: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
881
- background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04));
882
- }
883
- .ogrid-datagrid-empty__title { font-size: 18px; font-weight: 600; margin-bottom: 8px; color: var(--ogrid-fg, rgba(0, 0, 0, 0.87)); }
884
- .ogrid-datagrid-empty__message { font-size: 14px; color: var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.6)); }
885
- .ogrid-datagrid-empty__clear {
886
- background: none; border: none; color: var(--mat-sys-primary, #1976d2);
887
- cursor: pointer; font-size: inherit; text-decoration: underline; padding: 0;
888
- }
889
- .ogrid-datagrid-loading-overlay {
890
- position: absolute; inset: 0; z-index: 2;
891
- display: flex; align-items: center; justify-content: center;
892
- background: var(--ogrid-loading-overlay, rgba(255, 255, 255, 0.7));
893
- }
894
- .ogrid-datagrid-loading-inner {
895
- display: flex; flex-direction: column; align-items: center; gap: 8px;
896
- padding: 16px; background: var(--ogrid-bg, #ffffff); border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12)); border-radius: 4px;
897
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
898
- }
899
- .ogrid-datagrid-spinner {
900
- width: 24px; height: 24px; border: 3px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
901
- border-top-color: var(--mat-sys-primary, #1976d2);
902
- border-radius: 50%; animation: ogrid-spin 0.8s linear infinite;
903
- }
904
- @keyframes ogrid-spin { to { transform: rotate(360deg); } }
905
- .ogrid-datagrid-drop-indicator {
906
- position: absolute; top: 0; bottom: 0; width: 3px;
907
- background: var(--ogrid-selection-color, #217346);
908
- pointer-events: none; z-index: 100; transition: left 0.05s;
909
- }
910
- .ogrid-datagrid-context-menu-overlay {
911
- position: fixed; inset: 0; z-index: 1000;
912
- }
913
- .ogrid-column-letter-cell {
914
- text-align: center;
915
- font-size: 11px;
916
- font-weight: 500;
917
- color: var(--ogrid-fg-muted, rgba(0, 0, 0, 0.4));
918
- padding: 2px 4px;
919
- background: var(--ogrid-column-letter-bg, var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)));
920
- border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
921
- user-select: none;
922
- font-variant-numeric: tabular-nums;
923
- }
924
-
925
- /* Reveal column menu trigger on header hover without layout shift.
926
- The button always takes up space (visibility: hidden); shown when column is hovered. */
927
- @media (hover: hover) {
928
- th:hover .column-header-menu-trigger { visibility: visible; }
929
- }
930
-
931
- /* Angular Material Menu popup dark mode overrides.
932
- Double-class selector (0,2,0) beats MUI's single-class (0,1,0) defaults. */
933
- .mat-mdc-menu-panel.mat-mdc-menu-panel {
934
- background: var(--ogrid-bg, #ffffff);
935
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
936
- }
937
- .mat-mdc-menu-item.mat-mdc-menu-item {
938
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
939
- }
940
- .mat-mdc-menu-item.mat-mdc-menu-item:hover:not([disabled]) {
941
- background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04));
942
- }
943
- .mat-mdc-menu-item.mat-mdc-menu-item .mat-mdc-menu-item-text {
944
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
945
- }
946
- `]})],i);var c=class extends BaseColumnChooserComponent{onDocumentClick(a){a.target.closest("ogrid-column-chooser")||this.isOpen.set(false);}};c=e([Component({selector:"ogrid-column-chooser",standalone:true,changeDetection:ChangeDetectionStrategy.OnPush,template:`
947
- <div class="ogrid-column-chooser">
948
- <button
949
- class="ogrid-column-chooser__trigger"
950
- (click)="toggle()"
951
- [attr.aria-expanded]="isOpen()"
952
- aria-haspopup="listbox"
953
- >
954
- &#9638; Column Visibility ({{ visibleCount() }} of {{ totalCount() }})
955
- <span class="ogrid-column-chooser__caret">{{ isOpen() ? '&#9650;' : '&#9660;' }}</span>
956
- </button>
957
-
958
- @if (isOpen()) {
959
- <div class="ogrid-column-chooser__dropdown" (click)="$event.stopPropagation()">
960
- <div class="ogrid-column-chooser__header">
961
- Select Columns ({{ visibleCount() }} of {{ totalCount() }})
962
- </div>
963
-
964
- <div class="ogrid-column-chooser__list">
965
- @for (col of columns; track col.columnId) {
966
- <label class="ogrid-column-chooser__item">
967
- <input
968
- type="checkbox"
969
- [checked]="visibleColumns.has(col.columnId)"
970
- (change)="onCheckboxChange(col.columnId, $event)"
971
- />
972
- <span>{{ col.name }}</span>
973
- </label>
974
- }
975
- </div>
976
-
977
- <div class="ogrid-column-chooser__footer">
978
- <button class="ogrid-column-chooser__btn" (click)="onClearAll()">Clear All</button>
979
- <button class="ogrid-column-chooser__btn ogrid-column-chooser__btn--primary" (click)="selectAll()">Select All</button>
980
- </div>
981
- </div>
982
- }
983
- </div>
984
- `,styles:[`
985
- :host { display: inline-flex; position: relative; }
986
- .ogrid-column-chooser { position: relative; }
987
- .ogrid-column-chooser__trigger {
988
- display: inline-flex; align-items: center; gap: 6px;
989
- padding: 6px 12px; border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.23)); border-radius: 4px;
990
- background: transparent; cursor: pointer; font-size: 14px; font-weight: 600;
991
- text-transform: none; white-space: nowrap;
992
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
993
- }
994
- .ogrid-column-chooser__trigger:hover { background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)); }
995
- .ogrid-column-chooser__caret { font-size: 10px; }
996
- .ogrid-column-chooser__dropdown {
997
- position: absolute; top: 100%; right: 0; z-index: 1000;
998
- min-width: 220px; margin-top: 4px;
999
- background: var(--ogrid-bg, #ffffff); border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12)); border-radius: 4px;
1000
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
1001
- }
1002
- .ogrid-column-chooser__header {
1003
- padding: 8px 12px; font-size: 14px; font-weight: 600;
1004
- border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
1005
- background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04));
1006
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
1007
- }
1008
- .ogrid-column-chooser__list {
1009
- max-height: 320px; overflow-y: auto; padding: 4px 0;
1010
- }
1011
- .ogrid-column-chooser__item {
1012
- display: flex; align-items: center; gap: 8px;
1013
- padding: 4px 12px; min-height: 32px; cursor: pointer; font-size: 14px;
1014
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
1015
- }
1016
- .ogrid-column-chooser__item:hover { background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)); }
1017
- .ogrid-column-chooser__footer {
1018
- display: flex; justify-content: flex-end; gap: 8px;
1019
- padding: 8px 12px; border-top: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
1020
- background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04));
1021
- }
1022
- .ogrid-column-chooser__btn {
1023
- padding: 4px 12px; border: none; border-radius: 4px;
1024
- background: transparent; cursor: pointer; font-size: 13px; text-transform: none;
1025
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
1026
- }
1027
- .ogrid-column-chooser__btn:hover { background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)); }
1028
- .ogrid-column-chooser__btn--primary {
1029
- background: var(--mat-sys-primary, #1976d2); color: #fff;
1030
- }
1031
- .ogrid-column-chooser__btn--primary:hover {
1032
- opacity: 0.9;
1033
- }
1034
- `],host:{"(document:click)":"onDocumentClick($event)"}})],c);var p=class extends BasePaginationControlsComponent{};p=e([Component({selector:"ogrid-pagination-controls",standalone:true,changeDetection:ChangeDetectionStrategy.OnPush,template:`
1035
- @if (vm(); as vm) {
1036
- <nav class="ogrid-pagination" role="navigation" aria-label="Pagination">
1037
- <span class="ogrid-pagination__info">
1038
- Showing {{ vm.startItem }} to {{ vm.endItem }} of {{ totalCount.toLocaleString() }} {{ entityLabelPlural }}
1039
- </span>
1040
-
1041
- <span class="ogrid-pagination__pages">
1042
- <button
1043
- class="ogrid-pagination__btn"
1044
- [disabled]="currentPage === 1"
1045
- (click)="pageChange.emit(1)"
1046
- aria-label="First page"
1047
- >&laquo;</button>
1048
- <button
1049
- class="ogrid-pagination__btn"
1050
- [disabled]="currentPage === 1"
1051
- (click)="pageChange.emit(currentPage - 1)"
1052
- aria-label="Previous page"
1053
- >&lsaquo;</button>
1054
-
1055
- @if (vm.showStartEllipsis) {
1056
- <button class="ogrid-pagination__btn" (click)="pageChange.emit(1)" aria-label="Page 1">1</button>
1057
- <span class="ogrid-pagination__ellipsis" aria-hidden="true">&hellip;</span>
1058
- }
1059
-
1060
- @for (pageNum of vm.pageNumbers; track pageNum) {
1061
- <button
1062
- class="ogrid-pagination__btn"
1063
- [class.ogrid-pagination__btn--active]="currentPage === pageNum"
1064
- (click)="pageChange.emit(pageNum)"
1065
- [attr.aria-label]="'Page ' + pageNum"
1066
- [attr.aria-current]="currentPage === pageNum ? 'page' : null"
1067
- >{{ pageNum }}</button>
1068
- }
1069
-
1070
- @if (vm.showEndEllipsis) {
1071
- <span class="ogrid-pagination__ellipsis" aria-hidden="true">&hellip;</span>
1072
- <button
1073
- class="ogrid-pagination__btn"
1074
- (click)="pageChange.emit(vm.totalPages)"
1075
- [attr.aria-label]="'Page ' + vm.totalPages"
1076
- >{{ vm.totalPages }}</button>
1077
- }
1078
-
1079
- <button
1080
- class="ogrid-pagination__btn"
1081
- [disabled]="currentPage >= vm.totalPages"
1082
- (click)="pageChange.emit(currentPage + 1)"
1083
- aria-label="Next page"
1084
- >&rsaquo;</button>
1085
- <button
1086
- class="ogrid-pagination__btn"
1087
- [disabled]="currentPage >= vm.totalPages"
1088
- (click)="pageChange.emit(vm.totalPages)"
1089
- aria-label="Last page"
1090
- >&raquo;</button>
1091
- </span>
1092
-
1093
- <span class="ogrid-pagination__size">
1094
- <label>Rows
1095
- <select
1096
- [value]="pageSize"
1097
- (change)="onPageSizeSelect($event)"
1098
- aria-label="Rows per page"
1099
- >
1100
- @for (n of vm.pageSizeOptions; track n) {
1101
- <option [value]="n" [selected]="pageSize === n">{{ n }}</option>
1102
- }
1103
- </select>
1104
- </label>
1105
- </span>
1106
- </nav>
1107
- }
1108
- `,styles:[`
1109
- :host { display: block; }
1110
- .ogrid-pagination {
1111
- display: flex; align-items: center; justify-content: space-between;
1112
- flex-wrap: wrap; gap: 8px; padding: 6px 12px; font-size: 14px;
1113
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
1114
- }
1115
- .ogrid-pagination__info { color: var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.6)); }
1116
- .ogrid-pagination__pages { display: flex; align-items: center; gap: 2px; }
1117
- .ogrid-pagination__btn {
1118
- min-width: 32px; height: 32px; padding: 0 6px;
1119
- border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.23)); border-radius: 4px;
1120
- background: transparent; cursor: pointer; font-size: 14px;
1121
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
1122
- }
1123
- .ogrid-pagination__btn:hover:not(:disabled) { background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)); }
1124
- .ogrid-pagination__btn:disabled { opacity: 0.38; cursor: default; }
1125
- .ogrid-pagination__btn--active {
1126
- background: var(--mat-sys-primary, #1976d2); color: #fff;
1127
- border-color: var(--mat-sys-primary, #1976d2);
1128
- }
1129
- .ogrid-pagination__ellipsis { margin: 0 4px; color: var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.6)); }
1130
- .ogrid-pagination__size { display: flex; align-items: center; gap: 8px; color: var(--ogrid-fg, rgba(0, 0, 0, 0.87)); }
1131
- .ogrid-pagination__size select {
1132
- min-width: 60px; height: 32px; padding: 4px 8px;
1133
- border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.23)); border-radius: 4px;
1134
- font-size: 14px; margin-left: 8px;
1135
- background: var(--ogrid-bg, #ffffff); color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
1136
- }
1137
- @media (max-width: 576px) {
1138
- .ogrid-pagination { flex-direction: column; align-items: stretch; gap: 6px; padding: 6px 8px; font-size: 12px; }
1139
- .ogrid-pagination__pages { order: -1; justify-content: center; }
1140
- .ogrid-pagination__info { text-align: center; font-size: 11px; }
1141
- .ogrid-pagination__size { font-size: 11px; justify-content: center; }
1142
- }
1143
- `]})],p);var f=class extends BaseOGridComponent{};f=e([Component({selector:"ogrid",standalone:true,changeDetection:ChangeDetectionStrategy.OnPush,imports:[OGridLayoutComponent,i,c,p],providers:[OGridService],styles:[":host { display: block; height: 100%; }"],template:`
1144
- <ogrid-layout
1145
- [className]="ogridService.className()"
1146
- [sideBar]="ogridService.sideBarProps()"
1147
- [hasToolbar]="showToolbar"
1148
- [hasToolbarBelow]="false"
1149
- [hasPagination]="true"
1150
- [fullScreen]="ogridService.fullScreen()"
1151
- [showNameBox]="!!(ogridService.cellReferences() && !ogridService.formulasEnabled())"
1152
- [activeCellRef]="ogridService.activeCellRef()"
1153
- [formulaBar]="ogridService.formulasEnabled() ? ogridService.formulaBarState() : null"
1154
- [sheetDefs]="ogridService.sheetDefs()"
1155
- [activeSheet]="ogridService.activeSheet()"
1156
- [onSheetChange]="ogridService.onSheetChange()"
1157
- [onSheetAdd]="ogridService.onSheetAdd()"
1158
- >
1159
- <ng-container toolbarEnd>
1160
- @if (ogridService.columnChooserPlacement() === 'toolbar') {
1161
- <ogrid-column-chooser
1162
- [columns]="ogridService.columnChooser().columns"
1163
- [visibleColumns]="ogridService.columnChooser().visibleColumns"
1164
- (visibilityChange)="ogridService.columnChooser().onVisibilityChange($event.columnKey, $event.visible)"
1165
- />
1166
- }
1167
- </ng-container>
1168
-
1169
- <ogrid-datagrid-table [props]="ogridService.dataGridProps()" />
1170
-
1171
- <ng-container pagination>
1172
- <ogrid-pagination-controls
1173
- [currentPage]="ogridService.pagination().page"
1174
- [pageSize]="ogridService.pagination().pageSize"
1175
- [totalCount]="ogridService.pagination().displayTotalCount"
1176
- [pageSizeOptions]="ogridService.pagination().pageSizeOptions"
1177
- [entityLabelPlural]="ogridService.pagination().entityLabelPlural"
1178
- (pageChange)="ogridService.pagination().setPage($event)"
1179
- (pageSizeChange)="onPageSizeChange($event)"
1180
- />
1181
- </ng-container>
1182
- </ogrid-layout>
1183
- `})],f);export{c as ColumnChooserComponent,n as ColumnHeaderFilterComponent,l as ColumnHeaderMenuComponent,i as DataGridTableComponent,s as InlineCellEditorComponent,f as OGridComponent,p as PaginationControlsComponent,g as PopoverCellEditorComponent};
1
+ // Explicit named re-exports from base package (replaces export * for better tree-shaking).
2
+ // Core value exports
3
+ export { toUserLike, isInSelectionRange, normalizeSelectionRange, escapeCsvValue, buildCsvHeader, buildCsvRows, exportToCsv, triggerCsvDownload, getCellValue, flattenColumns, buildHeaderRows, isFilterConfig, getFilterField, mergeFilter, deriveFilterOptionsFromData, getMultiSelectFilterFields, getStatusBarParts, getDataGridStatusBarConfig, getPaginationViewModel, PAGE_SIZE_OPTIONS, MAX_PAGE_BUTTONS, GRID_CONTEXT_MENU_ITEMS, COLUMN_HEADER_MENU_ITEMS, getContextMenuHandlers, getColumnHeaderMenuItems, formatShortcut, parseValue, numberParser, currencyParser, dateParser, emailParser, booleanParser, computeAggregations, processClientSideData, areGridRowPropsEqual, isRowInRange, getPinStateForColumn, reorderColumnArray, calculateDropTarget, computeVisibleRange, computeTotalHeight, getScrollTopForRow, getHeaderFilterConfig, getCellRenderDescriptor, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, debounce, measureRange, injectGlobalStyles, computeNextSortState, measureColumnContentWidth, AUTOSIZE_EXTRA_PX, AUTOSIZE_MAX_PX, findCtrlArrowTarget, computeTabNavigation, computeArrowNavigation, applyCellDeletion, rangesEqual, clampSelectionToBounds, computeAutoScrollSpeed, applyRangeRowSelection, computeRowSelectionState, formatCellValueForTsv, formatSelectionAsTsv, parseTsvClipboard, applyPastedValues, applyCutClear, applyFillValues, UndoRedoStack, validateColumns, validateRowIds, CHECKBOX_COLUMN_WIDTH, ROW_NUMBER_COLUMN_WIDTH, DEFAULT_MIN_COLUMN_WIDTH, CELL_PADDING, GRID_BORDER_RADIUS, DEFAULT_DEBOUNCE_MS, PEOPLE_SEARCH_DEBOUNCE_MS, SIDEBAR_TRANSITION_MS, Z_INDEX, } from '@alaarab/ogrid-angular';
4
+ // Angular services and components
5
+ export { OGridService, DataGridStateService, DataGridLayoutHelper, DataGridEditingHelper, DataGridInteractionHelper, ColumnReorderService, VirtualScrollService, OGridLayoutComponent, StatusBarComponent, GridContextMenuComponent, SideBarComponent, MarchingAntsOverlayComponent, EmptyStateComponent, BaseOGridComponent, BaseDataGridTableComponent, BaseColumnHeaderFilterComponent, BaseColumnChooserComponent, BasePaginationControlsComponent, BaseInlineCellEditorComponent, INLINE_CELL_EDITOR_TEMPLATE, INLINE_CELL_EDITOR_STYLES, BasePopoverCellEditorComponent, POPOVER_CELL_EDITOR_TEMPLATE, POPOVER_CELL_EDITOR_OVERLAY_STYLES, OGRID_THEME_VARS_CSS, createDebouncedSignal, createDebouncedCallback, createLatestCallback, } from '@alaarab/ogrid-angular';
6
+ // Components
7
+ export { OGridComponent } from './ogrid/ogrid.component';
8
+ export { DataGridTableComponent } from './datagrid-table/datagrid-table.component';
9
+ export { ColumnHeaderFilterComponent } from './column-header-filter/column-header-filter.component';
10
+ // IColumnHeaderFilterProps is now exported from @alaarab/ogrid-angular (base class)
11
+ export { ColumnChooserComponent } from './column-chooser/column-chooser.component';
12
+ // IColumnChooserProps is now exported from @alaarab/ogrid-angular (base class)
13
+ export { PaginationControlsComponent } from './pagination-controls/pagination-controls.component';
14
+ export { ColumnHeaderMenuComponent } from './column-header-menu/column-header-menu.component';
15
+ export { InlineCellEditorComponent } from './datagrid-table/inline-cell-editor.component';
16
+ export { PopoverCellEditorComponent } from './datagrid-table/popover-cell-editor.component';