@trebco/treb 28.17.4 → 29.1.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.
Files changed (87) hide show
  1. package/dist/treb-spreadsheet-light.mjs +12 -12
  2. package/dist/treb-spreadsheet.mjs +12 -12
  3. package/dist/treb.d.ts +121 -82
  4. package/eslint.config.js +21 -0
  5. package/package.json +6 -6
  6. package/treb-base-types/src/area.ts +4 -2
  7. package/treb-base-types/src/cell.ts +1 -1
  8. package/treb-base-types/src/cells.ts +16 -7
  9. package/treb-base-types/src/dom-utilities.ts +4 -2
  10. package/treb-base-types/src/import.ts +2 -2
  11. package/treb-base-types/src/rectangle.ts +5 -5
  12. package/treb-base-types/src/union.ts +6 -1
  13. package/treb-base-types/src/value-type.ts +1 -1
  14. package/treb-calculator/src/calculator.ts +114 -165
  15. package/treb-calculator/src/dag/calculation_leaf_vertex.ts +1 -2
  16. package/treb-calculator/src/dag/graph.ts +3 -3
  17. package/treb-calculator/src/dag/spreadsheet_vertex.ts +2 -2
  18. package/treb-calculator/src/dag/state_leaf_vertex.ts +2 -4
  19. package/treb-calculator/src/descriptors.ts +28 -2
  20. package/treb-calculator/src/expression-calculator.ts +25 -34
  21. package/treb-calculator/src/function-error.ts +2 -2
  22. package/treb-calculator/src/function-library.ts +16 -0
  23. package/treb-calculator/src/functions/base-functions.ts +185 -211
  24. package/treb-calculator/src/functions/checkbox.ts +0 -1
  25. package/treb-calculator/src/functions/complex-functions.ts +49 -47
  26. package/treb-calculator/src/functions/finance-functions.ts +10 -10
  27. package/treb-calculator/src/functions/function-utilities.ts +26 -0
  28. package/treb-calculator/src/functions/information-functions.ts +21 -41
  29. package/treb-calculator/src/functions/matrix-functions.ts +8 -1
  30. package/treb-calculator/src/functions/sparkline.ts +6 -4
  31. package/treb-calculator/src/functions/statistics-functions.ts +21 -17
  32. package/treb-calculator/src/functions/text-functions.ts +14 -13
  33. package/treb-calculator/src/primitives.ts +48 -37
  34. package/treb-calculator/src/utilities.ts +117 -134
  35. package/treb-charts/src/chart-functions.ts +3 -3
  36. package/treb-charts/src/chart-types.ts +42 -1
  37. package/treb-charts/src/chart-utils.ts +155 -113
  38. package/treb-charts/src/chart.ts +6 -5
  39. package/treb-charts/src/default-chart-renderer.ts +6 -5
  40. package/treb-charts/src/renderer.ts +12 -11
  41. package/treb-charts/src/util.ts +25 -36
  42. package/treb-data-model/package.json +5 -0
  43. package/{treb-grid/src/types → treb-data-model/src}/annotation.ts +2 -2
  44. package/{treb-grid/src/types → treb-data-model/src}/conditional_format.ts +20 -0
  45. package/{treb-grid/src/types → treb-data-model/src}/data_model.ts +231 -133
  46. package/treb-data-model/src/index.ts +45 -0
  47. package/{treb-grid/src/types/named_range.ts → treb-data-model/src/named.ts} +459 -376
  48. package/{treb-grid/src/types → treb-data-model/src}/sheet.ts +13 -5
  49. package/treb-data-model/src/sheet_collection.ts +114 -0
  50. package/{treb-grid/src/types → treb-data-model/src}/sheet_types.ts +6 -3
  51. package/treb-embed/modern.tsconfig.json +1 -0
  52. package/treb-embed/src/custom-element/spreadsheet-constructor.ts +2 -3
  53. package/treb-embed/src/embedded-spreadsheet.ts +125 -270
  54. package/treb-embed/src/selection-state.ts +1 -1
  55. package/treb-embed/src/toolbar-message.ts +1 -1
  56. package/treb-embed/src/types.ts +13 -5
  57. package/treb-export/src/export-worker/export-worker.ts +22 -7
  58. package/treb-export/src/export2.ts +110 -41
  59. package/treb-export/src/import2.ts +6 -5
  60. package/treb-export/src/workbook2.ts +31 -13
  61. package/treb-export/src/xml-utils.ts +5 -1
  62. package/treb-format/src/format.ts +8 -6
  63. package/treb-grid/src/editors/autocomplete.ts +2 -2
  64. package/treb-grid/src/editors/autocomplete_matcher.ts +57 -19
  65. package/treb-grid/src/editors/editor.ts +27 -25
  66. package/treb-grid/src/editors/formula_bar.ts +5 -5
  67. package/treb-grid/src/editors/overlay_editor.ts +1 -2
  68. package/treb-grid/src/index.ts +0 -11
  69. package/treb-grid/src/layout/base_layout.ts +20 -8
  70. package/treb-grid/src/layout/grid_layout.ts +2 -2
  71. package/treb-grid/src/layout/mock-layout.ts +5 -6
  72. package/treb-grid/src/render/selection-renderer.ts +2 -3
  73. package/treb-grid/src/render/tile_renderer.ts +1 -1
  74. package/treb-grid/src/types/grid.ts +95 -66
  75. package/treb-grid/src/types/grid_base.ts +76 -60
  76. package/treb-grid/src/types/grid_command.ts +3 -2
  77. package/treb-grid/src/types/grid_events.ts +12 -6
  78. package/treb-grid/src/types/tab_bar.ts +1 -2
  79. package/treb-parser/src/parser-types.ts +2 -1
  80. package/treb-parser/src/parser.ts +7 -5
  81. package/treb-utils/src/event_source.ts +1 -1
  82. package/treb-utils/src/serialize_html.ts +31 -6
  83. package/.eslintignore +0 -8
  84. package/.eslintrc.cjs +0 -168
  85. package/treb-grid/src/layout/rectangle_cache.ts +0 -86
  86. /package/{treb-grid/src/types → treb-data-model/src}/serialize_options.ts +0 -0
  87. /package/{treb-grid/src/types/grid_selection.ts → treb-data-model/src/sheet_selection.ts} +0 -0
@@ -20,7 +20,6 @@
20
20
  */
21
21
 
22
22
  import type { RenderFunctionOptions, ClickFunctionOptions, ClickFunctionResult, RenderFunctionResult } from 'treb-base-types';
23
- import { Style } from 'treb-base-types';
24
23
 
25
24
  export const ClickCheckbox = (options: ClickFunctionOptions): ClickFunctionResult => {
26
25
  const { x, y, width, height, cell } = options;
@@ -20,12 +20,14 @@
20
20
  */
21
21
 
22
22
  import type { FunctionMap } from '../descriptors';
23
- import type { NumberUnion, UnionValue} from 'treb-base-types';
23
+ import type { CellValue, NumberUnion, UnionValue} from 'treb-base-types';
24
24
  import { IsComplex, ValueType } from 'treb-base-types';
25
- import * as Utils from '../utilities';
25
+ // import * as Utils from '../utilities';
26
26
  import { ValueError } from '../function-error';
27
27
  import { RectangularToPolar } from '../complex-math';
28
28
 
29
+ import { CoerceComplex } from './function-utilities';
30
+
29
31
  export const ComplexFunctionLibrary: FunctionMap = {
30
32
 
31
33
  IsComplex: {
@@ -33,22 +35,23 @@ export const ComplexFunctionLibrary: FunctionMap = {
33
35
  arguments: [{
34
36
  name: 'Reference',
35
37
  metadata: true, /* OK with array metadata */
38
+ unroll: true,
36
39
  }],
37
- fn: Utils.ApplyAsArray((ref: UnionValue): UnionValue => {
40
+ fn: (ref: UnionValue): UnionValue => {
38
41
  return {
39
42
  type: ValueType.boolean,
40
- value: ref?.value && IsComplex(ref.value.value),
43
+ value: !!(ref?.value) && IsComplex((ref.value as {value?: CellValue}).value),
41
44
  };
42
- }),
45
+ },
43
46
  },
44
47
 
45
48
 
46
49
  Real: {
47
50
  description: 'Returns the real part of a complex number',
48
51
  arguments: [
49
- { boxed: true },
52
+ { boxed: true, unroll: true },
50
53
  ],
51
- fn: Utils.ApplyAsArray((ref: UnionValue): UnionValue => {
54
+ fn: (ref: UnionValue): UnionValue => {
52
55
  if (ref.type === ValueType.number) {
53
56
  return { ...ref };
54
57
  }
@@ -65,15 +68,15 @@ export const ComplexFunctionLibrary: FunctionMap = {
65
68
  };
66
69
  }
67
70
  return ValueError();
68
- }),
71
+ },
69
72
  },
70
73
 
71
74
  Imaginary: {
72
75
  description: 'Returns the imaginary part of a complex number (as real)',
73
76
  arguments: [
74
- { boxed: true },
77
+ { boxed: true, unroll: true, },
75
78
  ],
76
- fn: Utils.ApplyAsArray((ref: UnionValue): UnionValue => {
79
+ fn: (ref: UnionValue): UnionValue => {
77
80
  if (ref.type === ValueType.complex) {
78
81
  return {
79
82
  type: ValueType.number,
@@ -89,41 +92,46 @@ export const ComplexFunctionLibrary: FunctionMap = {
89
92
  };
90
93
  }
91
94
  return ValueError();
92
- }),
95
+ },
93
96
  },
94
97
 
95
98
  Conjugate: {
96
99
  description: 'Returns the conjugate of a complex number',
97
100
  arguments: [
98
- { boxed: true },
101
+ { boxed: true, unroll: true },
99
102
  ],
100
- fn: Utils.ApplyAsArray((arg: UnionValue): UnionValue => {
101
- if (arg.type === ValueType.complex) {
103
+ fn: (arg: UnionValue): UnionValue => {
104
+
105
+ const complex = CoerceComplex(arg);
106
+
107
+ if (!complex) {
108
+ return ValueError();
109
+ }
110
+
111
+ if (complex.imaginary) {
102
112
  return {
103
113
  type: ValueType.complex,
104
114
  value: {
105
- real: arg.value.real,
106
- imaginary: -arg.value.imaginary,
115
+ real: complex.real,
116
+ imaginary: -complex.imaginary,
107
117
  },
108
- };
109
- }
110
- else if (arg.type === ValueType.number || arg.type === ValueType.undefined || !arg.value) {
111
- return {
112
- type: ValueType.number, value: arg.value || 0,
113
- };
114
- }
115
- else {
116
- return ValueError();
118
+ }
117
119
  }
118
- }),
120
+
121
+ return {
122
+ type: ValueType.number,
123
+ value: complex.real,
124
+ };
125
+
126
+ },
119
127
  },
120
128
 
121
129
  Arg: {
122
130
  description: 'Returns the principal argument of a complex number (in radians)',
123
131
  arguments: [
124
- { boxed: true },
132
+ { boxed: true, unroll: true },
125
133
  ],
126
- fn: Utils.ApplyAsArray((ref: UnionValue): UnionValue => {
134
+ fn: (ref: UnionValue): UnionValue => {
127
135
 
128
136
  if (ref.type === ValueType.complex) {
129
137
  return {
@@ -142,7 +150,7 @@ export const ComplexFunctionLibrary: FunctionMap = {
142
150
  }
143
151
 
144
152
  return ValueError();
145
- }),
153
+ },
146
154
  },
147
155
 
148
156
  Rectangular: {
@@ -165,30 +173,24 @@ export const ComplexFunctionLibrary: FunctionMap = {
165
173
  Complex: {
166
174
  description: 'Ensures that the given value will be treated as a complex number',
167
175
  arguments: [
168
- { boxed: true },
176
+ { boxed: true, unroll: true },
169
177
  ],
170
178
 
171
179
  // FIXME: this should use flatten? not sure
172
180
 
173
- fn: Utils.ApplyAsArray((a: UnionValue): UnionValue => {
181
+ fn: (a: UnionValue): UnionValue => {
174
182
 
175
- if (a.type === ValueType.complex) {
176
- return a;
177
- }
178
-
179
- if (a.type === ValueType.number || a.type === ValueType.undefined || !a.value) {
180
- return {
181
- type: ValueType.complex,
182
- value: {
183
- imaginary: 0,
184
- real: a.value || 0,
185
- },
186
- }
183
+ const complex = CoerceComplex(a);
184
+ if (complex) {
185
+ return {
186
+ type: ValueType.complex,
187
+ value: complex,
188
+ };
187
189
  }
188
190
 
189
191
  return ValueError();
190
192
 
191
- }),
193
+ },
192
194
  },
193
195
 
194
196
  /**
@@ -203,9 +205,9 @@ export const ComplexFunctionLibrary: FunctionMap = {
203
205
  ComplexLog: {
204
206
  description: 'Returns the principal value Log(z) of a complex number z',
205
207
  arguments: [
206
- { boxed: true },
208
+ { boxed: true, unroll: true },
207
209
  ],
208
- fn: Utils.ApplyAsArray((a: UnionValue): UnionValue => {
210
+ fn: (a: UnionValue): UnionValue => {
209
211
 
210
212
  // real -> complex
211
213
  if (a.type === ValueType.number) {
@@ -247,7 +249,7 @@ export const ComplexFunctionLibrary: FunctionMap = {
247
249
 
248
250
  return ValueError();
249
251
 
250
- }),
252
+ },
251
253
  },
252
254
 
253
255
  };
@@ -21,9 +21,9 @@
21
21
 
22
22
  import type { FunctionMap } from '../descriptors';
23
23
  import { type CellValue, type UnionValue, ValueType } from 'treb-base-types';
24
- import { FlattenUnboxed } from '../utilities';
24
+ import { FlattenCellValues } from '../utilities';
25
25
 
26
- import { ArgumentError, ReferenceError, UnknownError, ValueError, ExpressionError, NAError, DivideByZeroError } from '../function-error';
26
+ import { ArgumentError, ValueError } from '../function-error';
27
27
 
28
28
  // use a single, static object for base functions
29
29
 
@@ -98,11 +98,11 @@ export const FinanceFunctionLibrary: FunctionMap = {
98
98
  { name: 'Rate' },
99
99
  { name: 'Cashflow' },
100
100
  ],
101
- fn: (rate = 0, ...args: any[]): UnionValue => {
101
+ fn: (rate = 0, ...args: CellValue[]): UnionValue => {
102
102
 
103
103
  let result = 0;
104
104
 
105
- const flat = FlattenUnboxed(args);
105
+ const flat = FlattenCellValues(args);
106
106
  for (let i = 0; i < flat.length; i++) {
107
107
  const arg = flat[i];
108
108
  if (typeof arg === 'number') {
@@ -123,14 +123,14 @@ export const FinanceFunctionLibrary: FunctionMap = {
123
123
  { name: 'Values', },
124
124
  { name: 'Dates', },
125
125
  ],
126
- fn: (rate: UnionValue, input_values: CellValue[], input_dates: CellValue[]): UnionValue => {
126
+ fn: (rate: CellValue, input_values: CellValue[], input_dates: CellValue[]): UnionValue => {
127
127
 
128
128
  if (typeof rate !== 'number') {
129
129
  return ArgumentError();
130
130
  }
131
131
 
132
- input_values = FlattenUnboxed(input_values);
133
- input_dates = FlattenUnboxed(input_dates);
132
+ input_values = FlattenCellValues(input_values);
133
+ input_dates = FlattenCellValues(input_dates);
134
134
 
135
135
  // some validation...
136
136
 
@@ -186,8 +186,8 @@ export const FinanceFunctionLibrary: FunctionMap = {
186
186
  ],
187
187
  fn: (input_values: CellValue[], input_dates: CellValue[], guess = .1): UnionValue => {
188
188
 
189
- input_values = FlattenUnboxed(input_values);
190
- input_dates = FlattenUnboxed(input_dates);
189
+ input_values = FlattenCellValues(input_values);
190
+ input_dates = FlattenCellValues(input_dates);
191
191
 
192
192
  // some validation...
193
193
 
@@ -307,7 +307,7 @@ export const FinanceFunctionLibrary: FunctionMap = {
307
307
  ],
308
308
  fn: (args: CellValue[], guess = .1): UnionValue => {
309
309
 
310
- const flat = FlattenUnboxed(args).map(value => typeof value === 'number' ? value : 0);
310
+ const flat = FlattenCellValues(args).map(value => typeof value === 'number' ? value : 0);
311
311
 
312
312
  const step = .1; // initial step
313
313
 
@@ -0,0 +1,26 @@
1
+
2
+ import type { UnionValue, Complex } from 'treb-base-types';
3
+ import { ValueType } from 'treb-base-types';
4
+
5
+ export const CoerceComplex = (value: UnionValue): Complex|false => {
6
+
7
+ switch (value.type) {
8
+ case ValueType.complex:
9
+ return value.value;
10
+
11
+ case ValueType.number:
12
+ return { real: value.value, imaginary: 0 };
13
+
14
+ case ValueType.boolean:
15
+ return { real: value.value ? 1 : 0, imaginary: 0 };
16
+
17
+ // controversial? ...
18
+ case ValueType.undefined:
19
+ return { real: 0, imaginary: 0 };
20
+
21
+ }
22
+
23
+ return false;
24
+
25
+ };
26
+
@@ -21,64 +21,44 @@
21
21
 
22
22
  import type { FunctionMap } from '../descriptors';
23
23
  import { type UnionValue, ValueType } from 'treb-base-types';
24
- import * as Utils from '../utilities';
24
+
25
+ const MatchType = (type: string, ref: UnionValue): UnionValue => {
26
+ return {
27
+ type: ValueType.boolean,
28
+ value: typeof (ref.value as {value?: unknown})?.value === type,
29
+ };
30
+ };
31
+
32
+ const match_arguments = [{
33
+ name: 'Reference',
34
+ metadata: true,
35
+ unroll: true,
36
+ }];
25
37
 
26
38
  export const InformationFunctionLibrary: FunctionMap = {
27
39
 
28
40
  IsBlank: {
29
41
  description: 'Returns true if the reference is blank',
30
- arguments: [{
31
- name: 'Reference',
32
- metadata: true,
33
- }],
34
- fn: Utils.ApplyAsArray((ref: UnionValue): UnionValue => {
35
- return {
36
- type: ValueType.boolean,
37
- value: !ref?.value || typeof ref.value.value === 'undefined',
38
- };
39
- }),
42
+ arguments: match_arguments,
43
+ fn: MatchType.bind(0, 'undefined'),
40
44
  },
41
45
 
42
46
  IsNumber: {
43
47
  description: 'Returns true if the reference is a number',
44
- arguments: [{
45
- name: 'Reference',
46
- metadata: true,
47
- }],
48
- fn: Utils.ApplyAsArray((ref: UnionValue): UnionValue => {
49
- return {
50
- type: ValueType.boolean,
51
- value: ref?.value && typeof ref.value.value === 'number',
52
- };
53
- }),
48
+ arguments: match_arguments,
49
+ fn: MatchType.bind(0, 'number'),
54
50
  },
55
51
 
56
52
  IsLogical: {
57
53
  description: 'Returns true if the reference is a logical TRUE or FALSE',
58
- arguments: [{
59
- name: 'Reference',
60
- metadata: true,
61
- }],
62
- fn: Utils.ApplyAsArray((ref: UnionValue): UnionValue => {
63
- return {
64
- type: ValueType.boolean,
65
- value: ref?.value && typeof ref.value.value === 'boolean',
66
- };
67
- }),
54
+ arguments: match_arguments,
55
+ fn: MatchType.bind(0, 'boolean'),
68
56
  },
69
57
 
70
58
  IsText: {
71
59
  description: 'Returns true if the reference is text',
72
- arguments: [{
73
- name: 'Reference',
74
- metadata: true,
75
- }],
76
- fn: Utils.ApplyAsArray((ref: UnionValue): UnionValue => {
77
- return {
78
- type: ValueType.boolean,
79
- value: ref?.value && typeof ref.value.value === 'string'
80
- };
81
- }),
60
+ arguments: match_arguments,
61
+ fn: MatchType.bind(0, 'string'),
82
62
  },
83
63
 
84
64
  /* needs more data
@@ -37,11 +37,18 @@ const ComplexMatrix = (input: UnionValue): ComplexMatrixType => {
37
37
 
38
38
  // ensure array
39
39
 
40
+ // hmmm... this is confusing. what is this doing? is this for scalars?
41
+ // if that were the case shouldn't it wrap up the outer value, and not
42
+ // the value property? ...
43
+
40
44
  if (input.type === ValueType.array) {
41
45
  a = input.value;
42
46
  }
43
47
  else {
44
- a = [[input.value]];
48
+
49
+ // a = [[input.value]];
50
+ a = [[input]];
51
+
45
52
  }
46
53
 
47
54
  // if (!Array.isArray(a)) { a = [[a]]; }
@@ -30,7 +30,7 @@
30
30
  */
31
31
 
32
32
 
33
- import type { Cell, Style, CellStyle } from 'treb-base-types';
33
+ import type { Cell, CellStyle } from 'treb-base-types';
34
34
 
35
35
  export interface SparklineRenderOptions {
36
36
  context: CanvasRenderingContext2D;
@@ -62,7 +62,7 @@ export class Sparkline {
62
62
  * representation (loading file); in that case it's an object with numeric
63
63
  * indexes (sadly)
64
64
  */
65
- protected static UnpackValues(underlying: any): number[] {
65
+ protected static UnpackValues(underlying: unknown): number[] {
66
66
 
67
67
  if (Array.isArray(underlying)) {
68
68
  const test = underlying[0];
@@ -85,7 +85,9 @@ export class Sparkline {
85
85
  // if (keys.every(key => !isNaN(Number(key)))) {
86
86
 
87
87
  // check first, last
88
- if (typeof underlying['0'] !== 'undefined' && typeof underlying[(len - 1).toString()] !== 'undefined') {
88
+ if (typeof ((underlying as Record<string, number>)['0']) !== 'undefined' &&
89
+ typeof (underlying as Record<string, number>)[(len - 1).toString()] !== 'undefined') {
90
+
89
91
  const data: number[] = [];
90
92
 
91
93
  // we probably don't have to explicitly use strings -- although it's not
@@ -93,7 +95,7 @@ export class Sparkline {
93
95
  // conversion
94
96
 
95
97
  for (let i = 0; i < len; i++) {
96
- data[i] = underlying[i.toString()];
98
+ data[i] = (underlying as Record<string, number>)[i.toString()];
97
99
  }
98
100
  return data;
99
101
  }
@@ -22,7 +22,7 @@
22
22
  import type { FunctionMap } from '../descriptors';
23
23
  import * as Utils from '../utilities';
24
24
  import { ValueError, ArgumentError, NAError } from '../function-error';
25
- import { type Complex, type UnionValue, ValueType } from 'treb-base-types';
25
+ import { type Complex, type UnionValue, ValueType, type CellValue } from 'treb-base-types';
26
26
  import * as ComplexMath from '../complex-math';
27
27
 
28
28
  export const Variance = (data: number[], sample = false) => {
@@ -58,32 +58,32 @@ export const StatisticsFunctionLibrary: FunctionMap = {
58
58
  'StDev.P': {
59
59
  description: 'Returns the standard deviation of a set of values, corresponding to a population',
60
60
  arguments: [{ name: 'data', }],
61
- fn: (...args: any[]): UnionValue => {
62
- return { type: ValueType.number, value: Math.sqrt(Variance(Utils.FlattenUnboxed(args), false)) };
61
+ fn: (...args: CellValue[]): UnionValue => {
62
+ return { type: ValueType.number, value: Math.sqrt(Variance(Utils.FlattenNumbers(args), false)) };
63
63
  },
64
64
  },
65
65
 
66
66
  'StDev.S': {
67
67
  description: 'Returns the standard deviation of a set of values, corresponding to a sample of a population',
68
68
  arguments: [{ name: 'data', }],
69
- fn: (...args: any[]): UnionValue => {
70
- return { type: ValueType.number, value: Math.sqrt(Variance(Utils.FlattenUnboxed(args), true)) };
69
+ fn: (...args: CellValue[]): UnionValue => {
70
+ return { type: ValueType.number, value: Math.sqrt(Variance(Utils.FlattenNumbers(args), true)) };
71
71
  },
72
72
  },
73
73
 
74
74
  'Var.P': {
75
75
  description: 'Returns the variance of a set of values, corresponding to a population',
76
76
  arguments: [{ name: 'data', }],
77
- fn: (...args: any[]): UnionValue => {
78
- return { type: ValueType.number, value: Variance(Utils.FlattenUnboxed(args), false) };
77
+ fn: (...args: CellValue[]): UnionValue => {
78
+ return { type: ValueType.number, value: Variance(Utils.FlattenNumbers(args), false) };
79
79
  },
80
80
  },
81
81
 
82
82
  'Var.S': {
83
83
  description: 'Returns the variance of a set of values, corresponding to a sample of a population',
84
84
  arguments: [{ name: 'data', }],
85
- fn: (...args: any[]): UnionValue => {
86
- return { type: ValueType.number, value: Variance(Utils.FlattenUnboxed(args), true) };
85
+ fn: (...args: CellValue[]): UnionValue => {
86
+ return { type: ValueType.number, value: Variance(Utils.FlattenNumbers(args), true) };
87
87
  },
88
88
  },
89
89
 
@@ -94,7 +94,7 @@ export const StatisticsFunctionLibrary: FunctionMap = {
94
94
  }, {
95
95
  name: 'B',
96
96
  }],
97
- fn: (x: any[], y: any[]): UnionValue => {
97
+ fn: (x: number[][], y: number[][]): UnionValue => {
98
98
 
99
99
  // both must be 2d arrays, we're assuming the same or mostly similar shape
100
100
  if (!Array.isArray(x) || !Array.isArray(y)) { return ValueError(); }
@@ -153,7 +153,7 @@ export const StatisticsFunctionLibrary: FunctionMap = {
153
153
  }, {
154
154
  name: 'B',
155
155
  }],
156
- fn: (x: any[], y: any[]): UnionValue => {
156
+ fn: (x: number[][], y: number[][]): UnionValue => {
157
157
 
158
158
  // both must be 2d arrays, we're assuming the same or mostly similar shape
159
159
  if (!Array.isArray(x) || !Array.isArray(y)) { return ValueError(); }
@@ -201,7 +201,7 @@ export const StatisticsFunctionLibrary: FunctionMap = {
201
201
  description: 'Returns the geometric mean of all numeric arguments',
202
202
  arguments: [{ boxed: true }],
203
203
 
204
- fn: (...args: any[]): UnionValue => {
204
+ fn: (...args: UnionValue[]): UnionValue => {
205
205
 
206
206
  args = Utils.FlattenBoxed(args);
207
207
 
@@ -210,7 +210,7 @@ export const StatisticsFunctionLibrary: FunctionMap = {
210
210
  let complex = false;
211
211
  let negative = false;
212
212
 
213
- for (const arg of args as UnionValue[]) {
213
+ for (const arg of args) {
214
214
 
215
215
  if (arg.type === ValueType.complex) {
216
216
  complex = true;
@@ -265,7 +265,7 @@ export const StatisticsFunctionLibrary: FunctionMap = {
265
265
  description: 'Returns the arithmetic mean of all numeric arguments',
266
266
  arguments: [{ boxed: true }],
267
267
 
268
- fn: (...args: any[]): UnionValue => {
268
+ fn: (...args: UnionValue[]): UnionValue => {
269
269
  args = Utils.FlattenBoxed(args);
270
270
 
271
271
  const result = { real: 0, imaginary: 0 };
@@ -305,7 +305,9 @@ export const StatisticsFunctionLibrary: FunctionMap = {
305
305
  ],
306
306
  fn: (range: number[][], percentile: number): UnionValue => {
307
307
 
308
- const flat = Utils.FlattenUnboxed(range).filter((test) => typeof test === 'number');
308
+ // const flat = Utils.FlattenCellValues(range).filter((test): test is number => typeof test === 'number');
309
+ const flat = Utils.FlattenNumbers(range);
310
+
309
311
  flat.sort((a, b) => a - b);
310
312
  const n = flat.length;
311
313
 
@@ -326,9 +328,11 @@ export const StatisticsFunctionLibrary: FunctionMap = {
326
328
  arguments: [
327
329
  { name: 'range' },
328
330
  ],
329
- fn: (...args: any[]): UnionValue => {
331
+ fn: (...args: number[]): UnionValue => {
332
+
333
+ // const flat = Utils.FlattenCellValues(args).filter((test): test is number => typeof test === 'number');
334
+ const flat = Utils.FlattenNumbers(args);
330
335
 
331
- const flat = Utils.FlattenUnboxed(args).filter((test) => typeof test === 'number');
332
336
  flat.sort((a, b) => a - b);
333
337
  const n = flat.length;
334
338
 
@@ -19,9 +19,9 @@
19
19
  *
20
20
  */
21
21
 
22
- import type { FunctionMap } from '../descriptors';
22
+ import type { FunctionMap, IntrinsicValue } from '../descriptors';
23
23
  import { NumberFormatCache, ValueParser } from 'treb-format';
24
- import type { UnionValue} from 'treb-base-types';
24
+ import type { CellValue, UnionValue} from 'treb-base-types';
25
25
  import { Localization, ValueType } from 'treb-base-types';
26
26
  import * as Utils from '../utilities';
27
27
  import { ArgumentError, ValueError } from '../function-error';
@@ -78,15 +78,15 @@ export const TextFunctionLibrary: FunctionMap = {
78
78
  WildcardMatch: {
79
79
  visibility: 'internal',
80
80
  arguments: [
81
- { name: 'text', },
82
- { name: 'text', },
81
+ { name: 'text', unroll: true },
82
+ { name: 'text', unroll: true },
83
83
 
84
84
  // the invert parameter is optional, defaults to false. we add this
85
85
  // so we can invert wirhout requiring an extra function call.
86
86
 
87
87
  { name: 'invert' },
88
88
  ],
89
- fn: Utils.ApplyAsArray2((a: any, b: any, invert = false) => {
89
+ fn: (a: IntrinsicValue, b: IntrinsicValue, invert = false) => {
90
90
 
91
91
  if (typeof a === 'string' && typeof b === 'string') {
92
92
  const pattern = Utils.ParseWildcards(b);
@@ -102,21 +102,22 @@ export const TextFunctionLibrary: FunctionMap = {
102
102
  type: ValueType.boolean,
103
103
  value: (a === b || a?.toString() === b?.toString()),
104
104
  }
105
- }),
105
+ },
106
+
106
107
  },
107
108
 
108
109
  Exact: {
109
110
  arguments: [
110
- { name: 'text', boxed: true, },
111
- { name: 'text', boxed: true, },
111
+ { name: 'text', boxed: true, unroll: true },
112
+ { name: 'text', boxed: true, unroll: true },
112
113
  ],
113
114
  category: ['text'],
114
- fn: Utils.ApplyAsArray2((a: UnionValue, b: UnionValue): UnionValue => {
115
+ fn: (a: UnionValue, b: UnionValue): UnionValue => {
115
116
  return {
116
117
  type: ValueType.boolean,
117
118
  value: (a?.value?.toString()) === (b?.value?.toString()),
118
119
  };
119
- }),
120
+ },
120
121
  },
121
122
 
122
123
  Left: {
@@ -258,15 +259,15 @@ export const TextFunctionLibrary: FunctionMap = {
258
259
  /** canonical should be CONCAT; concatenate can be an alias */
259
260
  Concat: {
260
261
  description: 'Pastes strings together',
261
- fn: (...args: unknown[]): UnionValue => {
262
+ fn: (...args: CellValue[]): UnionValue => {
262
263
 
263
- const values = Utils.FlattenUnboxed(args) as unknown[];
264
+ const values = Utils.FlattenCellValues(args);
264
265
  const value = values.map((arg) => {
265
266
 
266
267
  // this is used when concatenating cells that contain numbers
267
268
  // FIXME: get cell number format? we'd need to use metadata
268
269
 
269
- const string_arg = (arg as any)?.toString() || '';
270
+ const string_arg = arg?.toString() || '';
270
271
 
271
272
  if (typeof arg === 'number' && Localization.decimal_separator === ',') {
272
273
  return string_arg.replace(/\./, ',');