@agility-workbench/angular-grid 1.0.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.
@@ -0,0 +1,1028 @@
1
+ import { isClassRenderer, isClassTooltipComponent, isClassActionFrameComponent, isClassSetFilterComponent, createGrid } from '@agility-workbench/grid';
2
+ export * from '@agility-workbench/grid';
3
+ import * as i0 from '@angular/core';
4
+ import { reflectComponentType, createComponent, input, output, inject, ElementRef, NgZone, Injector, ApplicationRef, EnvironmentInjector, afterNextRender, untracked, effect, ChangeDetectionStrategy, Component } from '@angular/core';
5
+
6
+ /** True when `value` is a compiled Angular component class (vs a core class or plain function). */
7
+ function isNgComponent(value) {
8
+ return typeof value === "function" && reflectComponentType(value) !== null;
9
+ }
10
+ /**
11
+ * Push params into a freshly created / refreshing component using whichever contract it implements:
12
+ * `awbInit(params)` (interface style) or a declared input named `params` (signal-input style).
13
+ */
14
+ function deliverParams(ref, mirror, params, kind) {
15
+ const instance = ref.instance;
16
+ if (typeof instance.awbInit === "function") {
17
+ instance.awbInit(params);
18
+ return;
19
+ }
20
+ if (mirror.inputs.some((i) => i.templateName === "params" || i.propName === "params")) {
21
+ ref.setInput("params", params);
22
+ return;
23
+ }
24
+ throw new Error(`[agility-workbench] ${kind} component ${mirror.selector || ref.componentType.name} must either ` +
25
+ `implement awbInit(params) or declare an input named 'params'.`);
26
+ }
27
+ /**
28
+ * Per-grid-instance adapter context. Owns the Angular machinery (injector, ApplicationRef, zone)
29
+ * needed to host arbitrary Angular components inside DOM elements owned by the framework-agnostic
30
+ * core, plus per-component caches so the same component class always maps to the same adapter class
31
+ * (core treats the renderer class identity as the "did the renderer change?" key).
32
+ */
33
+ class NgAdapters {
34
+ constructor(appRef, envInjector, zone) {
35
+ this.appRef = appRef;
36
+ this.envInjector = envInjector;
37
+ this.zone = zone;
38
+ this.rendererCache = new WeakMap();
39
+ this.tooltipCache = new WeakMap();
40
+ this.actionFrameCache = new WeakMap();
41
+ this.editorCache = new WeakMap();
42
+ this.setFilterComponentCache = new WeakMap();
43
+ }
44
+ /**
45
+ * Create `component` with `hostElement` as its host, deliver params, attach it to the app for
46
+ * change detection, and run the first CD cycle synchronously (the grid may read the DOM / call
47
+ * imperative methods immediately after init). Runs inside the Angular zone so template event
48
+ * listeners registered during creation trigger change detection in zone-based apps — the grid
49
+ * core itself lives outside the zone.
50
+ */
51
+ mount(component, params, hostElement, kind) {
52
+ return this.zone.run(() => {
53
+ const mirror = reflectComponentType(component);
54
+ const ref = createComponent(component, {
55
+ environmentInjector: this.envInjector,
56
+ hostElement,
57
+ });
58
+ deliverParams(ref, mirror, params, kind);
59
+ this.appRef.attachView(ref.hostView);
60
+ ref.changeDetectorRef.detectChanges();
61
+ return {
62
+ instance: ref.instance,
63
+ refresh: (p) => {
64
+ return this.zone.run(() => {
65
+ const instance = ref.instance;
66
+ let handled = true;
67
+ if (typeof instance.awbRefresh === "function") {
68
+ handled = instance.awbRefresh(p) !== false;
69
+ }
70
+ else {
71
+ deliverParams(ref, mirror, p, kind);
72
+ }
73
+ ref.changeDetectorRef.detectChanges();
74
+ return handled;
75
+ });
76
+ },
77
+ destroy: () => this.zone.run(() => ref.destroy()),
78
+ };
79
+ });
80
+ }
81
+ // --- cell renderers -------------------------------------------------------------------------
82
+ adaptCellRenderer(renderer) {
83
+ if (!renderer)
84
+ return undefined;
85
+ if (typeof renderer === "function" && isClassRenderer(renderer)) {
86
+ return renderer;
87
+ }
88
+ if (!isNgComponent(renderer))
89
+ return renderer;
90
+ const cached = this.rendererCache.get(renderer);
91
+ if (cached)
92
+ return cached;
93
+ const adapted = this.createRendererClass(renderer);
94
+ this.rendererCache.set(renderer, adapted);
95
+ return adapted;
96
+ }
97
+ createRendererClass(component) {
98
+ const adapters = this;
99
+ return class NgCellRendererAdapter {
100
+ constructor() {
101
+ this.el = document.createElement("span");
102
+ this.mounted = null;
103
+ }
104
+ init(params) {
105
+ this.el.style.display = "inline-flex";
106
+ this.el.style.alignItems = "center";
107
+ this.el.style.width = "100%";
108
+ this.el.style.height = "100%";
109
+ this.el.style.overflow = "hidden";
110
+ this.mounted = adapters.mount(component, getRendererProps(params), this.el, "cellRenderer");
111
+ }
112
+ getGui() {
113
+ return this.el;
114
+ }
115
+ refresh(params) {
116
+ return this.mounted?.refresh(getRendererProps(params)) ?? false;
117
+ }
118
+ destroy() {
119
+ this.mounted?.destroy();
120
+ this.mounted = null;
121
+ }
122
+ };
123
+ }
124
+ // --- tooltips --------------------------------------------------------------------------------
125
+ adaptTooltip(comp) {
126
+ if (!comp)
127
+ return undefined;
128
+ if (typeof comp === "function" && isClassTooltipComponent(comp)) {
129
+ return comp;
130
+ }
131
+ if (!isNgComponent(comp))
132
+ return comp;
133
+ const cached = this.tooltipCache.get(comp);
134
+ if (cached)
135
+ return cached;
136
+ const adapted = this.createTooltipClass(comp);
137
+ this.tooltipCache.set(comp, adapted);
138
+ return adapted;
139
+ }
140
+ /** Adapt an Angular tooltip component returned dynamically by `getRowPresentation`. */
141
+ adaptGetRowPresentation(getter) {
142
+ if (!getter)
143
+ return undefined;
144
+ return (params) => {
145
+ const presentation = getter(params);
146
+ if (!presentation || typeof presentation.tooltip !== "object" || presentation.tooltip == null) {
147
+ return presentation;
148
+ }
149
+ return {
150
+ ...presentation,
151
+ tooltip: {
152
+ ...presentation.tooltip,
153
+ component: this.adaptTooltip(presentation.tooltip.component),
154
+ },
155
+ };
156
+ };
157
+ }
158
+ /** headerTooltip may be a plain string (pass through) or a component (adapt like a tooltip). */
159
+ adaptHeaderTooltip(ht) {
160
+ if (ht == null || typeof ht === "string")
161
+ return ht;
162
+ return this.adaptTooltip(ht);
163
+ }
164
+ createTooltipClass(component) {
165
+ const adapters = this;
166
+ return class NgTooltipAdapter {
167
+ constructor() {
168
+ this.el = document.createElement("div");
169
+ this.mounted = null;
170
+ }
171
+ init(params) {
172
+ // One component instance lives for the life of this tooltip; refresh re-delivers params
173
+ // rather than recreating, so interactive content keeps its state across repositions.
174
+ this.mounted = adapters.mount(component, getTooltipProps(params), this.el, "tooltip");
175
+ }
176
+ getGui() {
177
+ return this.el;
178
+ }
179
+ refresh(params) {
180
+ return this.mounted?.refresh(getTooltipProps(params)) ?? false;
181
+ }
182
+ destroy() {
183
+ this.mounted?.destroy();
184
+ this.mounted = null;
185
+ }
186
+ };
187
+ }
188
+ // --- ActionFrame -----------------------------------------------------------------------------
189
+ adaptActionFrame(comp) {
190
+ if (!comp)
191
+ return undefined;
192
+ if (typeof comp === "function" && isClassActionFrameComponent(comp)) {
193
+ return comp;
194
+ }
195
+ if (!isNgComponent(comp))
196
+ return comp;
197
+ const cached = this.actionFrameCache.get(comp);
198
+ if (cached)
199
+ return cached;
200
+ const adapted = this.createActionFrameClass(comp);
201
+ this.actionFrameCache.set(comp, adapted);
202
+ return adapted;
203
+ }
204
+ createActionFrameClass(component) {
205
+ const adapters = this;
206
+ return class NgActionFrameAdapter {
207
+ constructor() {
208
+ this.el = document.createElement("div");
209
+ this.mounted = null;
210
+ }
211
+ init(params) {
212
+ // One component instance for the life of the open frame; refresh re-delivers params so the
213
+ // form keeps its state across repositions (scroll tracking repositions, not remounts).
214
+ this.mounted = adapters.mount(component, getActionFrameProps(params), this.el, "actionFrame");
215
+ }
216
+ getGui() {
217
+ return this.el;
218
+ }
219
+ refresh(params) {
220
+ return this.mounted?.refresh(getActionFrameProps(params)) ?? false;
221
+ }
222
+ destroy() {
223
+ this.mounted?.destroy();
224
+ this.mounted = null;
225
+ }
226
+ };
227
+ }
228
+ // --- cell editors ----------------------------------------------------------------------------
229
+ adaptCellEditor(editor) {
230
+ if (editor == null)
231
+ return undefined;
232
+ if (typeof editor === "string")
233
+ return editor; // built-in alias
234
+ if (isCoreEditorClass(editor))
235
+ return editor;
236
+ if (!isNgComponent(editor))
237
+ return editor;
238
+ const cached = this.editorCache.get(editor);
239
+ if (cached)
240
+ return cached;
241
+ const adapted = this.createEditorClass(editor);
242
+ this.editorCache.set(editor, adapted);
243
+ return adapted;
244
+ }
245
+ createEditorClass(component) {
246
+ const adapters = this;
247
+ return class NgCellEditorAdapter {
248
+ constructor() {
249
+ this.el = document.createElement("div");
250
+ this.mounted = null;
251
+ }
252
+ init(params) {
253
+ this.el.style.width = "100%";
254
+ this.el.style.height = "100%";
255
+ // mount() runs the first change-detection cycle synchronously, so the instance is fully
256
+ // initialized before the grid calls focus()/getValue().
257
+ this.mounted = adapters.mount(component, params, this.el, "cellEditor");
258
+ }
259
+ getGui() {
260
+ return this.el;
261
+ }
262
+ getValue() {
263
+ return this.mounted?.instance.getValue?.();
264
+ }
265
+ isParsed() {
266
+ return this.mounted?.instance.isParsed?.() ?? false;
267
+ }
268
+ focus() {
269
+ this.mounted?.instance.focus?.();
270
+ }
271
+ isCancelBeforeStart() {
272
+ return this.mounted?.instance.isCancelBeforeStart?.() ?? false;
273
+ }
274
+ destroy() {
275
+ // Defer teardown out of the current commit/keyboard dispatch: the destroy may be triggered
276
+ // by an event fired from inside the component's own template.
277
+ const mounted = this.mounted;
278
+ this.mounted = null;
279
+ if (mounted)
280
+ queueMicrotask(() => mounted.destroy());
281
+ }
282
+ };
283
+ }
284
+ // --- set-filter value components ------------------------------------------------------------
285
+ adaptSetFilterComponent(component) {
286
+ if (!component)
287
+ return undefined;
288
+ if (typeof component === "function" &&
289
+ isClassSetFilterComponent(component)) {
290
+ return component;
291
+ }
292
+ if (!isNgComponent(component))
293
+ return component;
294
+ const cached = this.setFilterComponentCache.get(component);
295
+ if (cached)
296
+ return cached;
297
+ const adapted = this.createSetFilterComponentClass(component);
298
+ this.setFilterComponentCache.set(component, adapted);
299
+ return adapted;
300
+ }
301
+ createSetFilterComponentClass(component) {
302
+ const adapters = this;
303
+ return class NgSetFilterComponentAdapter {
304
+ constructor() {
305
+ this.el = document.createElement("span");
306
+ this.mounted = null;
307
+ }
308
+ init(params) {
309
+ this.mounted = adapters.mount(component, params, this.el, "setFilterValueComponent");
310
+ }
311
+ getGui() {
312
+ return this.el;
313
+ }
314
+ refresh(params) {
315
+ return this.mounted?.refresh(params) ?? false;
316
+ }
317
+ destroy() {
318
+ this.mounted?.destroy();
319
+ this.mounted = null;
320
+ }
321
+ };
322
+ }
323
+ adaptFilterParams(filterParams) {
324
+ if (!filterParams)
325
+ return undefined;
326
+ return {
327
+ ...filterParams,
328
+ valueComponent: this.adaptSetFilterComponent(filterParams.valueComponent),
329
+ selectAllComponent: this.adaptSetFilterComponent(filterParams.selectAllComponent),
330
+ blanksComponent: this.adaptSetFilterComponent(filterParams.blanksComponent),
331
+ };
332
+ }
333
+ // --- column defs -----------------------------------------------------------------------------
334
+ /**
335
+ * Adapt the Angular-aware components carried by a single column def into their core equivalents.
336
+ * Used for real column defs and, via {@link adaptDefaultColDef}, the grid-level `defaultColDef`.
337
+ */
338
+ adaptColDef(colDef) {
339
+ return {
340
+ ...colDef,
341
+ cellRenderer: this.adaptCellRenderer(colDef.cellRenderer),
342
+ cellEditor: this.adaptCellEditor(colDef.cellEditor),
343
+ tooltipComponent: this.adaptTooltip(colDef.tooltipComponent),
344
+ headerTooltip: this.adaptHeaderTooltip(colDef.headerTooltip),
345
+ actionFrameComponent: this.adaptActionFrame(colDef.actionFrameComponent),
346
+ filterParams: this.adaptFilterParams(colDef.filterParams),
347
+ children: colDef.children ? (this.adaptColumnDefs(colDef.children) ?? undefined) : undefined,
348
+ };
349
+ }
350
+ adaptColumnDefs(columnDefs) {
351
+ if (columnDefs == null)
352
+ return columnDefs;
353
+ return columnDefs.map((colDef) => this.adaptColDef(colDef));
354
+ }
355
+ /**
356
+ * Adapt a grid-level `defaultColDef`: same per-field component adaptation as a real column def,
357
+ * but only the fields actually present are adapted (it is a partial), so an omitted field stays
358
+ * omitted rather than being forced to `undefined`.
359
+ */
360
+ adaptDefaultColDef(defaultColDef) {
361
+ if (defaultColDef == null)
362
+ return undefined;
363
+ const next = { ...defaultColDef };
364
+ if ("cellRenderer" in defaultColDef)
365
+ next.cellRenderer = this.adaptCellRenderer(defaultColDef.cellRenderer);
366
+ if ("cellEditor" in defaultColDef)
367
+ next.cellEditor = this.adaptCellEditor(defaultColDef.cellEditor);
368
+ if ("tooltipComponent" in defaultColDef)
369
+ next.tooltipComponent = this.adaptTooltip(defaultColDef.tooltipComponent);
370
+ if ("headerTooltip" in defaultColDef)
371
+ next.headerTooltip = this.adaptHeaderTooltip(defaultColDef.headerTooltip);
372
+ if ("actionFrameComponent" in defaultColDef) {
373
+ next.actionFrameComponent = this.adaptActionFrame(defaultColDef.actionFrameComponent);
374
+ }
375
+ if ("filterParams" in defaultColDef)
376
+ next.filterParams = this.adaptFilterParams(defaultColDef.filterParams);
377
+ return next;
378
+ }
379
+ }
380
+ function isCoreEditorClass(e) {
381
+ const proto = e?.prototype;
382
+ return (typeof e === "function" &&
383
+ !!proto &&
384
+ typeof proto.init === "function" &&
385
+ typeof proto.getGui === "function");
386
+ }
387
+ function getRendererProps(params) {
388
+ const extraParams = params.colDef.cellRendererParams;
389
+ if (extraParams == null || typeof extraParams !== "object")
390
+ return params;
391
+ return { ...params, ...extraParams };
392
+ }
393
+ function getTooltipProps(params) {
394
+ const extraParams = params.colDef?.tooltipComponentParams;
395
+ if (extraParams == null || typeof extraParams !== "object")
396
+ return params;
397
+ return { ...params, ...extraParams };
398
+ }
399
+ function getActionFrameProps(params) {
400
+ const extraParams = params.colDef?.actionFrameComponentParams;
401
+ if (extraParams == null || typeof extraParams !== "object")
402
+ return params;
403
+ return { ...params, ...extraParams };
404
+ }
405
+
406
+ function setIfDefined(options, key, value) {
407
+ if (value != null)
408
+ options[key] = value;
409
+ }
410
+ /**
411
+ * Snapshot the component's inputs into core GridOptions. Mirrors the React wrapper's
412
+ * `getGridOptions(props)`, reading Angular signal inputs instead of props. Event callbacks are
413
+ * bridged separately by the component (they become Angular outputs).
414
+ */
415
+ function getGridOptions(grid, adapters) {
416
+ const options = {};
417
+ setIfDefined(options, "headerHeight", grid.headerHeight());
418
+ setIfDefined(options, "leafHeaderHeight", grid.leafHeaderHeight());
419
+ setIfDefined(options, "parentHeaderHeight", grid.parentHeaderHeight());
420
+ setIfDefined(options, "rowHeight", grid.rowHeight());
421
+ setIfDefined(options, "pinnedTopRowData", grid.pinnedTopRowData());
422
+ setIfDefined(options, "pinnedBottomRowData", grid.pinnedBottomRowData());
423
+ setIfDefined(options, "getRowId", grid.getRowId());
424
+ setIfDefined(options, "rowIdKey", grid.rowIdKey());
425
+ setIfDefined(options, "rowDataMode", grid.rowDataMode());
426
+ setIfDefined(options, "asyncTransactionWaitMs", grid.asyncTransactionWaitMs());
427
+ setIfDefined(options, "overscanRowCount", grid.overscanRowCount());
428
+ setIfDefined(options, "minResizeWidth", grid.minResizeWidth());
429
+ setIfDefined(options, "maxColumnWidth", grid.maxColumnWidth());
430
+ setIfDefined(options, "autosizeColumnsOnDataChange", grid.autosizeColumnsOnDataChange());
431
+ setIfDefined(options, "allowExportAsCSV", grid.allowExportAsCSV());
432
+ setIfDefined(options, "allowExportAsExcel", grid.allowExportAsExcel());
433
+ setIfDefined(options, "pagination", grid.pagination());
434
+ setIfDefined(options, "paginationControls", grid.paginationControls());
435
+ setIfDefined(options, "rowNumbers", grid.rowNumbers());
436
+ setIfDefined(options, "rowHover", grid.rowHover());
437
+ setIfDefined(options, "columnHover", grid.columnHover());
438
+ setIfDefined(options, "zebraRows", grid.zebraRows());
439
+ setIfDefined(options, "getRowClass", grid.getRowClass());
440
+ setIfDefined(options, "getRowStyle", grid.getRowStyle());
441
+ setIfDefined(options, "getRowPresentation", adapters.adaptGetRowPresentation(grid.getRowPresentation()));
442
+ setIfDefined(options, "ariaLabel", grid.ariaLabel());
443
+ setIfDefined(options, "ariaLabelledBy", grid.ariaLabelledBy());
444
+ setIfDefined(options, "highlightActiveCell", grid.highlightActiveCell());
445
+ setIfDefined(options, "rowSelection", grid.rowSelection());
446
+ setIfDefined(options, "cellSelection", grid.cellSelection());
447
+ setIfDefined(options, "rangeSelection", grid.rangeSelection());
448
+ setIfDefined(options, "columnSelection", grid.columnSelection());
449
+ setIfDefined(options, "headerKeyboardNavigation", grid.headerKeyboardNavigation());
450
+ setIfDefined(options, "showColumnButtonsOnHover", grid.showColumnButtonsOnHover());
451
+ setIfDefined(options, "selectAllRowsOnHeaderClick", grid.selectAllRowsOnHeaderClick());
452
+ setIfDefined(options, "selectAllScope", grid.selectAllScope());
453
+ setIfDefined(options, "selectionPersistence", grid.selectionPersistence());
454
+ setIfDefined(options, "clearSelectionOnBodyClick", grid.clearSelectionOnBodyClick());
455
+ setIfDefined(options, "resetPageOn", grid.resetPageOn());
456
+ setIfDefined(options, "pageSize", grid.pageSize());
457
+ setIfDefined(options, "pageSizes", grid.pageSizes());
458
+ setIfDefined(options, "serverSideBlockSize", grid.serverSideBlockSize());
459
+ setIfDefined(options, "rowModelType", grid.rowModelType());
460
+ setIfDefined(options, "getGroupChildCount", grid.getGroupChildCount());
461
+ setIfDefined(options, "paginationUnknownTotalTooltip", grid.paginationUnknownTotalTooltip());
462
+ setIfDefined(options, "undoLimit", grid.undoLimit());
463
+ setIfDefined(options, "editTrigger", grid.editTrigger());
464
+ setIfDefined(options, "readOnlyEdit", grid.readOnlyEdit());
465
+ setIfDefined(options, "initialSort", grid.initialSort());
466
+ setIfDefined(options, "showSortPriority", grid.showSortPriority());
467
+ setIfDefined(options, "pinnedRowsEditable", grid.pinnedRowsEditable());
468
+ setIfDefined(options, "rowPinningMenu", grid.rowPinningMenu());
469
+ setIfDefined(options, "rowInsertionMenu", grid.rowInsertionMenu());
470
+ setIfDefined(options, "suppressKeyboardEdit", grid.suppressKeyboardEdit());
471
+ setIfDefined(options, "suppressTypeToEdit", grid.suppressTypeToEdit());
472
+ setIfDefined(options, "moveAfterEdit", grid.moveAfterEdit());
473
+ setIfDefined(options, "commitOnBlur", grid.commitOnBlur());
474
+ setIfDefined(options, "reevaluateOnEdit", grid.reevaluateOnEdit());
475
+ setIfDefined(options, "groupDisplayType", grid.groupDisplayType());
476
+ setIfDefined(options, "groupColumnDef", grid.groupColumnDef());
477
+ setIfDefined(options, "groupDefaultExpanded", grid.groupDefaultExpanded());
478
+ setIfDefined(options, "groupSortMode", grid.groupSortMode());
479
+ setIfDefined(options, "treeData", grid.treeData());
480
+ setIfDefined(options, "groupRowsSelectable", grid.groupRowsSelectable());
481
+ setIfDefined(options, "isRowSelectable", grid.isRowSelectable());
482
+ setIfDefined(options, "isRowPinned", grid.isRowPinned());
483
+ setIfDefined(options, "groupRowsSticky", grid.groupRowsSticky());
484
+ setIfDefined(options, "isFullWidthRow", grid.isFullWidthRow());
485
+ setIfDefined(options, "tooltip", grid.tooltip());
486
+ setIfDefined(options, "quickFilter", grid.quickFilter());
487
+ setIfDefined(options, "columnPanel", grid.columnPanel());
488
+ setIfDefined(options, "toolbar", grid.toolbar());
489
+ setIfDefined(options, "savedViews", grid.savedViews());
490
+ setIfDefined(options, "loadingMessage", grid.loadingMessage());
491
+ setIfDefined(options, "noRowsMessage", grid.noRowsMessage());
492
+ setIfDefined(options, "filterDebounceMs", grid.filterDebounceMs());
493
+ setIfDefined(options, "cellFlashDuration", grid.cellFlashDuration());
494
+ setIfDefined(options, "cellFadeDuration", grid.cellFadeDuration());
495
+ setIfDefined(options, "icons", grid.icons());
496
+ setIfDefined(options, "theme", grid.theme());
497
+ setIfDefined(options, "suppressStyleInjection", grid.suppressStyleInjection());
498
+ setIfDefined(options, "styleNonce", grid.styleNonce());
499
+ const fullWidthCellRenderer = grid.fullWidthCellRenderer();
500
+ if (fullWidthCellRenderer != null) {
501
+ options.fullWidthCellRenderer = adapters.adaptCellRenderer(fullWidthCellRenderer);
502
+ }
503
+ const defaultColDef = grid.defaultColDef();
504
+ if (defaultColDef != null)
505
+ options.defaultColDef = adapters.adaptDefaultColDef(defaultColDef);
506
+ // Forward only the boolean intent to core: false disables the menu (native menu shows);
507
+ // everything else (true / omitted / a function) leaves core at its "show menu" default and lets
508
+ // the body-menu adapter apply the function arm (so TemplateRef slots are handled). This avoids
509
+ // running a user callback twice (once in core, once in the adapter).
510
+ if (grid.bodyContextMenu() === false)
511
+ options.bodyContextMenu = false;
512
+ if (grid.rowModelType() === "serverSide") {
513
+ setIfDefined(options, "serverSideDataSource", grid.serverSideDataSource());
514
+ setIfDefined(options, "serverSideAggregationSource", grid.serverSideAggregationSource());
515
+ }
516
+ return options;
517
+ }
518
+
519
+ /**
520
+ * Shared slot normalization for both menu adapters: app-supplied menu items may carry
521
+ * `TemplateRef` slots; each open menu stamps them into detached spans and destroys the embedded
522
+ * views on close (the core calls `cleanup` when the menu is dismissed).
523
+ */
524
+ class NgMenuAdapterBase {
525
+ constructor(appRef, zone) {
526
+ this.appRef = appRef;
527
+ this.zone = zone;
528
+ }
529
+ normalizeItems(items, cleanups) {
530
+ return items.map((it) => {
531
+ if (it.isSeparator)
532
+ return { isSeparator: true };
533
+ const left = this.normalizeSlot(it.left, cleanups);
534
+ const right = this.normalizeSlot(it.right, cleanups);
535
+ return {
536
+ ...it,
537
+ left,
538
+ right,
539
+ subMenu: it.subMenu ? this.normalizeItems(it.subMenu, cleanups) : undefined,
540
+ };
541
+ });
542
+ }
543
+ normalizeSlot(slot, cleanups) {
544
+ if (!slot)
545
+ return undefined;
546
+ if (typeof slot === "string")
547
+ return slot;
548
+ if (slot instanceof HTMLElement)
549
+ return slot;
550
+ // Angular's concrete TemplateRef implementations are not guaranteed to preserve
551
+ // `instanceof TemplateRef` across compilation/runtime boundaries. Treat the public
552
+ // createEmbeddedView contract as the discriminator instead.
553
+ if (typeof slot.createEmbeddedView === "function") {
554
+ const { el, destroy } = this.stampTemplate(slot);
555
+ cleanups.push(destroy);
556
+ return el;
557
+ }
558
+ return undefined;
559
+ }
560
+ stampTemplate(tpl) {
561
+ return this.zone.run(() => {
562
+ const el = document.createElement("span");
563
+ el.style.display = "inline-flex";
564
+ el.style.alignItems = "center";
565
+ const view = tpl.createEmbeddedView({});
566
+ this.appRef.attachView(view);
567
+ view.detectChanges();
568
+ for (const node of view.rootNodes)
569
+ el.appendChild(node);
570
+ return { el, destroy: () => this.zone.run(() => view.destroy()) };
571
+ });
572
+ }
573
+ }
574
+ class NgMenuAdapter extends NgMenuAdapterBase {
575
+ constructor(appRef, zone, opts) {
576
+ super(appRef, zone);
577
+ this.opts = opts;
578
+ }
579
+ resolveMenuItems(ctx, defaults) {
580
+ const cleanups = [];
581
+ const defaultsNg = defaults;
582
+ // Read the hook through the getter so the adapter stays reactive to input changes without
583
+ // recreating the grid instance (the React wrapper's ref-read, in Angular clothing).
584
+ const hook = this.opts.getColumnMenuItems?.();
585
+ const appItems = hook ? hook({ ctx, items: defaultsNg }) : defaultsNg;
586
+ const items = this.normalizeItems(appItems, cleanups);
587
+ return {
588
+ items,
589
+ cleanup: () => {
590
+ for (const c of cleanups)
591
+ c();
592
+ },
593
+ };
594
+ }
595
+ }
596
+ class NgBodyMenuAdapter extends NgMenuAdapterBase {
597
+ constructor(appRef, zone, opts) {
598
+ super(appRef, zone);
599
+ this.opts = opts;
600
+ }
601
+ resolveMenuItems(ctx, defaults) {
602
+ const cleanups = [];
603
+ const defaultsNg = defaults;
604
+ const hook = this.opts.getBodyMenuItems?.();
605
+ const appItems = hook ? hook({ ctx, items: defaultsNg }) : defaultsNg;
606
+ const items = this.normalizeItems(appItems, cleanups);
607
+ return {
608
+ items,
609
+ cleanup: () => {
610
+ for (const c of cleanups)
611
+ c();
612
+ },
613
+ };
614
+ }
615
+ }
616
+
617
+ function destroyInstance(instance) {
618
+ if (instance.destroyed)
619
+ return;
620
+ instance.destroyed = true;
621
+ // createGrid's api.destroy() performs the whole guarded teardown (detach → renderer.destroy →
622
+ // core.destroy → api cleanup) in that order, exactly once. The flag above keeps this wrapper
623
+ // idempotent too, since teardown can be reached twice.
624
+ try {
625
+ instance.api.destroy();
626
+ }
627
+ catch { }
628
+ }
629
+ /**
630
+ * Angular host for the framework-agnostic grid. The core owns all DOM inside the host element;
631
+ * Angular's job is lifecycle (create on first render, destroy with the component), forwarding
632
+ * input changes to core/renderer setters, bridging core events to Angular outputs, and adapting
633
+ * Angular components (renderers, editors, tooltips, ActionFrames, menu templates) into the core's
634
+ * class-component contracts.
635
+ *
636
+ * The grid is created outside the Angular zone so its internal scroll/pointer listeners never
637
+ * trigger app-wide change detection; outputs re-enter the zone when they emit.
638
+ */
639
+ class AwbGrid {
640
+ /** The imperative grid API; available from `gridReady` onward (null before first render). */
641
+ get api() {
642
+ return this.instance?.api ?? null;
643
+ }
644
+ constructor() {
645
+ // --- data ---
646
+ this.rowData = input(...(ngDevMode ? [undefined, { debugName: "rowData" }] : []));
647
+ this.columnDefs = input(...(ngDevMode ? [undefined, { debugName: "columnDefs" }] : []));
648
+ this.defaultColDef = input(...(ngDevMode ? [undefined, { debugName: "defaultColDef" }] : []));
649
+ // --- layout / sizing ---
650
+ this.headerHeight = input(...(ngDevMode ? [undefined, { debugName: "headerHeight" }] : []));
651
+ this.leafHeaderHeight = input(...(ngDevMode ? [undefined, { debugName: "leafHeaderHeight" }] : []));
652
+ this.parentHeaderHeight = input(...(ngDevMode ? [undefined, { debugName: "parentHeaderHeight" }] : []));
653
+ this.rowHeight = input(...(ngDevMode ? [undefined, { debugName: "rowHeight" }] : []));
654
+ this.overscanRowCount = input(...(ngDevMode ? [undefined, { debugName: "overscanRowCount" }] : []));
655
+ this.minResizeWidth = input(...(ngDevMode ? [undefined, { debugName: "minResizeWidth" }] : []));
656
+ this.maxColumnWidth = input(...(ngDevMode ? [undefined, { debugName: "maxColumnWidth" }] : []));
657
+ this.autosizeColumnsOnDataChange = input(...(ngDevMode ? [undefined, { debugName: "autosizeColumnsOnDataChange" }] : []));
658
+ // --- row identity ---
659
+ this.getRowId = input(...(ngDevMode ? [undefined, { debugName: "getRowId" }] : []));
660
+ this.rowIdKey = input(...(ngDevMode ? [undefined, { debugName: "rowIdKey" }] : []));
661
+ this.rowDataMode = input(...(ngDevMode ? [undefined, { debugName: "rowDataMode" }] : []));
662
+ this.asyncTransactionWaitMs = input(...(ngDevMode ? [undefined, { debugName: "asyncTransactionWaitMs" }] : []));
663
+ // --- appearance / interaction ---
664
+ this.rowHover = input(...(ngDevMode ? [undefined, { debugName: "rowHover" }] : []));
665
+ this.columnHover = input(...(ngDevMode ? [undefined, { debugName: "columnHover" }] : []));
666
+ this.zebraRows = input(...(ngDevMode ? [undefined, { debugName: "zebraRows" }] : []));
667
+ this.getRowClass = input(...(ngDevMode ? [undefined, { debugName: "getRowClass" }] : []));
668
+ this.getRowStyle = input(...(ngDevMode ? [undefined, { debugName: "getRowStyle" }] : []));
669
+ this.getRowPresentation = input(...(ngDevMode ? [undefined, { debugName: "getRowPresentation" }] : []));
670
+ this.ariaLabel = input(...(ngDevMode ? [undefined, { debugName: "ariaLabel" }] : []));
671
+ this.ariaLabelledBy = input(...(ngDevMode ? [undefined, { debugName: "ariaLabelledBy" }] : []));
672
+ this.highlightActiveCell = input(...(ngDevMode ? [undefined, { debugName: "highlightActiveCell" }] : []));
673
+ this.rowNumbers = input(...(ngDevMode ? [undefined, { debugName: "rowNumbers" }] : []));
674
+ this.showColumnButtonsOnHover = input(...(ngDevMode ? [undefined, { debugName: "showColumnButtonsOnHover" }] : []));
675
+ this.theme = input(...(ngDevMode ? [undefined, { debugName: "theme" }] : []));
676
+ this.icons = input(...(ngDevMode ? [undefined, { debugName: "icons" }] : []));
677
+ // The renderer delivers the base stylesheet on attach, to whichever root the grid lands in.
678
+ // Suppress it when the application ships the CSS itself; `styleNonce` covers CSP `style-src`.
679
+ this.suppressStyleInjection = input(...(ngDevMode ? [undefined, { debugName: "suppressStyleInjection" }] : []));
680
+ this.styleNonce = input(...(ngDevMode ? [undefined, { debugName: "styleNonce" }] : []));
681
+ // --- selection ---
682
+ this.rowSelection = input(...(ngDevMode ? [undefined, { debugName: "rowSelection" }] : []));
683
+ this.isRowSelectable = input(...(ngDevMode ? [undefined, { debugName: "isRowSelectable" }] : []));
684
+ this.cellSelection = input(...(ngDevMode ? [undefined, { debugName: "cellSelection" }] : []));
685
+ this.rangeSelection = input(...(ngDevMode ? [undefined, { debugName: "rangeSelection" }] : []));
686
+ this.columnSelection = input(...(ngDevMode ? [undefined, { debugName: "columnSelection" }] : []));
687
+ this.headerKeyboardNavigation = input(...(ngDevMode ? [undefined, { debugName: "headerKeyboardNavigation" }] : []));
688
+ this.selectAllRowsOnHeaderClick = input(...(ngDevMode ? [undefined, { debugName: "selectAllRowsOnHeaderClick" }] : []));
689
+ this.selectAllScope = input(...(ngDevMode ? [undefined, { debugName: "selectAllScope" }] : []));
690
+ this.selectionPersistence = input(...(ngDevMode ? [undefined, { debugName: "selectionPersistence" }] : []));
691
+ this.clearSelectionOnBodyClick = input(...(ngDevMode ? [undefined, { debugName: "clearSelectionOnBodyClick" }] : []));
692
+ // --- editing ---
693
+ this.editTrigger = input(...(ngDevMode ? [undefined, { debugName: "editTrigger" }] : []));
694
+ // Value-returning pre-commit hook (A5). An input rather than an output because outputs cannot
695
+ // return the veto/transform result to the grid.
696
+ this.onBeforeCellCommit = input(...(ngDevMode ? [undefined, { debugName: "onBeforeCellCommit" }] : []));
697
+ this.readOnlyEdit = input(...(ngDevMode ? [undefined, { debugName: "readOnlyEdit" }] : []));
698
+ this.pinnedRowsEditable = input(...(ngDevMode ? [undefined, { debugName: "pinnedRowsEditable" }] : []));
699
+ this.suppressKeyboardEdit = input(...(ngDevMode ? [undefined, { debugName: "suppressKeyboardEdit" }] : []));
700
+ this.suppressTypeToEdit = input(...(ngDevMode ? [undefined, { debugName: "suppressTypeToEdit" }] : []));
701
+ this.moveAfterEdit = input(...(ngDevMode ? [undefined, { debugName: "moveAfterEdit" }] : []));
702
+ this.commitOnBlur = input(...(ngDevMode ? [undefined, { debugName: "commitOnBlur" }] : []));
703
+ this.reevaluateOnEdit = input(...(ngDevMode ? [undefined, { debugName: "reevaluateOnEdit" }] : []));
704
+ this.undoLimit = input(...(ngDevMode ? [undefined, { debugName: "undoLimit" }] : []));
705
+ // --- sorting ---
706
+ this.initialSort = input(...(ngDevMode ? [undefined, { debugName: "initialSort" }] : []));
707
+ this.showSortPriority = input(...(ngDevMode ? [undefined, { debugName: "showSortPriority" }] : []));
708
+ // --- filtering ---
709
+ this.quickFilter = input(...(ngDevMode ? [undefined, { debugName: "quickFilter" }] : []));
710
+ this.filterDebounceMs = input(...(ngDevMode ? [undefined, { debugName: "filterDebounceMs" }] : []));
711
+ // --- grouping / tree ---
712
+ this.groupDisplayType = input(...(ngDevMode ? [undefined, { debugName: "groupDisplayType" }] : []));
713
+ this.groupColumnDef = input(...(ngDevMode ? [undefined, { debugName: "groupColumnDef" }] : []));
714
+ this.groupDefaultExpanded = input(...(ngDevMode ? [undefined, { debugName: "groupDefaultExpanded" }] : []));
715
+ this.groupSortMode = input(...(ngDevMode ? [undefined, { debugName: "groupSortMode" }] : []));
716
+ this.groupRowsSelectable = input(...(ngDevMode ? [undefined, { debugName: "groupRowsSelectable" }] : []));
717
+ this.groupRowsSticky = input(...(ngDevMode ? [undefined, { debugName: "groupRowsSticky" }] : []));
718
+ this.getGroupChildCount = input(...(ngDevMode ? [undefined, { debugName: "getGroupChildCount" }] : []));
719
+ this.treeData = input(...(ngDevMode ? [undefined, { debugName: "treeData" }] : []));
720
+ // --- pinned rows ---
721
+ this.pinnedTopRowData = input(...(ngDevMode ? [undefined, { debugName: "pinnedTopRowData" }] : []));
722
+ this.pinnedBottomRowData = input(...(ngDevMode ? [undefined, { debugName: "pinnedBottomRowData" }] : []));
723
+ this.isRowPinned = input(...(ngDevMode ? [undefined, { debugName: "isRowPinned" }] : []));
724
+ this.rowPinningMenu = input(...(ngDevMode ? [undefined, { debugName: "rowPinningMenu" }] : []));
725
+ this.rowInsertionMenu = input(...(ngDevMode ? [undefined, { debugName: "rowInsertionMenu" }] : []));
726
+ // --- full-width rows ---
727
+ this.isFullWidthRow = input(...(ngDevMode ? [undefined, { debugName: "isFullWidthRow" }] : []));
728
+ this.fullWidthCellRenderer = input(...(ngDevMode ? [undefined, { debugName: "fullWidthCellRenderer" }] : []));
729
+ // --- pagination ---
730
+ this.pagination = input(...(ngDevMode ? [undefined, { debugName: "pagination" }] : []));
731
+ this.paginationControls = input(...(ngDevMode ? [undefined, { debugName: "paginationControls" }] : []));
732
+ this.pageSize = input(...(ngDevMode ? [undefined, { debugName: "pageSize" }] : []));
733
+ this.pageSizes = input(...(ngDevMode ? [undefined, { debugName: "pageSizes" }] : []));
734
+ this.resetPageOn = input(...(ngDevMode ? [undefined, { debugName: "resetPageOn" }] : []));
735
+ this.paginationUnknownTotalTooltip = input(...(ngDevMode ? [undefined, { debugName: "paginationUnknownTotalTooltip" }] : []));
736
+ // --- server-side row model ---
737
+ this.rowModelType = input(...(ngDevMode ? [undefined, { debugName: "rowModelType" }] : []));
738
+ this.serverSideDataSource = input(...(ngDevMode ? [undefined, { debugName: "serverSideDataSource" }] : []));
739
+ this.serverSideAggregationSource = input(...(ngDevMode ? [undefined, { debugName: "serverSideAggregationSource" }] : []));
740
+ this.serverSideBlockSize = input(...(ngDevMode ? [undefined, { debugName: "serverSideBlockSize" }] : []));
741
+ // --- widgets / chrome ---
742
+ this.tooltip = input(...(ngDevMode ? [undefined, { debugName: "tooltip" }] : []));
743
+ this.columnPanel = input(...(ngDevMode ? [undefined, { debugName: "columnPanel" }] : []));
744
+ this.toolbar = input(...(ngDevMode ? [undefined, { debugName: "toolbar" }] : []));
745
+ this.savedViews = input(...(ngDevMode ? [undefined, { debugName: "savedViews" }] : []));
746
+ this.allowExportAsCSV = input(...(ngDevMode ? [undefined, { debugName: "allowExportAsCSV" }] : []));
747
+ this.allowExportAsExcel = input(...(ngDevMode ? [undefined, { debugName: "allowExportAsExcel" }] : []));
748
+ // --- cell change flashing ---
749
+ this.cellFlashDuration = input(...(ngDevMode ? [undefined, { debugName: "cellFlashDuration" }] : []));
750
+ this.cellFadeDuration = input(...(ngDevMode ? [undefined, { debugName: "cellFadeDuration" }] : []));
751
+ // --- overlays ---
752
+ /** If true, shows the loading overlay. */
753
+ this.loading = input(...(ngDevMode ? [undefined, { debugName: "loading" }] : []));
754
+ this.loadingMessage = input(...(ngDevMode ? [undefined, { debugName: "loadingMessage" }] : []));
755
+ this.noRowsMessage = input(...(ngDevMode ? [undefined, { debugName: "noRowsMessage" }] : []));
756
+ // --- menus ---
757
+ /** Hook to customize column menu items (slots may be `TemplateRef`s). */
758
+ this.getColumnMenuItems = input(...(ngDevMode ? [undefined, { debugName: "getColumnMenuItems" }] : []));
759
+ /**
760
+ * Controls the body (right-click) context menu:
761
+ * - `true` / omitted (default): the grid's default body menu (Copy, Export, …).
762
+ * - `false`: no grid menu — the browser's native context menu appears instead.
763
+ * - a function: called with the menu context and the default items; return the items to show
764
+ * (slots may be `TemplateRef`s). Return `[]` to show nothing while still suppressing the
765
+ * native menu.
766
+ */
767
+ this.bodyContextMenu = input(...(ngDevMode ? [undefined, { debugName: "bodyContextMenu" }] : []));
768
+ // --- outputs ---
769
+ this.gridReady = output();
770
+ this.cellClicked = output();
771
+ this.rowClicked = output();
772
+ this.cellValueChanged = output();
773
+ this.selectionChanged = output();
774
+ this.sortChanged = output();
775
+ this.filterChanged = output();
776
+ this.historyChanged = output();
777
+ this.host = inject(ElementRef);
778
+ this.zone = inject(NgZone);
779
+ this.injector = inject(Injector);
780
+ this.appRef = inject(ApplicationRef);
781
+ this.adapters = new NgAdapters(this.appRef, inject(EnvironmentInjector), this.zone);
782
+ this.instance = null;
783
+ // afterNextRender only runs in the browser, which doubles as the SSR guard: on the server the
784
+ // grid is never created and the host renders as an empty element.
785
+ afterNextRender(() => this.create());
786
+ }
787
+ ngOnDestroy() {
788
+ const instance = this.instance;
789
+ this.instance = null;
790
+ if (instance)
791
+ destroyInstance(instance);
792
+ }
793
+ create() {
794
+ const instance = this.zone.runOutsideAngular(() => {
795
+ const options = getGridOptions(this, this.adapters);
796
+ // Stable bridges keep the core subscriptions intact while emitting through Angular outputs
797
+ // (re-entering the zone so listeners see a consistent change-detection world).
798
+ options.onCellClicked = (ev) => this.zone.run(() => this.cellClicked.emit(ev));
799
+ options.onRowClicked = (ev) => this.zone.run(() => this.rowClicked.emit(ev));
800
+ options.onCellValueChanged = (ev) => this.zone.run(() => this.cellValueChanged.emit(ev));
801
+ options.onSelectionChanged = (ev) => this.zone.run(() => this.selectionChanged.emit(ev));
802
+ options.onSortChanged = (ev) => this.zone.run(() => this.sortChanged.emit(ev));
803
+ options.onFilterChanged = (ev) => this.zone.run(() => this.filterChanged.emit(ev));
804
+ options.onHistoryChanged = (ev) => this.zone.run(() => this.historyChanged.emit(ev));
805
+ // Value-returning hook, read through the signal so it stays reactive to input changes.
806
+ // zone.run propagates the return value, so veto/transform results reach the grid.
807
+ options.onBeforeCellCommit = (params) => {
808
+ const hook = this.onBeforeCellCommit();
809
+ return hook ? this.zone.run(() => hook(params)) : undefined;
810
+ };
811
+ // createGrid applies columnDefs and rowData right after init, in the same synchronous
812
+ // sequence this component used to perform by hand (init → columnDefs → rowData). The sync
813
+ // effects' creation-time snapshots (lastDefs / lastRows) keep them from re-applying these.
814
+ const api = createGrid(this.host.nativeElement, {
815
+ ...options,
816
+ columnDefs: this.adapters.adaptColumnDefs(this.columnDefs()) ?? undefined,
817
+ // Client-side grids always get an initial rowDataSet (empty included); server-side grids
818
+ // must not, so their slot stays undefined and createGrid skips it.
819
+ rowData: this.rowModelType() !== "serverSide" ? this.rowData() ?? [] : undefined,
820
+ menuAdapter: new NgMenuAdapter(this.appRef, this.zone, {
821
+ getColumnMenuItems: () => this.getColumnMenuItems(),
822
+ }),
823
+ bodyMenuAdapter: new NgBodyMenuAdapter(this.appRef, this.zone, {
824
+ // Only the function arm customizes items here; boolean modes (default / native menu) are
825
+ // forwarded to core by getGridOptions. Read through the signal so the callback stays
826
+ // reactive to input changes without recreating the grid instance.
827
+ getBodyMenuItems: () => {
828
+ const opt = this.bodyContextMenu();
829
+ return typeof opt === "function" ? opt : undefined;
830
+ },
831
+ }),
832
+ });
833
+ const created = { api, destroyed: false };
834
+ return created;
835
+ });
836
+ this.instance = instance;
837
+ this.startSyncEffects(instance);
838
+ this.gridReady.emit(instance.api);
839
+ }
840
+ /**
841
+ * One effect per reconcilable option group, mirroring the React wrapper's per-prop layout
842
+ * effects. Effects are created after the grid instance exists; each one's first run re-applies
843
+ * the value the instance was just created with, which is harmless for these idempotent setters
844
+ * (the React wrapper's mount-run effects do the same). The four widget configs that would
845
+ * rebuild UI on re-application skip their first run via `keyedEffect`.
846
+ */
847
+ startSyncEffects(instance) {
848
+ const { api } = instance;
849
+ // columnDefs/rowData were already applied synchronously by create(); these effects compare
850
+ // against that creation-time snapshot so startup applies them exactly once.
851
+ let lastDefs = untracked(() => this.columnDefs());
852
+ this.syncEffect(() => {
853
+ const defs = this.columnDefs();
854
+ if (defs === lastDefs)
855
+ return null;
856
+ lastDefs = defs;
857
+ // Presence-based: an undefined input still carries the key, releasing caller ownership of
858
+ // the schema exactly as setColumnDefsFromProps(undefined) did.
859
+ return () => api.updateGridOptions({ columnDefs: this.adapters.adaptColumnDefs(defs) });
860
+ });
861
+ let lastRows = untracked(() => this.rowData());
862
+ this.syncEffect(() => {
863
+ const rows = this.rowData();
864
+ if (rows === lastRows || this.rowModelType() === "serverSide")
865
+ return null;
866
+ lastRows = rows;
867
+ return () => api.setRowData(rows ?? []);
868
+ });
869
+ this.syncEffect(() => {
870
+ const v = this.groupDisplayType();
871
+ return () => api.updateGridOptions({ groupDisplayType: v });
872
+ });
873
+ this.syncEffect(() => {
874
+ const v = this.groupSortMode();
875
+ return () => api.updateGridOptions({ groupSortMode: v });
876
+ });
877
+ this.syncEffect(() => {
878
+ const v = this.groupRowsSelectable();
879
+ return () => api.updateGridOptions({ groupRowsSelectable: v });
880
+ });
881
+ this.syncEffect(() => {
882
+ const v = this.isRowSelectable();
883
+ return () => api.updateGridOptions({ isRowSelectable: v });
884
+ });
885
+ this.keyedEffect(() => this.rowSelection(), (value) => api.updateGridOptions({ rowSelection: value }));
886
+ this.syncEffect(() => {
887
+ const treeData = this.treeData();
888
+ // Both keys are always supplied so each restates its current value rather than being read
889
+ // back off the core (the API's presence-based contract).
890
+ return () => api.setTreeDataKeyboardNavigationOptions({
891
+ keyboardNavigationMode: treeData?.keyboardNavigationMode,
892
+ enableKeyboardNavigationModeSwitch: treeData?.enableKeyboardNavigationModeSwitch ?? false,
893
+ });
894
+ });
895
+ this.syncEffect(() => {
896
+ const opts = {
897
+ pinnedTopRowData: this.pinnedTopRowData(),
898
+ pinnedBottomRowData: this.pinnedBottomRowData(),
899
+ isRowPinned: this.isRowPinned(),
900
+ groupRowsSticky: this.groupRowsSticky(),
901
+ };
902
+ return () => api.updateGridOptions(opts);
903
+ });
904
+ this.syncEffect(() => {
905
+ const opts = {
906
+ rowHover: this.rowHover() ?? true,
907
+ columnHover: this.columnHover() ?? false,
908
+ zebraRows: this.zebraRows() ?? false,
909
+ getRowClass: this.getRowClass(),
910
+ getRowStyle: this.getRowStyle(),
911
+ getRowPresentation: this.adapters.adaptGetRowPresentation(this.getRowPresentation()),
912
+ ariaLabel: this.ariaLabel(),
913
+ ariaLabelledBy: this.ariaLabelledBy(),
914
+ highlightActiveCell: this.highlightActiveCell() ?? false,
915
+ cellSelection: this.cellSelection() ?? true,
916
+ rangeSelection: this.rangeSelection() ?? true,
917
+ columnSelection: this.columnSelection() ?? true,
918
+ headerKeyboardNavigation: this.headerKeyboardNavigation() ?? true,
919
+ showColumnButtonsOnHover: this.showColumnButtonsOnHover() ?? false,
920
+ // Function-valued customization is resolved through the body-menu adapter. Core only owns
921
+ // whether the browser-native mode disables the grid menu entirely.
922
+ bodyContextMenu: this.bodyContextMenu() === false ? false : true,
923
+ editTrigger: this.editTrigger() ?? "doubleClick",
924
+ readOnlyEdit: this.readOnlyEdit() ?? false,
925
+ pinnedRowsEditable: this.pinnedRowsEditable() ?? false,
926
+ rowPinningMenu: this.rowPinningMenu() ?? false,
927
+ rowInsertionMenu: this.rowInsertionMenu(),
928
+ suppressKeyboardEdit: this.suppressKeyboardEdit() ?? false,
929
+ suppressTypeToEdit: this.suppressTypeToEdit() ?? false,
930
+ moveAfterEdit: this.moveAfterEdit() ?? true,
931
+ commitOnBlur: this.commitOnBlur() ?? true,
932
+ asyncTransactionWaitMs: this.asyncTransactionWaitMs() ?? 16,
933
+ };
934
+ return () => api.updateGridOptions(opts);
935
+ });
936
+ this.syncEffect(() => {
937
+ const source = this.serverSideDataSource();
938
+ if (this.rowModelType() !== "serverSide" || !source)
939
+ return null;
940
+ return () => api.updateGridOptions({ serverSideDataSource: source });
941
+ });
942
+ this.syncEffect(() => {
943
+ const source = this.serverSideAggregationSource();
944
+ if (this.rowModelType() !== "serverSide" || !source)
945
+ return null;
946
+ return () => api.updateGridOptions({ serverSideAggregationSource: source });
947
+ });
948
+ this.syncEffect(() => {
949
+ const loading = this.loading();
950
+ return () => api.dispatch({ type: "overlayShow", overlayType: loading ? "loading" : "none" });
951
+ });
952
+ this.syncEffect(() => {
953
+ const pagination = this.pagination();
954
+ return () => api.updateGridOptions({ pagination });
955
+ });
956
+ this.keyedEffect(() => this.paginationControls(), (options) => api.updateGridOptions({ paginationControls: options }));
957
+ // Widget configs reconcile live without remounting the grid, but a rebuild on first run would
958
+ // be disruptive (the create path already applied them), so these compare serialized contents
959
+ // and skip the initial application — the Angular translation of the React wrapper's
960
+ // JSON.stringify keys + mounted refs.
961
+ this.keyedEffect(() => this.quickFilter(), (v) => api.updateGridOptions({ quickFilter: v }));
962
+ this.keyedEffect(() => this.tooltip(), (v) => api.updateGridOptions({ tooltip: v }));
963
+ this.keyedEffect(() => this.columnPanel(), (v) => api.updateGridOptions({ columnPanel: v }));
964
+ this.keyedEffect(() => this.toolbar(), (v) => api.updateGridOptions({ toolbar: v }));
965
+ // Saved views are application-owned. Reconcile a new list/callback object in place so a
966
+ // persistence update immediately refreshes the Views menu without remounting the grid.
967
+ this.syncEffect(() => {
968
+ const savedViews = this.savedViews();
969
+ return () => api.updateGridOptions({ savedViews });
970
+ });
971
+ // Theme vars and icons are reconciled together: `icons` overrides any icons carried by
972
+ // `theme`, so recompute the merged set whenever either changes. The merge is done here (not
973
+ // left to the API's theme/icon resolution) because that resolution reads creation-time icons
974
+ // off the core's options, not the current input.
975
+ this.syncEffect(() => {
976
+ const theme = this.theme();
977
+ const icons = this.icons();
978
+ return () => api.updateGridOptions({ theme, icons: { ...theme?.getIcons(), ...icons } });
979
+ });
980
+ }
981
+ /**
982
+ * Effect helper: `read` runs tracked (signal reads register dependencies) and returns the core
983
+ * call to make, or null to skip; the call itself runs outside the Angular zone so core-side
984
+ * listener churn never schedules change detection.
985
+ */
986
+ syncEffect(read) {
987
+ effect(() => {
988
+ const apply = read();
989
+ if (!apply || !this.instance)
990
+ return;
991
+ this.zone.runOutsideAngular(apply);
992
+ }, { injector: this.injector });
993
+ }
994
+ /**
995
+ * Like syncEffect, but compares serialized contents against the value the grid was created with,
996
+ * so an inline-object input doesn't rebuild the widget unless its contents actually changed —
997
+ * and the creation-time application is never repeated. (The effect's first run is NOT guaranteed
998
+ * to happen at mount: with OnPush it can be deferred to the first input change, so "skip the
999
+ * first run" would swallow a real change — compare values, not run counts.)
1000
+ */
1001
+ keyedEffect(read, apply) {
1002
+ let lastKey = JSON.stringify(untracked(read) ?? null);
1003
+ effect(() => {
1004
+ const value = read();
1005
+ const key = JSON.stringify(value ?? null);
1006
+ if (key === lastKey || !this.instance)
1007
+ return;
1008
+ lastKey = key;
1009
+ this.zone.runOutsideAngular(() => apply(value));
1010
+ }, { injector: this.injector });
1011
+ }
1012
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: AwbGrid, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1013
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.27", type: AwbGrid, isStandalone: true, selector: "awb-grid", inputs: { rowData: { classPropertyName: "rowData", publicName: "rowData", isSignal: true, isRequired: false, transformFunction: null }, columnDefs: { classPropertyName: "columnDefs", publicName: "columnDefs", isSignal: true, isRequired: false, transformFunction: null }, defaultColDef: { classPropertyName: "defaultColDef", publicName: "defaultColDef", isSignal: true, isRequired: false, transformFunction: null }, headerHeight: { classPropertyName: "headerHeight", publicName: "headerHeight", isSignal: true, isRequired: false, transformFunction: null }, leafHeaderHeight: { classPropertyName: "leafHeaderHeight", publicName: "leafHeaderHeight", isSignal: true, isRequired: false, transformFunction: null }, parentHeaderHeight: { classPropertyName: "parentHeaderHeight", publicName: "parentHeaderHeight", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, overscanRowCount: { classPropertyName: "overscanRowCount", publicName: "overscanRowCount", isSignal: true, isRequired: false, transformFunction: null }, minResizeWidth: { classPropertyName: "minResizeWidth", publicName: "minResizeWidth", isSignal: true, isRequired: false, transformFunction: null }, maxColumnWidth: { classPropertyName: "maxColumnWidth", publicName: "maxColumnWidth", isSignal: true, isRequired: false, transformFunction: null }, autosizeColumnsOnDataChange: { classPropertyName: "autosizeColumnsOnDataChange", publicName: "autosizeColumnsOnDataChange", isSignal: true, isRequired: false, transformFunction: null }, getRowId: { classPropertyName: "getRowId", publicName: "getRowId", isSignal: true, isRequired: false, transformFunction: null }, rowIdKey: { classPropertyName: "rowIdKey", publicName: "rowIdKey", isSignal: true, isRequired: false, transformFunction: null }, rowDataMode: { classPropertyName: "rowDataMode", publicName: "rowDataMode", isSignal: true, isRequired: false, transformFunction: null }, asyncTransactionWaitMs: { classPropertyName: "asyncTransactionWaitMs", publicName: "asyncTransactionWaitMs", isSignal: true, isRequired: false, transformFunction: null }, rowHover: { classPropertyName: "rowHover", publicName: "rowHover", isSignal: true, isRequired: false, transformFunction: null }, columnHover: { classPropertyName: "columnHover", publicName: "columnHover", isSignal: true, isRequired: false, transformFunction: null }, zebraRows: { classPropertyName: "zebraRows", publicName: "zebraRows", isSignal: true, isRequired: false, transformFunction: null }, getRowClass: { classPropertyName: "getRowClass", publicName: "getRowClass", isSignal: true, isRequired: false, transformFunction: null }, getRowStyle: { classPropertyName: "getRowStyle", publicName: "getRowStyle", isSignal: true, isRequired: false, transformFunction: null }, getRowPresentation: { classPropertyName: "getRowPresentation", publicName: "getRowPresentation", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "ariaLabelledBy", isSignal: true, isRequired: false, transformFunction: null }, highlightActiveCell: { classPropertyName: "highlightActiveCell", publicName: "highlightActiveCell", isSignal: true, isRequired: false, transformFunction: null }, rowNumbers: { classPropertyName: "rowNumbers", publicName: "rowNumbers", isSignal: true, isRequired: false, transformFunction: null }, showColumnButtonsOnHover: { classPropertyName: "showColumnButtonsOnHover", publicName: "showColumnButtonsOnHover", isSignal: true, isRequired: false, transformFunction: null }, theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: false, transformFunction: null }, icons: { classPropertyName: "icons", publicName: "icons", isSignal: true, isRequired: false, transformFunction: null }, suppressStyleInjection: { classPropertyName: "suppressStyleInjection", publicName: "suppressStyleInjection", isSignal: true, isRequired: false, transformFunction: null }, styleNonce: { classPropertyName: "styleNonce", publicName: "styleNonce", isSignal: true, isRequired: false, transformFunction: null }, rowSelection: { classPropertyName: "rowSelection", publicName: "rowSelection", isSignal: true, isRequired: false, transformFunction: null }, isRowSelectable: { classPropertyName: "isRowSelectable", publicName: "isRowSelectable", isSignal: true, isRequired: false, transformFunction: null }, cellSelection: { classPropertyName: "cellSelection", publicName: "cellSelection", isSignal: true, isRequired: false, transformFunction: null }, rangeSelection: { classPropertyName: "rangeSelection", publicName: "rangeSelection", isSignal: true, isRequired: false, transformFunction: null }, columnSelection: { classPropertyName: "columnSelection", publicName: "columnSelection", isSignal: true, isRequired: false, transformFunction: null }, headerKeyboardNavigation: { classPropertyName: "headerKeyboardNavigation", publicName: "headerKeyboardNavigation", isSignal: true, isRequired: false, transformFunction: null }, selectAllRowsOnHeaderClick: { classPropertyName: "selectAllRowsOnHeaderClick", publicName: "selectAllRowsOnHeaderClick", isSignal: true, isRequired: false, transformFunction: null }, selectAllScope: { classPropertyName: "selectAllScope", publicName: "selectAllScope", isSignal: true, isRequired: false, transformFunction: null }, selectionPersistence: { classPropertyName: "selectionPersistence", publicName: "selectionPersistence", isSignal: true, isRequired: false, transformFunction: null }, clearSelectionOnBodyClick: { classPropertyName: "clearSelectionOnBodyClick", publicName: "clearSelectionOnBodyClick", isSignal: true, isRequired: false, transformFunction: null }, editTrigger: { classPropertyName: "editTrigger", publicName: "editTrigger", isSignal: true, isRequired: false, transformFunction: null }, onBeforeCellCommit: { classPropertyName: "onBeforeCellCommit", publicName: "onBeforeCellCommit", isSignal: true, isRequired: false, transformFunction: null }, readOnlyEdit: { classPropertyName: "readOnlyEdit", publicName: "readOnlyEdit", isSignal: true, isRequired: false, transformFunction: null }, pinnedRowsEditable: { classPropertyName: "pinnedRowsEditable", publicName: "pinnedRowsEditable", isSignal: true, isRequired: false, transformFunction: null }, suppressKeyboardEdit: { classPropertyName: "suppressKeyboardEdit", publicName: "suppressKeyboardEdit", isSignal: true, isRequired: false, transformFunction: null }, suppressTypeToEdit: { classPropertyName: "suppressTypeToEdit", publicName: "suppressTypeToEdit", isSignal: true, isRequired: false, transformFunction: null }, moveAfterEdit: { classPropertyName: "moveAfterEdit", publicName: "moveAfterEdit", isSignal: true, isRequired: false, transformFunction: null }, commitOnBlur: { classPropertyName: "commitOnBlur", publicName: "commitOnBlur", isSignal: true, isRequired: false, transformFunction: null }, reevaluateOnEdit: { classPropertyName: "reevaluateOnEdit", publicName: "reevaluateOnEdit", isSignal: true, isRequired: false, transformFunction: null }, undoLimit: { classPropertyName: "undoLimit", publicName: "undoLimit", isSignal: true, isRequired: false, transformFunction: null }, initialSort: { classPropertyName: "initialSort", publicName: "initialSort", isSignal: true, isRequired: false, transformFunction: null }, showSortPriority: { classPropertyName: "showSortPriority", publicName: "showSortPriority", isSignal: true, isRequired: false, transformFunction: null }, quickFilter: { classPropertyName: "quickFilter", publicName: "quickFilter", isSignal: true, isRequired: false, transformFunction: null }, filterDebounceMs: { classPropertyName: "filterDebounceMs", publicName: "filterDebounceMs", isSignal: true, isRequired: false, transformFunction: null }, groupDisplayType: { classPropertyName: "groupDisplayType", publicName: "groupDisplayType", isSignal: true, isRequired: false, transformFunction: null }, groupColumnDef: { classPropertyName: "groupColumnDef", publicName: "groupColumnDef", isSignal: true, isRequired: false, transformFunction: null }, groupDefaultExpanded: { classPropertyName: "groupDefaultExpanded", publicName: "groupDefaultExpanded", isSignal: true, isRequired: false, transformFunction: null }, groupSortMode: { classPropertyName: "groupSortMode", publicName: "groupSortMode", isSignal: true, isRequired: false, transformFunction: null }, groupRowsSelectable: { classPropertyName: "groupRowsSelectable", publicName: "groupRowsSelectable", isSignal: true, isRequired: false, transformFunction: null }, groupRowsSticky: { classPropertyName: "groupRowsSticky", publicName: "groupRowsSticky", isSignal: true, isRequired: false, transformFunction: null }, getGroupChildCount: { classPropertyName: "getGroupChildCount", publicName: "getGroupChildCount", isSignal: true, isRequired: false, transformFunction: null }, treeData: { classPropertyName: "treeData", publicName: "treeData", isSignal: true, isRequired: false, transformFunction: null }, pinnedTopRowData: { classPropertyName: "pinnedTopRowData", publicName: "pinnedTopRowData", isSignal: true, isRequired: false, transformFunction: null }, pinnedBottomRowData: { classPropertyName: "pinnedBottomRowData", publicName: "pinnedBottomRowData", isSignal: true, isRequired: false, transformFunction: null }, isRowPinned: { classPropertyName: "isRowPinned", publicName: "isRowPinned", isSignal: true, isRequired: false, transformFunction: null }, rowPinningMenu: { classPropertyName: "rowPinningMenu", publicName: "rowPinningMenu", isSignal: true, isRequired: false, transformFunction: null }, rowInsertionMenu: { classPropertyName: "rowInsertionMenu", publicName: "rowInsertionMenu", isSignal: true, isRequired: false, transformFunction: null }, isFullWidthRow: { classPropertyName: "isFullWidthRow", publicName: "isFullWidthRow", isSignal: true, isRequired: false, transformFunction: null }, fullWidthCellRenderer: { classPropertyName: "fullWidthCellRenderer", publicName: "fullWidthCellRenderer", isSignal: true, isRequired: false, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: false, transformFunction: null }, paginationControls: { classPropertyName: "paginationControls", publicName: "paginationControls", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, pageSizes: { classPropertyName: "pageSizes", publicName: "pageSizes", isSignal: true, isRequired: false, transformFunction: null }, resetPageOn: { classPropertyName: "resetPageOn", publicName: "resetPageOn", isSignal: true, isRequired: false, transformFunction: null }, paginationUnknownTotalTooltip: { classPropertyName: "paginationUnknownTotalTooltip", publicName: "paginationUnknownTotalTooltip", isSignal: true, isRequired: false, transformFunction: null }, rowModelType: { classPropertyName: "rowModelType", publicName: "rowModelType", isSignal: true, isRequired: false, transformFunction: null }, serverSideDataSource: { classPropertyName: "serverSideDataSource", publicName: "serverSideDataSource", isSignal: true, isRequired: false, transformFunction: null }, serverSideAggregationSource: { classPropertyName: "serverSideAggregationSource", publicName: "serverSideAggregationSource", isSignal: true, isRequired: false, transformFunction: null }, serverSideBlockSize: { classPropertyName: "serverSideBlockSize", publicName: "serverSideBlockSize", isSignal: true, isRequired: false, transformFunction: null }, tooltip: { classPropertyName: "tooltip", publicName: "tooltip", isSignal: true, isRequired: false, transformFunction: null }, columnPanel: { classPropertyName: "columnPanel", publicName: "columnPanel", isSignal: true, isRequired: false, transformFunction: null }, toolbar: { classPropertyName: "toolbar", publicName: "toolbar", isSignal: true, isRequired: false, transformFunction: null }, savedViews: { classPropertyName: "savedViews", publicName: "savedViews", isSignal: true, isRequired: false, transformFunction: null }, allowExportAsCSV: { classPropertyName: "allowExportAsCSV", publicName: "allowExportAsCSV", isSignal: true, isRequired: false, transformFunction: null }, allowExportAsExcel: { classPropertyName: "allowExportAsExcel", publicName: "allowExportAsExcel", isSignal: true, isRequired: false, transformFunction: null }, cellFlashDuration: { classPropertyName: "cellFlashDuration", publicName: "cellFlashDuration", isSignal: true, isRequired: false, transformFunction: null }, cellFadeDuration: { classPropertyName: "cellFadeDuration", publicName: "cellFadeDuration", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingMessage: { classPropertyName: "loadingMessage", publicName: "loadingMessage", isSignal: true, isRequired: false, transformFunction: null }, noRowsMessage: { classPropertyName: "noRowsMessage", publicName: "noRowsMessage", isSignal: true, isRequired: false, transformFunction: null }, getColumnMenuItems: { classPropertyName: "getColumnMenuItems", publicName: "getColumnMenuItems", isSignal: true, isRequired: false, transformFunction: null }, bodyContextMenu: { classPropertyName: "bodyContextMenu", publicName: "bodyContextMenu", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { gridReady: "gridReady", cellClicked: "cellClicked", rowClicked: "rowClicked", cellValueChanged: "cellValueChanged", selectionChanged: "selectionChanged", sortChanged: "sortChanged", filterChanged: "filterChanged", historyChanged: "historyChanged" }, exportAs: ["awbGrid"], ngImport: i0, template: "", isInline: true, styles: [":host{position:relative;display:block;width:100%;height:100%;overflow:hidden}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1014
+ }
1015
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: AwbGrid, decorators: [{
1016
+ type: Component,
1017
+ args: [{ selector: "awb-grid", standalone: true, exportAs: "awbGrid", template: "", changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{position:relative;display:block;width:100%;height:100%;overflow:hidden}\n"] }]
1018
+ }], ctorParameters: () => [], propDecorators: { rowData: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowData", required: false }] }], columnDefs: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnDefs", required: false }] }], defaultColDef: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultColDef", required: false }] }], headerHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerHeight", required: false }] }], leafHeaderHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "leafHeaderHeight", required: false }] }], parentHeaderHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentHeaderHeight", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], overscanRowCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "overscanRowCount", required: false }] }], minResizeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minResizeWidth", required: false }] }], maxColumnWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxColumnWidth", required: false }] }], autosizeColumnsOnDataChange: [{ type: i0.Input, args: [{ isSignal: true, alias: "autosizeColumnsOnDataChange", required: false }] }], getRowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "getRowId", required: false }] }], rowIdKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowIdKey", required: false }] }], rowDataMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowDataMode", required: false }] }], asyncTransactionWaitMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "asyncTransactionWaitMs", required: false }] }], rowHover: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHover", required: false }] }], columnHover: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnHover", required: false }] }], zebraRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "zebraRows", required: false }] }], getRowClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "getRowClass", required: false }] }], getRowStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "getRowStyle", required: false }] }], getRowPresentation: [{ type: i0.Input, args: [{ isSignal: true, alias: "getRowPresentation", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaLabelledBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelledBy", required: false }] }], highlightActiveCell: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightActiveCell", required: false }] }], rowNumbers: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowNumbers", required: false }] }], showColumnButtonsOnHover: [{ type: i0.Input, args: [{ isSignal: true, alias: "showColumnButtonsOnHover", required: false }] }], theme: [{ type: i0.Input, args: [{ isSignal: true, alias: "theme", required: false }] }], icons: [{ type: i0.Input, args: [{ isSignal: true, alias: "icons", required: false }] }], suppressStyleInjection: [{ type: i0.Input, args: [{ isSignal: true, alias: "suppressStyleInjection", required: false }] }], styleNonce: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleNonce", required: false }] }], rowSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowSelection", required: false }] }], isRowSelectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRowSelectable", required: false }] }], cellSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellSelection", required: false }] }], rangeSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "rangeSelection", required: false }] }], columnSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnSelection", required: false }] }], headerKeyboardNavigation: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerKeyboardNavigation", required: false }] }], selectAllRowsOnHeaderClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllRowsOnHeaderClick", required: false }] }], selectAllScope: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllScope", required: false }] }], selectionPersistence: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionPersistence", required: false }] }], clearSelectionOnBodyClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearSelectionOnBodyClick", required: false }] }], editTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "editTrigger", required: false }] }], onBeforeCellCommit: [{ type: i0.Input, args: [{ isSignal: true, alias: "onBeforeCellCommit", required: false }] }], readOnlyEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "readOnlyEdit", required: false }] }], pinnedRowsEditable: [{ type: i0.Input, args: [{ isSignal: true, alias: "pinnedRowsEditable", required: false }] }], suppressKeyboardEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "suppressKeyboardEdit", required: false }] }], suppressTypeToEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "suppressTypeToEdit", required: false }] }], moveAfterEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "moveAfterEdit", required: false }] }], commitOnBlur: [{ type: i0.Input, args: [{ isSignal: true, alias: "commitOnBlur", required: false }] }], reevaluateOnEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "reevaluateOnEdit", required: false }] }], undoLimit: [{ type: i0.Input, args: [{ isSignal: true, alias: "undoLimit", required: false }] }], initialSort: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialSort", required: false }] }], showSortPriority: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSortPriority", required: false }] }], quickFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilter", required: false }] }], filterDebounceMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterDebounceMs", required: false }] }], groupDisplayType: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupDisplayType", required: false }] }], groupColumnDef: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupColumnDef", required: false }] }], groupDefaultExpanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupDefaultExpanded", required: false }] }], groupSortMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupSortMode", required: false }] }], groupRowsSelectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupRowsSelectable", required: false }] }], groupRowsSticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupRowsSticky", required: false }] }], getGroupChildCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "getGroupChildCount", required: false }] }], treeData: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeData", required: false }] }], pinnedTopRowData: [{ type: i0.Input, args: [{ isSignal: true, alias: "pinnedTopRowData", required: false }] }], pinnedBottomRowData: [{ type: i0.Input, args: [{ isSignal: true, alias: "pinnedBottomRowData", required: false }] }], isRowPinned: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRowPinned", required: false }] }], rowPinningMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowPinningMenu", required: false }] }], rowInsertionMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowInsertionMenu", required: false }] }], isFullWidthRow: [{ type: i0.Input, args: [{ isSignal: true, alias: "isFullWidthRow", required: false }] }], fullWidthCellRenderer: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidthCellRenderer", required: false }] }], pagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagination", required: false }] }], paginationControls: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginationControls", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], pageSizes: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizes", required: false }] }], resetPageOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "resetPageOn", required: false }] }], paginationUnknownTotalTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginationUnknownTotalTooltip", required: false }] }], rowModelType: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowModelType", required: false }] }], serverSideDataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "serverSideDataSource", required: false }] }], serverSideAggregationSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "serverSideAggregationSource", required: false }] }], serverSideBlockSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "serverSideBlockSize", required: false }] }], tooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltip", required: false }] }], columnPanel: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnPanel", required: false }] }], toolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbar", required: false }] }], savedViews: [{ type: i0.Input, args: [{ isSignal: true, alias: "savedViews", required: false }] }], allowExportAsCSV: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowExportAsCSV", required: false }] }], allowExportAsExcel: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowExportAsExcel", required: false }] }], cellFlashDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellFlashDuration", required: false }] }], cellFadeDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellFadeDuration", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingMessage", required: false }] }], noRowsMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "noRowsMessage", required: false }] }], getColumnMenuItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "getColumnMenuItems", required: false }] }], bodyContextMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "bodyContextMenu", required: false }] }], gridReady: [{ type: i0.Output, args: ["gridReady"] }], cellClicked: [{ type: i0.Output, args: ["cellClicked"] }], rowClicked: [{ type: i0.Output, args: ["rowClicked"] }], cellValueChanged: [{ type: i0.Output, args: ["cellValueChanged"] }], selectionChanged: [{ type: i0.Output, args: ["selectionChanged"] }], sortChanged: [{ type: i0.Output, args: ["sortChanged"] }], filterChanged: [{ type: i0.Output, args: ["filterChanged"] }], historyChanged: [{ type: i0.Output, args: ["historyChanged"] }] } });
1019
+
1020
+ // Re-export the full framework-agnostic core surface so consumers can import everything they need
1021
+ // (ColDef, GridOptions, themes, types, …) from the Angular entry alone:
1022
+ // `import { AwbGrid, themeDark, type ColDef } from "@agility-workbench/angular-grid"`.
1023
+
1024
+ /**
1025
+ * Generated bundle index. Do not edit.
1026
+ */
1027
+
1028
+ export { AwbGrid };