@trebco/treb 27.9.0 → 27.11.4
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.mjs +9 -9
- package/dist/treb.d.ts +8 -6
- package/package.json +1 -1
- package/{treb-grid/src/util/dom_utilities.ts → treb-base-types/src/dom-utilities.ts} +29 -20
- package/treb-base-types/src/index.ts +1 -0
- package/treb-base-types/src/theme.ts +3 -5
- package/treb-embed/src/custom-element/global.d.ts +3 -1
- package/treb-embed/src/custom-element/spreadsheet-constructor.ts +13 -19
- package/treb-embed/src/embedded-spreadsheet.ts +67 -93
- package/treb-embed/src/spinner.ts +3 -3
- package/treb-embed/style/layout.scss +1 -1
- package/treb-embed/style/overlay-editor.scss +9 -0
- package/treb-export/src/drawing2/chart2.ts +11 -2
- package/treb-export/src/export2.ts +14 -4
- package/treb-export/src/workbook-style2.ts +3 -2
- package/treb-grid/src/editors/autocomplete.ts +28 -24
- package/treb-grid/src/editors/editor.ts +32 -4
- package/treb-grid/src/editors/formula_bar.ts +1 -1
- package/treb-grid/src/layout/base_layout.ts +11 -16
- package/treb-grid/src/layout/grid_layout.ts +17 -28
- package/treb-grid/src/render/selection-renderer.ts +2 -3
- package/treb-grid/src/render/svg_header_overlay.ts +4 -11
- package/treb-grid/src/render/svg_selection_block.ts +27 -34
- package/treb-grid/src/render/tile_renderer.ts +6 -5
- package/treb-grid/src/types/grid.ts +32 -41
- package/treb-grid/src/types/grid_base.ts +2 -0
- package/treb-grid/src/types/scale-control.ts +2 -2
- package/treb-grid/src/types/sheet.ts +2 -2
- package/treb-grid/src/types/tab_bar.ts +4 -8
- package/treb-utils/src/index.ts +0 -1
- package/treb-utils/src/resizable.ts +26 -27
- package/treb-utils/src/template.ts +0 -70
|
@@ -1,25 +1,25 @@
|
|
|
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
|
-
import { DOMUtilities } from '
|
|
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
|
+
import { DOMUtilities } from 'treb-base-types';
|
|
23
23
|
import type { Theme, Rectangle } from 'treb-base-types';
|
|
24
24
|
import type { AutocompleteExecResult, DescriptorType } from './autocomplete_matcher';
|
|
25
25
|
|
|
@@ -76,7 +76,7 @@ export class Autocomplete {
|
|
|
76
76
|
|
|
77
77
|
// this.scope = 'AC' + Math.round(Math.random() * Math.pow(10, 10)).toString(16);
|
|
78
78
|
|
|
79
|
-
this.completion_list = DOMUtilities.
|
|
79
|
+
this.completion_list = DOMUtilities.Div(
|
|
80
80
|
'treb-cell-editor-ac-list treb-autocomplete',
|
|
81
81
|
options.container || document.body,
|
|
82
82
|
); // this.scope);
|
|
@@ -87,7 +87,7 @@ export class Autocomplete {
|
|
|
87
87
|
|
|
88
88
|
this.completion_list.addEventListener('mousemove', (event) => this.ListMouseMove(event));
|
|
89
89
|
|
|
90
|
-
this.tooltip = DOMUtilities.
|
|
90
|
+
this.tooltip = DOMUtilities.Div('treb-cell-editor-ac-tooltip treb-autocomplete-tooltip',
|
|
91
91
|
options.container || document.body,
|
|
92
92
|
); // this.scope);
|
|
93
93
|
|
|
@@ -173,6 +173,10 @@ export class Autocomplete {
|
|
|
173
173
|
this.active_element = undefined;
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
+
public SetBlock(): void {
|
|
177
|
+
this.block = true;
|
|
178
|
+
}
|
|
179
|
+
|
|
176
180
|
public ResetBlock(): void {
|
|
177
181
|
this.block = false;
|
|
178
182
|
}
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
*
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
|
-
import { Area, type IArea, type ICellAddress, IsCellAddress, Localization, type Theme, Rectangle, type Cell } from 'treb-base-types';
|
|
37
|
+
import { Area, type IArea, type ICellAddress, IsCellAddress, Localization, type Theme, Rectangle, type Cell, DOMUtilities } from 'treb-base-types';
|
|
38
38
|
import type { ExpressionUnit, ParseResult, UnitAddress, UnitRange } from 'treb-parser';
|
|
39
39
|
import { Parser, QuotedSheetNameRegex } from 'treb-parser';
|
|
40
40
|
import type { DataModel, ViewModel } from '../types/data_model';
|
|
@@ -291,7 +291,6 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
|
|
|
291
291
|
super();
|
|
292
292
|
|
|
293
293
|
this.parser = model.parser;
|
|
294
|
-
// this.measurement_node = document.createElement('div');
|
|
295
294
|
|
|
296
295
|
}
|
|
297
296
|
|
|
@@ -866,13 +865,13 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
|
|
|
866
865
|
|
|
867
866
|
if (type !== 'text') {
|
|
868
867
|
|
|
869
|
-
const span =
|
|
868
|
+
const span = DOMUtilities.Create('span', type);
|
|
870
869
|
|
|
871
870
|
if (reference) {
|
|
872
871
|
span.dataset.reference = reference;
|
|
873
872
|
}
|
|
874
873
|
|
|
875
|
-
span.className = type;
|
|
874
|
+
// span.className = type;
|
|
876
875
|
span.appendChild(text_node);
|
|
877
876
|
fragment.appendChild(span);
|
|
878
877
|
|
|
@@ -1114,6 +1113,35 @@ export class Editor<E = FormulaEditorEvent> extends EventSource<E|FormulaEditorE
|
|
|
1114
1113
|
|
|
1115
1114
|
const Consume = (element: Node, range: Range) => {
|
|
1116
1115
|
|
|
1116
|
+
// it only seems to happen in firefox, but sometimes we'll get
|
|
1117
|
+
// a non-text node that is the start container and endcontainer.
|
|
1118
|
+
//
|
|
1119
|
+
// in that case we need to interpret the endOffset as nodes, not
|
|
1120
|
+
// characters. that's what's causing the firefox issues. I guess
|
|
1121
|
+
// that applies to startoffset as well?
|
|
1122
|
+
|
|
1123
|
+
// not sure if this is bugged or what but when we hit this case,
|
|
1124
|
+
// it's always "all the text in there" regardless of the offsets.
|
|
1125
|
+
// not sure what the offsets are even referring to, since we get
|
|
1126
|
+
// offsets > the number of child nodes. is this a bug in firefox?
|
|
1127
|
+
|
|
1128
|
+
if (element === range.startContainer && element === range.endContainer && !(element instanceof Text)) {
|
|
1129
|
+
|
|
1130
|
+
/*
|
|
1131
|
+
if (range.startOffset !== 0 || range.endOffset !== 0) {
|
|
1132
|
+
console.info("warn offset", range.startOffset, range.endOffset);
|
|
1133
|
+
console.info(element);
|
|
1134
|
+
}
|
|
1135
|
+
*/
|
|
1136
|
+
|
|
1137
|
+
complete[0] = complete[1] = true;
|
|
1138
|
+
|
|
1139
|
+
result[0] += element.textContent;
|
|
1140
|
+
result[1] += element.textContent;
|
|
1141
|
+
|
|
1142
|
+
return;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1117
1145
|
if (element === range.startContainer) {
|
|
1118
1146
|
result[0] += (element.textContent || '').substring(0, range.startOffset);
|
|
1119
1147
|
complete[0] = true;
|
|
@@ -25,7 +25,7 @@ import { Parser } from 'treb-parser';
|
|
|
25
25
|
import type { DataModel, ViewModel } from '../types/data_model';
|
|
26
26
|
import type { GridOptions } from '../types/grid_options';
|
|
27
27
|
import { Autocomplete } from './autocomplete';
|
|
28
|
-
import { DOMUtilities } from '
|
|
28
|
+
import { DOMUtilities } from 'treb-base-types';
|
|
29
29
|
|
|
30
30
|
// --- from formula_bar ---
|
|
31
31
|
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import { DOMUtilities } from '
|
|
22
|
+
import { DOMUtilities } from 'treb-base-types';
|
|
23
23
|
import type { DataModel, ViewModel } from '../types/data_model';
|
|
24
24
|
|
|
25
25
|
import type { Tile } from '../types/tile';
|
|
@@ -46,8 +46,6 @@ import type { Annotation } from '../types/annotation';
|
|
|
46
46
|
|
|
47
47
|
export { Area as TileRange } from 'treb-base-types';
|
|
48
48
|
|
|
49
|
-
const SVGNS = 'http://www.w3.org/2000/svg';
|
|
50
|
-
|
|
51
49
|
export interface TooltipOptions {
|
|
52
50
|
up?: true;
|
|
53
51
|
left?: true;
|
|
@@ -203,19 +201,16 @@ export abstract class BaseLayout {
|
|
|
203
201
|
// contexts; the mask will be under the next sheet. so either
|
|
204
202
|
// global in body, or instance local.
|
|
205
203
|
|
|
206
|
-
this.mask =
|
|
207
|
-
|
|
208
|
-
this.tooltip = // document.querySelector('.treb-tooltip'); // ||
|
|
209
|
-
DOMUtilities.CreateDiv('treb-tooltip');
|
|
204
|
+
this.mask = DOMUtilities.Div('treb-mouse-mask');
|
|
205
|
+
this.tooltip = DOMUtilities.Div('treb-tooltip');
|
|
210
206
|
|
|
211
207
|
// this.error_highlight = DOMUtilities.CreateDiv('treb-error-highlight');
|
|
212
208
|
|
|
213
|
-
this.dropdown_caret =
|
|
214
|
-
this.dropdown_caret.setAttribute('class', 'treb-dropdown-caret');
|
|
209
|
+
this.dropdown_caret = DOMUtilities.SVG('svg', 'treb-dropdown-caret');
|
|
215
210
|
this.dropdown_caret.setAttribute('viewBox', '0 0 24 24');
|
|
216
211
|
this.dropdown_caret.tabIndex = -1;
|
|
217
212
|
|
|
218
|
-
const caret =
|
|
213
|
+
const caret =DOMUtilities.SVG('path');
|
|
219
214
|
caret.setAttribute('d', 'M5,7 L12,17 L19,7');
|
|
220
215
|
this.dropdown_caret.appendChild(caret);
|
|
221
216
|
|
|
@@ -252,7 +247,7 @@ export abstract class BaseLayout {
|
|
|
252
247
|
});
|
|
253
248
|
*/
|
|
254
249
|
|
|
255
|
-
this.dropdown_list = DOMUtilities.
|
|
250
|
+
this.dropdown_list = DOMUtilities.Div('treb-dropdown-list');
|
|
256
251
|
this.dropdown_list.setAttribute('tabindex', '-1'); // focusable
|
|
257
252
|
|
|
258
253
|
// this.dropdown_caret.addEventListener('keydown', (event) => {
|
|
@@ -351,11 +346,11 @@ export abstract class BaseLayout {
|
|
|
351
346
|
this.dropdown_selected = target as HTMLElement;
|
|
352
347
|
});
|
|
353
348
|
|
|
354
|
-
this.mock_selection = DOMUtilities.
|
|
349
|
+
this.mock_selection = DOMUtilities.Div('mock-selection-node');
|
|
355
350
|
this.mock_selection.innerHTML = ' ';
|
|
356
351
|
|
|
357
|
-
this.note_node = DOMUtilities.
|
|
358
|
-
this.title_node = DOMUtilities.
|
|
352
|
+
this.note_node = DOMUtilities.Div('treb-note');
|
|
353
|
+
this.title_node = DOMUtilities.Div('treb-hover-title');
|
|
359
354
|
|
|
360
355
|
this.sort_button = DOMUtilities.Create(
|
|
361
356
|
'button',
|
|
@@ -1199,7 +1194,7 @@ export abstract class BaseLayout {
|
|
|
1199
1194
|
parent: HTMLElement,
|
|
1200
1195
|
mark_dirty = true): Tile {
|
|
1201
1196
|
|
|
1202
|
-
const tile =
|
|
1197
|
+
const tile = DOMUtilities.Create('canvas') as Tile;
|
|
1203
1198
|
tile.setAttribute('class', classes);
|
|
1204
1199
|
tile.logical_size = size;
|
|
1205
1200
|
tile.width = size.width * this.dpr;
|
|
@@ -1408,7 +1403,7 @@ export abstract class BaseLayout {
|
|
|
1408
1403
|
|
|
1409
1404
|
this.dropdown_list.textContent = '';
|
|
1410
1405
|
for (const value of list) {
|
|
1411
|
-
const entry = DOMUtilities.
|
|
1406
|
+
const entry = DOMUtilities.Div(undefined, this.dropdown_list);
|
|
1412
1407
|
if (current === value) {
|
|
1413
1408
|
this.dropdown_selected = entry;
|
|
1414
1409
|
entry.classList.add('selected');
|
|
@@ -21,10 +21,9 @@
|
|
|
21
21
|
|
|
22
22
|
import { BaseLayout } from './base_layout';
|
|
23
23
|
import type { Tile } from '../types/tile';
|
|
24
|
-
import { DOMUtilities } from '
|
|
24
|
+
import { DOMUtilities } from 'treb-base-types';
|
|
25
25
|
import type { DataModel, ViewModel } from '../types/data_model';
|
|
26
26
|
|
|
27
|
-
const SVGNS = 'http://www.w3.org/2000/svg';
|
|
28
27
|
|
|
29
28
|
/**
|
|
30
29
|
* we used to have two layouts, this one and a legacy layout for IE11.
|
|
@@ -42,47 +41,37 @@ export class GridLayout extends BaseLayout {
|
|
|
42
41
|
// mask needs to get attached to a container, when it's
|
|
43
42
|
// available
|
|
44
43
|
|
|
45
|
-
this.column_header = DOMUtilities.
|
|
46
|
-
this.row_header = DOMUtilities.
|
|
44
|
+
this.column_header = DOMUtilities.Div('treb-top-header');
|
|
45
|
+
this.row_header = DOMUtilities.Div('treb-left-header');
|
|
47
46
|
|
|
48
|
-
this.corner = DOMUtilities.
|
|
49
|
-
this.corner_canvas =
|
|
47
|
+
this.corner = DOMUtilities.Div('treb-corner');
|
|
48
|
+
this.corner_canvas = DOMUtilities.Create('canvas');
|
|
50
49
|
this.corner.appendChild(this.corner_canvas);
|
|
51
50
|
|
|
52
|
-
this.contents = DOMUtilities.
|
|
51
|
+
this.contents = DOMUtilities.Div('treb-contents');
|
|
53
52
|
this.buffer_canvas = DOMUtilities.Create('canvas', 'treb-buffer-canvas', this.contents);
|
|
54
53
|
|
|
55
54
|
// selection node attached to contents
|
|
56
|
-
this.grid_selection =
|
|
57
|
-
this.grid_selection.classList.add('treb-grid-selection');
|
|
58
|
-
this.contents.appendChild(this.grid_selection);
|
|
55
|
+
this.grid_selection = DOMUtilities.SVG('svg', 'treb-grid-selection', this.contents);
|
|
59
56
|
|
|
60
57
|
// selection node for frozen rows
|
|
61
|
-
this.row_header_selection =
|
|
62
|
-
this.
|
|
63
|
-
this.row_header_selection.classList.add('frozen-selection-rows');
|
|
64
|
-
this.column_header.appendChild(this.row_header_selection);
|
|
65
|
-
this.row_header_annotations = DOMUtilities.CreateDiv('frozen-annotation-container frozen-annotation-container-rows', this.column_header);
|
|
58
|
+
this.row_header_selection = DOMUtilities.SVG('svg', ['frozen-selection', 'frozen-selection-rows'], this.column_header);
|
|
59
|
+
this.row_header_annotations = DOMUtilities.Div('frozen-annotation-container frozen-annotation-container-rows', this.column_header);
|
|
66
60
|
|
|
67
61
|
// ...columns
|
|
68
|
-
this.column_header_selection =
|
|
69
|
-
this.
|
|
70
|
-
this.column_header_selection.classList.add('frozen-selection-columns');
|
|
71
|
-
this.row_header.appendChild(this.column_header_selection);
|
|
72
|
-
this.column_header_annotations = DOMUtilities.CreateDiv('frozen-annotation-container frozen-annotation-container-columns', this.row_header);
|
|
62
|
+
this.column_header_selection = DOMUtilities.SVG('svg', ['frozen-selection', 'frozen-selection-columns'], this.row_header);
|
|
63
|
+
this.column_header_annotations = DOMUtilities.Div('frozen-annotation-container frozen-annotation-container-columns', this.row_header);
|
|
73
64
|
|
|
74
65
|
// ...corner
|
|
75
|
-
this.corner_selection =
|
|
76
|
-
this.
|
|
77
|
-
this.corner.appendChild(this.corner_selection);
|
|
78
|
-
this.corner_annotations = DOMUtilities.CreateDiv('frozen-annotation-container frozen-annotation-container-corner', this.corner);
|
|
66
|
+
this.corner_selection = DOMUtilities.SVG('svg', 'frozen-selection', this.corner);
|
|
67
|
+
this.corner_annotations = DOMUtilities.Div('frozen-annotation-container frozen-annotation-container-corner', this.corner);
|
|
79
68
|
|
|
80
69
|
|
|
81
|
-
this.annotation_container = DOMUtilities.
|
|
70
|
+
this.annotation_container = DOMUtilities.Div('treb-annotation-container');
|
|
82
71
|
|
|
83
|
-
this.grid_cover = DOMUtilities.
|
|
84
|
-
this.column_header_cover = DOMUtilities.
|
|
85
|
-
this.row_header_cover = DOMUtilities.
|
|
72
|
+
this.grid_cover = DOMUtilities.Div('tile-cover grid-cover');
|
|
73
|
+
this.column_header_cover = DOMUtilities.Div('tile-cover column-header-cover');
|
|
74
|
+
this.row_header_cover = DOMUtilities.Div('tile-cover row-header-cover');
|
|
86
75
|
|
|
87
76
|
}
|
|
88
77
|
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import type { Theme, ICellAddress } from 'treb-base-types';
|
|
23
|
-
import { Rectangle } from 'treb-base-types';
|
|
23
|
+
import { DOMUtilities, 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';
|
|
@@ -302,8 +302,7 @@ export class SelectionRenderer {
|
|
|
302
302
|
|
|
303
303
|
let group: SVGElement = node.querySelector('.alternate-selections') as SVGElement;
|
|
304
304
|
if (!group) {
|
|
305
|
-
group =
|
|
306
|
-
group.setAttribute('class', 'alternate-selections');
|
|
305
|
+
group = DOMUtilities.SVG('g', 'alternate-selections');
|
|
307
306
|
node.appendChild(group);
|
|
308
307
|
}
|
|
309
308
|
group?.appendChild(selection_block.g);
|
|
@@ -19,9 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import type
|
|
23
|
-
|
|
24
|
-
const SVGNS = 'http://www.w3.org/2000/svg';
|
|
22
|
+
import { DOMUtilities, type Theme } from 'treb-base-types';
|
|
25
23
|
|
|
26
24
|
export enum Orientation {
|
|
27
25
|
Horizontal,
|
|
@@ -39,14 +37,9 @@ export class HeaderOverlay {
|
|
|
39
37
|
private container: SVGElement,
|
|
40
38
|
private orientation: Orientation) {
|
|
41
39
|
|
|
42
|
-
this.g =
|
|
43
|
-
this.
|
|
44
|
-
|
|
45
|
-
this.overlay = document.createElementNS(SVGNS, 'rect');
|
|
46
|
-
this.overlay.setAttribute('class', 'treb-overlay');
|
|
47
|
-
|
|
48
|
-
this.highlight = document.createElementNS(SVGNS, 'rect');
|
|
49
|
-
this.highlight.setAttribute('class', 'treb-highlight');
|
|
40
|
+
this.g = DOMUtilities.SVG('g', 'treb-header-overlay');
|
|
41
|
+
this.overlay = DOMUtilities.SVG('rect', 'treb-overlay');
|
|
42
|
+
this.highlight = DOMUtilities.SVG('rect', 'treb-highlight');
|
|
50
43
|
|
|
51
44
|
this.g.style.display = 'none';
|
|
52
45
|
this.g.appendChild(this.highlight);
|
|
@@ -1,25 +1,25 @@
|
|
|
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
|
-
import type
|
|
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
|
+
import { type Theme, type Rectangle, DOMUtilities } from 'treb-base-types';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* the original selections -- a canvas overlaid over the tile canvases --
|
|
@@ -30,8 +30,6 @@ import type { Theme, Rectangle } from 'treb-base-types';
|
|
|
30
30
|
* attributes.
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
|
-
const SVGNS = 'http://www.w3.org/2000/svg';
|
|
34
|
-
|
|
35
33
|
export interface SelectionOffset {
|
|
36
34
|
x: number;
|
|
37
35
|
y: number;
|
|
@@ -48,11 +46,10 @@ export class SVGSelectionBlock {
|
|
|
48
46
|
private theme: Theme,
|
|
49
47
|
private offset: SelectionOffset = {x: 0, y: 0}) {
|
|
50
48
|
|
|
51
|
-
this.g =
|
|
49
|
+
this.g = DOMUtilities.SVG('g');
|
|
52
50
|
this.g.setAttribute('transform', `translate(${offset.x}, ${offset.y})`);
|
|
53
51
|
|
|
54
|
-
this.outline =
|
|
55
|
-
this.outline.setAttribute('class', 'outline');
|
|
52
|
+
this.outline = DOMUtilities.SVG('rect', 'outline');
|
|
56
53
|
|
|
57
54
|
if (primary) {
|
|
58
55
|
|
|
@@ -61,11 +58,8 @@ export class SVGSelectionBlock {
|
|
|
61
58
|
// primary selections have a separate fill, plus the nub. separate
|
|
62
59
|
// fill because the "target" is unfilled.
|
|
63
60
|
|
|
64
|
-
this.fill =
|
|
65
|
-
this.
|
|
66
|
-
|
|
67
|
-
this.nub = document.createElementNS(SVGNS, 'rect');
|
|
68
|
-
this.nub.setAttribute('class', 'nub');
|
|
61
|
+
this.fill = DOMUtilities.SVG('path', 'fill');
|
|
62
|
+
this.nub = DOMUtilities.SVG('rect', 'nub');
|
|
69
63
|
|
|
70
64
|
this.g.appendChild(this.fill);
|
|
71
65
|
this.g.appendChild(this.outline);
|
|
@@ -81,8 +75,7 @@ export class SVGSelectionBlock {
|
|
|
81
75
|
// and use currentColor, but we can't set opacity separately so we
|
|
82
76
|
// need another node. which is a waste, but ergonomics ftw!
|
|
83
77
|
|
|
84
|
-
this.fill =
|
|
85
|
-
this.fill.setAttribute('class', 'fill');
|
|
78
|
+
this.fill = DOMUtilities.SVG('rect', 'fill');
|
|
86
79
|
|
|
87
80
|
// this.SetThemeColor(0);
|
|
88
81
|
// if (theme.additional_selection_line_dash_array) {
|
|
@@ -99,10 +99,7 @@ export class TileRenderer {
|
|
|
99
99
|
protected view: ViewModel,
|
|
100
100
|
protected options: GridOptions, ) {
|
|
101
101
|
|
|
102
|
-
// this.buffer_canvas = document.createElement('canvas');
|
|
103
|
-
|
|
104
102
|
this.buffer_canvas = layout.buffer_canvas;
|
|
105
|
-
|
|
106
103
|
this.buffer_canvas.width = this.buffer_canvas_size.width;
|
|
107
104
|
this.buffer_canvas.height = this.buffer_canvas_size.height;
|
|
108
105
|
|
|
@@ -912,6 +909,8 @@ export class TileRenderer {
|
|
|
912
909
|
line_width = test;
|
|
913
910
|
words.shift();
|
|
914
911
|
|
|
912
|
+
max_width = Math.max(max_width, line_width);
|
|
913
|
+
|
|
915
914
|
}
|
|
916
915
|
|
|
917
916
|
// trim the last word, then insert a row (we're relying on the
|
|
@@ -920,6 +919,8 @@ export class TileRenderer {
|
|
|
920
919
|
last.text = last.text.trim();
|
|
921
920
|
last.width = last.trimmed;
|
|
922
921
|
|
|
922
|
+
max_width = Math.max(max_width, last.width);
|
|
923
|
+
|
|
923
924
|
strings.push(line2.map((metric) => {
|
|
924
925
|
return {
|
|
925
926
|
...metric.part,
|
|
@@ -928,11 +929,11 @@ export class TileRenderer {
|
|
|
928
929
|
text: metric.text,
|
|
929
930
|
};
|
|
930
931
|
}));
|
|
931
|
-
|
|
932
|
+
|
|
932
933
|
}
|
|
933
934
|
|
|
934
935
|
}
|
|
935
|
-
|
|
936
|
+
|
|
936
937
|
}
|
|
937
938
|
else {
|
|
938
939
|
|
|
@@ -111,7 +111,7 @@ import { CommandKey
|
|
|
111
111
|
|
|
112
112
|
import type { DataModel, SerializedModel } from './data_model';
|
|
113
113
|
|
|
114
|
-
import { DOMUtilities } from '
|
|
114
|
+
import { DOMUtilities } from 'treb-base-types';
|
|
115
115
|
import { GridBase } from './grid_base';
|
|
116
116
|
import type { SetRangeOptions } from './set_range_options';
|
|
117
117
|
import type { ClipboardCellData } from './clipboard_data';
|
|
@@ -262,6 +262,9 @@ export class Grid extends GridBase {
|
|
|
262
262
|
/** new key capture overlay/ICE */
|
|
263
263
|
private overlay_editor?: OverlayEditor;
|
|
264
264
|
|
|
265
|
+
/** moving autocomplete to a class field */
|
|
266
|
+
private autocomplete?: Autocomplete;
|
|
267
|
+
|
|
265
268
|
/** formula bar editor (optional) */
|
|
266
269
|
private formula_bar?: FormulaBar;
|
|
267
270
|
|
|
@@ -568,13 +571,13 @@ export class Grid extends GridBase {
|
|
|
568
571
|
|
|
569
572
|
// FIXME: why is this not in layout? it is layout.
|
|
570
573
|
|
|
571
|
-
view.node =
|
|
574
|
+
view.node = DOMUtilities.Div();
|
|
572
575
|
view.node.dataset.scale = this.layout.scale.toString();
|
|
573
576
|
view.node.style.fontSize = `${10 * this.layout.scale}pt`;
|
|
574
577
|
|
|
575
|
-
view.content_node = DOMUtilities.
|
|
576
|
-
const move_target = DOMUtilities.
|
|
577
|
-
const resize_target = DOMUtilities.
|
|
578
|
+
view.content_node = DOMUtilities.Div('annotation-content', view.node);
|
|
579
|
+
const move_target = DOMUtilities.Div('annotation-move-target', view.node);
|
|
580
|
+
const resize_target = DOMUtilities.Div('annotation-resize-target', view.node);
|
|
578
581
|
|
|
579
582
|
if (view.node) {
|
|
580
583
|
const node = view.node;
|
|
@@ -1275,13 +1278,13 @@ export class Grid extends GridBase {
|
|
|
1275
1278
|
const higher_level_container = view_node.querySelector('.treb-spreadsheet-body') as HTMLElement;
|
|
1276
1279
|
const container = higher_level_container.querySelector('div') as HTMLElement;
|
|
1277
1280
|
|
|
1278
|
-
let autocomplete: Autocomplete | undefined;
|
|
1281
|
+
// let autocomplete: Autocomplete | undefined;
|
|
1279
1282
|
|
|
1280
1283
|
if (this.options.formula_bar) {
|
|
1281
|
-
if (!autocomplete) {
|
|
1282
|
-
autocomplete = new Autocomplete({ theme: this.theme, container });
|
|
1284
|
+
if (!this.autocomplete) {
|
|
1285
|
+
this.autocomplete = new Autocomplete({ theme: this.theme, container });
|
|
1283
1286
|
}
|
|
1284
|
-
this.InitFormulaBar(view_node, autocomplete);
|
|
1287
|
+
this.InitFormulaBar(view_node, this.autocomplete);
|
|
1285
1288
|
}
|
|
1286
1289
|
|
|
1287
1290
|
if (this.options.tab_bar) {
|
|
@@ -1408,10 +1411,10 @@ export class Grid extends GridBase {
|
|
|
1408
1411
|
|
|
1409
1412
|
// Sheet.sheet_events.Subscribe(this.HandleSheetEvent.bind(this));
|
|
1410
1413
|
|
|
1411
|
-
if (!autocomplete) {
|
|
1412
|
-
autocomplete = new Autocomplete({ theme: this.theme, container });
|
|
1414
|
+
if (!this.autocomplete) {
|
|
1415
|
+
this.autocomplete = new Autocomplete({ theme: this.theme, container });
|
|
1413
1416
|
}
|
|
1414
|
-
this.InitOverlayEditor(autocomplete);
|
|
1417
|
+
this.InitOverlayEditor(this.autocomplete);
|
|
1415
1418
|
|
|
1416
1419
|
this.AttachListeners();
|
|
1417
1420
|
|
|
@@ -2695,35 +2698,6 @@ export class Grid extends GridBase {
|
|
|
2695
2698
|
|
|
2696
2699
|
this.OverlayKeyDown(event.event);
|
|
2697
2700
|
|
|
2698
|
-
/*
|
|
2699
|
-
let cloned_event: KeyboardEvent;
|
|
2700
|
-
if (UA.trident) {
|
|
2701
|
-
cloned_event = document.createEvent('KeyboardEvent');
|
|
2702
|
-
const modifiers = [];
|
|
2703
|
-
if (event.event.ctrlKey) modifiers.push('Control');
|
|
2704
|
-
if (event.event.altKey) modifiers.push('Alt');
|
|
2705
|
-
if (event.event.shiftKey) modifiers.push('Shift');
|
|
2706
|
-
|
|
2707
|
-
// have to mask type for trident
|
|
2708
|
-
(cloned_event as any).initKeyboardEvent(
|
|
2709
|
-
event.event.type,
|
|
2710
|
-
false,
|
|
2711
|
-
false,
|
|
2712
|
-
event.event.view,
|
|
2713
|
-
event.event.key,
|
|
2714
|
-
event.event.location,
|
|
2715
|
-
modifiers.join(' '),
|
|
2716
|
-
event.event.repeat,
|
|
2717
|
-
Localization.locale);
|
|
2718
|
-
}
|
|
2719
|
-
else {
|
|
2720
|
-
cloned_event = new KeyboardEvent(event.event.type, event.event);
|
|
2721
|
-
}
|
|
2722
|
-
|
|
2723
|
-
if (cloned_event && this.container) {
|
|
2724
|
-
this.container.dispatchEvent(cloned_event);
|
|
2725
|
-
}
|
|
2726
|
-
*/
|
|
2727
2701
|
}
|
|
2728
2702
|
break;
|
|
2729
2703
|
|
|
@@ -3763,6 +3737,17 @@ export class Grid extends GridBase {
|
|
|
3763
3737
|
|
|
3764
3738
|
const selecting_argument = this.SelectingArgument();
|
|
3765
3739
|
|
|
3740
|
+
/*
|
|
3741
|
+
let blocking_tooltip = false;
|
|
3742
|
+
if (selecting_argument) {
|
|
3743
|
+
if (this.autocomplete?.tooltip_visible) {
|
|
3744
|
+
this.autocomplete.SetBlock();
|
|
3745
|
+
this.autocomplete.Hide();
|
|
3746
|
+
blocking_tooltip = true;
|
|
3747
|
+
}
|
|
3748
|
+
}
|
|
3749
|
+
*/
|
|
3750
|
+
|
|
3766
3751
|
if (!selecting_argument && this.additional_selections.length) {
|
|
3767
3752
|
this.ClearAdditionalSelections();
|
|
3768
3753
|
}
|
|
@@ -4052,6 +4037,12 @@ export class Grid extends GridBase {
|
|
|
4052
4037
|
// console.info('end');
|
|
4053
4038
|
this.UpdateAddressLabel();
|
|
4054
4039
|
|
|
4040
|
+
/*
|
|
4041
|
+
if (blocking_tooltip) {
|
|
4042
|
+
this.autocomplete?.ResetBlock();
|
|
4043
|
+
}
|
|
4044
|
+
*/
|
|
4045
|
+
|
|
4055
4046
|
if (selecting_argument) {
|
|
4056
4047
|
if (this.overlay_editor?.editing) {
|
|
4057
4048
|
// ...
|
|
@@ -2452,6 +2452,7 @@ export class GridBase {
|
|
|
2452
2452
|
});
|
|
2453
2453
|
if (transformed) {
|
|
2454
2454
|
|
|
2455
|
+
/*
|
|
2455
2456
|
if (!this.flags.warned_r1c1) {
|
|
2456
2457
|
|
|
2457
2458
|
// 1-time warning
|
|
@@ -2459,6 +2460,7 @@ export class GridBase {
|
|
|
2459
2460
|
this.flags.warned_r1c1 = true;
|
|
2460
2461
|
console.warn('NOTE: R1C1 support is experimental. the semantics may change in the future.');
|
|
2461
2462
|
}
|
|
2463
|
+
*/
|
|
2462
2464
|
|
|
2463
2465
|
value = '=' + this.parser.Render(result.expression, { missing: '' });
|
|
2464
2466
|
}
|