@trebco/treb 23.6.5 → 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.
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} +285 -269
  11. package/esbuild-custom-element.mjs +336 -0
  12. package/esbuild.js +305 -0
  13. package/package.json +43 -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 +1227 -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 +5362 -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 +320 -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,216 @@
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 { Rectangle, ICellAddress, AnnotationLayout } from 'treb-base-types';
23
+
24
+ /**
25
+ * new annotation class. annotations are arbitrary content
26
+ * inserted into the sheet, using a floating div element. the
27
+ * class is serialized with the sheet, so the caller can recreate
28
+ * the content if desired.
29
+ *
30
+ * because there's an element of layout involved, callers should
31
+ * interact with annotations through the grid class rather than the
32
+ * sheet.
33
+ *
34
+ * we are redesigning layout so that instead of a rectangle, in
35
+ * coordinate space, annotations use extents and offsets in cell space.
36
+ * so layout should now have a TL cell and a BR cell plus offsets for
37
+ * each. Offset is implemented as a % of the given cell, so offsets are
38
+ * inverted in the TL/BR cells.
39
+ *
40
+ * UPDATE: actually while the inverted BR offset makes intuitive sense,
41
+ * it doesn't make technical sense -- easier to always calcluate offsets
42
+ * in the same direction. so offsets are always positive.
43
+ *
44
+ * we'll leave the old extent in there (for now, at least) to prevent
45
+ * any unintended consequences.
46
+ *
47
+ * UPDATE: adding a view interface for view-specific data. this is prep
48
+ * for supporting annotations in split views; we have to change how we
49
+ * manage nodes and callbacks.
50
+ *
51
+ */
52
+
53
+ let key_generator = 100;
54
+
55
+ /**
56
+ * moving view-specific data into a separate interface to support split.
57
+ * nothing in view is serialized.
58
+ */
59
+ export interface ViewData {
60
+
61
+ /** flag indicating we have inflated this. not serialized */
62
+ inflated?: boolean;
63
+
64
+ /** if function exists, will be called when the annotation is resized */
65
+ resize_callback?: () => void;
66
+
67
+ /** if function exists, will be called when the annotation needs to update */
68
+ update_callback?: () => void;
69
+
70
+ /** layout node */
71
+ node?: HTMLDivElement;
72
+
73
+ /** content node */
74
+ content_node?: HTMLDivElement;
75
+
76
+ /** view-specific dirty flag */
77
+ dirty?: boolean;
78
+
79
+ }
80
+
81
+ export class Annotation {
82
+
83
+ public get key(): number { return this.key_; }
84
+
85
+ /** coordinates, in sheet space */
86
+ public rect?: Rectangle;
87
+
88
+ // public get rect(): Rectangle|undefined { return this.rect_; }
89
+
90
+ /** display coordinates, possibly scaled. not persisted. */
91
+ public scaled_rect?: Rectangle;
92
+
93
+ /** the new layout, persisted and takes preference over the old one */
94
+ public layout?: AnnotationLayout;
95
+
96
+ /** opaque data. this is serialized, so it's persistent data */
97
+ public data: any = {};
98
+
99
+ // opaque string which will be added to the class of any containing node
100
+ // public class_name?: string;
101
+
102
+ /** type, for filtering. ensure a value */
103
+ public type = '';
104
+
105
+ /** also opaque data, but not serialized. */
106
+ public temp: any = {};
107
+
108
+ /* * flag indicating we have inflated this. not serialized */
109
+ // public inflated = false;
110
+
111
+ /* * if function exists, will be called when the annotation is resized */
112
+ // public resize_callback?: () => void;
113
+
114
+ /* * if function exists, will be called when the annotation needs to update */
115
+ // public update_callback?: () => void;
116
+
117
+ /** annotation can be resized. this is advisory, for UI */
118
+ public resizable = true;
119
+
120
+ /** annotation can be moved. this is advisory, for UI */
121
+ public movable = true;
122
+
123
+ /** annotation can be removed/deleted. this is advisory, for UI */
124
+ public removable = true;
125
+
126
+ /** annotation can be selected. this is advisory, for UI */
127
+ public selectable = true;
128
+
129
+ /** move when resizing/inserting rows/columns */
130
+ public move_with_cells = true;
131
+
132
+ /** resize when resizing/inserting rows/columns */
133
+ public resize_with_cells = true;
134
+
135
+ /* * layout node, obviously not serialized */
136
+ // public node?: HTMLDivElement;
137
+
138
+ /* * content node */
139
+ // public content_node?: HTMLDivElement;
140
+
141
+ public view: ViewData[] = [];
142
+
143
+ /**
144
+ * advisory, meaning we probably need an update if there's an opportunity.
145
+ * only advisory and not persisted.
146
+ */
147
+ public dirty?: boolean;
148
+
149
+ /**
150
+ * optional formula. the formula will be updated on structure events
151
+ * (insert/delete row/column).
152
+ */
153
+ public formula = '';
154
+
155
+ /**
156
+ * extent, useful for exporting. we could probably serialize this,
157
+ * just be sure to clear it when layout changes so it will be
158
+ * recalculated.
159
+ *
160
+ * the idea is to know the bottom/right row/column of the annotation,
161
+ * so when we preserve/restore the sheet we don't trim those rows/columns.
162
+ * they don't need any data, but it just looks bad. we can do this
163
+ * dynamically but since it won't change all that often, we might
164
+ * as well precalculate.
165
+ */
166
+ public extent?: ICellAddress;
167
+
168
+ private key_ = (key_generator++);
169
+
170
+ /**
171
+ * constructor takes a property bag (from json, generally). note that
172
+ * if you are iterating keys on `this`, there has to be an initial value
173
+ * or the key won't exist.
174
+ */
175
+ constructor(opts: Partial<Annotation>&{rect?: Partial<Rectangle>} = {}) {
176
+ for (const key of Object.keys(this) as Array<keyof Annotation>){
177
+ if (key !== 'layout' // && key !== 'rect'
178
+ && opts[key]) { // key !== 'cell_address' && opts[key]) {
179
+ (this as any)[key] = opts[key];
180
+ }
181
+ }
182
+
183
+ if (opts.layout) {
184
+ this.layout = JSON.parse(JSON.stringify(opts.layout));
185
+ }
186
+ if (opts.rect) {
187
+ this.rect = Rectangle.Create(opts.rect);
188
+ }
189
+ }
190
+
191
+ /**
192
+ * serialization method drops node and trims
193
+ */
194
+ public toJSON(): Partial<Annotation> {
195
+ const result: Partial<Annotation> = {}; // { rect: this.rect };
196
+
197
+ if (this.data) result.data = this.data;
198
+ if (this.formula) result.formula = this.formula;
199
+ if (this.type) result.type = this.type;
200
+ // if (this.class_name) result.class_name = this.class_name;
201
+
202
+ if (!this.resizable) result.resizable = this.resizable;
203
+ if (!this.movable) result.movable = this.movable;
204
+ if (!this.removable) result.removable = this.removable;
205
+ if (!this.selectable) result.selectable = this.selectable;
206
+
207
+ if (!this.move_with_cells) result.move_with_cells = this.move_with_cells;
208
+ if (!this.resize_with_cells) result.resize_with_cells = this.resize_with_cells;
209
+
210
+ if (this.layout) result.layout = this.layout;
211
+ if (this.extent) result.extent = this.extent;
212
+
213
+ return result;
214
+ }
215
+
216
+ }
@@ -0,0 +1,34 @@
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
+ // switching to string constants to make it easier to set manually
23
+
24
+ export enum BorderConstants {
25
+ None = 'none',
26
+ All = 'all',
27
+ Outside = 'outside',
28
+ Top = 'top',
29
+ Bottom = 'bottom',
30
+ Left = 'left',
31
+ Right = 'right',
32
+ // DoubleTop = 'double-top',
33
+ // DoubleBottom = 'double-bottom',
34
+ }
@@ -0,0 +1,31 @@
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
+ import type { ICellAddress, CellValue, ValueType, Style } from 'treb-base-types';
24
+
25
+ export interface ClipboardCellData {
26
+ address: ICellAddress;
27
+ data: CellValue;
28
+ type: ValueType;
29
+ style?: Style.Properties;
30
+ array?: {rows: number, columns: number};
31
+ }
@@ -0,0 +1,334 @@
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 { Sheet } from './sheet';
23
+ import type { IArea, ICellAddress, Table } from 'treb-base-types';
24
+ import type { SerializedSheet } from './sheet_types';
25
+ import { NamedRangeCollection } from './named_range';
26
+ import type { ExpressionUnit, UnitAddress, UnitStructuredReference, UnitRange } from 'treb-parser';
27
+ import { Style } from 'treb-base-types';
28
+
29
+ export interface MacroFunction {
30
+ name: string;
31
+ function_def: string;
32
+ argument_names?: string[];
33
+ // argument_default_values?: any[]; // <- new
34
+ description?: string;
35
+ expression?: ExpressionUnit;
36
+ }
37
+
38
+ /**
39
+ * we spend a lot of time looking up sheets by name, or id, or
40
+ * sometimes index. it makes sense to have a class that can
41
+ * support all of these, ideally without looping.
42
+ *
43
+ * we just have to make sure that no one is assigning to the
44
+ * array, or we'll lose track.
45
+ *
46
+ * also there are some operations -- rename, in particular -- that
47
+ * require updating indexes.
48
+ *
49
+ *
50
+ * FIXME: new file (1 class per file)
51
+ */
52
+ export class SheetCollection {
53
+
54
+ /**
55
+ * returns a read-only copy of the list. useful for indexing or
56
+ * functional-style calls. it's not actually read-only, but it's a
57
+ * copy, so changes will be ignored.
58
+ */
59
+ public get list() {
60
+ return this.sheets_.slice(0);
61
+ }
62
+
63
+ /**
64
+ * length of list
65
+ */
66
+ public get length() {
67
+ return this.sheets_.length;
68
+ }
69
+
70
+ /** map of (normalized) name -> sheet */
71
+ protected names: Map<string, Sheet> = new Map();
72
+
73
+ /** map of id -> sheet */
74
+ protected ids: Map<number, Sheet> = new Map();
75
+
76
+ /** the actual list */
77
+ private sheets_: Sheet[] = [];
78
+
79
+ /**
80
+ * remove any existing sheets and add the passed list. updates indexes.
81
+ */
82
+ public Assign(sheets: Sheet[]) {
83
+ this.sheets_ = [...sheets];
84
+ this.UpdateIndexes();
85
+ }
86
+
87
+ /**
88
+ * add a new sheet to the end of the list (push). updates indexes.
89
+ */
90
+ public Add(sheet: Sheet) {
91
+ this.sheets_.push(sheet);
92
+ this.UpdateIndexes();
93
+ }
94
+
95
+ /**
96
+ * wrapper for array splice. updates indexes.
97
+ */
98
+ public Splice(insert_index: number, delete_count: number, ...items: Sheet[]) {
99
+ this.sheets_.splice(insert_index, delete_count, ...items);
100
+ this.UpdateIndexes();
101
+ }
102
+
103
+ /**
104
+ * so our new strategy is to add lookup methods first -- then
105
+ * we can fix the underlying storage implementation.
106
+ *
107
+ * NOTE we normalize strings here so you do not need to do it (don't)
108
+ */
109
+ public Find(id: string|number): Sheet|undefined {
110
+
111
+ // console.info('get', typeof id);
112
+
113
+ if (typeof id === 'string') {
114
+ return this.names.get(id.toLocaleUpperCase());
115
+ }
116
+ else {
117
+ return this.ids.get(id);
118
+ }
119
+
120
+ return undefined;
121
+ }
122
+
123
+ /** get name for sheet with given id */
124
+ public Name(id: number): string|undefined {
125
+ return this.ids.get(id)?.name || undefined;
126
+ }
127
+
128
+ /** get ID for sheet with given name */
129
+ public ID(name: string): number|undefined {
130
+ return this.names.get(name.toLocaleUpperCase())?.id || undefined;
131
+ }
132
+
133
+ /** not sure why this is private, makes it a little more complicated */
134
+ public UpdateIndexes(): void {
135
+
136
+ this.names.clear();
137
+ this.ids.clear();
138
+
139
+ for (const sheet of this.sheets_) {
140
+ const uc = sheet.name.toLocaleUpperCase();
141
+ this.names.set(uc, sheet);
142
+ this.ids.set(sheet.id, sheet);
143
+ }
144
+
145
+ }
146
+
147
+
148
+ }
149
+
150
+ /**
151
+ * FIXME: this should move out of the grid module, grid should be focused on view
152
+ */
153
+ export class DataModel {
154
+
155
+ /** document metadata */
156
+ public document_name?: string;
157
+
158
+ /** document metadata */
159
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
160
+ public user_data?: any;
161
+
162
+ /**
163
+ * list of sheets. we _should_ index these by ID, so we
164
+ * don't have to look up. FIXME/TODO
165
+ */
166
+ // public sheets: Sheet[] = [];
167
+
168
+ /**
169
+ * this prevents assignment, but not push/pop/splice (baby steps)
170
+ */
171
+ // public get sheets(): Sheet[] {
172
+ // return this._sheets;
173
+ //}
174
+ public readonly sheets = new SheetCollection();
175
+
176
+ /** named ranges are document-scope, we don't support sheet-scope names */
177
+ public readonly named_ranges = new NamedRangeCollection;
178
+
179
+ /** macro functions are functions written in spreadsheet language */
180
+ // public macro_functions: Record<string, MacroFunction> = {};
181
+ public readonly macro_functions: Map<string, MacroFunction> = new Map();
182
+
183
+ /**
184
+ * new, for parametric. these might move to a different construct.
185
+ */
186
+ //public named_expressions: Record<string, ExpressionUnit> = {};
187
+ public readonly named_expressions: Map<string, ExpressionUnit> = new Map();
188
+
189
+ /** index for views */
190
+ public view_count = 0;
191
+
192
+ /**
193
+ * base style properties moved to model, so we can have a single
194
+ * and consistent reference.
195
+ */
196
+ public theme_style_properties: Style.Properties = JSON.parse(JSON.stringify(Style.DefaultProperties));
197
+
198
+ /**
199
+ * tables are global, because we need to reference them by name; and they
200
+ * need unique names, so we need to keep track of names. name matching is
201
+ * icase so we lc the names before inserting.
202
+ */
203
+ public tables: Map<string, Table> = new Map();
204
+
205
+ /**
206
+ * putting this here temporarily. it should probably move into a table
207
+ * manager class or something like that.
208
+ */
209
+ public ResolveStructuredReference(ref: UnitStructuredReference, context: ICellAddress): UnitAddress|UnitRange|undefined {
210
+
211
+ let table: Table|undefined;
212
+
213
+ // if there's no table specified, it means "I am in the table".
214
+ // in that case we need to find the table from the cell.
215
+
216
+ if (ref.table) {
217
+ table = this.tables.get(ref.table.toLowerCase());
218
+ }
219
+ else {
220
+ if (context.sheet_id) {
221
+ const sheet = this.sheets.Find(context.sheet_id);
222
+ const cell = sheet?.CellData(context);
223
+ table = cell?.table;
224
+ }
225
+ }
226
+
227
+ if (!table) {
228
+ return undefined; // table not found
229
+ }
230
+
231
+ // resolve the column
232
+ const reference_column = ref.column.toLowerCase();
233
+ let column = -1;
234
+
235
+ if (table.columns) { // FIXME: make this required
236
+ for (let i = 0; i < table.columns.length; i++) {
237
+ if (reference_column === table.columns[i]) {
238
+ column = table.area.start.column + i;
239
+ break;
240
+ }
241
+ }
242
+ }
243
+
244
+ if (column < 0) {
245
+ return undefined; // invalid column
246
+ }
247
+
248
+ // for row scope, make sure we're in a valid row.
249
+
250
+ if (ref.scope === 'row') {
251
+
252
+ const row = context.row;
253
+ if (row < table.area.start.row || row > table.area.end.row) {
254
+ return undefined; // invalid row for "this row"
255
+ }
256
+
257
+ // OK, we can use this
258
+
259
+ return {
260
+ label: ref.label,
261
+ type: 'address',
262
+ row,
263
+ column,
264
+ sheet_id: table.area.start.sheet_id,
265
+ id: ref.id,
266
+ position: ref.position,
267
+ };
268
+
269
+ }
270
+ else {
271
+
272
+ // the difference between 'all' and 'column' is that 'all' includes
273
+ // the first (header) row and the last (totals) row, if we have one.
274
+
275
+ let start_row = table.area.start.row;
276
+ let end_row = table.area.end.row;
277
+
278
+ if (ref.scope === 'column') {
279
+ start_row++; // skip headers
280
+ if (table.totals_row) {
281
+ end_row--; // skip totals
282
+ }
283
+ }
284
+
285
+ return {
286
+ label: ref.label,
287
+ type: 'range',
288
+ position: ref.position,
289
+ id: ref.id,
290
+ start: {
291
+ type: 'address',
292
+ row: start_row,
293
+ column,
294
+ sheet_id: table.area.start.sheet_id,
295
+ label: ref.label,
296
+ position: ref.position,
297
+ id: 0,
298
+ },
299
+ end: {
300
+ type: 'address',
301
+ row: end_row,
302
+ column,
303
+ label: ref.label,
304
+ position: ref.position,
305
+ id: 0,
306
+ },
307
+ }
308
+
309
+ }
310
+
311
+ return undefined;
312
+ }
313
+
314
+ }
315
+
316
+ export interface ViewModel {
317
+ active_sheet: Sheet;
318
+ view_index: number;
319
+ }
320
+
321
+ export interface SerializedNamedExpression {
322
+ name: string;
323
+ expression: string;
324
+ }
325
+
326
+ export interface SerializedModel {
327
+ sheet_data: SerializedSheet[];
328
+ active_sheet: number;
329
+ named_ranges?: Record<string, IArea>;
330
+ macro_functions?: MacroFunction[];
331
+ tables?: Table[];
332
+ named_expressions?: SerializedNamedExpression[];
333
+ decimal_mark?: ','|'.';
334
+ }
@@ -0,0 +1,81 @@
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
+ * generic method for mouse drag handling. this method will insert an
24
+ * event mask to capture mouse events over the whole window, and call
25
+ * optional functions on events.
26
+ *
27
+ * @param classes optional list of classes to attach to the mask node
28
+ * @param move callback function on mouse move events
29
+ * @param end callback function on end (mouse up or button up)
30
+ */
31
+ export function MouseDrag(
32
+ mask_node: HTMLElement,
33
+ classes: string|string[] = [],
34
+ move?: (event: MouseEvent) => void,
35
+ end?: (event: MouseEvent) => void) {
36
+
37
+ if (typeof classes === 'string') {
38
+ classes = [classes];
39
+ }
40
+
41
+ // eslint-disable-next-line prefer-const
42
+ let cleanup: () => void;
43
+
44
+ const handle_up = (event: MouseEvent) => {
45
+ event.stopPropagation();
46
+ event.preventDefault();
47
+ cleanup();
48
+ // if (end) end.call(this, event);
49
+ if (end) { end(event); }
50
+ };
51
+
52
+ const handle_move = (event: MouseEvent) => {
53
+ event.stopPropagation();
54
+ event.preventDefault();
55
+ if (!event.buttons) {
56
+ cleanup();
57
+ // if (end) end.call(this, event);
58
+ if (end) { end(event); }
59
+ return;
60
+ }
61
+ // if (move) move.call(this, event);
62
+ if (move) { move(event); }
63
+ };
64
+
65
+ cleanup = () => {
66
+ mask_node.style.display = 'none';
67
+ mask_node.removeEventListener('mousemove', handle_move);
68
+ mask_node.removeEventListener('mouseup', handle_up);
69
+ for (const class_entry of classes) mask_node.classList.remove(class_entry);
70
+ };
71
+
72
+ for (const class_entry of classes) mask_node.classList.add(class_entry);
73
+ mask_node.style.display = 'block';
74
+
75
+ // listeners are only added if we're going to use the callbacks.
76
+ // still safe to call remove listener even if they're not added.
77
+
78
+ if (move) mask_node.addEventListener('mousemove', handle_move);
79
+ if (end) mask_node.addEventListener('mouseup', handle_up);
80
+
81
+ }