@alaarab/ogrid-angular 2.6.0 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/esm/components/base-column-chooser.component.js +77 -0
  2. package/dist/esm/components/base-column-header-filter.component.js +267 -0
  3. package/dist/esm/components/base-column-header-menu.component.js +80 -0
  4. package/dist/esm/components/base-datagrid-table.component.js +768 -0
  5. package/dist/esm/components/base-inline-cell-editor.component.js +380 -0
  6. package/dist/esm/components/base-ogrid.component.js +36 -0
  7. package/dist/esm/components/base-pagination-controls.component.js +68 -0
  8. package/dist/esm/components/base-popover-cell-editor.component.js +122 -0
  9. package/dist/esm/components/empty-state.component.js +68 -0
  10. package/dist/esm/components/formula-bar.component.js +99 -0
  11. package/dist/esm/components/formula-ref-overlay.component.js +115 -0
  12. package/dist/esm/components/grid-context-menu.component.js +197 -0
  13. package/dist/esm/components/inline-cell-editor-template.js +134 -0
  14. package/dist/esm/components/marching-ants-overlay.component.js +177 -0
  15. package/dist/esm/components/ogrid-layout.component.js +302 -0
  16. package/dist/esm/components/sheet-tabs.component.js +83 -0
  17. package/dist/esm/components/sidebar.component.js +431 -0
  18. package/dist/esm/components/status-bar.component.js +92 -0
  19. package/dist/esm/index.js +39 -819
  20. package/dist/esm/services/column-reorder.service.js +176 -0
  21. package/dist/esm/services/datagrid-editing.service.js +59 -0
  22. package/dist/esm/services/datagrid-interaction.service.js +744 -0
  23. package/dist/esm/services/datagrid-layout.service.js +157 -0
  24. package/dist/esm/services/datagrid-state.service.js +636 -0
  25. package/dist/esm/services/formula-engine.service.js +223 -0
  26. package/dist/esm/services/ogrid.service.js +1094 -0
  27. package/dist/esm/services/virtual-scroll.service.js +114 -0
  28. package/dist/esm/styles/ogrid-theme-vars.js +112 -0
  29. package/dist/esm/types/columnTypes.js +1 -0
  30. package/dist/esm/types/dataGridTypes.js +1 -0
  31. package/dist/esm/types/index.js +1 -0
  32. package/dist/esm/utils/dataGridViewModel.js +6 -0
  33. package/dist/esm/utils/debounce.js +68 -0
  34. package/dist/esm/utils/index.js +8 -0
  35. package/dist/esm/utils/latestRef.js +41 -0
  36. package/dist/types/components/base-column-chooser.component.d.ts +3 -0
  37. package/dist/types/components/base-column-header-filter.component.d.ts +3 -0
  38. package/dist/types/components/base-column-header-menu.component.d.ts +3 -0
  39. package/dist/types/components/base-datagrid-table.component.d.ts +4 -19
  40. package/dist/types/components/base-inline-cell-editor.component.d.ts +7 -0
  41. package/dist/types/components/base-ogrid.component.d.ts +3 -0
  42. package/dist/types/components/base-pagination-controls.component.d.ts +3 -0
  43. package/dist/types/components/base-popover-cell-editor.component.d.ts +3 -0
  44. package/dist/types/components/empty-state.component.d.ts +3 -0
  45. package/dist/types/components/formula-bar.component.d.ts +3 -8
  46. package/dist/types/components/formula-ref-overlay.component.d.ts +3 -6
  47. package/dist/types/components/grid-context-menu.component.d.ts +3 -0
  48. package/dist/types/components/inline-cell-editor-template.d.ts +2 -2
  49. package/dist/types/components/marching-ants-overlay.component.d.ts +3 -0
  50. package/dist/types/components/ogrid-layout.component.d.ts +3 -0
  51. package/dist/types/components/sheet-tabs.component.d.ts +3 -8
  52. package/dist/types/components/sidebar.component.d.ts +3 -0
  53. package/dist/types/components/status-bar.component.d.ts +3 -0
  54. package/dist/types/index.d.ts +0 -2
  55. package/dist/types/services/column-reorder.service.d.ts +3 -0
  56. package/dist/types/services/datagrid-interaction.service.d.ts +1 -0
  57. package/dist/types/services/datagrid-state.service.d.ts +5 -0
  58. package/dist/types/services/formula-engine.service.d.ts +3 -9
  59. package/dist/types/services/ogrid.service.d.ts +8 -11
  60. package/dist/types/services/virtual-scroll.service.d.ts +3 -0
  61. package/dist/types/types/dataGridTypes.d.ts +0 -4
  62. package/package.json +4 -3
@@ -0,0 +1,223 @@
1
+ /**
2
+ * FormulaEngineService - Angular service for integrating the formula engine with the grid.
3
+ *
4
+ * Lazily creates a FormulaEngine instance when configured with `formulas: true`.
5
+ * Provides an accessor bridge between grid data and formula coordinates.
6
+ * Uses Angular signals for reactive state.
7
+ *
8
+ * Port of React's useFormulaEngine hook.
9
+ */
10
+ import { Injectable, signal, computed, DestroyRef, inject } from '@angular/core';
11
+ import { createGridDataAccessor } from '@alaarab/ogrid-core';
12
+ import { FormulaEngine } from '@alaarab/ogrid-core/formula';
13
+ import * as i0 from "@angular/core";
14
+ /**
15
+ * Per-component injectable service that wraps FormulaEngine from @alaarab/ogrid-core.
16
+ *
17
+ * Not providedIn: 'root' - provide it per component so each grid instance
18
+ * gets its own formula engine.
19
+ */
20
+ export class FormulaEngineService {
21
+ constructor() {
22
+ this.destroyRef = inject(DestroyRef);
23
+ // --- Internal state ---
24
+ this.engine = null;
25
+ this.initialLoaded = false;
26
+ // --- Data references (updated via configure or setData) ---
27
+ this.items = [];
28
+ this.flatColumns = [];
29
+ // --- Signals ---
30
+ /** Whether formula support is currently enabled. */
31
+ this.enabled = signal(false, ...(ngDevMode ? [{ debugName: "enabled" }] : []));
32
+ /** Last recalculation result, for UI to react to formula changes. */
33
+ this.lastRecalcResult = signal(null, ...(ngDevMode ? [{ debugName: "lastRecalcResult" }] : []));
34
+ /** Number of formulas currently registered. */
35
+ this.formulaCount = computed(() => {
36
+ // Re-read lastRecalcResult to ensure reactivity when formulas change
37
+ this.lastRecalcResult();
38
+ return this.engine?.getAllFormulas().length ?? 0;
39
+ }, ...(ngDevMode ? [{ debugName: "formulaCount" }] : []));
40
+ this.destroyRef.onDestroy(() => {
41
+ this.engine?.clear();
42
+ this.engine = null;
43
+ });
44
+ }
45
+ /**
46
+ * Configure the formula engine. Call this when the grid component initializes.
47
+ *
48
+ * Lazily creates the FormulaEngine only when `formulas: true`.
49
+ */
50
+ configure(options) {
51
+ const { formulas, initialFormulas, formulaFunctions, onFormulaRecalc, namedRanges, sheets } = options;
52
+ this.onFormulaRecalcFn = onFormulaRecalc;
53
+ if (formulas && !this.engine) {
54
+ // Create engine lazily
55
+ this.engine = new FormulaEngine({
56
+ customFunctions: formulaFunctions,
57
+ namedRanges,
58
+ });
59
+ // Register sheet accessors
60
+ if (sheets) {
61
+ for (const [name, accessor] of Object.entries(sheets)) {
62
+ this.engine.registerSheet(name, accessor);
63
+ }
64
+ }
65
+ this.enabled.set(true);
66
+ }
67
+ else if (!formulas && this.engine) {
68
+ // Tear down engine
69
+ this.engine.clear();
70
+ this.engine = null;
71
+ this.enabled.set(false);
72
+ this.lastRecalcResult.set(null);
73
+ this.initialLoaded = false;
74
+ }
75
+ // Load initial formulas once
76
+ if (formulas && this.engine && initialFormulas && !this.initialLoaded) {
77
+ this.initialLoaded = true;
78
+ const accessor = this.createAccessor();
79
+ const result = this.engine.loadFormulas(initialFormulas, accessor);
80
+ if (result.updatedCells.length > 0) {
81
+ this.lastRecalcResult.set(result);
82
+ this.onFormulaRecalcFn?.(result);
83
+ }
84
+ }
85
+ }
86
+ /**
87
+ * Update the data references used by the accessor bridge.
88
+ * Call this whenever the grid's items or columns change.
89
+ */
90
+ setData(items, flatColumns) {
91
+ this.items = items;
92
+ this.flatColumns = flatColumns;
93
+ }
94
+ /**
95
+ * Set or clear a formula for a cell. Triggers recalculation of dependents.
96
+ */
97
+ setFormula(col, row, formula, accessor) {
98
+ if (!this.engine)
99
+ return;
100
+ const acc = accessor ?? this.createAccessor();
101
+ const result = this.engine.setFormula(col, row, formula, acc);
102
+ if (result.updatedCells.length > 0) {
103
+ this.lastRecalcResult.set(result);
104
+ this.onFormulaRecalcFn?.(result);
105
+ }
106
+ }
107
+ /**
108
+ * Notify the engine that a non-formula cell's value changed.
109
+ * Triggers recalculation of any formulas that depend on this cell.
110
+ */
111
+ onCellChanged(col, row, accessor) {
112
+ if (!this.engine)
113
+ return;
114
+ const acc = accessor ?? this.createAccessor();
115
+ const result = this.engine.onCellChanged(col, row, acc);
116
+ if (result.updatedCells.length > 0) {
117
+ this.lastRecalcResult.set(result);
118
+ this.onFormulaRecalcFn?.(result);
119
+ }
120
+ }
121
+ /**
122
+ * Get the formula engine's computed value for a cell coordinate.
123
+ */
124
+ getValue(col, row) {
125
+ return this.engine?.getValue(col, row);
126
+ }
127
+ /**
128
+ * Check if a cell has a formula.
129
+ */
130
+ hasFormula(col, row) {
131
+ return this.engine?.hasFormula(col, row) ?? false;
132
+ }
133
+ /**
134
+ * Get the formula string for a cell.
135
+ */
136
+ getFormula(col, row) {
137
+ return this.engine?.getFormula(col, row);
138
+ }
139
+ /**
140
+ * Trigger a full recalculation of all formulas.
141
+ */
142
+ recalcAll(accessor) {
143
+ if (!this.engine)
144
+ return;
145
+ const acc = accessor ?? this.createAccessor();
146
+ const result = this.engine.recalcAll(acc);
147
+ if (result.updatedCells.length > 0) {
148
+ this.lastRecalcResult.set(result);
149
+ this.onFormulaRecalcFn?.(result);
150
+ }
151
+ }
152
+ /**
153
+ * Get all formulas for serialization.
154
+ */
155
+ getAllFormulas() {
156
+ return this.engine?.getAllFormulas() ?? [];
157
+ }
158
+ /**
159
+ * Register a custom function at runtime.
160
+ */
161
+ registerFunction(name, fn) {
162
+ this.engine?.registerFunction(name, fn);
163
+ }
164
+ /**
165
+ * Clear all formulas and cached values.
166
+ */
167
+ clear() {
168
+ this.engine?.clear();
169
+ this.lastRecalcResult.set(null);
170
+ }
171
+ /**
172
+ * Define a named range.
173
+ */
174
+ defineNamedRange(name, ref) {
175
+ this.engine?.defineNamedRange(name, ref);
176
+ }
177
+ /**
178
+ * Remove a named range.
179
+ */
180
+ removeNamedRange(name) {
181
+ this.engine?.removeNamedRange(name);
182
+ }
183
+ /**
184
+ * Register a sheet accessor for cross-sheet references.
185
+ */
186
+ registerSheet(name, accessor) {
187
+ this.engine?.registerSheet(name, accessor);
188
+ }
189
+ /**
190
+ * Unregister a sheet accessor.
191
+ */
192
+ unregisterSheet(name) {
193
+ this.engine?.unregisterSheet(name);
194
+ }
195
+ /**
196
+ * Get all cells that a cell depends on (deep, transitive).
197
+ */
198
+ getPrecedents(col, row) {
199
+ return this.engine?.getPrecedents(col, row) ?? [];
200
+ }
201
+ /**
202
+ * Get all cells that depend on a cell (deep, transitive).
203
+ */
204
+ getDependents(col, row) {
205
+ return this.engine?.getDependents(col, row) ?? [];
206
+ }
207
+ /**
208
+ * Get full audit trail for a cell.
209
+ */
210
+ getAuditTrail(col, row) {
211
+ return this.engine?.getAuditTrail(col, row) ?? null;
212
+ }
213
+ // --- Private helpers ---
214
+ /** Create a data accessor that bridges grid data to formula coordinates. */
215
+ createAccessor() {
216
+ return createGridDataAccessor(this.items, this.flatColumns);
217
+ }
218
+ static { this.ɵfac = function FormulaEngineService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || FormulaEngineService)(); }; }
219
+ static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: FormulaEngineService, factory: FormulaEngineService.ɵfac }); }
220
+ }
221
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FormulaEngineService, [{
222
+ type: Injectable
223
+ }], () => [], null); })();