@trebco/treb 23.6.5 → 25.0.0-rc2

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.
Files changed (217) hide show
  1. package/.eslintignore +8 -0
  2. package/.eslintrc.js +164 -0
  3. package/README-shadow-DOM.md +88 -0
  4. package/README.md +37 -130
  5. package/api-config.json +29 -0
  6. package/api-generator/api-generator-types.ts +82 -0
  7. package/api-generator/api-generator.ts +1172 -0
  8. package/api-generator/package.json +3 -0
  9. package/build/treb-spreadsheet.mjs +14 -0
  10. package/{treb.d.ts → build/treb.d.ts} +323 -271
  11. package/esbuild-custom-element.mjs +336 -0
  12. package/esbuild.js +305 -0
  13. package/package.json +49 -14
  14. package/treb-base-types/package.json +5 -0
  15. package/treb-base-types/src/api_types.ts +36 -0
  16. package/treb-base-types/src/area.ts +583 -0
  17. package/treb-base-types/src/basic_types.ts +45 -0
  18. package/treb-base-types/src/cell.ts +612 -0
  19. package/treb-base-types/src/cells.ts +1066 -0
  20. package/treb-base-types/src/color.ts +124 -0
  21. package/treb-base-types/src/import.ts +71 -0
  22. package/treb-base-types/src/index-standalone.ts +29 -0
  23. package/treb-base-types/src/index.ts +42 -0
  24. package/treb-base-types/src/layout.ts +47 -0
  25. package/treb-base-types/src/localization.ts +187 -0
  26. package/treb-base-types/src/rectangle.ts +145 -0
  27. package/treb-base-types/src/render_text.ts +72 -0
  28. package/treb-base-types/src/style.ts +545 -0
  29. package/treb-base-types/src/table.ts +109 -0
  30. package/treb-base-types/src/text_part.ts +54 -0
  31. package/treb-base-types/src/theme.ts +608 -0
  32. package/treb-base-types/src/union.ts +152 -0
  33. package/treb-base-types/src/value-type.ts +164 -0
  34. package/treb-base-types/style/resizable.css +59 -0
  35. package/treb-calculator/modern.tsconfig.json +11 -0
  36. package/treb-calculator/package.json +5 -0
  37. package/treb-calculator/src/calculator.ts +2546 -0
  38. package/treb-calculator/src/complex-math.ts +558 -0
  39. package/treb-calculator/src/dag/array-vertex.ts +198 -0
  40. package/treb-calculator/src/dag/graph.ts +951 -0
  41. package/treb-calculator/src/dag/leaf_vertex.ts +118 -0
  42. package/treb-calculator/src/dag/spreadsheet_vertex.ts +327 -0
  43. package/treb-calculator/src/dag/spreadsheet_vertex_base.ts +44 -0
  44. package/treb-calculator/src/dag/vertex.ts +352 -0
  45. package/treb-calculator/src/descriptors.ts +162 -0
  46. package/treb-calculator/src/expression-calculator.ts +1069 -0
  47. package/treb-calculator/src/function-error.ts +103 -0
  48. package/treb-calculator/src/function-library.ts +103 -0
  49. package/treb-calculator/src/functions/base-functions.ts +1214 -0
  50. package/treb-calculator/src/functions/checkbox.ts +164 -0
  51. package/treb-calculator/src/functions/complex-functions.ts +253 -0
  52. package/treb-calculator/src/functions/finance-functions.ts +399 -0
  53. package/treb-calculator/src/functions/information-functions.ts +102 -0
  54. package/treb-calculator/src/functions/matrix-functions.ts +182 -0
  55. package/treb-calculator/src/functions/sparkline.ts +335 -0
  56. package/treb-calculator/src/functions/statistics-functions.ts +350 -0
  57. package/treb-calculator/src/functions/text-functions.ts +298 -0
  58. package/treb-calculator/src/index.ts +27 -0
  59. package/treb-calculator/src/notifier-types.ts +59 -0
  60. package/treb-calculator/src/primitives.ts +428 -0
  61. package/treb-calculator/src/utilities.ts +305 -0
  62. package/treb-charts/package.json +5 -0
  63. package/treb-charts/src/chart-functions.ts +156 -0
  64. package/treb-charts/src/chart-types.ts +230 -0
  65. package/treb-charts/src/chart.ts +1288 -0
  66. package/treb-charts/src/index.ts +24 -0
  67. package/treb-charts/src/main.ts +37 -0
  68. package/treb-charts/src/rectangle.ts +52 -0
  69. package/treb-charts/src/renderer.ts +1841 -0
  70. package/treb-charts/src/util.ts +122 -0
  71. package/treb-charts/style/charts.scss +221 -0
  72. package/treb-charts/style/old-charts.scss +250 -0
  73. package/treb-embed/markup/layout.html +137 -0
  74. package/treb-embed/markup/toolbar.html +175 -0
  75. package/treb-embed/modern.tsconfig.json +25 -0
  76. package/treb-embed/src/custom-element/content-types.d.ts +18 -0
  77. package/treb-embed/src/custom-element/global.d.ts +11 -0
  78. package/treb-embed/src/custom-element/spreadsheet-constructor.ts +1228 -0
  79. package/treb-embed/src/custom-element/treb-global.ts +44 -0
  80. package/treb-embed/src/custom-element/treb-spreadsheet-element.ts +52 -0
  81. package/treb-embed/src/embedded-spreadsheet.ts +5358 -0
  82. package/treb-embed/src/index.ts +16 -0
  83. package/treb-embed/src/language-model.ts +41 -0
  84. package/treb-embed/src/options.ts +298 -0
  85. package/treb-embed/src/progress-dialog.ts +228 -0
  86. package/treb-embed/src/selection-state.ts +16 -0
  87. package/treb-embed/src/spinner.ts +42 -0
  88. package/treb-embed/src/toolbar-message.ts +96 -0
  89. package/treb-embed/src/types.ts +167 -0
  90. package/treb-embed/style/autocomplete.scss +103 -0
  91. package/treb-embed/style/dark-theme.scss +114 -0
  92. package/treb-embed/style/defaults.scss +36 -0
  93. package/treb-embed/style/dialog.scss +181 -0
  94. package/treb-embed/style/dropdown-select.scss +101 -0
  95. package/treb-embed/style/formula-bar.scss +193 -0
  96. package/treb-embed/style/grid.scss +374 -0
  97. package/treb-embed/style/layout.scss +424 -0
  98. package/treb-embed/style/mouse-mask.scss +67 -0
  99. package/treb-embed/style/note.scss +92 -0
  100. package/treb-embed/style/overlay-editor.scss +102 -0
  101. package/treb-embed/style/spinner.scss +92 -0
  102. package/treb-embed/style/tab-bar.scss +228 -0
  103. package/treb-embed/style/table.scss +80 -0
  104. package/treb-embed/style/theme-defaults.scss +444 -0
  105. package/treb-embed/style/toolbar.scss +416 -0
  106. package/treb-embed/style/tooltip.scss +68 -0
  107. package/treb-embed/style/treb-icons.scss +130 -0
  108. package/treb-embed/style/treb-spreadsheet-element.scss +20 -0
  109. package/treb-embed/style/z-index.scss +43 -0
  110. package/treb-export/docs/charts.md +68 -0
  111. package/treb-export/modern.tsconfig.json +19 -0
  112. package/treb-export/package.json +4 -0
  113. package/treb-export/src/address-type.ts +77 -0
  114. package/treb-export/src/base-template.ts +22 -0
  115. package/treb-export/src/column-width.ts +85 -0
  116. package/treb-export/src/drawing2/chart-template-components2.ts +389 -0
  117. package/treb-export/src/drawing2/chart2.ts +282 -0
  118. package/treb-export/src/drawing2/column-chart-template2.ts +521 -0
  119. package/treb-export/src/drawing2/donut-chart-template2.ts +296 -0
  120. package/treb-export/src/drawing2/drawing2.ts +355 -0
  121. package/treb-export/src/drawing2/embedded-image.ts +71 -0
  122. package/treb-export/src/drawing2/scatter-chart-template2.ts +555 -0
  123. package/treb-export/src/export-worker/export-worker.ts +99 -0
  124. package/treb-export/src/export-worker/index-modern.ts +22 -0
  125. package/treb-export/src/export2.ts +2204 -0
  126. package/treb-export/src/import2.ts +882 -0
  127. package/treb-export/src/relationship.ts +36 -0
  128. package/treb-export/src/shared-strings2.ts +128 -0
  129. package/treb-export/src/template-2.ts +22 -0
  130. package/treb-export/src/unescape_xml.ts +47 -0
  131. package/treb-export/src/workbook-sheet2.ts +182 -0
  132. package/treb-export/src/workbook-style2.ts +1285 -0
  133. package/treb-export/src/workbook-theme2.ts +88 -0
  134. package/treb-export/src/workbook2.ts +491 -0
  135. package/treb-export/src/xml-utils.ts +201 -0
  136. package/treb-export/template/base/[Content_Types].xml +2 -0
  137. package/treb-export/template/base/_rels/.rels +2 -0
  138. package/treb-export/template/base/docProps/app.xml +2 -0
  139. package/treb-export/template/base/docProps/core.xml +12 -0
  140. package/treb-export/template/base/xl/_rels/workbook.xml.rels +2 -0
  141. package/treb-export/template/base/xl/sharedStrings.xml +2 -0
  142. package/treb-export/template/base/xl/styles.xml +2 -0
  143. package/treb-export/template/base/xl/theme/theme1.xml +2 -0
  144. package/treb-export/template/base/xl/workbook.xml +2 -0
  145. package/treb-export/template/base/xl/worksheets/sheet1.xml +2 -0
  146. package/treb-export/template/base.xlsx +0 -0
  147. package/treb-format/package.json +8 -0
  148. package/treb-format/src/format.test.ts +213 -0
  149. package/treb-format/src/format.ts +942 -0
  150. package/treb-format/src/format_cache.ts +199 -0
  151. package/treb-format/src/format_parser.ts +723 -0
  152. package/treb-format/src/index.ts +25 -0
  153. package/treb-format/src/number_format_section.ts +100 -0
  154. package/treb-format/src/value_parser.ts +337 -0
  155. package/treb-grid/package.json +5 -0
  156. package/treb-grid/src/editors/autocomplete.ts +394 -0
  157. package/treb-grid/src/editors/autocomplete_matcher.ts +260 -0
  158. package/treb-grid/src/editors/formula_bar.ts +473 -0
  159. package/treb-grid/src/editors/formula_editor_base.ts +910 -0
  160. package/treb-grid/src/editors/overlay_editor.ts +511 -0
  161. package/treb-grid/src/index.ts +37 -0
  162. package/treb-grid/src/layout/base_layout.ts +2618 -0
  163. package/treb-grid/src/layout/grid_layout.ts +299 -0
  164. package/treb-grid/src/layout/rectangle_cache.ts +86 -0
  165. package/treb-grid/src/render/selection-renderer.ts +414 -0
  166. package/treb-grid/src/render/svg_header_overlay.ts +93 -0
  167. package/treb-grid/src/render/svg_selection_block.ts +187 -0
  168. package/treb-grid/src/render/tile_renderer.ts +2122 -0
  169. package/treb-grid/src/types/annotation.ts +216 -0
  170. package/treb-grid/src/types/border_constants.ts +34 -0
  171. package/treb-grid/src/types/clipboard_data.ts +31 -0
  172. package/treb-grid/src/types/data_model.ts +334 -0
  173. package/treb-grid/src/types/drag_mask.ts +81 -0
  174. package/treb-grid/src/types/grid.ts +7743 -0
  175. package/treb-grid/src/types/grid_base.ts +3644 -0
  176. package/treb-grid/src/types/grid_command.ts +470 -0
  177. package/treb-grid/src/types/grid_events.ts +124 -0
  178. package/treb-grid/src/types/grid_options.ts +97 -0
  179. package/treb-grid/src/types/grid_selection.ts +60 -0
  180. package/treb-grid/src/types/named_range.ts +369 -0
  181. package/treb-grid/src/types/scale-control.ts +202 -0
  182. package/treb-grid/src/types/serialize_options.ts +72 -0
  183. package/treb-grid/src/types/set_range_options.ts +52 -0
  184. package/treb-grid/src/types/sheet.ts +3099 -0
  185. package/treb-grid/src/types/sheet_types.ts +95 -0
  186. package/treb-grid/src/types/tab_bar.ts +464 -0
  187. package/treb-grid/src/types/tile.ts +59 -0
  188. package/treb-grid/src/types/update_flags.ts +75 -0
  189. package/treb-grid/src/util/dom_utilities.ts +44 -0
  190. package/treb-grid/src/util/fontmetrics2.ts +179 -0
  191. package/treb-grid/src/util/ua.ts +104 -0
  192. package/treb-logo.svg +18 -0
  193. package/treb-parser/package.json +5 -0
  194. package/treb-parser/src/csv-parser.ts +122 -0
  195. package/treb-parser/src/index.ts +25 -0
  196. package/treb-parser/src/md-parser.ts +526 -0
  197. package/treb-parser/src/parser-types.ts +397 -0
  198. package/treb-parser/src/parser.test.ts +298 -0
  199. package/treb-parser/src/parser.ts +2673 -0
  200. package/treb-utils/package.json +5 -0
  201. package/treb-utils/src/dispatch.ts +57 -0
  202. package/treb-utils/src/event_source.ts +147 -0
  203. package/treb-utils/src/ievent_source.ts +33 -0
  204. package/treb-utils/src/index.ts +31 -0
  205. package/treb-utils/src/measurement.ts +174 -0
  206. package/treb-utils/src/resizable.ts +160 -0
  207. package/treb-utils/src/scale.ts +137 -0
  208. package/treb-utils/src/serialize_html.ts +124 -0
  209. package/treb-utils/src/template.ts +70 -0
  210. package/treb-utils/src/validate_uri.ts +61 -0
  211. package/tsconfig.json +10 -0
  212. package/tsproject.json +30 -0
  213. package/util/license-plugin-esbuild.js +86 -0
  214. package/util/list-css-vars.sh +46 -0
  215. package/README-esm.md +0 -37
  216. package/treb-bundle.css +0 -2
  217. 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';