@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,36 @@
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 { ICellAddress, IArea } from './area';
23
+
24
+ // for updated API functions
25
+
26
+ /**
27
+ * type represents a reference passed in to API functions. it can be an
28
+ * address object, or a string.
29
+ */
30
+ export type AddressReference = string | ICellAddress;
31
+
32
+ /**
33
+ * type represents a reference passed in to API functions. it can be an
34
+ * address object, an area (range) object, or a string.
35
+ */
36
+ export type RangeReference = string | ICellAddress | IArea;
@@ -0,0 +1,583 @@
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
+ * Structure represents a cell address. Note that row and column are 0-based.
24
+ */
25
+ export interface ICellAddress {
26
+
27
+ /** 0-based row */
28
+ row: number;
29
+
30
+ /** 0-based column */
31
+ column: number;
32
+
33
+ absolute_row?: boolean;
34
+ absolute_column?: boolean;
35
+ sheet_id?: number;
36
+ }
37
+
38
+ /**
39
+ * this version of the interface requires a sheet ID
40
+ */
41
+ export interface ICellAddress2 extends ICellAddress {
42
+ sheet_id: number;
43
+ }
44
+
45
+ /**
46
+ * Structure represents a 2d range of cells.
47
+ *
48
+ * @privateRemarks
49
+ *
50
+ * FIXME: should be just Partial<Area>? (...) OTOH, this at least
51
+ * enforces two addresses, which seems useful
52
+ */
53
+ export interface IArea {
54
+ start: ICellAddress;
55
+ end: ICellAddress;
56
+ }
57
+
58
+ /**
59
+ * type guard function
60
+ * FIXME: is there a naming convention for these?
61
+ *
62
+ * @internal
63
+ */
64
+ export const IsCellAddress = (obj: any): obj is ICellAddress => {
65
+ return (
66
+ typeof obj === 'object' &&
67
+ typeof obj.row !== 'undefined' &&
68
+ typeof obj.column !== 'undefined');
69
+ };
70
+
71
+ /** @internal */
72
+ export const IsArea = (obj: any): obj is IArea => {
73
+ return (
74
+ typeof obj === 'object' &&
75
+ IsCellAddress(obj.start) &&
76
+ IsCellAddress(obj.end));
77
+ };
78
+
79
+ export interface Dimensions {
80
+ rows: number;
81
+ columns: number;
82
+ }
83
+
84
+ /**
85
+ * class represents a rectangular area on a sheet. can be a range,
86
+ * single cell, entire row/column, or entire sheet.
87
+ *
88
+ * "entire" row/column/sheet is represented with an infinity in the
89
+ * start/end value for row/column/both, so watch out on loops. the
90
+ * sheet class has a method for reducing infinite ranges to actual
91
+ * populated ranges.
92
+ */
93
+ export class Area implements IArea { // }, IterableIterator<ICellAddress> {
94
+
95
+ // tslint:disable-next-line:variable-name
96
+ private start_: ICellAddress;
97
+
98
+ // tslint:disable-next-line:variable-name
99
+ private end_: ICellAddress;
100
+
101
+ /**
102
+ *
103
+ * @param start
104
+ * @param end
105
+ * @param normalize: calls the normalize function
106
+ */
107
+ constructor(start: ICellAddress, end: ICellAddress = start, normalize = false){
108
+
109
+ /*
110
+ // copy
111
+ this.start_ = {
112
+ row: start.row, column: start.column,
113
+ absolute_column: !!start.absolute_column,
114
+ absolute_row: !!start.absolute_row };
115
+
116
+ this.end_ = {
117
+ row: end.row, column: end.column,
118
+ absolute_column: !!end.absolute_column,
119
+ absolute_row: !!end.absolute_row };
120
+ */
121
+
122
+ // patch nulls. this is an effect of transferring via JSON,
123
+ // infinities are -> null. make sure to strict === null.
124
+
125
+ // NOTE that the patch function returns a clone, so we can store the
126
+ // returned object (instead of copying, which we used to do).
127
+
128
+ this.end_ = this.PatchNull(end);
129
+ this.start_ = this.PatchNull(start);
130
+
131
+ if (normalize) this.Normalize();
132
+
133
+ // this.ResetIterator();
134
+
135
+ }
136
+
137
+ public static FromColumn(column: number): Area {
138
+ return new Area({row: Infinity, column});
139
+ }
140
+
141
+ public static FromRow(row: number): Area {
142
+ return new Area({row, column: Infinity});
143
+ }
144
+
145
+ public static ColumnToLabel(c: number): string {
146
+ let s = String.fromCharCode(65 + c % 26);
147
+ while (c > 25){
148
+ c = Math.floor(c / 26) - 1;
149
+ s = String.fromCharCode(65 + c % 26) + s;
150
+ }
151
+ return s;
152
+ }
153
+
154
+ public static CellAddressToLabel(address: ICellAddress, sheet_id = false): string {
155
+
156
+ const prefix = sheet_id ? `${address.sheet_id || 0}!` : '';
157
+
158
+ return prefix
159
+ + (address.absolute_column ? '$' : '')
160
+ + this.ColumnToLabel(address.column)
161
+ + (address.absolute_row ? '$' : '')
162
+ + (address.row + 1);
163
+
164
+ }
165
+
166
+ /**
167
+ * merge two areas and return a new area.
168
+ * UPDATE to support arbitrary arguments
169
+ */
170
+ public static Join(base: IArea, ...args: Array<IArea|undefined>): Area {
171
+ const area = new Area(base.start, base.end);
172
+ for (const arg of args) {
173
+ if (arg) {
174
+ area.ConsumeAddress(arg.start);
175
+ area.ConsumeAddress(arg.end);
176
+ }
177
+ }
178
+ return area;
179
+ }
180
+
181
+ /**
182
+ * creates an area that expands the original area in all directions
183
+ * (except at the top/left edges)
184
+ */
185
+ public static Bleed(area: IArea, length = 1): Area {
186
+ return new Area({
187
+ row: Math.max(0, area.start.row - length),
188
+ column: Math.max(0, area.start.column - length),
189
+ sheet_id: area.start.sheet_id,
190
+ }, {
191
+ row: area.end.row + length,
192
+ column: area.end.column + length,
193
+ });
194
+ }
195
+
196
+
197
+
198
+ /** accessor returns a _copy_ of the start address */
199
+ public get start(): ICellAddress {
200
+ return { ...this.start_ };
201
+ }
202
+
203
+ /** accessor */
204
+ public set start(value: ICellAddress){ this.start_ = value; }
205
+
206
+ /** accessor returns a _copy_ of the end address */
207
+ public get end(): ICellAddress {
208
+ return { ...this.end_ };
209
+ }
210
+
211
+ /** accessor */
212
+ public set end(value: ICellAddress){ this.end_ = value; }
213
+
214
+ /** returns number of rows, possibly infinity */
215
+ public get rows(): number {
216
+ if (this.start_.row === Infinity || this.end_.row === Infinity) return Infinity;
217
+ return this.end_.row - this.start_.row + 1;
218
+ }
219
+
220
+ /** returns number of columns, possibly infinity */
221
+ public get columns(): number {
222
+ if (this.start_.column === Infinity || this.end_.column === Infinity) return Infinity;
223
+ return this.end_.column - this.start_.column + 1;
224
+ }
225
+
226
+ /** returns number of cells, possibly infinity */
227
+ public get count(): number {
228
+ return this.rows * this.columns;
229
+ }
230
+
231
+ /** returns flag indicating this is the entire sheet, usually after "select all" */
232
+ public get entire_sheet(): boolean {
233
+ return this.entire_row && this.entire_column;
234
+ }
235
+
236
+ /** returns flag indicating this range includes infinite rows */
237
+ public get entire_column(): boolean {
238
+ return (this.start_.row === Infinity);
239
+ }
240
+
241
+ /** returns flag indicating this range includes infinite columns */
242
+ public get entire_row(): boolean {
243
+ return (this.start_.column === Infinity);
244
+ }
245
+
246
+ public PatchNull(address: ICellAddress): ICellAddress {
247
+ const copy = { ...address };
248
+ if (copy.row === null) { copy.row = Infinity; }
249
+ if (copy.column === null) { copy.column = Infinity; }
250
+ return copy;
251
+ }
252
+
253
+ public SetSheetID(id: number) {
254
+ this.start_.sheet_id = id;
255
+ }
256
+
257
+ public Normalize(){
258
+ /*
259
+ let columns = [this.start.column, this.end.column].sort((a, b) => a-b);
260
+ let rows = [this.start.row, this.end.row].sort((a, b) => a-b);
261
+
262
+ this.start_ = {row: rows[0], column: columns[0]};
263
+ this.end = {row:rows[1], column: columns[1]};
264
+ */
265
+
266
+ // we need to bind the element and the absolute/relative status
267
+ // so sorting is too simple
268
+
269
+ const start = { ...this.start_ };
270
+ const end = { ...this.end_ };
271
+
272
+ /*
273
+ const start = {
274
+ sheet_id: this.start_.sheet_id,
275
+ row: this.start_.row,
276
+ column: this.start_.column,
277
+ absolute_column: this.start_.absolute_column,
278
+ absolute_row: this.start_.absolute_row };
279
+
280
+ const end = {
281
+ sheet_id: this.end_.sheet_id, // we don't ever use this, but copy JIC
282
+ row: this.end_.row,
283
+ column: this.end_.column,
284
+ absolute_column: this.end_.absolute_column,
285
+ absolute_row: this.end_.absolute_row };
286
+ */
287
+
288
+ // swap row
289
+
290
+ if (start.row === Infinity || end.row === Infinity){
291
+ start.row = end.row = Infinity;
292
+ }
293
+ else if (start.row > end.row){
294
+ start.row = this.end_.row;
295
+ start.absolute_row = this.end_.absolute_row;
296
+ end.row = this.start_.row;
297
+ end.absolute_row = this.start_.absolute_row;
298
+ }
299
+
300
+ // swap column
301
+
302
+ if (start.column === Infinity || end.column === Infinity){
303
+ start.column = end.column = Infinity;
304
+ }
305
+ else if (start.column > end.column){
306
+ start.column = this.end_.column;
307
+ start.absolute_column = this.end_.absolute_column;
308
+ end.column = this.start_.column;
309
+ end.absolute_column = this.start_.absolute_column;
310
+ }
311
+
312
+ this.start_ = start;
313
+ this.end_ = end;
314
+
315
+ }
316
+
317
+ /** returns the top-left cell in the area */
318
+ public TopLeft(): ICellAddress {
319
+ const address = {row: 0, column: 0};
320
+ if (!this.entire_row) address.column = this.start.column;
321
+ if (!this.entire_column) address.row = this.start.row;
322
+ return address;
323
+ }
324
+
325
+ /** returns the bottom-right cell in the area */
326
+ public BottomRight(): ICellAddress {
327
+ const address = {row: 0, column: 0};
328
+ if (!this.entire_row) address.column = this.end.column;
329
+ if (!this.entire_column) address.row = this.end.row;
330
+ return address;
331
+ }
332
+
333
+ public ContainsRow(row: number): boolean {
334
+ return this.entire_column || (row >= this.start_.row && row <= this.end_.row);
335
+ }
336
+
337
+ public ContainsColumn(column: number): boolean {
338
+ return this.entire_row || (column >= this.start_.column && column <= this.end_.column);
339
+ }
340
+
341
+ public Contains(address: ICellAddress): boolean {
342
+ return (this.entire_column || (address.row >= this.start_.row && address.row <= this.end_.row))
343
+ && (this.entire_row || (address.column >= this.start_.column && address.column <= this.end_.column));
344
+ }
345
+
346
+ /**
347
+ * returns true if this area completely contains the argument area
348
+ * (also if areas are ===, as a side effect). note that this returns
349
+ * true if A contains B, but not vice-versa
350
+ */
351
+ public ContainsArea(area: Area): boolean {
352
+ return this.start.column <= area.start.column
353
+ && this.end.column >= area.end.column
354
+ && this.start.row <= area.start.row
355
+ && this.end.row >= area.end.row;
356
+ }
357
+
358
+ /**
359
+ * returns true if there's an intersection. note that this won't work
360
+ * if there are infinities -- needs real area ?
361
+ */
362
+ public Intersects(area: Area): boolean {
363
+ return !(area.start.column > this.end.column
364
+ || this.start.column > area.end.column
365
+ || area.start.row > this.end.row
366
+ || this.start.row > area.end.row);
367
+ }
368
+
369
+ public Equals(area: Area): boolean {
370
+ return area.start_.row === this.start_.row
371
+ && area.start_.column === this.start_.column
372
+ && area.end_.row === this.end_.row
373
+ && area.end_.column === this.end_.column;
374
+ }
375
+
376
+ public Clone(): Area {
377
+ return new Area(this.start, this.end); // ensure copies
378
+ }
379
+
380
+ public Array(): ICellAddress[] {
381
+ if (this.entire_column || this.entire_row) throw new Error('can\'t convert infinite area to array');
382
+ const array: ICellAddress[] = new Array<ICellAddress>(this.rows * this.columns);
383
+
384
+ const sheet_id = this.start_.sheet_id;
385
+ let index = 0;
386
+
387
+ // does this need sheet ID?
388
+
389
+ for (let row = this.start_.row; row <= this.end_.row; row++){
390
+ for (let column = this.start_.column; column <= this.end_.column; column++){
391
+ array[index++] = { row, column, sheet_id };
392
+ }
393
+ }
394
+ return array;
395
+ }
396
+
397
+ get left(): Area{
398
+ const area = new Area(this.start_, this.end_);
399
+ area.end_.column = area.start_.column;
400
+ return area;
401
+ }
402
+
403
+ get right(): Area{
404
+ const area = new Area(this.start_, this.end_);
405
+ area.start_.column = area.end_.column;
406
+ return area;
407
+ }
408
+
409
+ get top(): Area{
410
+ const area = new Area(this.start_, this.end_);
411
+ area.end_.row = area.start_.row;
412
+ return area;
413
+ }
414
+
415
+ get bottom(): Area{
416
+ const area = new Area(this.start_, this.end_);
417
+ area.start_.row = area.end_.row;
418
+ return area;
419
+ }
420
+
421
+ /** shifts range in place */
422
+ public Shift(rows: number, columns: number): Area {
423
+ this.start_.row += rows;
424
+ this.start_.column += columns;
425
+ this.end_.row += rows;
426
+ this.end_.column += columns;
427
+ return this; // fluent
428
+ }
429
+
430
+ /** Resizes range in place so that it includes the given address */
431
+ public ConsumeAddress(addr: ICellAddress): void {
432
+ if (!this.entire_row){
433
+ if (addr.column < this.start_.column) this.start_.column = addr.column;
434
+ if (addr.column > this.end_.column) this.end_.column = addr.column;
435
+ }
436
+ if (!this.entire_column){
437
+ if (addr.row < this.start_.row) this.start_.row = addr.row;
438
+ if (addr.row > this.end_.row) this.end_.row = addr.row;
439
+ }
440
+ }
441
+
442
+ /** Resizes range in place so that it includes the given area (merge) */
443
+ public ConsumeArea(area: IArea): void {
444
+ this.ConsumeAddress(area.start);
445
+ this.ConsumeAddress(area.end);
446
+ }
447
+
448
+ /** resizes range in place (updates end) */
449
+ public Resize(rows: number, columns: number): Area {
450
+ this.end_.row = this.start_.row + rows - 1;
451
+ this.end_.column = this.start_.column + columns - 1;
452
+ return this; // fluent
453
+ }
454
+
455
+ public Iterate(f: (...args: any[]) => any): void {
456
+ if (this.entire_column || this.entire_row) {
457
+ console.warn(`don't iterate infinite area`);
458
+ return;
459
+ }
460
+ for (let c = this.start_.column; c <= this.end_.column; c++){
461
+ for (let r = this.start_.row; r <= this.end_.row; r++){
462
+ f({column: c, row: r, sheet_id: this.start_.sheet_id});
463
+ }
464
+ }
465
+ }
466
+
467
+ /* *
468
+ * testing: we may have to polyfill for IE11, or just not use it at
469
+ * all, depending on support level... but it works OK (kind of a clumsy
470
+ * implementation though).
471
+ *
472
+ * as it turns out we don't really use iteration that much (I thought
473
+ * we did) so it's probably not worth the polyfill...
474
+ *
475
+ * /
476
+ public next(): IteratorResult<ICellAddress> {
477
+
478
+ // sanity
479
+
480
+ if (this.entire_column || this.entire_row) {
481
+ console.warn('don\'t iterate over infinte range');
482
+ return { value: undefined, done: true };
483
+ }
484
+
485
+ // return current, unless it's OOB; if so, advance
486
+
487
+ if (this.iterator_index.column > this.end.column) {
488
+ this.iterator_index.column = this.start_.column;
489
+ this.iterator_index.row++;
490
+
491
+ if (this.iterator_index.row > this.end.row) {
492
+ this.ResetIterator();
493
+ return { value: undefined, done: true };
494
+ }
495
+
496
+ }
497
+
498
+ const result = { value: { ...this.iterator_index }, done: false };
499
+ this.iterator_index.column++;
500
+
501
+ return result;
502
+ }
503
+
504
+ public [Symbol.iterator](): IterableIterator <ICellAddress> {
505
+ return this;
506
+ }
507
+ */
508
+
509
+ /**
510
+ * returns the range in A1-style spreadsheet addressing. if the
511
+ * entire sheet is selected, returns nothing (there's no way to
512
+ * express that in A1 notation). returns the row numbers for entire
513
+ * columns and vice-versa for rows.
514
+ */
515
+ get spreadsheet_label(): string {
516
+
517
+ let s: string;
518
+
519
+ if (this.entire_sheet) return '';
520
+
521
+ if (this.entire_column){
522
+ s = Area.ColumnToLabel(this.start_.column);
523
+ s += ':' + Area.ColumnToLabel(this.end_.column);
524
+ return s;
525
+ }
526
+
527
+ if (this.entire_row){
528
+ s = String(this.start_.row + 1);
529
+ s += ':' + (this.end_.row + 1);
530
+ return s;
531
+ }
532
+
533
+ s = Area.CellAddressToLabel(this.start_);
534
+ if (this.columns > 1 || this.rows > 1) return s + ':' + Area.CellAddressToLabel(this.end_);
535
+ return s;
536
+
537
+ }
538
+
539
+ /**
540
+ * FIXME: is this different than what would be returned if
541
+ * we just used the default json serializer? (...)
542
+ *
543
+ * NOTE: we could return just the start if size === 1. if
544
+ * you pass an undefined to the Area class ctor it will reuse
545
+ * the start.
546
+ *
547
+ */
548
+ public toJSON(): any {
549
+
550
+ return {
551
+ start: { ...this.start_ },
552
+ end: { ...this.end_ },
553
+ };
554
+
555
+ /*
556
+ return {
557
+ start: {
558
+ row: this.start.row,
559
+ absolute_row: this.start.absolute_row,
560
+ column: this.start.column,
561
+ absolute_column: this.start.absolute_column,
562
+ },
563
+ end: {
564
+ row: this.end.row,
565
+ absolute_row: this.end.absolute_row,
566
+ column: this.end.column,
567
+ absolute_column: this.end.absolute_column,
568
+ },
569
+ };
570
+ */
571
+ }
572
+
573
+ /*
574
+ private ResetIterator() {
575
+ this.iterator_index = {
576
+ row: this.start_.row,
577
+ column: this.start_.column,
578
+ sheet_id: this.start_.sheet_id,
579
+ };
580
+ }
581
+ */
582
+
583
+ }
@@ -0,0 +1,45 @@
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
+ * utility types collected from various other files,
24
+ * attempting to consolidate
25
+ */
26
+
27
+ export interface Size {
28
+ width: number;
29
+ height: number;
30
+ }
31
+
32
+ export interface Point {
33
+ x: number;
34
+ y: number;
35
+ }
36
+
37
+ export interface Position {
38
+ row: number;
39
+ column: number;
40
+ }
41
+
42
+ export interface Extent {
43
+ rows: number;
44
+ columns: number;
45
+ }