@trebco/treb 23.6.2 → 25.0.0-rc1
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/.eslintignore +8 -0
- package/.eslintrc.js +164 -0
- package/README-shadow-DOM.md +88 -0
- package/README.md +37 -130
- package/api-config.json +29 -0
- package/api-generator/api-generator-types.ts +82 -0
- package/api-generator/api-generator.ts +1172 -0
- package/api-generator/package.json +3 -0
- package/build/treb-spreadsheet.mjs +14 -0
- package/{treb.d.ts → build/treb.d.ts} +293 -299
- package/esbuild-custom-element.mjs +336 -0
- package/esbuild.js +305 -0
- package/package.json +43 -14
- package/treb-base-types/package.json +5 -0
- package/treb-base-types/src/api_types.ts +36 -0
- package/treb-base-types/src/area.ts +583 -0
- package/treb-base-types/src/basic_types.ts +45 -0
- package/treb-base-types/src/cell.ts +612 -0
- package/treb-base-types/src/cells.ts +1066 -0
- package/treb-base-types/src/color.ts +124 -0
- package/treb-base-types/src/import.ts +71 -0
- package/treb-base-types/src/index-standalone.ts +29 -0
- package/treb-base-types/src/index.ts +42 -0
- package/treb-base-types/src/layout.ts +47 -0
- package/treb-base-types/src/localization.ts +187 -0
- package/treb-base-types/src/rectangle.ts +145 -0
- package/treb-base-types/src/render_text.ts +72 -0
- package/treb-base-types/src/style.ts +545 -0
- package/treb-base-types/src/table.ts +109 -0
- package/treb-base-types/src/text_part.ts +54 -0
- package/treb-base-types/src/theme.ts +608 -0
- package/treb-base-types/src/union.ts +152 -0
- package/treb-base-types/src/value-type.ts +164 -0
- package/treb-base-types/style/resizable.css +59 -0
- package/treb-calculator/modern.tsconfig.json +11 -0
- package/treb-calculator/package.json +5 -0
- package/treb-calculator/src/calculator.ts +2546 -0
- package/treb-calculator/src/complex-math.ts +558 -0
- package/treb-calculator/src/dag/array-vertex.ts +198 -0
- package/treb-calculator/src/dag/graph.ts +951 -0
- package/treb-calculator/src/dag/leaf_vertex.ts +118 -0
- package/treb-calculator/src/dag/spreadsheet_vertex.ts +327 -0
- package/treb-calculator/src/dag/spreadsheet_vertex_base.ts +44 -0
- package/treb-calculator/src/dag/vertex.ts +352 -0
- package/treb-calculator/src/descriptors.ts +162 -0
- package/treb-calculator/src/expression-calculator.ts +1069 -0
- package/treb-calculator/src/function-error.ts +103 -0
- package/treb-calculator/src/function-library.ts +103 -0
- package/treb-calculator/src/functions/base-functions.ts +1214 -0
- package/treb-calculator/src/functions/checkbox.ts +164 -0
- package/treb-calculator/src/functions/complex-functions.ts +253 -0
- package/treb-calculator/src/functions/finance-functions.ts +399 -0
- package/treb-calculator/src/functions/information-functions.ts +102 -0
- package/treb-calculator/src/functions/matrix-functions.ts +182 -0
- package/treb-calculator/src/functions/sparkline.ts +335 -0
- package/treb-calculator/src/functions/statistics-functions.ts +350 -0
- package/treb-calculator/src/functions/text-functions.ts +298 -0
- package/treb-calculator/src/index.ts +27 -0
- package/treb-calculator/src/notifier-types.ts +59 -0
- package/treb-calculator/src/primitives.ts +428 -0
- package/treb-calculator/src/utilities.ts +305 -0
- package/treb-charts/package.json +5 -0
- package/treb-charts/src/chart-functions.ts +156 -0
- package/treb-charts/src/chart-types.ts +230 -0
- package/treb-charts/src/chart.ts +1288 -0
- package/treb-charts/src/index.ts +24 -0
- package/treb-charts/src/main.ts +37 -0
- package/treb-charts/src/rectangle.ts +52 -0
- package/treb-charts/src/renderer.ts +1841 -0
- package/treb-charts/src/util.ts +122 -0
- package/treb-charts/style/charts.scss +221 -0
- package/treb-charts/style/old-charts.scss +250 -0
- package/treb-embed/markup/layout.html +137 -0
- package/treb-embed/markup/toolbar.html +175 -0
- package/treb-embed/modern.tsconfig.json +25 -0
- package/treb-embed/src/custom-element/content-types.d.ts +18 -0
- package/treb-embed/src/custom-element/global.d.ts +11 -0
- package/treb-embed/src/custom-element/spreadsheet-constructor.ts +1227 -0
- package/treb-embed/src/custom-element/treb-global.ts +44 -0
- package/treb-embed/src/custom-element/treb-spreadsheet-element.ts +52 -0
- package/treb-embed/src/embedded-spreadsheet.ts +5362 -0
- package/treb-embed/src/index.ts +16 -0
- package/treb-embed/src/language-model.ts +41 -0
- package/treb-embed/src/options.ts +320 -0
- package/treb-embed/src/progress-dialog.ts +228 -0
- package/treb-embed/src/selection-state.ts +16 -0
- package/treb-embed/src/spinner.ts +42 -0
- package/treb-embed/src/toolbar-message.ts +96 -0
- package/treb-embed/src/types.ts +167 -0
- package/treb-embed/style/autocomplete.scss +103 -0
- package/treb-embed/style/dark-theme.scss +114 -0
- package/treb-embed/style/defaults.scss +36 -0
- package/treb-embed/style/dialog.scss +181 -0
- package/treb-embed/style/dropdown-select.scss +101 -0
- package/treb-embed/style/formula-bar.scss +193 -0
- package/treb-embed/style/grid.scss +374 -0
- package/treb-embed/style/layout.scss +424 -0
- package/treb-embed/style/mouse-mask.scss +67 -0
- package/treb-embed/style/note.scss +92 -0
- package/treb-embed/style/overlay-editor.scss +102 -0
- package/treb-embed/style/spinner.scss +92 -0
- package/treb-embed/style/tab-bar.scss +228 -0
- package/treb-embed/style/table.scss +80 -0
- package/treb-embed/style/theme-defaults.scss +444 -0
- package/treb-embed/style/toolbar.scss +416 -0
- package/treb-embed/style/tooltip.scss +68 -0
- package/treb-embed/style/treb-icons.scss +130 -0
- package/treb-embed/style/treb-spreadsheet-element.scss +20 -0
- package/treb-embed/style/z-index.scss +43 -0
- package/treb-export/docs/charts.md +68 -0
- package/treb-export/modern.tsconfig.json +19 -0
- package/treb-export/package.json +4 -0
- package/treb-export/src/address-type.ts +77 -0
- package/treb-export/src/base-template.ts +22 -0
- package/treb-export/src/column-width.ts +85 -0
- package/treb-export/src/drawing2/chart-template-components2.ts +389 -0
- package/treb-export/src/drawing2/chart2.ts +282 -0
- package/treb-export/src/drawing2/column-chart-template2.ts +521 -0
- package/treb-export/src/drawing2/donut-chart-template2.ts +296 -0
- package/treb-export/src/drawing2/drawing2.ts +355 -0
- package/treb-export/src/drawing2/embedded-image.ts +71 -0
- package/treb-export/src/drawing2/scatter-chart-template2.ts +555 -0
- package/treb-export/src/export-worker/export-worker.ts +99 -0
- package/treb-export/src/export-worker/index-modern.ts +22 -0
- package/treb-export/src/export2.ts +2204 -0
- package/treb-export/src/import2.ts +882 -0
- package/treb-export/src/relationship.ts +36 -0
- package/treb-export/src/shared-strings2.ts +128 -0
- package/treb-export/src/template-2.ts +22 -0
- package/treb-export/src/unescape_xml.ts +47 -0
- package/treb-export/src/workbook-sheet2.ts +182 -0
- package/treb-export/src/workbook-style2.ts +1285 -0
- package/treb-export/src/workbook-theme2.ts +88 -0
- package/treb-export/src/workbook2.ts +491 -0
- package/treb-export/src/xml-utils.ts +201 -0
- package/treb-export/template/base/[Content_Types].xml +2 -0
- package/treb-export/template/base/_rels/.rels +2 -0
- package/treb-export/template/base/docProps/app.xml +2 -0
- package/treb-export/template/base/docProps/core.xml +12 -0
- package/treb-export/template/base/xl/_rels/workbook.xml.rels +2 -0
- package/treb-export/template/base/xl/sharedStrings.xml +2 -0
- package/treb-export/template/base/xl/styles.xml +2 -0
- package/treb-export/template/base/xl/theme/theme1.xml +2 -0
- package/treb-export/template/base/xl/workbook.xml +2 -0
- package/treb-export/template/base/xl/worksheets/sheet1.xml +2 -0
- package/treb-export/template/base.xlsx +0 -0
- package/treb-format/package.json +8 -0
- package/treb-format/src/format.test.ts +213 -0
- package/treb-format/src/format.ts +942 -0
- package/treb-format/src/format_cache.ts +199 -0
- package/treb-format/src/format_parser.ts +723 -0
- package/treb-format/src/index.ts +25 -0
- package/treb-format/src/number_format_section.ts +100 -0
- package/treb-format/src/value_parser.ts +337 -0
- package/treb-grid/package.json +5 -0
- package/treb-grid/src/editors/autocomplete.ts +394 -0
- package/treb-grid/src/editors/autocomplete_matcher.ts +260 -0
- package/treb-grid/src/editors/formula_bar.ts +473 -0
- package/treb-grid/src/editors/formula_editor_base.ts +910 -0
- package/treb-grid/src/editors/overlay_editor.ts +511 -0
- package/treb-grid/src/index.ts +37 -0
- package/treb-grid/src/layout/base_layout.ts +2618 -0
- package/treb-grid/src/layout/grid_layout.ts +299 -0
- package/treb-grid/src/layout/rectangle_cache.ts +86 -0
- package/treb-grid/src/render/selection-renderer.ts +414 -0
- package/treb-grid/src/render/svg_header_overlay.ts +93 -0
- package/treb-grid/src/render/svg_selection_block.ts +187 -0
- package/treb-grid/src/render/tile_renderer.ts +2122 -0
- package/treb-grid/src/types/annotation.ts +216 -0
- package/treb-grid/src/types/border_constants.ts +34 -0
- package/treb-grid/src/types/clipboard_data.ts +31 -0
- package/treb-grid/src/types/data_model.ts +334 -0
- package/treb-grid/src/types/drag_mask.ts +81 -0
- package/treb-grid/src/types/grid.ts +7743 -0
- package/treb-grid/src/types/grid_base.ts +3644 -0
- package/treb-grid/src/types/grid_command.ts +470 -0
- package/treb-grid/src/types/grid_events.ts +124 -0
- package/treb-grid/src/types/grid_options.ts +97 -0
- package/treb-grid/src/types/grid_selection.ts +60 -0
- package/treb-grid/src/types/named_range.ts +369 -0
- package/treb-grid/src/types/scale-control.ts +202 -0
- package/treb-grid/src/types/serialize_options.ts +72 -0
- package/treb-grid/src/types/set_range_options.ts +52 -0
- package/treb-grid/src/types/sheet.ts +3099 -0
- package/treb-grid/src/types/sheet_types.ts +95 -0
- package/treb-grid/src/types/tab_bar.ts +464 -0
- package/treb-grid/src/types/tile.ts +59 -0
- package/treb-grid/src/types/update_flags.ts +75 -0
- package/treb-grid/src/util/dom_utilities.ts +44 -0
- package/treb-grid/src/util/fontmetrics2.ts +179 -0
- package/treb-grid/src/util/ua.ts +104 -0
- package/treb-logo.svg +18 -0
- package/treb-parser/package.json +5 -0
- package/treb-parser/src/csv-parser.ts +122 -0
- package/treb-parser/src/index.ts +25 -0
- package/treb-parser/src/md-parser.ts +526 -0
- package/treb-parser/src/parser-types.ts +397 -0
- package/treb-parser/src/parser.test.ts +298 -0
- package/treb-parser/src/parser.ts +2673 -0
- package/treb-utils/package.json +5 -0
- package/treb-utils/src/dispatch.ts +57 -0
- package/treb-utils/src/event_source.ts +147 -0
- package/treb-utils/src/ievent_source.ts +33 -0
- package/treb-utils/src/index.ts +31 -0
- package/treb-utils/src/measurement.ts +174 -0
- package/treb-utils/src/resizable.ts +160 -0
- package/treb-utils/src/scale.ts +137 -0
- package/treb-utils/src/serialize_html.ts +124 -0
- package/treb-utils/src/template.ts +70 -0
- package/treb-utils/src/validate_uri.ts +61 -0
- package/tsconfig.json +10 -0
- package/tsproject.json +30 -0
- package/util/license-plugin-esbuild.js +86 -0
- package/util/list-css-vars.sh +46 -0
- package/README-esm.md +0 -37
- package/treb-bundle.css +0 -2
- package/treb-bundle.mjs +0 -15
|
@@ -0,0 +1,511 @@
|
|
|
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
|
+
/**
|
|
23
|
+
* this is a new version of the ICE that doubles as a key handler
|
|
24
|
+
* for the grid; the aim is to support IME in ICE, which did not work
|
|
25
|
+
* in our old scheme.
|
|
26
|
+
*
|
|
27
|
+
* update: trying to clean up the node structure, remove one node,
|
|
28
|
+
* and get layout working properly.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import { Style, Theme, CellValue, Rectangle, ThemeColor2, Cell } from 'treb-base-types';
|
|
32
|
+
import { Yield } from 'treb-utils';
|
|
33
|
+
import type { Parser } from 'treb-parser';
|
|
34
|
+
import type { GridSelection } from '../types/grid_selection';
|
|
35
|
+
import { FormulaEditorBase } from './formula_editor_base';
|
|
36
|
+
import type { Autocomplete } from './autocomplete';
|
|
37
|
+
import type { DataModel, ViewModel } from '../types/data_model';
|
|
38
|
+
import { UA } from '../util/ua';
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* new return type for key event handler, has some additional state
|
|
42
|
+
*/
|
|
43
|
+
export enum OverlayEditorResult {
|
|
44
|
+
not_handled = 0,
|
|
45
|
+
handled = 1,
|
|
46
|
+
commit = 2,
|
|
47
|
+
discard = 3,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** legacy */
|
|
51
|
+
// const support_cloned_events = (typeof KeyboardEvent === 'function');
|
|
52
|
+
|
|
53
|
+
/** legacy */
|
|
54
|
+
// const use_create_text_range = (typeof ((document?.body as any)?.createTextRange) === 'function');
|
|
55
|
+
|
|
56
|
+
export class OverlayEditor extends FormulaEditorBase {
|
|
57
|
+
|
|
58
|
+
// we could add these back, always construct them, and then
|
|
59
|
+
// just assign, that would get us around all the conditionals
|
|
60
|
+
|
|
61
|
+
public edit_node: HTMLElement & ElementContentEditable;
|
|
62
|
+
public edit_container: HTMLElement;
|
|
63
|
+
|
|
64
|
+
public edit_inset: HTMLElement;
|
|
65
|
+
|
|
66
|
+
public scale = 1; // this should go into theme, since it tends to follow it
|
|
67
|
+
|
|
68
|
+
/** FIXME: shouldn't this be a lint error? did we drop that rule? */
|
|
69
|
+
private _editing = false;
|
|
70
|
+
|
|
71
|
+
public get editing(): boolean {
|
|
72
|
+
return this._editing;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public set editing(state: boolean) {
|
|
76
|
+
if (this._editing !== state) {
|
|
77
|
+
this._editing = state;
|
|
78
|
+
if (state) {
|
|
79
|
+
this.edit_container.style.opacity = '1';
|
|
80
|
+
this.edit_container.style.pointerEvents = 'initial';
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
this.edit_container.style.opacity = '0';
|
|
84
|
+
this.edit_container.style.pointerEvents = 'none';
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
constructor(private container: HTMLElement, parser: Parser, theme: Theme, model: DataModel, view: ViewModel, autocomplete: Autocomplete) {
|
|
90
|
+
|
|
91
|
+
super(parser, theme, model, view, autocomplete);
|
|
92
|
+
|
|
93
|
+
this.edit_container = container.querySelector('.treb-overlay-container') as HTMLElement;
|
|
94
|
+
this.edit_node = this.edit_container.querySelector('.treb-overlay-editor') as HTMLElement & ElementContentEditable;
|
|
95
|
+
|
|
96
|
+
if (UA.is_firefox) {
|
|
97
|
+
this.edit_node.classList.add('firefox');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// attempting to cancel "auto" keyboard on ios
|
|
101
|
+
this.edit_node.inputMode = 'none';
|
|
102
|
+
|
|
103
|
+
//
|
|
104
|
+
// so clearly I am doing this when rendering, not sure how it
|
|
105
|
+
// happens, but we're offsetting by this much. checked on mac
|
|
106
|
+
// (dpr = 2) and windows (dpr = 1, dpr = 1.5). 1 is the default.
|
|
107
|
+
//
|
|
108
|
+
// NOTE that there's a `resolution` media query, not implemented in safari
|
|
109
|
+
//
|
|
110
|
+
// https://bugs.webkit.org/show_bug.cgi?id=78087
|
|
111
|
+
//
|
|
112
|
+
// and another nonstandard -webkit-max-device-pixel-ratio, which seems
|
|
113
|
+
// to be in all modern browsers (possibly with -moz prefix in ffx). OTOH
|
|
114
|
+
// this is not complicated and only called on construct, so probably fine,
|
|
115
|
+
// if somewhat obscure.
|
|
116
|
+
//
|
|
117
|
+
|
|
118
|
+
// NOTE: it's not that simple (see linux). it has something to do with
|
|
119
|
+
// measuring the font. we probably need to figure out exactly what we are
|
|
120
|
+
// doing in the renderer, and do that. which also means it might be cell
|
|
121
|
+
// specific if there are font face/size changes. also we can get it to
|
|
122
|
+
// offset incorrectly on windows with some fonts (I'm looking at you, comic
|
|
123
|
+
// sans)
|
|
124
|
+
|
|
125
|
+
// although it probably still has something to do with dpr, maybe that's
|
|
126
|
+
// a factor...
|
|
127
|
+
|
|
128
|
+
//if (self.devicePixelRatio && self.devicePixelRatio > 1) {
|
|
129
|
+
// this.edit_node.style.paddingBottom = `${self.devicePixelRatio}px`;
|
|
130
|
+
//}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
this.edit_node.addEventListener('input', (event: Event) => {
|
|
135
|
+
|
|
136
|
+
if (event instanceof InputEvent && event.isComposing) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// this is a new thing that popped up in chrome (actually edge).
|
|
141
|
+
// not sure what's happening but this seems to clean it up.
|
|
142
|
+
// we technically could allow a newline here, but... call that a TODO
|
|
143
|
+
|
|
144
|
+
const first_child = this.edit_node.firstChild as HTMLElement;
|
|
145
|
+
if (first_child && first_child.tagName === 'BR') {
|
|
146
|
+
this.edit_node.removeChild(first_child);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// should we dynamically add this when editing? (...)
|
|
150
|
+
if (!this.editing) { return; }
|
|
151
|
+
|
|
152
|
+
this.Reconstruct();
|
|
153
|
+
this.UpdateSelectState();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
this.edit_node.addEventListener('keyup', (event: KeyboardEvent) => {
|
|
157
|
+
|
|
158
|
+
if (event.isComposing) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// should we dynamically add this when editing? (...)
|
|
163
|
+
if (!this.editing) { return; }
|
|
164
|
+
|
|
165
|
+
const ac = this.autocomplete.HandleKey('keyup', event);
|
|
166
|
+
if (ac.handled) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (this.selecting_){
|
|
171
|
+
switch (event.key){
|
|
172
|
+
case 'ArrowUp':
|
|
173
|
+
case 'ArrowDown':
|
|
174
|
+
case 'ArrowLeft':
|
|
175
|
+
case 'ArrowRight':
|
|
176
|
+
case 'Shift': // also selection modifiers
|
|
177
|
+
case 'Control': // ...
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// clear node. new ones will be created as necessary.
|
|
183
|
+
this.FlushReference();
|
|
184
|
+
this.UpdateSelectState(true);
|
|
185
|
+
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
this.edit_inset = this.edit_container.querySelector('.treb-overlay-inset') as HTMLElement;
|
|
189
|
+
|
|
190
|
+
// this.edit_inset = document.createElement('div');
|
|
191
|
+
// this.edit_inset.classList.add('treb-overlay-inset');
|
|
192
|
+
// this.edit_container.appendChild(this.edit_node);
|
|
193
|
+
// this.edit_container.appendChild(this.edit_inset);
|
|
194
|
+
// this.edit_inset.appendChild(this.edit_node);
|
|
195
|
+
// this.edit_container.appendChild(this.edit_node); // dropping inset
|
|
196
|
+
// container.appendChild(this.edit_container);
|
|
197
|
+
// this.edit_container.style.opacity = '0';
|
|
198
|
+
|
|
199
|
+
this.editor_node = this.edit_node as HTMLDivElement; // wtf is this?
|
|
200
|
+
this.container_node = this.edit_container as HTMLDivElement; // wtf is this?
|
|
201
|
+
|
|
202
|
+
this.ClearContents();
|
|
203
|
+
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* * this is here only for compatibility with the old ICE; not sure if we need it * /
|
|
207
|
+
public HandleMouseEvent(event: MouseEvent): boolean {
|
|
208
|
+
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
*/
|
|
212
|
+
|
|
213
|
+
public UpdateCaption(text = ''): void {
|
|
214
|
+
this.edit_node.setAttribute('aria-label', text);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
public Focus(text = ''): void {
|
|
218
|
+
|
|
219
|
+
// we get unexpected scroll behavior if we focus on the overlay editor
|
|
220
|
+
// when it is not already focused, and the grid is scrolled. that's because
|
|
221
|
+
// by default the editor is at (0, 0), so we need to move it before we
|
|
222
|
+
// focus on it (but only in this case).
|
|
223
|
+
|
|
224
|
+
if (this.edit_node !== document.activeElement) {
|
|
225
|
+
|
|
226
|
+
// this was not correct, but should we add those 2 pixels back?
|
|
227
|
+
|
|
228
|
+
// this.edit_container.style.top = `${this.container.scrollTop + 2}px`;
|
|
229
|
+
// this.edit_container.style.left = `${this.container.scrollLeft + 2}px`;
|
|
230
|
+
|
|
231
|
+
this.edit_container.style.top = `${this.container.scrollTop + this.view.active_sheet.header_offset.y}px`;
|
|
232
|
+
this.edit_container.style.left = `${this.container.scrollLeft + this.view.active_sheet.header_offset.x}px`;
|
|
233
|
+
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
this.edit_node.focus();
|
|
237
|
+
this.UpdateCaption(text);
|
|
238
|
+
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* TEMP (should be Hide() ?) */
|
|
242
|
+
public CloseEditor(): void {
|
|
243
|
+
this.editing = false;
|
|
244
|
+
|
|
245
|
+
// this (all) should go into the set visible accessor? (...)
|
|
246
|
+
|
|
247
|
+
this.ClearContents();
|
|
248
|
+
this.edit_node.spellcheck = true; // default
|
|
249
|
+
this.autocomplete.Hide();
|
|
250
|
+
|
|
251
|
+
this.active_cell = undefined;
|
|
252
|
+
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* remove contents, plus add mozilla junk node
|
|
257
|
+
*/
|
|
258
|
+
public ClearContents(): void {
|
|
259
|
+
|
|
260
|
+
// UA doesn't change, so this should be mapped directly
|
|
261
|
+
// (meaning function pointer and no test)
|
|
262
|
+
|
|
263
|
+
// ...maybe overoptimizing
|
|
264
|
+
|
|
265
|
+
if (UA.is_firefox) {
|
|
266
|
+
|
|
267
|
+
// in firefox if the node is empty when you focus on it the
|
|
268
|
+
// cursor shifts up like 1/2 em or something, no idea why
|
|
269
|
+
// (TODO: check bugs)
|
|
270
|
+
|
|
271
|
+
this.edit_node.innerHTML = '<span></span>';
|
|
272
|
+
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
this.edit_node.textContent = '';
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
public Edit(gridselection: GridSelection, rect: Rectangle, cell: Cell, value?: CellValue, event?: Event): void {
|
|
281
|
+
|
|
282
|
+
this.Publish({
|
|
283
|
+
type: 'start-editing',
|
|
284
|
+
editor: 'ice',
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
this.active_cell = cell;
|
|
288
|
+
this.target_address = {...gridselection.target};
|
|
289
|
+
|
|
290
|
+
const style: Style.Properties = cell.style || {};
|
|
291
|
+
|
|
292
|
+
this.edit_node.style.font = Style.Font(style, this.scale);
|
|
293
|
+
this.edit_node.style.color = ThemeColor2(this.theme, style.text, 1);
|
|
294
|
+
|
|
295
|
+
this.edit_inset.style.backgroundColor = ThemeColor2(this.theme, style.fill, 0);
|
|
296
|
+
// this.edit_container.style.backgroundColor = ThemeColor2(this.theme, style.fill, 0);
|
|
297
|
+
|
|
298
|
+
// NOTE: now that we dropped support for IE11, we can probably
|
|
299
|
+
// remove more than one class at the same time.
|
|
300
|
+
|
|
301
|
+
// (but apparently firefox didn't support multiple classes either,
|
|
302
|
+
// until v[x]? I think that may have been years ago...)
|
|
303
|
+
|
|
304
|
+
switch (style.horizontal_align) {
|
|
305
|
+
case Style.HorizontalAlign.Right:
|
|
306
|
+
this.edit_container.classList.remove('align-center', 'align-left');
|
|
307
|
+
this.edit_container.classList.add('align-right');
|
|
308
|
+
break;
|
|
309
|
+
case Style.HorizontalAlign.Center:
|
|
310
|
+
this.edit_container.classList.remove('align-right', 'align-left');
|
|
311
|
+
this.edit_container.classList.add('align-center');
|
|
312
|
+
break;
|
|
313
|
+
default:
|
|
314
|
+
this.edit_container.classList.remove('align-right', 'align-center');
|
|
315
|
+
this.edit_container.classList.add('align-left');
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
this.edit_node.style.paddingBottom = `${ Math.max(0, (self.devicePixelRatio||1) - 1)}px`;
|
|
320
|
+
|
|
321
|
+
// console.info('pb', this.edit_node.style.paddingBottom);
|
|
322
|
+
|
|
323
|
+
// TODO: alignment, underline (strike?)
|
|
324
|
+
// bold/italic already work because those are font properties.
|
|
325
|
+
|
|
326
|
+
const value_string = value?.toString() || '';
|
|
327
|
+
|
|
328
|
+
// do this only if there's existing text, in which case we're not
|
|
329
|
+
// typing... or it could be a %, which is OK because the key is a number
|
|
330
|
+
|
|
331
|
+
if (value_string && value_string[0] === '=') {
|
|
332
|
+
this.edit_node.spellcheck = false;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
this.autocomplete.ResetBlock();
|
|
336
|
+
this.FlushReference();
|
|
337
|
+
this.selection = gridselection;
|
|
338
|
+
|
|
339
|
+
if (typeof value !== 'undefined') {
|
|
340
|
+
|
|
341
|
+
const percent = value_string[0] !== '=' && value_string[value_string.length - 1] === '%';
|
|
342
|
+
const value_length = value_string.length;
|
|
343
|
+
this.edit_node.textContent = value_string;
|
|
344
|
+
|
|
345
|
+
// legacy
|
|
346
|
+
|
|
347
|
+
/*
|
|
348
|
+
if (use_create_text_range) {
|
|
349
|
+
|
|
350
|
+
Yield().then(() => {
|
|
351
|
+
const r = (document.body as any).createTextRange();
|
|
352
|
+
r.moveToElementText(this.editor_node);
|
|
353
|
+
|
|
354
|
+
// the weird logic here is as follows: move to the end, unless
|
|
355
|
+
// it's a percent; in which case move to just before the % sign;
|
|
356
|
+
// unless, in the special case of overtyping a %, don't do anything.
|
|
357
|
+
// it works (the last case) because this is called via a yield. IE
|
|
358
|
+
// will somehow end up doing the right thing in this case.
|
|
359
|
+
|
|
360
|
+
if (percent) {
|
|
361
|
+
if (value_length > 1) {
|
|
362
|
+
r.moveStart('character', value_length);
|
|
363
|
+
r.move('character', -1);
|
|
364
|
+
r.select();
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
r.moveStart('character', value_length);
|
|
369
|
+
r.select();
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
else
|
|
375
|
+
*/
|
|
376
|
+
{
|
|
377
|
+
|
|
378
|
+
const range = document.createRange();
|
|
379
|
+
const selection = window.getSelection();
|
|
380
|
+
|
|
381
|
+
if (!selection) throw new Error('invalid selection object');
|
|
382
|
+
|
|
383
|
+
if (this.edit_node.lastChild){
|
|
384
|
+
if (percent) {
|
|
385
|
+
range.setStart(this.edit_node.lastChild, value_length - 1);
|
|
386
|
+
range.setEnd(this.edit_node.lastChild, value_length - 1);
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
range.setStartAfter(this.edit_node.lastChild);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
range.collapse(true);
|
|
394
|
+
selection.removeAllRanges();
|
|
395
|
+
selection.addRange(range);
|
|
396
|
+
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (!event) {
|
|
400
|
+
const dependencies = this.ListDependencies();
|
|
401
|
+
this.Publish({type: 'update', text: value.toString(), dependencies});
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
|
|
407
|
+
// FIXME: mozilla junk? check old ICE
|
|
408
|
+
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
rect.ApplyStyle(this.edit_container);
|
|
412
|
+
this.editing = true;
|
|
413
|
+
|
|
414
|
+
// I'm not sure we need to do this...
|
|
415
|
+
|
|
416
|
+
Yield().then(() => {
|
|
417
|
+
|
|
418
|
+
// we probably do need to do this, but maybe not the next one
|
|
419
|
+
this.last_reconstructed_text = '';
|
|
420
|
+
this.Reconstruct();
|
|
421
|
+
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* we probably need more state in the return value to move stuff from
|
|
428
|
+
* the async handler to directly in the sync handler -- we no longer need
|
|
429
|
+
* to redispatch events, because we're in the same event stream
|
|
430
|
+
*
|
|
431
|
+
* @param event
|
|
432
|
+
* @returns
|
|
433
|
+
*/
|
|
434
|
+
public HandleKeyDown(event: KeyboardEvent): OverlayEditorResult {
|
|
435
|
+
|
|
436
|
+
if (!this.editing) {
|
|
437
|
+
return OverlayEditorResult.not_handled;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// pass through to autocomplete
|
|
441
|
+
|
|
442
|
+
const ac = this.autocomplete.HandleKey('keydown', event);
|
|
443
|
+
|
|
444
|
+
if (ac.accept){
|
|
445
|
+
this.AcceptAutocomplete(ac);
|
|
446
|
+
}
|
|
447
|
+
if (ac.handled) {
|
|
448
|
+
return OverlayEditorResult.handled;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
switch (event.key) {
|
|
452
|
+
|
|
453
|
+
case 'Enter':
|
|
454
|
+
case 'Tab':
|
|
455
|
+
{
|
|
456
|
+
/*
|
|
457
|
+
// we're going to trap this event, and then re-send it, as we do with
|
|
458
|
+
// the formula bar editor. this is so that the grid can send the data
|
|
459
|
+
// event before the selection event, to better support undo.
|
|
460
|
+
|
|
461
|
+
const value = this.edit_node.textContent || undefined;
|
|
462
|
+
const array = (event.key === 'Enter' && event.ctrlKey && event.shiftKey);
|
|
463
|
+
this.Publish({type: 'commit', value, selection: this.selection, array, event});
|
|
464
|
+
*/
|
|
465
|
+
|
|
466
|
+
this.selecting_ = false;
|
|
467
|
+
|
|
468
|
+
// do this so we don't tab-switch-focus
|
|
469
|
+
// event.stopPropagation();
|
|
470
|
+
// event.preventDefault();
|
|
471
|
+
|
|
472
|
+
return OverlayEditorResult.commit;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
case 'Escape':
|
|
476
|
+
case 'Esc':
|
|
477
|
+
|
|
478
|
+
// this.Publish({type: 'discard'});
|
|
479
|
+
this.selecting_ = false;
|
|
480
|
+
return OverlayEditorResult.discard;
|
|
481
|
+
|
|
482
|
+
case 'ArrowUp':
|
|
483
|
+
case 'ArrowDown':
|
|
484
|
+
case 'ArrowLeft':
|
|
485
|
+
case 'ArrowRight':
|
|
486
|
+
case 'Up':
|
|
487
|
+
case 'Down':
|
|
488
|
+
case 'Left':
|
|
489
|
+
case 'Right':
|
|
490
|
+
return this.selecting_ ? OverlayEditorResult.not_handled : OverlayEditorResult.handled;
|
|
491
|
+
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// for all other keys, we consume the key if we're in edit mode; otherwise
|
|
495
|
+
// return false and let the calling routine (in grid) handle the key
|
|
496
|
+
|
|
497
|
+
// return this.editing;
|
|
498
|
+
|
|
499
|
+
return OverlayEditorResult.handled; // always true because we test at the top
|
|
500
|
+
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// --- from old ICE ----------------------------------------------------------
|
|
504
|
+
|
|
505
|
+
public UpdateTheme(scale: number): void {
|
|
506
|
+
this.scale = scale;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
export { Grid } from './types/grid';
|
|
23
|
+
export { GridBase } from './types/grid_base';
|
|
24
|
+
export { Sheet } from './types/sheet';
|
|
25
|
+
export { DataModel, MacroFunction, SerializedNamedExpression, SerializedModel } from './types/data_model';
|
|
26
|
+
export * from './types/grid_events';
|
|
27
|
+
export { SerializedSheet, FreezePane } from './types/sheet_types';
|
|
28
|
+
export { Annotation, ViewData as AnnotationViewData } from './types/annotation';
|
|
29
|
+
export { GridOptions } from './types/grid_options';
|
|
30
|
+
export { Command, CommandKey } from './types/grid_command';
|
|
31
|
+
export { NamedRangeCollection } from './types/named_range';
|
|
32
|
+
export { GridSelection } from './types/grid_selection';
|
|
33
|
+
export { BorderConstants } from './types/border_constants';
|
|
34
|
+
export { SerializeOptions } from './types/serialize_options';
|
|
35
|
+
export { FunctionDescriptor, ArgumentDescriptor } from './editors/autocomplete_matcher';
|
|
36
|
+
export { UA } from './util/ua';
|
|
37
|
+
export { SetRangeOptions } from './types/set_range_options';
|