@trebco/treb 27.2.1 → 27.5.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/dist/treb.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- /*! API v27.2. Copyright 2018-2023 trebco, llc. All rights reserved. LGPL: https://treb.app/license */
1
+ /*! API v27.5. Copyright 2018-2023 trebco, llc. All rights reserved. LGPL: https://treb.app/license */
2
2
 
3
3
  /**
4
4
  * add our tag to the map
@@ -306,6 +306,18 @@ export declare class EmbeddedSpreadsheet {
306
306
  */
307
307
  get dirty(): boolean;
308
308
 
309
+ /**
310
+ * returns the names of all sheets in the current document
311
+ */
312
+ get sheet_names(): string[];
313
+
314
+ /**
315
+ * set or remove an external editor. external editor is an interface used
316
+ * to support outside tooling by highlighting a list of arguments and
317
+ * responding to selection.
318
+ */
319
+ ExternalEditor(editor?: Partial<ExternalEditorType>): void;
320
+
309
321
  /**
310
322
  * Use this function to batch multiple document changes. Essentially the
311
323
  * grid stops broadcasting events for the duration of the function call,
@@ -741,6 +753,16 @@ export declare class EmbeddedSpreadsheet {
741
753
  */
742
754
  Resolve(reference: string): ICellAddress | IArea | undefined;
743
755
 
756
+ /**
757
+ * Convert an address/range object to a string. this is a convenience
758
+ * function for composing formulas.
759
+ *
760
+ * @param ref sheet reference as a string or structured object
761
+ * @param [qualified=true] include sheet names
762
+ * @param [named=true] resolve to named ranges, where applicable
763
+ */
764
+ Unresolve(ref: RangeReference, qualified?: boolean, named?: boolean): string;
765
+
744
766
  /**
745
767
  * Evaluate an arbitrary expression in the spreadsheet. You should generally
746
768
  * use sheet names when referring to cells, to avoid ambiguity. Otherwise
@@ -844,11 +866,12 @@ export declare class EmbeddedSpreadsheet {
844
866
 
845
867
  /**
846
868
  * Select a range. This function will change sheets if your reference
847
- * refers to a different sheet.
869
+ * refers to a different sheet. if the argument is undefined or falsy
870
+ * it will remove the selection (set to no selection).
848
871
  *
849
872
  * @public
850
873
  */
851
- Select(range: RangeReference): void;
874
+ Select(range?: RangeReference): void;
852
875
 
853
876
  /**
854
877
  *
@@ -1032,6 +1055,28 @@ export interface SetRangeOptions {
1032
1055
  */
1033
1056
  r1c1?: boolean;
1034
1057
  }
1058
+ export interface ExternalEditorType {
1059
+
1060
+ /**
1061
+ * list of dependencies to highlight. we support undefined entries in
1062
+ * this list so you can use the result of `EmbeddedSpreadsheet.Resolve`,
1063
+ * which may return undefined.
1064
+ */
1065
+ dependencies: DependencyList;
1066
+
1067
+ /**
1068
+ * this callback will be called when the selection changes in the
1069
+ * spreadsheet and this external editor is active. return an updated
1070
+ * list of dependencies to highlight.
1071
+ *
1072
+ * NOTE: this is currently synchronous, but don't rely on that. it
1073
+ * might switch to async in the future depending on how it works in
1074
+ * practice.
1075
+ */
1076
+ update: ExternalEditorCallback;
1077
+ }
1078
+ export type DependencyList = Array<IArea | ICellAddress | undefined>;
1079
+ export type ExternalEditorCallback = (selection?: string) => DependencyList | undefined;
1035
1080
 
1036
1081
  /**
1037
1082
  * Structure represents a 2d range of cells.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trebco/treb",
3
- "version": "27.2.1",
3
+ "version": "27.5.3",
4
4
  "license": "LGPL-3.0-or-later",
5
5
  "homepage": "https://treb.app",
6
6
  "repository": {
@@ -1,24 +1,24 @@
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-2023 trebco, llc.
18
- * info@treb.app
19
- *
20
- */
21
-
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-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
22
  /** structure represents rectangle coordinates */
23
23
  export interface IRectangle {
24
24
  top: number;
@@ -81,6 +81,10 @@ export class Rectangle implements IRectangle {
81
81
  );
82
82
  }
83
83
 
84
+ /*
85
+ * removing this method as part of cleaning up bitwise flags.
86
+ * if you need this method, rewrite it to use explicit flags.
87
+ *
84
88
  public CheckEdges(x: number, y: number, border = 16): number{
85
89
 
86
90
  let edge = 0;
@@ -99,6 +103,7 @@ export class Rectangle implements IRectangle {
99
103
 
100
104
  return edge;
101
105
  }
106
+ */
102
107
 
103
108
  /**
104
109
  * check if rectangle contains the given coordinates, optionally with
@@ -31,6 +31,7 @@ import type {
31
31
  GridSelection, CellEvent, FunctionDescriptor,
32
32
  AnnotationViewData,
33
33
  AnnotationType,
34
+ ExternalEditorType,
34
35
  } from 'treb-grid';
35
36
 
36
37
  import {
@@ -478,6 +479,13 @@ export class EmbeddedSpreadsheet {
478
479
  return this.file_version !== this.last_save_version;
479
480
  }
480
481
 
482
+ /**
483
+ * returns the names of all sheets in the current document
484
+ */
485
+ public get sheet_names() {
486
+ return this.model.sheets.list.map(sheet => sheet.name);
487
+ }
488
+
481
489
  /**
482
490
  * constructor takes spreadsheet options. type should be implicit, either
483
491
  * the default (here) or a subclass
@@ -1164,6 +1172,15 @@ export class EmbeddedSpreadsheet {
1164
1172
  }
1165
1173
  }
1166
1174
 
1175
+ /**
1176
+ * set or remove an external editor. external editor is an interface used
1177
+ * to support outside tooling by highlighting a list of arguments and
1178
+ * responding to selection.
1179
+ */
1180
+ public ExternalEditor(editor?: Partial<ExternalEditorType>) {
1181
+ this.grid.ExternalEditor(editor);
1182
+ }
1183
+
1167
1184
  /**
1168
1185
  * this is not very efficient atm. we create another whole instance of this
1169
1186
  * class, do a lot of unecssary painting and layout. it works but it could
@@ -3397,6 +3414,55 @@ export class EmbeddedSpreadsheet {
3397
3414
 
3398
3415
  }
3399
3416
 
3417
+ /**
3418
+ * Convert an address/range object to a string. this is a convenience
3419
+ * function for composing formulas.
3420
+ *
3421
+ * @param ref sheet reference as a string or structured object
3422
+ * @param [qualified=true] include sheet names
3423
+ * @param [named=true] resolve to named ranges, where applicable
3424
+ */
3425
+ public Unresolve(ref: RangeReference, qualified = true, named = true): string {
3426
+
3427
+ if (typeof ref === 'string') {
3428
+ const resolved = this.Resolve(ref);
3429
+ if (!resolved) {
3430
+ throw new Error('invalid reference');
3431
+ }
3432
+ ref = resolved;
3433
+ }
3434
+
3435
+ let range = '';
3436
+ const area = IsCellAddress(ref) ? new Area(ref) : new Area(ref.start, ref.end);
3437
+
3438
+ if (named) {
3439
+ const named_range = this.model.named_ranges.MatchSelection(area);
3440
+ if (named_range) {
3441
+ return named_range;
3442
+ }
3443
+ }
3444
+
3445
+ if (area.count > 1) {
3446
+ range = Area.CellAddressToLabel(area.start) + ':' + Area.CellAddressToLabel(area.end);
3447
+ }
3448
+ else {
3449
+ range = Area.CellAddressToLabel(area.start);
3450
+ }
3451
+
3452
+ if (!qualified) {
3453
+ return range;
3454
+ }
3455
+
3456
+ // is there a function to resolve sheet? actually, don't we know that
3457
+ // the active selection must be on the active sheet? (...)
3458
+
3459
+ const sheet_id = area.start.sheet_id || this.grid.active_sheet.id;
3460
+ const sheet_name = this.ResolveSheetName(sheet_id, true);
3461
+
3462
+ return sheet_name ? sheet_name + '!' + range : range;
3463
+
3464
+ }
3465
+
3400
3466
  /**
3401
3467
  * Evaluate an arbitrary expression in the spreadsheet. You should generally
3402
3468
  * use sheet names when referring to cells, to avoid ambiguity. Otherwise
@@ -3708,18 +3774,24 @@ export class EmbeddedSpreadsheet {
3708
3774
 
3709
3775
  /**
3710
3776
  * Select a range. This function will change sheets if your reference
3711
- * refers to a different sheet.
3777
+ * refers to a different sheet. if the argument is undefined or falsy
3778
+ * it will remove the selection (set to no selection).
3712
3779
  *
3713
3780
  * @public
3714
3781
  */
3715
- public Select(range: RangeReference): void {
3782
+ public Select(range?: RangeReference): void {
3783
+
3784
+ let resolved: Area|undefined = undefined;
3785
+
3786
+ if (!!range) {
3787
+ resolved = this.calculator.ResolveArea(range, this.grid.active_sheet);
3788
+ if (resolved.start.sheet_id) {
3789
+ if (resolved.start.sheet_id !== this.grid.active_sheet.id) {
3790
+ this.grid.ActivateSheetID(resolved.start.sheet_id);
3791
+ }
3792
+ }
3793
+ }
3716
3794
 
3717
- const resolved = this.calculator.ResolveArea(range, this.grid.active_sheet);
3718
- if (resolved.start.sheet_id) {
3719
- if (resolved.start.sheet_id !== this.grid.active_sheet.id) {
3720
- this.grid.ActivateSheetID(resolved.start.sheet_id);
3721
- }
3722
- }
3723
3795
  this.grid.SelectRange(resolved);
3724
3796
 
3725
3797
  }
@@ -3898,42 +3970,6 @@ export class EmbeddedSpreadsheet {
3898
3970
 
3899
3971
  }
3900
3972
 
3901
- /**
3902
- *
3903
- */
3904
- protected Unresolve(ref: ICellAddress|IArea, qualified = true, named = true): string {
3905
-
3906
- let range = '';
3907
- const area = IsCellAddress(ref) ? new Area(ref) : new Area(ref.start, ref.end);
3908
-
3909
- if (named) {
3910
- const named_range = this.model.named_ranges.MatchSelection(area);
3911
- if (named_range) {
3912
- return named_range;
3913
- }
3914
- }
3915
-
3916
- if (area.count > 1) {
3917
- range = Area.CellAddressToLabel(area.start) + ':' + Area.CellAddressToLabel(area.end);
3918
- }
3919
- else {
3920
- range = Area.CellAddressToLabel(area.start);
3921
- }
3922
-
3923
- if (!qualified) {
3924
- return range;
3925
- }
3926
-
3927
- // is there a function to resolve sheet? actually, don't we know that
3928
- // the active selection must be on the active sheet? (...)
3929
-
3930
- const sheet_id = area.start.sheet_id || this.grid.active_sheet.id;
3931
- const sheet_name = this.ResolveSheetName(sheet_id, true);
3932
-
3933
- return sheet_name ? sheet_name + '!' + range : range;
3934
-
3935
- }
3936
-
3937
3973
  /**
3938
3974
  * replacement for (the great) FileSaver lib. we can now rely on all
3939
3975
  * browsers to handle this properly (fingers crossed).
@@ -35,7 +35,7 @@ import { UnlotusDate } from './format';
35
35
 
36
36
  // tslint:disable:no-bitwise
37
37
 
38
- /** hints is a bitfield */
38
+ /* * hints is a bitfield * /
39
39
  export enum Hints {
40
40
  None = 0x00,
41
41
  Nan = 0x01,
@@ -47,6 +47,18 @@ export enum Hints {
47
47
  Date = 0x40,
48
48
  Time = 0x80,
49
49
  }
50
+ */
51
+
52
+ export interface Hints {
53
+ Nan?: boolean;
54
+ Exponential?: boolean;
55
+ Percent?: boolean;
56
+ Currency?: boolean;
57
+ Grouping?: boolean;
58
+ Parens?: boolean;
59
+ Date?: boolean;
60
+ Time?: boolean;
61
+ }
50
62
 
51
63
  /**
52
64
  * parse result now uses base valuetype
@@ -222,7 +234,7 @@ class ValueParserType {
222
234
  */
223
235
  public TryParse(text = ''): ParseResult {
224
236
 
225
- let hints: Hints = Hints.None;
237
+ let hints: Hints = {}; // Hints.None;
226
238
 
227
239
  // starts with SINGLE quote mark. express string.
228
240
  if (text[0] === '\'') return { value: text, type: ValueType.string };
@@ -233,7 +245,11 @@ class ValueParserType {
233
245
  // we test if the conversion returns NaN, which usually means
234
246
  // it's not a number -- unless the string is actually NaN, which
235
247
  // is something we want to preserve.
236
- if ( text === 'NaN' ) return { value: NaN, type: ValueType.number, hints: Hints.Nan };
248
+ if ( text === 'NaN' ) return {
249
+ value: NaN,
250
+ type: ValueType.number,
251
+ hints: { Nan: true },
252
+ };
237
253
 
238
254
  let x = text.trim();
239
255
  // x = x.replace(/^[\$£€]/, '').trim();
@@ -241,25 +257,29 @@ class ValueParserType {
241
257
  const currency = x.match(/^[$](.*?)$/);
242
258
  if (currency) {
243
259
  x = currency[1];
244
- hints |= Hints.Currency;
260
+ // hints |= Hints.Currency;
261
+ hints.Currency = true;
245
262
  }
246
263
 
247
264
  const parens = x.match(/^\((.*?)\)$/);
248
265
  if (parens) {
249
266
  x = parens[1];
250
- hints |= Hints.Parens;
267
+ // hints |= Hints.Parens;
268
+ hints.Parens = true;
251
269
  }
252
270
 
253
271
  const pct = x.match(/^(.*?)%\s*$/);
254
272
  if (pct) {
255
273
  x = pct[1];
256
- hints |= Hints.Percent;
274
+ // hints |= Hints.Percent;
275
+ hints.Percent = true;
257
276
  }
258
277
 
259
278
  if (Localization.decimal_separator === '.'){
260
279
  if (/,/.test(x)) {
261
280
  x = x.replace(/,/g, '');
262
- hints |= Hints.Grouping;
281
+ // hints |= Hints.Grouping;
282
+ hints.Grouping = true;
263
283
  }
264
284
  }
265
285
  else {
@@ -295,10 +315,10 @@ class ValueParserType {
295
315
  const year = check.getUTCFullYear();
296
316
 
297
317
  if (year >= (this_year - 200) && year <= (this_year + 200)) {
298
- hints = Hints.Date;
318
+ hints = { Date: true };
299
319
 
300
320
  if (check.getHours() || check.getMinutes() || check.getSeconds()) {
301
- hints |= Hints.Time;
321
+ hints.Time = true;
302
322
  }
303
323
 
304
324
  return {
@@ -328,7 +348,7 @@ class ValueParserType {
328
348
 
329
349
  }
330
350
 
331
- if (/e/.test(text)) hints |= Hints.Exponential;
351
+ if (/e/.test(text)) hints.Exponential = true;
332
352
  return { value: num, type: ValueType.number, hints };
333
353
 
334
354
  }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "treb-grid",
3
- "version": "16.0.2",
3
+ "version": "16.1.0",
4
4
  "main": "src/index.ts"
5
5
  }
@@ -38,4 +38,5 @@ export type { SerializeOptions } from './types/serialize_options';
38
38
  export type { FunctionDescriptor, ArgumentDescriptor } from './editors/autocomplete_matcher';
39
39
  export { UA } from './util/ua';
40
40
  export type { SetRangeOptions } from './types/set_range_options';
41
- export type { AnnotationData, AnnotationType } from './types/annotation';
41
+ export type { AnnotationData, AnnotationType } from './types/annotation';
42
+ export type { ExternalEditorType, DependencyList, ExternalEditorCallback } from './types/external_editor';
@@ -394,6 +394,9 @@ export class TileRenderer {
394
394
  public RenderColumnLabels(context: CanvasRenderingContext2D, column: number, end: number) {
395
395
 
396
396
  const header_y = this.layout.header_offset.y;
397
+ if (header_y <= 1) {
398
+ return;
399
+ }
397
400
 
398
401
  context.fillStyle = ThemeColor2(this.theme, this.theme.headers?.text, 0);
399
402
 
@@ -418,7 +421,10 @@ export class TileRenderer {
418
421
  public RenderRowLabels(context: CanvasRenderingContext2D, row: number, end: number, block: number) {
419
422
 
420
423
  const header_x = this.layout.header_offset.x;
421
-
424
+ if (header_x <= 1) {
425
+ return;
426
+ }
427
+
422
428
  context.fillStyle = ThemeColor2(this.theme, this.theme.headers?.text, 0);
423
429
 
424
430
  context.beginPath();
@@ -0,0 +1,27 @@
1
+
2
+ import type { IArea, ICellAddress } from "treb-base-types";
3
+
4
+ export type DependencyList = Array<IArea|ICellAddress|undefined>;
5
+ export type ExternalEditorCallback = (selection?: string) => DependencyList|undefined;
6
+
7
+ export interface ExternalEditorType {
8
+
9
+ /**
10
+ * list of dependencies to highlight. we support undefined entries in
11
+ * this list so you can use the result of `EmbeddedSpreadsheet.Resolve`,
12
+ * which may return undefined.
13
+ */
14
+ dependencies: DependencyList;
15
+
16
+ /**
17
+ * this callback will be called when the selection changes in the
18
+ * spreadsheet and this external editor is active. return an updated
19
+ * list of dependencies to highlight.
20
+ *
21
+ * NOTE: this is currently synchronous, but don't rely on that. it
22
+ * might switch to async in the future depending on how it works in
23
+ * practice.
24
+ */
25
+ update: ExternalEditorCallback;
26
+
27
+ }