@alaarab/ogrid-core 2.0.4 → 2.0.6

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.
@@ -30,12 +30,22 @@ export function computeAggregations(items, visibleCols, selectionRange) {
30
30
  // Need at least 2 cells selected and at least 1 numeric value to show aggregation
31
31
  if (totalCells < 2 || numericValues.length === 0)
32
32
  return null;
33
- const sum = numericValues.reduce((a, b) => a + b, 0);
33
+ let sum = 0;
34
+ let min = numericValues[0];
35
+ let max = numericValues[0];
36
+ for (let i = 0; i < numericValues.length; i++) {
37
+ const v = numericValues[i];
38
+ sum += v;
39
+ if (v < min)
40
+ min = v;
41
+ if (v > max)
42
+ max = v;
43
+ }
34
44
  return {
35
45
  sum,
36
46
  avg: sum / numericValues.length,
37
- min: Math.min(...numericValues),
38
- max: Math.max(...numericValues),
47
+ min,
48
+ max,
39
49
  count: numericValues.length,
40
50
  };
41
51
  }
@@ -12,6 +12,11 @@ import { getFilterField } from './ogridHelpers';
12
12
  * @returns Filtered and sorted array
13
13
  */
14
14
  export function processClientSideData(data, columns, filters, sortBy, sortDirection) {
15
+ // Build column lookup map for O(1) access by columnId
16
+ const columnMap = new Map();
17
+ for (let i = 0; i < columns.length; i++) {
18
+ columnMap.set(columns[i].columnId, columns[i]);
19
+ }
15
20
  // --- Filtering (single-pass: build predicates, then one .filter()) ---
16
21
  const predicates = [];
17
22
  for (let i = 0; i < columns.length; i++) {
@@ -71,37 +76,59 @@ export function processClientSideData(data, columns, filters, sortBy, sortDirect
71
76
  : data.slice();
72
77
  // --- Sorting ---
73
78
  if (sortBy) {
74
- const sortCol = columns.find((c) => c.columnId === sortBy);
79
+ const sortCol = columnMap.get(sortBy);
75
80
  const compare = sortCol?.compare;
76
81
  const dir = sortDirection === 'asc' ? 1 : -1;
77
- rows.sort((a, b) => {
78
- if (compare)
79
- return compare(a, b) * dir;
80
- const av = sortCol
81
- ? getCellValue(a, sortCol)
82
- : a[sortBy];
83
- const bv = sortCol
84
- ? getCellValue(b, sortCol)
85
- : b[sortBy];
86
- if (av == null && bv == null)
87
- return 0;
88
- if (av == null)
89
- return -1 * dir;
90
- if (bv == null)
91
- return 1 * dir;
92
- if (sortCol?.type === 'date') {
93
- const at = new Date(String(av)).getTime();
94
- const bt = new Date(String(bv)).getTime();
95
- const aN = Number.isNaN(at) ? 0 : at;
96
- const bN = Number.isNaN(bt) ? 0 : bt;
97
- return aN === bN ? 0 : aN > bN ? dir : -dir;
82
+ const isDateSort = sortCol?.type === 'date';
83
+ // For date columns, pre-compute timestamps to avoid repeated new Date() in O(n log n) comparisons
84
+ if (isDateSort && !compare) {
85
+ const timestampCache = new Map();
86
+ for (let i = 0; i < rows.length; i++) {
87
+ const row = rows[i];
88
+ const val = sortCol ? getCellValue(row, sortCol) : row[sortBy];
89
+ if (val == null) {
90
+ timestampCache.set(row, NaN);
91
+ }
92
+ else {
93
+ const t = new Date(String(val)).getTime();
94
+ timestampCache.set(row, Number.isNaN(t) ? 0 : t);
95
+ }
98
96
  }
99
- if (typeof av === 'number' && typeof bv === 'number')
100
- return av === bv ? 0 : av > bv ? dir : -dir;
101
- const as = String(av).toLowerCase();
102
- const bs = String(bv).toLowerCase();
103
- return as === bs ? 0 : as > bs ? dir : -dir;
104
- });
97
+ rows.sort((a, b) => {
98
+ const at = timestampCache.get(a);
99
+ const bt = timestampCache.get(b);
100
+ if (Number.isNaN(at) && Number.isNaN(bt))
101
+ return 0;
102
+ if (Number.isNaN(at))
103
+ return -1 * dir;
104
+ if (Number.isNaN(bt))
105
+ return 1 * dir;
106
+ return at === bt ? 0 : at > bt ? dir : -dir;
107
+ });
108
+ }
109
+ else {
110
+ rows.sort((a, b) => {
111
+ if (compare)
112
+ return compare(a, b) * dir;
113
+ const av = sortCol
114
+ ? getCellValue(a, sortCol)
115
+ : a[sortBy];
116
+ const bv = sortCol
117
+ ? getCellValue(b, sortCol)
118
+ : b[sortBy];
119
+ if (av == null && bv == null)
120
+ return 0;
121
+ if (av == null)
122
+ return -1 * dir;
123
+ if (bv == null)
124
+ return 1 * dir;
125
+ if (typeof av === 'number' && typeof bv === 'number')
126
+ return av === bv ? 0 : av > bv ? dir : -dir;
127
+ const as = String(av).toLowerCase();
128
+ const bs = String(bv).toLowerCase();
129
+ return as === bs ? 0 : as > bs ? dir : -dir;
130
+ });
131
+ }
105
132
  }
106
133
  return rows;
107
134
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alaarab/ogrid-core",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "description": "OGrid core – framework-agnostic types, algorithms, and utilities for OGrid data grids.",
5
5
  "main": "dist/esm/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -21,5 +21,6 @@
21
21
  "license": "MIT",
22
22
  "files": ["dist", "README.md", "LICENSE"],
23
23
  "engines": { "node": ">=18" },
24
+ "sideEffects": false,
24
25
  "publishConfig": { "access": "public" }
25
26
  }