@alaarab/ogrid-angular 2.5.9 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/components/base-column-chooser.component.js +77 -0
- package/dist/esm/components/base-column-header-filter.component.js +267 -0
- package/dist/esm/components/base-column-header-menu.component.js +80 -0
- package/dist/esm/components/base-datagrid-table.component.js +768 -0
- package/dist/esm/components/base-inline-cell-editor.component.js +380 -0
- package/dist/esm/components/base-ogrid.component.js +36 -0
- package/dist/esm/components/base-pagination-controls.component.js +68 -0
- package/dist/esm/components/base-popover-cell-editor.component.js +122 -0
- package/dist/esm/components/empty-state.component.js +68 -0
- package/dist/esm/components/formula-bar.component.js +99 -0
- package/dist/esm/components/formula-ref-overlay.component.js +115 -0
- package/dist/esm/components/grid-context-menu.component.js +197 -0
- package/dist/esm/components/inline-cell-editor-template.js +134 -0
- package/dist/esm/components/marching-ants-overlay.component.js +177 -0
- package/dist/esm/components/ogrid-layout.component.js +302 -0
- package/dist/esm/components/sheet-tabs.component.js +83 -0
- package/dist/esm/components/sidebar.component.js +431 -0
- package/dist/esm/components/status-bar.component.js +92 -0
- package/dist/esm/index.js +39 -819
- package/dist/esm/services/column-reorder.service.js +176 -0
- package/dist/esm/services/datagrid-editing.service.js +59 -0
- package/dist/esm/services/datagrid-interaction.service.js +744 -0
- package/dist/esm/services/datagrid-layout.service.js +157 -0
- package/dist/esm/services/datagrid-state.service.js +636 -0
- package/dist/esm/services/formula-engine.service.js +223 -0
- package/dist/esm/services/ogrid.service.js +1094 -0
- package/dist/esm/services/virtual-scroll.service.js +114 -0
- package/dist/esm/styles/ogrid-theme-vars.js +112 -0
- package/dist/esm/types/columnTypes.js +1 -0
- package/dist/esm/types/dataGridTypes.js +1 -0
- package/dist/esm/types/index.js +1 -0
- package/dist/esm/utils/dataGridViewModel.js +6 -0
- package/dist/esm/utils/debounce.js +68 -0
- package/dist/esm/utils/index.js +8 -0
- package/dist/esm/utils/latestRef.js +41 -0
- package/dist/types/components/base-column-chooser.component.d.ts +3 -0
- package/dist/types/components/base-column-header-filter.component.d.ts +3 -0
- package/dist/types/components/base-column-header-menu.component.d.ts +3 -0
- package/dist/types/components/base-datagrid-table.component.d.ts +3 -0
- package/dist/types/components/base-inline-cell-editor.component.d.ts +7 -0
- package/dist/types/components/base-ogrid.component.d.ts +3 -0
- package/dist/types/components/base-pagination-controls.component.d.ts +3 -0
- package/dist/types/components/base-popover-cell-editor.component.d.ts +3 -0
- package/dist/types/components/empty-state.component.d.ts +3 -0
- package/dist/types/components/formula-bar.component.d.ts +3 -8
- package/dist/types/components/formula-ref-overlay.component.d.ts +3 -6
- package/dist/types/components/grid-context-menu.component.d.ts +3 -0
- package/dist/types/components/inline-cell-editor-template.d.ts +2 -2
- package/dist/types/components/marching-ants-overlay.component.d.ts +3 -0
- package/dist/types/components/ogrid-layout.component.d.ts +3 -0
- package/dist/types/components/sheet-tabs.component.d.ts +3 -8
- package/dist/types/components/sidebar.component.d.ts +3 -0
- package/dist/types/components/status-bar.component.d.ts +3 -0
- package/dist/types/services/column-reorder.service.d.ts +3 -0
- package/dist/types/services/datagrid-interaction.service.d.ts +1 -0
- package/dist/types/services/datagrid-state.service.d.ts +5 -0
- package/dist/types/services/formula-engine.service.d.ts +3 -9
- package/dist/types/services/ogrid.service.d.ts +8 -2
- package/dist/types/services/virtual-scroll.service.d.ts +3 -0
- package/package.json +4 -3
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { signal, computed, effect } from '@angular/core';
|
|
2
|
+
import { flattenColumns, CHECKBOX_COLUMN_WIDTH, DEFAULT_MIN_COLUMN_WIDTH, CELL_PADDING, resolveResponsiveConfig, applyResponsiveHiding, } from '@alaarab/ogrid-core';
|
|
3
|
+
/**
|
|
4
|
+
* Manages column layout, visibility, sizing, and container measurement.
|
|
5
|
+
* Extracted from DataGridStateService for modularity.
|
|
6
|
+
*
|
|
7
|
+
* Not @Injectable - instantiated and owned by DataGridStateService.
|
|
8
|
+
*/
|
|
9
|
+
export class DataGridLayoutHelper {
|
|
10
|
+
constructor(props, wrapperEl, ngZone) {
|
|
11
|
+
// --- Internal state ---
|
|
12
|
+
this.containerWidthSig = signal(0, ...(ngDevMode ? [{ debugName: "containerWidthSig" }] : []));
|
|
13
|
+
this.columnSizingOverridesSig = signal({}, ...(ngDevMode ? [{ debugName: "columnSizingOverridesSig" }] : []));
|
|
14
|
+
// ResizeObserver
|
|
15
|
+
this.resizeObserver = null;
|
|
16
|
+
this.props = props;
|
|
17
|
+
this.wrapperEl = wrapperEl;
|
|
18
|
+
this.initialColumnWidthsSig = computed(() => this.props()?.initialColumnWidths, ...(ngDevMode ? [{ debugName: "initialColumnWidthsSig" }] : []));
|
|
19
|
+
this.flatColumnsRaw = computed(() => {
|
|
20
|
+
const p = this.props();
|
|
21
|
+
if (!p)
|
|
22
|
+
return [];
|
|
23
|
+
return flattenColumns(p.columns);
|
|
24
|
+
}, ...(ngDevMode ? [{ debugName: "flatColumnsRaw" }] : []));
|
|
25
|
+
this.flatColumns = computed(() => {
|
|
26
|
+
const raw = this.flatColumnsRaw();
|
|
27
|
+
const p = this.props();
|
|
28
|
+
const pinnedColumns = p?.pinnedColumns;
|
|
29
|
+
if (!pinnedColumns || Object.keys(pinnedColumns).length === 0)
|
|
30
|
+
return raw;
|
|
31
|
+
return raw.map((col) => {
|
|
32
|
+
const override = pinnedColumns[col.columnId];
|
|
33
|
+
if (override && col.pinned !== override)
|
|
34
|
+
return { ...col, pinned: override };
|
|
35
|
+
return col;
|
|
36
|
+
});
|
|
37
|
+
}, ...(ngDevMode ? [{ debugName: "flatColumns" }] : []));
|
|
38
|
+
this.visibleCols = computed(() => {
|
|
39
|
+
const p = this.props();
|
|
40
|
+
if (!p)
|
|
41
|
+
return [];
|
|
42
|
+
const flatCols = this.flatColumns();
|
|
43
|
+
const filtered = p.visibleColumns
|
|
44
|
+
? flatCols.filter((c) => p.visibleColumns.has(c.columnId))
|
|
45
|
+
: flatCols;
|
|
46
|
+
let ordered;
|
|
47
|
+
const order = p.columnOrder;
|
|
48
|
+
if (!order?.length) {
|
|
49
|
+
ordered = filtered;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const orderMap = new Map();
|
|
53
|
+
for (let i = 0; i < order.length; i++) {
|
|
54
|
+
orderMap.set(order[i], i);
|
|
55
|
+
}
|
|
56
|
+
ordered = [...filtered].sort((a, b) => {
|
|
57
|
+
const ia = orderMap.get(a.columnId) ?? -1;
|
|
58
|
+
const ib = orderMap.get(b.columnId) ?? -1;
|
|
59
|
+
if (ia === -1 && ib === -1)
|
|
60
|
+
return 0;
|
|
61
|
+
if (ia === -1)
|
|
62
|
+
return 1;
|
|
63
|
+
if (ib === -1)
|
|
64
|
+
return -1;
|
|
65
|
+
return ia - ib;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
// Responsive column hiding
|
|
69
|
+
return applyResponsiveHiding(ordered, this.containerWidthSig(), resolveResponsiveConfig(p.responsiveColumns));
|
|
70
|
+
}, ...(ngDevMode ? [{ debugName: "visibleCols" }] : []));
|
|
71
|
+
this.visibleColumnCount = computed(() => this.visibleCols().length, ...(ngDevMode ? [{ debugName: "visibleColumnCount" }] : []));
|
|
72
|
+
this.hasCheckboxCol = computed(() => (this.props()?.rowSelection ?? 'none') === 'multiple', ...(ngDevMode ? [{ debugName: "hasCheckboxCol" }] : []));
|
|
73
|
+
this.hasRowNumbersCol = computed(() => !!this.props()?.showRowNumbers, ...(ngDevMode ? [{ debugName: "hasRowNumbersCol" }] : []));
|
|
74
|
+
this.specialColsCount = computed(() => (this.hasCheckboxCol() ? 1 : 0) + (this.hasRowNumbersCol() ? 1 : 0), ...(ngDevMode ? [{ debugName: "specialColsCount" }] : []));
|
|
75
|
+
this.totalColCount = computed(() => this.visibleColumnCount() + this.specialColsCount(), ...(ngDevMode ? [{ debugName: "totalColCount" }] : []));
|
|
76
|
+
this.colOffset = computed(() => this.specialColsCount(), ...(ngDevMode ? [{ debugName: "colOffset" }] : []));
|
|
77
|
+
this.rowIndexByRowId = computed(() => {
|
|
78
|
+
const p = this.props();
|
|
79
|
+
if (!p)
|
|
80
|
+
return new Map();
|
|
81
|
+
const m = new Map();
|
|
82
|
+
p.items.forEach((item, idx) => m.set(p.getRowId(item), idx));
|
|
83
|
+
return m;
|
|
84
|
+
}, ...(ngDevMode ? [{ debugName: "rowIndexByRowId" }] : []));
|
|
85
|
+
this.minTableWidth = computed(() => {
|
|
86
|
+
const checkboxW = this.hasCheckboxCol() ? CHECKBOX_COLUMN_WIDTH : 0;
|
|
87
|
+
return this.visibleCols().reduce((sum, c) => sum + (c.minWidth ?? DEFAULT_MIN_COLUMN_WIDTH) + CELL_PADDING, checkboxW);
|
|
88
|
+
}, ...(ngDevMode ? [{ debugName: "minTableWidth" }] : []));
|
|
89
|
+
this.desiredTableWidth = computed(() => {
|
|
90
|
+
const checkboxW = this.hasCheckboxCol() ? CHECKBOX_COLUMN_WIDTH : 0;
|
|
91
|
+
const overrides = this.columnSizingOverridesSig();
|
|
92
|
+
return this.visibleCols().reduce((sum, c) => {
|
|
93
|
+
const override = overrides[c.columnId];
|
|
94
|
+
const w = override
|
|
95
|
+
? override.widthPx
|
|
96
|
+
: (c.idealWidth ?? c.defaultWidth ?? c.minWidth ?? DEFAULT_MIN_COLUMN_WIDTH);
|
|
97
|
+
return sum + Math.max(c.minWidth ?? DEFAULT_MIN_COLUMN_WIDTH, w) + CELL_PADDING;
|
|
98
|
+
}, checkboxW);
|
|
99
|
+
}, ...(ngDevMode ? [{ debugName: "desiredTableWidth" }] : []));
|
|
100
|
+
// Initialize column sizing overrides from initial widths
|
|
101
|
+
effect(() => {
|
|
102
|
+
const widths = this.initialColumnWidthsSig();
|
|
103
|
+
if (widths) {
|
|
104
|
+
const result = {};
|
|
105
|
+
for (const [id, width] of Object.entries(widths)) {
|
|
106
|
+
result[id] = { widthPx: width };
|
|
107
|
+
}
|
|
108
|
+
this.columnSizingOverridesSig.set(result);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
// Container width measurement via ResizeObserver
|
|
112
|
+
effect(() => {
|
|
113
|
+
const el = this.wrapperEl();
|
|
114
|
+
if (this.resizeObserver) {
|
|
115
|
+
this.resizeObserver.disconnect();
|
|
116
|
+
this.resizeObserver = null;
|
|
117
|
+
}
|
|
118
|
+
if (!el)
|
|
119
|
+
return;
|
|
120
|
+
const measure = () => {
|
|
121
|
+
const rect = el.getBoundingClientRect();
|
|
122
|
+
const cs = window.getComputedStyle(el);
|
|
123
|
+
const borderX = (parseFloat(cs.borderLeftWidth || '0') || 0) +
|
|
124
|
+
(parseFloat(cs.borderRightWidth || '0') || 0);
|
|
125
|
+
this.containerWidthSig.set(Math.max(0, rect.width - borderX));
|
|
126
|
+
};
|
|
127
|
+
ngZone.runOutsideAngular(() => {
|
|
128
|
+
this.resizeObserver = new ResizeObserver(measure);
|
|
129
|
+
this.resizeObserver.observe(el);
|
|
130
|
+
});
|
|
131
|
+
measure();
|
|
132
|
+
});
|
|
133
|
+
// Clean up column sizing overrides for removed columns
|
|
134
|
+
effect(() => {
|
|
135
|
+
const colIds = new Set(this.flatColumns().map((c) => c.columnId));
|
|
136
|
+
this.columnSizingOverridesSig.update((prev) => {
|
|
137
|
+
const next = {};
|
|
138
|
+
let changed = false;
|
|
139
|
+
for (const [id, value] of Object.entries(prev)) {
|
|
140
|
+
if (colIds.has(id)) {
|
|
141
|
+
next[id] = value;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
changed = true;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return changed ? next : prev;
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
destroy() {
|
|
152
|
+
if (this.resizeObserver) {
|
|
153
|
+
this.resizeObserver.disconnect();
|
|
154
|
+
this.resizeObserver = null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|