@trebco/treb 32.11.0 → 32.13.2

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/treb.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- /*! API v32.11. Copyright 2018-2025 trebco, llc. All rights reserved. LGPL: https://treb.app/license */
1
+ /*! API v32.13. Copyright 2018-2025 trebco, llc. All rights reserved. LGPL: https://treb.app/license */
2
2
  /*
3
3
  * This file is part of TREB.
4
4
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trebco/treb",
3
- "version": "32.11.0",
3
+ "version": "32.13.2",
4
4
  "license": "LGPL-3.0-or-later",
5
5
  "homepage": "https://treb.app",
6
6
  "repository": {
@@ -1757,8 +1757,10 @@ export const BaseFunctionLibrary: FunctionMap = {
1757
1757
  //}
1758
1758
 
1759
1759
  let rng: Area|undefined;
1760
+ let return_from_array = false;
1760
1761
 
1761
1762
  if (return_array.type === ValueType.array) {
1763
+
1762
1764
  // console.info({return_array});
1763
1765
 
1764
1766
  const arr = return_array.value;
@@ -1772,9 +1774,16 @@ export const BaseFunctionLibrary: FunctionMap = {
1772
1774
  rng = new Area(start.value.address, end.value.address);
1773
1775
  }
1774
1776
 
1777
+ // we can allow a regular array here... perhaps we should
1778
+ // check the dimensions to ensure they match? TODO/FIXME
1779
+
1780
+ else {
1781
+ return_from_array = true;
1782
+ }
1783
+
1775
1784
  }
1776
1785
 
1777
- if (!rng) {
1786
+ if (!rng && !return_from_array) {
1778
1787
  console.info('invalid range');
1779
1788
  return ReferenceError();
1780
1789
  }
@@ -1848,7 +1857,55 @@ export const BaseFunctionLibrary: FunctionMap = {
1848
1857
  // an array. we might prefer to return a scalar if there's only
1849
1858
  // one value, not sure what's the intended behavior
1850
1859
  //
1851
- const ReturnIndex = (rng: Area, index: number): UnionValue => {
1860
+ const ReturnIndex = (index: number): UnionValue => {
1861
+
1862
+ // FIXME: we could almost certainly merge these two paths
1863
+
1864
+ if (return_from_array && return_array.type === ValueType.array) {
1865
+
1866
+ // instead of a range, we're returning values from a static array
1867
+
1868
+ const src_columns = return_array.value.length;
1869
+ const src_rows = return_array.value[0]?.length || 0;
1870
+ const result: UnionValue[][] = [];
1871
+
1872
+ let start_row = 0;
1873
+ let end_row = src_rows - 1;
1874
+
1875
+ let start_column = 0;
1876
+ let end_column = src_columns - 1;
1877
+
1878
+ if (transpose) {
1879
+ if (search_mode < 0) {
1880
+ index = src_rows - 1 - index; // invert FIXME: test
1881
+ }
1882
+ start_row = end_row = index;
1883
+ }
1884
+ else {
1885
+ if (search_mode < 0) {
1886
+ index = src_columns - 1 - index; // invert FIXME: test
1887
+ }
1888
+ start_column = end_column = index;
1889
+ }
1890
+
1891
+ for (let c = start_column; c <= end_column; c++) {
1892
+ const column: UnionValue[] = [];
1893
+ for (let r = start_row; r <= end_row; r++) {
1894
+ column.push(return_array.value[c][r]);
1895
+ }
1896
+ result.push(column);
1897
+ }
1898
+
1899
+ return {
1900
+ type: ValueType.array,
1901
+ value: result,
1902
+ };
1903
+
1904
+ }
1905
+
1906
+ if (!rng) {
1907
+ throw new Error('invalid range');
1908
+ }
1852
1909
 
1853
1910
  // console.info("transpose?", transpose, {rng}, 'shape', rng.rows, rng.columns);
1854
1911
 
@@ -1953,7 +2010,7 @@ export const BaseFunctionLibrary: FunctionMap = {
1953
2010
 
1954
2011
  // check for exact match first, just in case
1955
2012
  if (value === lookup_value) {
1956
- return ReturnIndex(rng, i);
2013
+ return ReturnIndex(i);
1957
2014
  }
1958
2015
 
1959
2016
  const delta = Math.abs(value - lookup_value);
@@ -1969,7 +2026,7 @@ export const BaseFunctionLibrary: FunctionMap = {
1969
2026
  }
1970
2027
 
1971
2028
  if (index >= 0) {
1972
- return ReturnIndex(rng, index);
2029
+ return ReturnIndex(index);
1973
2030
  }
1974
2031
 
1975
2032
  }
@@ -1987,7 +2044,7 @@ export const BaseFunctionLibrary: FunctionMap = {
1987
2044
  for (let i = 0; i < lookup_array.length; i++) {
1988
2045
  const value = lookup_array[i][0];
1989
2046
  if (typeof value === 'string' && regex.exec(value)) {
1990
- return ReturnIndex(rng, i);
2047
+ return ReturnIndex(i);
1991
2048
  }
1992
2049
  }
1993
2050
 
@@ -2005,7 +2062,7 @@ export const BaseFunctionLibrary: FunctionMap = {
2005
2062
  value = value.toLowerCase();
2006
2063
  }
2007
2064
  if (value === lookup_value) {
2008
- return ReturnIndex(rng, i);
2065
+ return ReturnIndex(i);
2009
2066
  }
2010
2067
  }
2011
2068
 
@@ -20,9 +20,10 @@
20
20
  */
21
21
 
22
22
  import type { FunctionMap } from '../descriptors';
23
- import type { FunctionUnion, UnionValue} from 'treb-base-types';
24
- import { ValueType } from 'treb-base-types';
23
+ import type { CellValue, FunctionUnion, UnionValue} from 'treb-base-types';
24
+ import { Box, ValueType } from 'treb-base-types';
25
25
  import { ArgumentError, ValueError } from '../function-error';
26
+ import { FlattenCellValues } from '../utilities';
26
27
 
27
28
  export const FPFunctionLibrary: FunctionMap = {
28
29
 
@@ -67,6 +68,195 @@ export const FPFunctionLibrary: FunctionMap = {
67
68
  },
68
69
  },
69
70
 
71
+ ChooseCols: {
72
+ description: 'Returns one or more columns from an array, by column index',
73
+ arguments: [{
74
+ name: 'array',
75
+ }, {
76
+ name: 'column',
77
+ repeat: true,
78
+ }],
79
+ fn: function(data: CellValue|CellValue[][], ...args: number[]) {
80
+
81
+ if (!Array.isArray(data)) {
82
+ data = [[data]];
83
+ }
84
+
85
+ const flat = FlattenCellValues(args);
86
+ // console.info({flat});
87
+
88
+ const columns = data.length;
89
+ const result: UnionValue[][] = [];
90
+
91
+ for (let arg of flat) {
92
+ if (typeof arg === 'number') {
93
+
94
+ if (arg < 0) {
95
+ arg = columns + arg;
96
+ }
97
+ else {
98
+ arg--;
99
+ }
100
+
101
+ const col = data[arg];
102
+ if (col) {
103
+ const column: UnionValue[] = [];
104
+ for (const value of col) {
105
+ column.push(Box(value));
106
+ }
107
+ result.push(column);
108
+ }
109
+ else {
110
+ return ArgumentError(); // invalid column
111
+ }
112
+ }
113
+ }
114
+
115
+ if (!result.length) {
116
+ result.push([]);
117
+ }
118
+
119
+ return {
120
+ type: ValueType.array,
121
+ value: result,
122
+ };
123
+
124
+ },
125
+ },
126
+
127
+ ChooseRows: {
128
+ description: 'Returns one or more rows from an array, by row index',
129
+ arguments: [{
130
+ name: 'array',
131
+ }, {
132
+ name: 'row',
133
+ repeat: true,
134
+ }],
135
+ fn: function(data: CellValue|CellValue[][], ...args: number[]) {
136
+
137
+ if (!Array.isArray(data)) {
138
+ data = [[data]];
139
+ }
140
+
141
+ const flat = FlattenCellValues(args);
142
+ // console.info({flat});
143
+
144
+ const rows = data[0]?.length || 0;
145
+ const result: UnionValue[][] = [];
146
+
147
+ for (let arg of flat) {
148
+ if (typeof arg === 'number') {
149
+
150
+ if (arg < 0) {
151
+ arg = rows + arg;
152
+ }
153
+ else {
154
+ arg--;
155
+ }
156
+
157
+ for (const [column_index, col] of data.entries()) {
158
+ const column = result[column_index] || [];
159
+ if (arg < 0 || arg >= col.length) {
160
+ return ArgumentError();
161
+ }
162
+ column.push(Box(col[arg]));
163
+ result[column_index] = column;
164
+ }
165
+
166
+ }
167
+ }
168
+
169
+ if (!result.length) {
170
+ result.push([]);
171
+ }
172
+
173
+ return {
174
+ type: ValueType.array,
175
+ value: result,
176
+ };
177
+
178
+ },
179
+ },
180
+
181
+ Take: {
182
+ description: 'Returns some number of rows/columns from the start or end of an array',
183
+ arguments: [{
184
+ name: 'array',
185
+ }, {
186
+ name: 'rows',
187
+ }, {
188
+ name: 'columns',
189
+ }],
190
+ fn: function(data: CellValue|CellValue[][], rows?: number, columns?: number) {
191
+
192
+ // we need one of rows, columns to be defined. neither can === 0.
193
+
194
+ if ((!rows && !columns) || rows === 0 || columns === 0 || (typeof rows !== 'number' && typeof rows !== 'undefined') || (typeof columns !== 'number' && typeof columns !== 'undefined')) {
195
+ return ArgumentError();
196
+ }
197
+
198
+ if (!Array.isArray(data)) {
199
+ data = [[data]];
200
+ }
201
+
202
+ const data_columns = data.length;
203
+ const data_rows = data[0].length;
204
+ const result: UnionValue[][] = [];
205
+
206
+ // I guess we can compose?
207
+
208
+ // data is column-first
209
+
210
+ let start_column = 0;
211
+ let end_column = data_columns - 1;
212
+
213
+ let start_row = 0;
214
+ let end_row = data_rows - 1;
215
+
216
+ if (typeof columns === 'number') {
217
+
218
+ // clip data so it has the first (or last) X columns
219
+
220
+ if (columns > 0) {
221
+ end_column = Math.min(columns, data_columns) - 1;
222
+ }
223
+ else if (columns < 0) {
224
+ end_column = data_columns - 1;
225
+ start_column = Math.max(0, end_column + columns + 1);
226
+ }
227
+
228
+ }
229
+
230
+ if (typeof rows === 'number') {
231
+
232
+ // clip data so it has the first (or last) X columns
233
+
234
+ if (rows > 0) {
235
+ end_row = Math.min(rows, data_rows) - 1;
236
+ }
237
+ else if (rows < 0) {
238
+ end_row = data_rows - 1;
239
+ start_row = Math.max(0, end_row + rows + 1);
240
+ }
241
+
242
+ }
243
+
244
+ for (let c = start_column; c <= end_column; c++) {
245
+ const column: UnionValue[] = [];
246
+ for (let r = start_row; r <= end_row; r++) {
247
+ column.push(Box(data[c][r]));
248
+ }
249
+ result.push(column);
250
+ }
251
+
252
+ return {
253
+ type: ValueType.array,
254
+ value: result,
255
+ }
256
+
257
+ },
258
+ },
259
+
70
260
  Reduce: {
71
261
  description: 'Accumulates a value by applying a function to a set of values',
72
262
  arguments: [
@@ -140,11 +140,15 @@ export class ScaleControl extends EventSource<ScaleEvent> {
140
140
  }
141
141
  });
142
142
 
143
+ // we're overriding scroll behavior here, but it's a tiny panel.
144
+ // if we explicitly mark passive:false we can avoid the console
145
+ // warning (I think)
146
+
143
147
  container.addEventListener('wheel', (event: WheelEvent) => {
144
148
  event.stopPropagation();
145
149
  event.preventDefault();
146
150
  this.Tick(event.deltaY)
147
- });
151
+ }, { passive: false });
148
152
 
149
153
  }
150
154