@trebco/treb 30.6.0 → 30.6.3

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/esbuild-utils.mjs CHANGED
@@ -74,7 +74,7 @@ export const FormatSize = (size, precision = 1) => {
74
74
 
75
75
  /**
76
76
  * @function
77
- * @param {{verbose?: boolean, minify?: boolean}} [options]
77
+ * @param {{verbose?: boolean, minify?: boolean, define?: Record<string, string>}} [options]
78
78
  * @returns {esbuild.Plugin}
79
79
  *
80
80
  * inlining the worker build. this works out well with one limitation:
@@ -147,6 +147,8 @@ export const WorkerPlugin = (options) => ({
147
147
  bundle: true,
148
148
  format: 'esm',
149
149
 
150
+ define: options?.define,
151
+
150
152
  // don't write to filesystem
151
153
  write: false,
152
154
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trebco/treb",
3
- "version": "30.6.0",
3
+ "version": "30.6.3",
4
4
  "license": "LGPL-3.0-or-later",
5
5
  "homepage": "https://treb.app",
6
6
  "repository": {
@@ -534,7 +534,6 @@ export const BaseFunctionLibrary: FunctionMap = {
534
534
  value: delta / divisor,
535
535
  };
536
536
 
537
- return NAError();
538
537
  },
539
538
  },
540
539
 
@@ -196,6 +196,7 @@ export const ChartFunctions: Record<ChartFunction|SupportFunction, CompositeFunc
196
196
  arguments: [
197
197
  { name: 'Data', metadata: true, },
198
198
  { name: 'Chart Title' },
199
+ { name: 'Min/Max Style' }
199
200
  ],
200
201
  fn: Identity,
201
202
  category: ['chart functions'],
@@ -1,3 +1,23 @@
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2024 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
1
21
 
2
22
  import { type UnionValue, ValueType, type ArrayUnion, IsComplex, type CellValue } from 'treb-base-types';
3
23
  import { IsArrayUnion, IsMetadata, IsSeries, LegendStyle } from './chart-types';
@@ -7,6 +27,8 @@ import { Util } from './util';
7
27
  import type { ReferenceSeries } from './chart-types';
8
28
  import type { RangeScale } from 'treb-utils';
9
29
 
30
+ import { QuickSort } from './quicksort';
31
+
10
32
  /**
11
33
  * this file is the concrete translation from function arguments
12
34
  * to chart data. chart data is a (somewhat complicated) type with
@@ -148,6 +170,48 @@ export const ArrayToSeries = (array_data: ArrayUnion): SeriesType => {
148
170
 
149
171
  // series.y.data = flat.map(item => typeof item.value === 'number' ? item.value : undefined);
150
172
 
173
+ // console.trace();
174
+
175
+ const values: number[] = []; // filter any undefineds
176
+
177
+ for (const [index, item] of flat.entries()) {
178
+
179
+ let value = 0;
180
+
181
+ // why is this testing type instead of using the union type?
182
+
183
+ if (typeof item.value === 'number') {
184
+ value = item.value;
185
+ // series.y.data[index] = item.value;
186
+ values.push(item.value);
187
+ }
188
+ else if (IsMetadata(item)) {
189
+ if (IsComplex(item.value.value)) {
190
+ series.x.data[index] = item.value.value.real;
191
+ // series.y.data[index] = item.value.value.imaginary;
192
+ // values.push(item.value.value.imaginary);
193
+ value = item.value.value.imaginary;
194
+ }
195
+ else if (typeof item.value.value === 'number') {
196
+ // series.y.data[index] = item.value.value;
197
+ // values.push(item.value.value);
198
+ value = item.value.value;
199
+ }
200
+ else {
201
+ continue;
202
+ }
203
+ }
204
+ else {
205
+ // series.y.data[index] = undefined;
206
+ continue;
207
+ }
208
+
209
+ series.y.data[index] = value;
210
+ values.push(value);
211
+
212
+ }
213
+
214
+ /*
151
215
  series.y.data = flat.map((item, index) => {
152
216
 
153
217
  // if the data is passed in from the output of a function, it will not
@@ -178,6 +242,7 @@ export const ArrayToSeries = (array_data: ArrayUnion): SeriesType => {
178
242
  return undefined;
179
243
 
180
244
  });
245
+ */
181
246
 
182
247
  let first_format = '';
183
248
  if (IsMetadata(flat[0])) {
@@ -190,7 +255,9 @@ export const ArrayToSeries = (array_data: ArrayUnion): SeriesType => {
190
255
  series.y.labels = series.y.data.map(value => (value === undefined) ? undefined : format.Format(value));
191
256
  }
192
257
 
193
- const values = series.y.data.filter(value => value || value === 0) as number[];
258
+ // moved up, integrated loops
259
+ // const values = series.y.data.filter(value => value || value === 0) as number[];
260
+
194
261
  series.y.range = ArrayMinMax(values);
195
262
 
196
263
  // experimenting with complex... this should only be set if we populated
@@ -589,19 +656,31 @@ export const CreateBoxPlot = (args: UnionValue[]): ChartData => {
589
656
 
590
657
  let max_n = 0;
591
658
 
659
+ // change to min-max style
660
+ const minmax = !!args[2];
661
+
592
662
  const stats: BoxPlotData['data'] = series.map(series => {
593
663
  // const data = series.y.data.slice(0).filter((test): test is number => test !== undefined).sort((a, b) => a - b);
594
664
  const data: number[] = [];
595
665
  for (const entry of series.y.data) {
596
666
  if (entry !== undefined) { data.push(entry); }
597
667
  }
598
- data.sort((a, b) => a - b);
668
+
669
+ // data.sort((a, b) => a - b);
670
+ QuickSort(data);
599
671
 
600
672
  const result = BoxStats(data);
601
673
  max_n = Math.max(max_n, result.n);
674
+
675
+ if (minmax) {
676
+ result.whiskers[0] = result.min;
677
+ result.whiskers[1] = result.max;
678
+ }
679
+
602
680
  return result;
603
681
  });
604
682
 
683
+
605
684
  const title = args[1]?.toString() || undefined;
606
685
  const x_labels: string[] = [];
607
686
  const series_names: string[] = [];
@@ -0,0 +1,54 @@
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2024 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
+ // FIXME: move
23
+
24
+ export const QuickSort = (data: number[]) => {
25
+ Sort(data, 0, data.length);
26
+ };
27
+
28
+ const Partition = (data: number[], left: number, right: number) => {
29
+ const compare = data[right - 1];
30
+ let min_end = left;
31
+ for (let max_end = left; max_end < right - 1; max_end += 1) {
32
+ if (data[max_end] <= compare) {
33
+ Swap(data, max_end, min_end);
34
+ min_end += 1;
35
+ }
36
+ }
37
+ Swap(data, min_end, right - 1);
38
+ return min_end;
39
+ };
40
+
41
+ const Swap = (data: number[], i: number, j: number) => {
42
+ const temp = data[i];
43
+ data[i] = data[j];
44
+ data[j] = temp;
45
+ };
46
+
47
+ const Sort = (data: number[], left: number, right: number) => {
48
+ if (left < right) {
49
+ const p = Partition(data, left, right);
50
+ Sort(data, left, p);
51
+ Sort(data, p + 1, right);
52
+ }
53
+ }
54
+
@@ -246,8 +246,8 @@ export class EmbeddedSpreadsheet<USER_DATA_TYPE = unknown> {
246
246
  /* * @internal */
247
247
  // public static export_worker_text = '';
248
248
 
249
- /** @internal */
250
- public static treb_embedded_script_path = '';
249
+ /* * @internal */
250
+ // public static treb_embedded_script_path = '';
251
251
 
252
252
  /**
253
253
  * @internal
@@ -567,7 +567,7 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
567
567
  * that's fine, but it needs a new name.
568
568
  *
569
569
  */
570
- protected UpdateColors(force_event = false) {
570
+ protected UpdateColors(force_event = false, toll_update = false) {
571
571
 
572
572
  // const view = this.active_editor?.node.ownerDocument.defaultView as (Window & typeof globalThis);
573
573
 
@@ -623,8 +623,10 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
623
623
 
624
624
  this.composite_dependencies = list;
625
625
 
626
- this.Publish({ type: 'update', dependencies: this.composite_dependencies });
627
-
626
+ if (!toll_update) {
627
+ this.Publish({ type: 'update', dependencies: this.composite_dependencies });
628
+ }
629
+
628
630
  }
629
631
 
630
632
  /**
@@ -57,6 +57,8 @@ export type FormulaBar2Event
57
57
  export class FormulaBar extends Editor<FormulaBar2Event|FormulaEditorEvent> {
58
58
 
59
59
 
60
+ public committed = false;
61
+
60
62
  /** is the _editor_ currently focused */
61
63
  // tslint:disable-next-line:variable-name
62
64
  public focused_ = false;
@@ -219,7 +221,7 @@ export class FormulaBar extends Editor<FormulaBar2Event|FormulaEditorEvent> {
219
221
  this.active_editor.node.spellcheck = false; // change the default back
220
222
 
221
223
  this.RegisterListener(descriptor, 'focusin', () => {
222
-
224
+
223
225
  // this.editor_node.addEventListener('focusin', () => {
224
226
 
225
227
  // can't happen
@@ -239,7 +241,9 @@ export class FormulaBar extends Editor<FormulaBar2Event|FormulaEditorEvent> {
239
241
  this.autocomplete?.ResetBlock();
240
242
 
241
243
  this.UpdateText(this.active_editor);
242
- this.UpdateColors();
244
+ this.UpdateColors(undefined, true); // toll update event -- we will send in order, below
245
+
246
+ this.committed = false;
243
247
 
244
248
  this.Publish([
245
249
  { type: 'start-editing', editor: 'formula-bar' },
@@ -256,11 +260,32 @@ export class FormulaBar extends Editor<FormulaBar2Event|FormulaEditorEvent> {
256
260
  console.info('focusout, but selecting...');
257
261
  }
258
262
 
259
- // console.info('focus out');
260
-
261
263
  this.autocomplete?.Hide();
264
+
265
+ const text = (this.active_editor ?
266
+ this.GetTextContent(this.active_editor.node).join('') : '').trim();
267
+
268
+ if (this.committed) {
269
+ this.Publish([
270
+ { type: 'stop-editing' },
271
+ ]);
272
+ }
273
+ else {
274
+ this.committed = true;
275
+ this.Publish({
276
+ type: 'commit',
277
+ value: text,
278
+ });
279
+ }
280
+
262
281
  this.Publish([
263
282
  { type: 'stop-editing' },
283
+ /*
284
+ {
285
+ type: 'commit',
286
+ value: text,
287
+ }
288
+ */
264
289
  ]);
265
290
 
266
291
  this.focused_ = false;
@@ -441,6 +466,7 @@ export class FormulaBar extends Editor<FormulaBar2Event|FormulaEditorEvent> {
441
466
  const text = (this.active_editor ?
442
467
  this.GetTextContent(this.active_editor.node).join('') : '').trim();
443
468
 
469
+ this.committed = true;
444
470
  this.Publish({
445
471
  type: 'commit',
446
472
  // selection: this.selection,
@@ -193,6 +193,9 @@ export class Grid extends GridBase {
193
193
  /** if we are editing, what is the cell? */
194
194
  private editing_cell: ICellAddress = { row: -1, column: -1, sheet_id: 0 };
195
195
 
196
+ /** */
197
+ private editing_selection: GridSelection|undefined;
198
+
196
199
  /** */
197
200
  private selected_annotation?: Annotation;
198
201
 
@@ -2859,6 +2862,7 @@ export class Grid extends GridBase {
2859
2862
 
2860
2863
  this.editing_state = EditingState.FormulaBar;
2861
2864
  this.editing_cell = { ...this.primary_selection.target };
2865
+ this.editing_selection = { ...this.primary_selection };
2862
2866
  break;
2863
2867
 
2864
2868
  case 'discard':
@@ -2924,7 +2928,15 @@ export class Grid extends GridBase {
2924
2928
 
2925
2929
  if (this.container) this.Focus();
2926
2930
 
2927
- this.SetInferredType(this.primary_selection, event.value, event.array);
2931
+ if (event.event) {
2932
+ this.SetInferredType(this.primary_selection, event.value, event.array);
2933
+ }
2934
+ else {
2935
+ if (this.editing_selection) {
2936
+ this.SetInferredType(this.editing_selection, event.value, event.array);
2937
+ }
2938
+ }
2939
+
2928
2940
  this.ClearAdditionalSelections();
2929
2941
  this.ClearSelection(this.active_selection);
2930
2942