@trebco/treb 28.17.5 → 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.
- package/dist/treb-spreadsheet-light.mjs +12 -12
- package/dist/treb-spreadsheet.mjs +12 -12
- package/dist/treb.d.ts +121 -82
- package/eslint.config.js +21 -0
- package/package.json +6 -6
- package/treb-base-types/src/area.ts +4 -2
- package/treb-base-types/src/cell.ts +1 -1
- package/treb-base-types/src/cells.ts +16 -7
- package/treb-base-types/src/dom-utilities.ts +4 -2
- package/treb-base-types/src/import.ts +2 -2
- package/treb-base-types/src/rectangle.ts +5 -5
- package/treb-base-types/src/union.ts +6 -1
- package/treb-base-types/src/value-type.ts +1 -1
- package/treb-calculator/src/calculator.ts +114 -165
- package/treb-calculator/src/dag/calculation_leaf_vertex.ts +1 -2
- package/treb-calculator/src/dag/graph.ts +3 -3
- package/treb-calculator/src/dag/spreadsheet_vertex.ts +2 -2
- package/treb-calculator/src/dag/state_leaf_vertex.ts +2 -4
- package/treb-calculator/src/descriptors.ts +28 -2
- package/treb-calculator/src/expression-calculator.ts +25 -34
- package/treb-calculator/src/function-error.ts +2 -2
- package/treb-calculator/src/function-library.ts +16 -0
- package/treb-calculator/src/functions/base-functions.ts +185 -211
- package/treb-calculator/src/functions/checkbox.ts +0 -1
- package/treb-calculator/src/functions/complex-functions.ts +49 -47
- package/treb-calculator/src/functions/finance-functions.ts +10 -10
- package/treb-calculator/src/functions/function-utilities.ts +26 -0
- package/treb-calculator/src/functions/information-functions.ts +21 -41
- package/treb-calculator/src/functions/matrix-functions.ts +8 -1
- package/treb-calculator/src/functions/sparkline.ts +6 -4
- package/treb-calculator/src/functions/statistics-functions.ts +21 -17
- package/treb-calculator/src/functions/text-functions.ts +14 -13
- package/treb-calculator/src/primitives.ts +48 -37
- package/treb-calculator/src/utilities.ts +117 -134
- package/treb-charts/src/chart-functions.ts +3 -3
- package/treb-charts/src/chart-types.ts +42 -1
- package/treb-charts/src/chart-utils.ts +155 -113
- package/treb-charts/src/chart.ts +6 -5
- package/treb-charts/src/default-chart-renderer.ts +6 -5
- package/treb-charts/src/renderer.ts +12 -11
- package/treb-charts/src/util.ts +25 -36
- package/treb-data-model/package.json +5 -0
- package/{treb-grid/src/types → treb-data-model/src}/annotation.ts +2 -2
- package/{treb-grid/src/types → treb-data-model/src}/conditional_format.ts +20 -0
- package/{treb-grid/src/types → treb-data-model/src}/data_model.ts +231 -133
- package/treb-data-model/src/index.ts +45 -0
- package/{treb-grid/src/types/named_range.ts → treb-data-model/src/named.ts} +459 -376
- package/{treb-grid/src/types → treb-data-model/src}/sheet.ts +13 -5
- package/treb-data-model/src/sheet_collection.ts +114 -0
- package/{treb-grid/src/types → treb-data-model/src}/sheet_types.ts +6 -3
- package/treb-embed/modern.tsconfig.json +1 -0
- package/treb-embed/src/custom-element/spreadsheet-constructor.ts +2 -2
- package/treb-embed/src/embedded-spreadsheet.ts +125 -270
- package/treb-embed/src/selection-state.ts +1 -1
- package/treb-embed/src/toolbar-message.ts +1 -1
- package/treb-embed/src/types.ts +13 -5
- package/treb-export/src/export-worker/export-worker.ts +22 -7
- package/treb-export/src/export2.ts +110 -41
- package/treb-export/src/import2.ts +6 -5
- package/treb-export/src/workbook2.ts +31 -13
- package/treb-export/src/xml-utils.ts +5 -1
- package/treb-format/src/format.ts +8 -6
- package/treb-grid/src/editors/autocomplete.ts +2 -2
- package/treb-grid/src/editors/autocomplete_matcher.ts +57 -19
- package/treb-grid/src/editors/editor.ts +27 -25
- package/treb-grid/src/editors/formula_bar.ts +5 -5
- package/treb-grid/src/editors/overlay_editor.ts +1 -2
- package/treb-grid/src/index.ts +0 -11
- package/treb-grid/src/layout/base_layout.ts +20 -8
- package/treb-grid/src/layout/grid_layout.ts +2 -2
- package/treb-grid/src/layout/mock-layout.ts +5 -6
- package/treb-grid/src/render/selection-renderer.ts +2 -3
- package/treb-grid/src/render/tile_renderer.ts +1 -1
- package/treb-grid/src/types/grid.ts +95 -66
- package/treb-grid/src/types/grid_base.ts +76 -60
- package/treb-grid/src/types/grid_command.ts +3 -2
- package/treb-grid/src/types/grid_events.ts +12 -6
- package/treb-grid/src/types/tab_bar.ts +1 -2
- package/treb-parser/src/parser-types.ts +2 -1
- package/treb-parser/src/parser.ts +7 -5
- package/treb-utils/src/event_source.ts +1 -1
- package/treb-utils/src/serialize_html.ts +31 -6
- package/.eslintignore +0 -8
- package/.eslintrc.cjs +0 -168
- package/treb-grid/src/layout/rectangle_cache.ts +0 -86
- /package/{treb-grid/src/types → treb-data-model/src}/serialize_options.ts +0 -0
- /package/{treb-grid/src/types/grid_selection.ts → treb-data-model/src/sheet_selection.ts} +0 -0
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
import { DOMContext } from 'treb-base-types';
|
|
23
23
|
import type { Theme, Rectangle } from 'treb-base-types';
|
|
24
|
-
import type { AutocompleteExecResult,
|
|
24
|
+
import type { AutocompleteExecResult, FunctionDescriptor } from './autocomplete_matcher';
|
|
25
25
|
|
|
26
26
|
export interface AutocompleteResult {
|
|
27
27
|
handled: boolean;
|
|
@@ -29,7 +29,7 @@ export interface AutocompleteResult {
|
|
|
29
29
|
data?: AutocompleteExecResult;
|
|
30
30
|
value?: string;
|
|
31
31
|
click?: boolean;
|
|
32
|
-
type?:
|
|
32
|
+
type?: FunctionDescriptor['type'];
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/*
|
|
@@ -41,15 +41,25 @@ export interface ArgumentDescriptor {
|
|
|
41
41
|
name?: string;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
/*
|
|
44
45
|
export enum DescriptorType {
|
|
45
46
|
Function, Token
|
|
46
47
|
}
|
|
48
|
+
*/
|
|
47
49
|
|
|
48
50
|
export interface FunctionDescriptor {
|
|
49
51
|
name: string;
|
|
50
52
|
description?: string;
|
|
51
53
|
arguments?: ArgumentDescriptor[];
|
|
52
|
-
|
|
54
|
+
|
|
55
|
+
/** switching to literals */
|
|
56
|
+
type?: 'function'|'token';
|
|
57
|
+
|
|
58
|
+
/** this is a named range or named expression. meaning a user/non-system name. */
|
|
59
|
+
named?: boolean;
|
|
60
|
+
|
|
61
|
+
/** scope refers to sheet IDs. names may be scoped. */
|
|
62
|
+
scope?: number;
|
|
53
63
|
}
|
|
54
64
|
|
|
55
65
|
export interface AutocompleteMatchData {
|
|
@@ -77,43 +87,61 @@ export interface TooltipParserResult {
|
|
|
77
87
|
export class AutocompleteMatcher {
|
|
78
88
|
|
|
79
89
|
private function_names: string[] = [];
|
|
80
|
-
|
|
81
|
-
//private function_map: {[index: string]: FunctionDescriptor} = {};
|
|
90
|
+
// private function_map: {[index: string]: FunctionDescriptor} = {};
|
|
82
91
|
|
|
83
92
|
private argument_separator = Localization.argument_separator.charCodeAt(0);
|
|
84
93
|
|
|
85
94
|
/**
|
|
86
95
|
* making this public (and scrubbing the type). we need it public so we
|
|
87
96
|
* can check collisions. I'm not sure why it was originally private...
|
|
97
|
+
*
|
|
98
|
+
* that's backwards. this should be private, and anyone checking
|
|
99
|
+
* collisions should ask. also updating to modern type.
|
|
100
|
+
*
|
|
101
|
+
* OK so now a map. all names should be lower-cased for consistency (they
|
|
102
|
+
* can maintain canonical names inside the object).
|
|
88
103
|
*/
|
|
89
|
-
|
|
104
|
+
private function_map: Map<string, FunctionDescriptor> = new Map();
|
|
90
105
|
|
|
91
106
|
public RemoveFunctions(functions: FunctionDescriptor|FunctionDescriptor[]): void {
|
|
92
107
|
if (!Array.isArray(functions)) { functions = [functions]; }
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
list = list.filter(test => test.name !== func.name);
|
|
108
|
+
for (const entry of functions) {
|
|
109
|
+
this.function_map.delete(entry.name.toLowerCase());
|
|
96
110
|
}
|
|
97
|
-
this.
|
|
111
|
+
this.UpdateNameList();
|
|
98
112
|
}
|
|
99
113
|
|
|
100
114
|
public AddFunctions(functions: FunctionDescriptor|FunctionDescriptor[]): void {
|
|
101
115
|
if (!Array.isArray(functions)) { functions = [functions]; }
|
|
102
|
-
const
|
|
103
|
-
|
|
116
|
+
for (const entry of functions) {
|
|
117
|
+
this.function_map.set(entry.name.toLowerCase(), entry);
|
|
118
|
+
}
|
|
119
|
+
this.UpdateNameList();
|
|
104
120
|
}
|
|
105
121
|
|
|
106
122
|
public SetFunctions(functions: FunctionDescriptor[]): void {
|
|
107
|
-
this.function_map
|
|
108
|
-
|
|
109
|
-
this.function_map
|
|
110
|
-
|
|
111
|
-
|
|
123
|
+
this.function_map.clear();
|
|
124
|
+
for (const entry of functions) {
|
|
125
|
+
this.function_map.set(entry.name.toLowerCase(), entry);
|
|
126
|
+
}
|
|
127
|
+
this.UpdateNameList();
|
|
112
128
|
}
|
|
113
129
|
|
|
130
|
+
/**
|
|
131
|
+
* returns the canonical version of the name, if it exists.
|
|
132
|
+
* @param name
|
|
133
|
+
* @returns
|
|
134
|
+
*/
|
|
114
135
|
public NormalizeIdentifier(name: string): string|undefined {
|
|
115
|
-
|
|
116
|
-
|
|
136
|
+
return this.function_map.get(name.toLowerCase())?.name;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* accessor for entries. we're not stopping you from modifying
|
|
141
|
+
* in place, for now, but don't do that.
|
|
142
|
+
*/
|
|
143
|
+
public Get(name: string): FunctionDescriptor|undefined {
|
|
144
|
+
return this.function_map.get(name.toLowerCase());
|
|
117
145
|
}
|
|
118
146
|
|
|
119
147
|
public Exec(data: AutocompleteMatchData): AutocompleteExecResult {
|
|
@@ -139,7 +167,9 @@ export class AutocompleteMatcher {
|
|
|
139
167
|
if (match) {
|
|
140
168
|
const token = match[1];
|
|
141
169
|
const rex = new RegExp('^' + token.replace('.', '\\.'), 'i');
|
|
142
|
-
const list = this.function_names.filter((name) =>
|
|
170
|
+
const list = this.function_names.filter((name) =>
|
|
171
|
+
rex.test(name)).map((name) =>
|
|
172
|
+
this.function_map.get(name.toLowerCase())).filter((test): test is FunctionDescriptor => !!test);
|
|
143
173
|
|
|
144
174
|
result = {
|
|
145
175
|
completions: list,
|
|
@@ -154,7 +184,7 @@ export class AutocompleteMatcher {
|
|
|
154
184
|
const parsed = this.ParseTooltip(data.text.substr(0, data.cursor));
|
|
155
185
|
|
|
156
186
|
if (parsed.function) {
|
|
157
|
-
const func = this.function_map
|
|
187
|
+
const func = this.function_map.get(parsed.function.toLowerCase());
|
|
158
188
|
if (func) {
|
|
159
189
|
// if (func.canonical_name) result.tooltip = func.canonical_name;
|
|
160
190
|
// else result.tooltip = tt.toUpperCase();
|
|
@@ -257,4 +287,12 @@ export class AutocompleteMatcher {
|
|
|
257
287
|
|
|
258
288
|
}
|
|
259
289
|
|
|
290
|
+
/**
|
|
291
|
+
* we maintain a sorted list of names. this needs to get updated
|
|
292
|
+
* when the list changes.
|
|
293
|
+
*/
|
|
294
|
+
private UpdateNameList() {
|
|
295
|
+
this.function_names = [...this.function_map.keys()].sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
296
|
+
}
|
|
297
|
+
|
|
260
298
|
}
|
|
@@ -40,13 +40,13 @@
|
|
|
40
40
|
*
|
|
41
41
|
*/
|
|
42
42
|
|
|
43
|
-
import { Area, type
|
|
43
|
+
import { Area, type ICellAddress, IsCellAddress, Localization, Rectangle, type Cell, DOMContext } from 'treb-base-types';
|
|
44
44
|
import type { ExpressionUnit, ParseResult, UnitAddress, UnitRange } from 'treb-parser';
|
|
45
|
-
import { Parser
|
|
46
|
-
import type { DataModel, ViewModel } from '
|
|
45
|
+
import { Parser } from 'treb-parser';
|
|
46
|
+
import type { DataModel, ViewModel } from 'treb-data-model';
|
|
47
47
|
import type { Autocomplete, AutocompleteResult } from './autocomplete';
|
|
48
48
|
import { EventSource } from 'treb-utils';
|
|
49
|
-
import { type AutocompleteExecResult, AutocompleteMatcher,
|
|
49
|
+
import { type AutocompleteExecResult, AutocompleteMatcher, type FunctionDescriptor } from './autocomplete_matcher';
|
|
50
50
|
|
|
51
51
|
export interface UpdateTextOptions {
|
|
52
52
|
rewrite_addresses: boolean;
|
|
@@ -56,7 +56,7 @@ export interface UpdateTextOptions {
|
|
|
56
56
|
toll_events: boolean;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
type GenericEventListener = (event: Event) =>
|
|
59
|
+
type GenericEventListener = (event: Event) => unknown;
|
|
60
60
|
|
|
61
61
|
// ----------------
|
|
62
62
|
|
|
@@ -313,7 +313,7 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
|
|
|
313
313
|
*
|
|
314
314
|
* listeners moved to node descriptors so we can have multiple sets.
|
|
315
315
|
*/
|
|
316
|
-
protected RegisterListener<K extends keyof HTMLElementEventMap>(descriptor: NodeDescriptor, key: K, handler: (event: HTMLElementEventMap[K]) =>
|
|
316
|
+
protected RegisterListener<K extends keyof HTMLElementEventMap>(descriptor: NodeDescriptor, key: K, handler: (event: HTMLElementEventMap[K]) => unknown) {
|
|
317
317
|
descriptor.node.addEventListener(key, handler);
|
|
318
318
|
if (!descriptor.listeners) {
|
|
319
319
|
descriptor.listeners = new Map();
|
|
@@ -369,12 +369,12 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
|
|
|
369
369
|
}
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
-
}
|
|
372
|
+
}
|
|
373
373
|
|
|
374
374
|
/**
|
|
375
|
-
*
|
|
375
|
+
*
|
|
376
376
|
*/
|
|
377
|
-
public InsertReference(reference: string
|
|
377
|
+
public InsertReference(reference: string) {
|
|
378
378
|
|
|
379
379
|
if (!this.active_editor) {
|
|
380
380
|
return;
|
|
@@ -392,7 +392,7 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
|
|
|
392
392
|
return '';
|
|
393
393
|
}
|
|
394
394
|
|
|
395
|
-
|
|
395
|
+
const range = selection.getRangeAt(0);
|
|
396
396
|
const text = this.active_editor.node.textContent || '';
|
|
397
397
|
|
|
398
398
|
// so what we are doing here depends on where the caret is.
|
|
@@ -472,9 +472,9 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
|
|
|
472
472
|
const substring = this.SubstringToCaret2(this.active_editor.node)[1];
|
|
473
473
|
|
|
474
474
|
let leader = '';
|
|
475
|
-
let trailer = '';
|
|
475
|
+
// let trailer = '';
|
|
476
476
|
|
|
477
|
-
|
|
477
|
+
const trimmed = substring.trim();
|
|
478
478
|
if (trimmed.length) {
|
|
479
479
|
const char = trimmed[trimmed.length - 1];
|
|
480
480
|
if (!Editor.FormulaChars.includes(char)) {
|
|
@@ -675,12 +675,12 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
|
|
|
675
675
|
|
|
676
676
|
case 'identifier':
|
|
677
677
|
{
|
|
678
|
-
const named_range = this.model.
|
|
679
|
-
if (named_range) {
|
|
680
|
-
if (named_range.count === 1) {
|
|
678
|
+
const named_range = this.model.GetName(unit.name, this.view.active_sheet.id); // FIXME: scoped?
|
|
679
|
+
if (named_range?.type === 'range') {
|
|
680
|
+
if (named_range.area.count === 1) {
|
|
681
681
|
reference_list.push({
|
|
682
682
|
type: 'address',
|
|
683
|
-
...named_range.start,
|
|
683
|
+
...named_range.area.start,
|
|
684
684
|
label: unit.name,
|
|
685
685
|
position: unit.position,
|
|
686
686
|
id: unit.id,
|
|
@@ -694,14 +694,14 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
|
|
|
694
694
|
position: unit.position,
|
|
695
695
|
id: unit.id,
|
|
696
696
|
label: unit.name,
|
|
697
|
-
...named_range.start,
|
|
697
|
+
...named_range.area.start,
|
|
698
698
|
},
|
|
699
699
|
end: {
|
|
700
700
|
type: 'address',
|
|
701
701
|
position: unit.position,
|
|
702
702
|
label: unit.name,
|
|
703
703
|
id: unit.id,
|
|
704
|
-
...named_range.end,
|
|
704
|
+
...named_range.area.end,
|
|
705
705
|
},
|
|
706
706
|
label: unit.name,
|
|
707
707
|
position: unit.position,
|
|
@@ -730,7 +730,7 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
|
|
|
730
730
|
|
|
731
731
|
for (const entry of reference_list) {
|
|
732
732
|
|
|
733
|
-
const label = this.model.AddressToLabel(entry, this.view.active_sheet);
|
|
733
|
+
const label = this.model.AddressToLabel(entry); // , this.view.active_sheet);
|
|
734
734
|
const area = IsCellAddress(entry) ?
|
|
735
735
|
new Area(entry) :
|
|
736
736
|
new Area(entry.start, entry.end);
|
|
@@ -834,7 +834,7 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
|
|
|
834
834
|
|
|
835
835
|
// console.info({text, substr, substr2});
|
|
836
836
|
|
|
837
|
-
|
|
837
|
+
const caret_start = substring_start.length;
|
|
838
838
|
let caret_end = substring_end.length;
|
|
839
839
|
|
|
840
840
|
// this is a little hacky
|
|
@@ -1053,11 +1053,13 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
|
|
|
1053
1053
|
|
|
1054
1054
|
if (!this.active_editor) return;
|
|
1055
1055
|
|
|
1056
|
-
let type = DescriptorType.Function;
|
|
1056
|
+
// let type = DescriptorType.Function;
|
|
1057
|
+
let type: FunctionDescriptor['type'];
|
|
1058
|
+
|
|
1057
1059
|
if (ac_result.data && ac_result.data.completions) {
|
|
1058
1060
|
for (const completion of ac_result.data.completions) {
|
|
1059
1061
|
if (completion.name.toLowerCase() === ac_result.value?.toLowerCase()) {
|
|
1060
|
-
type = completion.type || DescriptorType.Function;
|
|
1062
|
+
type = completion.type ; // || DescriptorType.Function;
|
|
1061
1063
|
break;
|
|
1062
1064
|
}
|
|
1063
1065
|
}
|
|
@@ -1073,11 +1075,11 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
|
|
|
1073
1075
|
const start = ac_result.data?.position || 0;
|
|
1074
1076
|
const end = start + (ac_result.data?.token?.length || 0);
|
|
1075
1077
|
|
|
1076
|
-
const insertion = (type ===
|
|
1078
|
+
const insertion = (type === 'token') ? ac_result.value : ac_result.value + '(';
|
|
1077
1079
|
|
|
1078
1080
|
const text = this.active_editor.node.textContent || '';
|
|
1079
1081
|
let adjusted = text.substring(0, start) + insertion;
|
|
1080
|
-
|
|
1082
|
+
const caret = adjusted.length;
|
|
1081
1083
|
adjusted += text.substring(end);
|
|
1082
1084
|
|
|
1083
1085
|
this.active_editor.node.textContent = adjusted;
|
|
@@ -1137,7 +1139,7 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
|
|
|
1137
1139
|
// how about string concat instead of array join, it's faster in
|
|
1138
1140
|
// chrome (!)
|
|
1139
1141
|
|
|
1140
|
-
|
|
1142
|
+
const complete = [ false, false ];
|
|
1141
1143
|
|
|
1142
1144
|
const Consume = (element: Node, range: Range) => {
|
|
1143
1145
|
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
*
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import type { Area, Cell, Theme } from 'treb-base-types';
|
|
22
|
+
// import type { Area, Cell, Theme } from 'treb-base-types';
|
|
23
23
|
import { Editor, type NodeDescriptor, type FormulaEditorEvent } from './editor';
|
|
24
|
-
import { Parser } from 'treb-parser';
|
|
25
|
-
import type { DataModel, ViewModel } from '
|
|
24
|
+
// import { Parser } from 'treb-parser';
|
|
25
|
+
import type { DataModel, ViewModel } from 'treb-data-model';
|
|
26
26
|
import type { GridOptions } from '../types/grid_options';
|
|
27
27
|
import { Autocomplete } from './autocomplete';
|
|
28
28
|
import { DOMContext } from 'treb-base-types';
|
|
@@ -250,7 +250,7 @@ export class FormulaBar extends Editor<FormulaBar2Event|FormulaEditorEvent> {
|
|
|
250
250
|
|
|
251
251
|
});
|
|
252
252
|
|
|
253
|
-
this.RegisterListener(descriptor, 'focusout', (
|
|
253
|
+
this.RegisterListener(descriptor, 'focusout', () => {
|
|
254
254
|
|
|
255
255
|
if (this.selecting) {
|
|
256
256
|
console.info('focusout, but selecting...');
|
|
@@ -328,7 +328,7 @@ export class FormulaBar extends Editor<FormulaBar2Event|FormulaEditorEvent> {
|
|
|
328
328
|
// Q: do we do this in other places? we should consolidate
|
|
329
329
|
// A: I don't think we do just this, usually there's additional logic for % and such
|
|
330
330
|
|
|
331
|
-
this.address_label.addEventListener('focusin', (
|
|
331
|
+
this.address_label.addEventListener('focusin', () => {
|
|
332
332
|
|
|
333
333
|
const doc = this.address_label.ownerDocument;
|
|
334
334
|
|
|
@@ -21,10 +21,9 @@
|
|
|
21
21
|
|
|
22
22
|
import { Editor, type NodeDescriptor } from './editor';
|
|
23
23
|
import { Area, Cell, type CellStyle, type CellValue, Rectangle, Style, type Theme, ThemeColor2 } from 'treb-base-types';
|
|
24
|
-
import { DataModel, type ViewModel } from '
|
|
24
|
+
import { DataModel, type ViewModel, type GridSelection } from 'treb-data-model';
|
|
25
25
|
import { Autocomplete } from './autocomplete';
|
|
26
26
|
import { UA } from '../util/ua';
|
|
27
|
-
import type { GridSelection } from '../types/grid_selection';
|
|
28
27
|
|
|
29
28
|
export type OverlayEditorResult = 'handled' | 'commit' | 'discard';
|
|
30
29
|
|
package/treb-grid/src/index.ts
CHANGED
|
@@ -21,23 +21,12 @@
|
|
|
21
21
|
|
|
22
22
|
export { Grid } from './types/grid';
|
|
23
23
|
export { GridBase } from './types/grid_base';
|
|
24
|
-
export { Sheet } from './types/sheet';
|
|
25
|
-
export { DataModel, type MacroFunction, type ConnectedElementType } from './types/data_model';
|
|
26
|
-
export type { SerializedNamedExpression, SerializedModel } from './types/data_model';
|
|
27
24
|
export * from './types/grid_events';
|
|
28
|
-
export type { SerializedSheet, FreezePane } from './types/sheet_types';
|
|
29
|
-
export { Annotation } from './types/annotation';
|
|
30
|
-
export type { ViewData as AnnotationViewData } from './types/annotation';
|
|
31
25
|
export type { GridOptions } from './types/grid_options';
|
|
32
26
|
export { CommandKey } from './types/grid_command';
|
|
33
27
|
export type { Command } from './types/grid_command';
|
|
34
|
-
export { NamedRangeCollection } from './types/named_range';
|
|
35
|
-
export type { GridSelection } from './types/grid_selection';
|
|
36
28
|
export { BorderConstants } from './types/border_constants';
|
|
37
|
-
export type { SerializeOptions } from './types/serialize_options';
|
|
38
29
|
export type { FunctionDescriptor, ArgumentDescriptor } from './editors/autocomplete_matcher';
|
|
39
30
|
export { UA } from './util/ua';
|
|
40
31
|
export type { SetRangeOptions } from './types/set_range_options';
|
|
41
|
-
export type { AnnotationData, AnnotationType } from './types/annotation';
|
|
42
32
|
export type { ExternalEditorConfig, DependencyList, ExternalEditorCallback } from './types/external_editor_config';
|
|
43
|
-
export * from './types/conditional_format';
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import { DOMContext } from 'treb-base-types';
|
|
23
|
-
import type { DataModel, ViewModel } from '
|
|
23
|
+
import type { DataModel, ViewModel, Annotation } from 'treb-data-model';
|
|
24
24
|
|
|
25
25
|
import type { Tile } from '../types/tile';
|
|
26
26
|
import type { Theme, Point, Extent, Size, Position, ICellAddress, Table, IArea } from 'treb-base-types';
|
|
@@ -42,7 +42,6 @@ import type { GridEvent } from '../types/grid_events';
|
|
|
42
42
|
|
|
43
43
|
import type { CellValue, AnnotationLayout, Corner } from 'treb-base-types';
|
|
44
44
|
import { Area as TileRange } from 'treb-base-types';
|
|
45
|
-
import type { Annotation } from '../types/annotation';
|
|
46
45
|
|
|
47
46
|
export { Area as TileRange } from 'treb-base-types';
|
|
48
47
|
|
|
@@ -282,7 +281,9 @@ export abstract class BaseLayout {
|
|
|
282
281
|
this.dropdown_caret.setAttribute('class', 'treb-dropdown-caret');
|
|
283
282
|
if (event.key === 'Enter' && this.dropdown_callback) {
|
|
284
283
|
if (this.dropdown_selected) {
|
|
285
|
-
|
|
284
|
+
const value = this.dropdown_selected.dataset.dropdown_value;
|
|
285
|
+
// this.dropdown_callback.call(0, (this.dropdown_selected as any).dropdown_value);
|
|
286
|
+
this.dropdown_callback.call(0, value ? JSON.parse(value) : undefined);
|
|
286
287
|
}
|
|
287
288
|
}
|
|
288
289
|
}
|
|
@@ -333,7 +334,11 @@ export abstract class BaseLayout {
|
|
|
333
334
|
this.dropdown_caret.setAttribute('class', 'treb-dropdown-caret');
|
|
334
335
|
|
|
335
336
|
if (this.dropdown_callback) {
|
|
336
|
-
this.dropdown_callback.call(0, (target as any).dropdown_value);
|
|
337
|
+
// this.dropdown_callback.call(0, (target as any).dropdown_value);
|
|
338
|
+
|
|
339
|
+
const value = target.dataset.dropdown_value;
|
|
340
|
+
this.dropdown_callback.call(0, value ? JSON.parse(value) : undefined);
|
|
341
|
+
|
|
337
342
|
}
|
|
338
343
|
});
|
|
339
344
|
|
|
@@ -608,7 +613,7 @@ export abstract class BaseLayout {
|
|
|
608
613
|
*
|
|
609
614
|
*/
|
|
610
615
|
public PointToAnnotationCorner(point: Point): Corner {
|
|
611
|
-
const address = this.PointToAddress_Grid(point,
|
|
616
|
+
const address = this.PointToAddress_Grid(point, false);
|
|
612
617
|
const cell_rect = this.CellAddressToRectangle(address);
|
|
613
618
|
|
|
614
619
|
return {
|
|
@@ -1417,7 +1422,14 @@ export abstract class BaseLayout {
|
|
|
1417
1422
|
this.dropdown_selected = entry;
|
|
1418
1423
|
entry.classList.add('selected');
|
|
1419
1424
|
}
|
|
1420
|
-
|
|
1425
|
+
|
|
1426
|
+
// we're attaching random data to DOM nodes here. that works, but
|
|
1427
|
+
// it's sloppy. I think the reason is we want to preserve type, and
|
|
1428
|
+
// this is simpler than any other solution.
|
|
1429
|
+
|
|
1430
|
+
// (entry as any).dropdown_value = value;
|
|
1431
|
+
entry.dataset.dropdown_value = JSON.stringify(value);
|
|
1432
|
+
|
|
1421
1433
|
entry.textContent = value?.toString() || '';
|
|
1422
1434
|
}
|
|
1423
1435
|
|
|
@@ -1519,7 +1531,7 @@ export abstract class BaseLayout {
|
|
|
1519
1531
|
// in two scroll events. however in practice this is called on key events,
|
|
1520
1532
|
// so it's unlikely.
|
|
1521
1533
|
|
|
1522
|
-
|
|
1534
|
+
const options: ScrollToOptions = {
|
|
1523
1535
|
behavior: smooth ? 'smooth' : 'auto',
|
|
1524
1536
|
};
|
|
1525
1537
|
|
|
@@ -1662,7 +1674,7 @@ export abstract class BaseLayout {
|
|
|
1662
1674
|
*
|
|
1663
1675
|
* FIXME: implement cap_maximum parameter (not sure where we would need it)
|
|
1664
1676
|
*/
|
|
1665
|
-
public PointToAddress_Grid(point: Point,
|
|
1677
|
+
public PointToAddress_Grid(point: Point, offset_freeze = true): ICellAddress {
|
|
1666
1678
|
|
|
1667
1679
|
// offset for freeze pane
|
|
1668
1680
|
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
import { BaseLayout } from './base_layout';
|
|
23
23
|
import type { Tile } from '../types/tile';
|
|
24
24
|
import { DOMContext } from 'treb-base-types';
|
|
25
|
-
import type { DataModel, ViewModel } from '
|
|
25
|
+
import type { DataModel, ViewModel } from 'treb-data-model';
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
/**
|
|
@@ -151,7 +151,7 @@ export class GridLayout extends BaseLayout {
|
|
|
151
151
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
protected UpdateGridTemplates(
|
|
154
|
+
protected UpdateGridTemplates(): void {
|
|
155
155
|
|
|
156
156
|
let width = 0;
|
|
157
157
|
let height = 0;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import type { DataModel, ViewModel } from '
|
|
3
|
-
import type { Tile } from '../types/tile';
|
|
2
|
+
import type { DataModel, ViewModel } from 'treb-data-model';
|
|
4
3
|
import { BaseLayout } from './base_layout';
|
|
5
4
|
|
|
6
5
|
export class MockLayout extends BaseLayout {
|
|
@@ -9,15 +8,15 @@ export class MockLayout extends BaseLayout {
|
|
|
9
8
|
super(model, view, true);
|
|
10
9
|
}
|
|
11
10
|
|
|
12
|
-
public InitializeInternal(
|
|
11
|
+
public InitializeInternal(): void {
|
|
13
12
|
|
|
14
13
|
}
|
|
15
14
|
|
|
16
|
-
protected UpdateGridTemplates(
|
|
15
|
+
protected UpdateGridTemplates(): void {
|
|
17
16
|
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
protected UpdateTileGridPosition(
|
|
19
|
+
protected UpdateTileGridPosition(): void {
|
|
21
20
|
|
|
22
21
|
}
|
|
23
22
|
|
|
@@ -25,7 +24,7 @@ export class MockLayout extends BaseLayout {
|
|
|
25
24
|
|
|
26
25
|
}
|
|
27
26
|
|
|
28
|
-
public ResizeCursor(
|
|
27
|
+
public ResizeCursor(): void {
|
|
29
28
|
|
|
30
29
|
}
|
|
31
30
|
|
|
@@ -20,13 +20,12 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import type { Theme, ICellAddress } from 'treb-base-types';
|
|
23
|
-
import {
|
|
23
|
+
import { Rectangle } from 'treb-base-types';
|
|
24
24
|
import type { BaseLayout } from '../layout/base_layout';
|
|
25
25
|
import type { SelectionOffset } from './svg_selection_block';
|
|
26
26
|
import { SVGSelectionBlock } from './svg_selection_block';
|
|
27
|
-
import type { GridSelection } from '../types/grid_selection';
|
|
28
27
|
import { HeaderOverlay, Orientation } from './svg_header_overlay';
|
|
29
|
-
import type { DataModel, ViewModel } from '
|
|
28
|
+
import type { GridSelection, DataModel, ViewModel } from 'treb-data-model';
|
|
30
29
|
|
|
31
30
|
// const SVGNS = 'http://www.w3.org/2000/svg';
|
|
32
31
|
|
|
@@ -32,7 +32,7 @@ import { FontMetricsCache as FontMetricsCache2 } from '../util/fontmetrics2';
|
|
|
32
32
|
import type { FormattedString} from 'treb-parser';
|
|
33
33
|
import { MDParser } from 'treb-parser';
|
|
34
34
|
import type { BaseLayout, TileRange } from '../layout/base_layout';
|
|
35
|
-
import type { DataModel, ViewModel } from '
|
|
35
|
+
import type { DataModel, ViewModel } from 'treb-data-model';
|
|
36
36
|
import type { GridOptions } from '../types/grid_options';
|
|
37
37
|
|
|
38
38
|
const DEFAULT_INDENT = ' '; // two spaces in the current font
|