@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,60 @@
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 { Area, ICellAddress } from 'treb-base-types';
23
+
24
+ /**
25
+ * FIXME: this is broken. we treat this as a simple javascript object,
26
+ * cloning and creating via JSON, but area is a class instance.
27
+ *
28
+ * that means cloned objects won't work properly (if anyone is relying on
29
+ * that object).
30
+ */
31
+ export interface GridSelection {
32
+
33
+ /** target or main cell in the selection */
34
+ target: ICellAddress;
35
+
36
+ /** selection area */
37
+ area: Area;
38
+
39
+ /** there is nothing selected, even though this object exists */
40
+ empty?: boolean;
41
+
42
+ /** for cacheing addtional selections. optimally don't serialize */
43
+ rendered?: boolean;
44
+
45
+ }
46
+
47
+ /**
48
+ * create an empty selection
49
+ */
50
+ export const CreateSelection = (): GridSelection => {
51
+ return {
52
+ target: {row: 0, column: 0},
53
+ area: new Area({row: 0, column: 0}),
54
+ empty: true,
55
+ };
56
+ };
57
+
58
+ export const CloneSelection = (rhs: GridSelection): GridSelection => {
59
+ return JSON.parse(JSON.stringify(rhs));
60
+ };
@@ -0,0 +1,369 @@
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 { IArea, Area } from 'treb-base-types';
23
+
24
+ /**
25
+ * I want to repurpose named ranges (a little) to allow either values or
26
+ * arbitrary expressions. this is sort of 1/2 way between named ranges and
27
+ * "macro functions".
28
+ *
29
+ * not sure if we should change named ranges, or create a side path for
30
+ * "named expressions".
31
+ */
32
+
33
+ export class NamedRangeCollection {
34
+
35
+ private forward: {[index: string]: Area} = {};
36
+ private backward: Array<{name: string; range: Area}> = [];
37
+
38
+ /** FIXME: why not an accessor? */
39
+ public Count(): number {
40
+ return this.backward.length;
41
+ }
42
+
43
+ /** FIXME: why not just use toJSON? */
44
+ public Serialize(): Record<string, IArea> {
45
+ return JSON.parse(JSON.stringify(this.Map()));
46
+ }
47
+
48
+ public Deserialize(data?: Record<string, IArea>): void {
49
+ this.Reset();
50
+ if (data) {
51
+ for (const key of Object.keys(data)) {
52
+ this.SetName(key, new Area(data[key].start, data[key].end), false);
53
+ }
54
+ this.RebuildList();
55
+ }
56
+ }
57
+
58
+ /**
59
+ * match an area, optionally a target within a larger area (for selections).
60
+ * we don't use the selection directly, as we may need to adjust target for
61
+ * merge area.
62
+ */
63
+ public MatchSelection(area: Area, target?: Area): string|undefined {
64
+
65
+ if (!area.start.sheet_id) {
66
+ throw new Error('match selection without sheet id');
67
+ }
68
+
69
+ let label: string|undefined;
70
+ for (const entry of this.List()) {
71
+ if (entry.range.start.sheet_id === area.start.sheet_id) {
72
+ if (entry.range.Equals(area)) {
73
+ label = entry.name; // don't break, in case there's a match for target which takes precendence.
74
+ }
75
+ if (target?.Equals(entry.range)) {
76
+ return entry.name;
77
+ }
78
+ }
79
+ }
80
+ return label;
81
+ }
82
+
83
+ /**
84
+ * add name. names are case-insensitive. if the name already
85
+ * exists, it will be overwritten.
86
+ *
87
+ * update: returns success (FIXME: proper errors)
88
+ */
89
+ public SetName(name: string, range: Area, apply = true): boolean {
90
+ const validated = this.ValidateNamed(name);
91
+ if (!validated) {
92
+ console.warn('invalid name');
93
+ return false;
94
+ }
95
+ if (range.entire_column || range.entire_row) {
96
+ console.warn('invalid range');
97
+ return false;
98
+ }
99
+ this.forward[validated] = range;
100
+ if (apply) {
101
+ this.RebuildList();
102
+ }
103
+ return true;
104
+ }
105
+
106
+ public SetNames(list: {[index: string]: IArea}): void {
107
+ for (const key of Object.keys(list)) {
108
+ const area = list[key];
109
+ this.SetName(key, new Area(area.start, area.end), false);
110
+ }
111
+ this.RebuildList();
112
+ }
113
+
114
+ public ClearName(name: string, apply = true): void {
115
+ delete this.forward[name];
116
+ if (apply) {
117
+ this.RebuildList();
118
+ }
119
+ }
120
+
121
+ /**
122
+ * if we delete a sheet, remove ranges in that sheet
123
+ * @param sheet_id
124
+ */
125
+ public RemoveRangesForSheet(sheet_id: number, apply = true) {
126
+
127
+ const temp: {[index: string]: Area} = {};
128
+ const list = this.List();
129
+
130
+ for (const entry of list) {
131
+ if (entry.range.start.sheet_id !== sheet_id) {
132
+ temp[entry.name] = entry.range;
133
+ }
134
+ }
135
+
136
+ this.forward = temp;
137
+
138
+ if (apply) {
139
+ this.RebuildList();
140
+ }
141
+ }
142
+
143
+ public Reset(): void {
144
+ this.forward = {};
145
+ this.backward = [];
146
+ }
147
+
148
+ public Get(name: string) {
149
+ return this.forward[name.toUpperCase()];
150
+ }
151
+
152
+ /** FIXME: accessor */
153
+ public Map() {
154
+ return this.forward;
155
+ }
156
+
157
+ /** FIXME: accessor */
158
+ public List() {
159
+ return this.backward;
160
+ }
161
+
162
+ /**
163
+ * named range rules:
164
+ *
165
+ * - legal characters are alphanumeric, underscore and dot.
166
+ * - must start with letter or underscore (not a number or dot).
167
+ * - cannot look like a spreadsheet address, which is 1-3 letters followed by numbers.
168
+ *
169
+ * returns a normalized name (just caps, atm)
170
+ */
171
+ public ValidateNamed(name: string): string|false {
172
+ name = name.trim();
173
+ if (!name.length) return false;
174
+ if (/^[A-Za-z]{1,3}\d+$/.test(name)) return false;
175
+ if (/[^A-Za-z\d_.]/.test(name)) return false;
176
+ if (/^[^A-Za-z_]/.test(name)) return false;
177
+ return name.toUpperCase();
178
+ }
179
+
180
+ // was in sheet
181
+
182
+
183
+ /**
184
+ * fix named range references after row/column insert/delete
185
+ */
186
+ public PatchNamedRanges(sheet_id: number, before_column: number, column_count: number, before_row: number, row_count: number) {
187
+
188
+ const copy = this.List().slice(0);
189
+
190
+ for (const entry of copy) {
191
+
192
+ const key = entry.name;
193
+ const range = entry.range;
194
+
195
+ if (range.start.sheet_id !== sheet_id) {
196
+ console.info('skipping name', key);
197
+ continue;
198
+ }
199
+
200
+ if (column_count && before_column <= range.end.column) {
201
+
202
+ /*
203
+ // (1) we are before the insert point, not affected
204
+
205
+ if (before_column > range.end.column) {
206
+ continue;
207
+ }
208
+ */
209
+
210
+ if (column_count > 0) {
211
+
212
+ // (2) it's an insert and we are past the insert point:
213
+ // increment [start] and [end] by [count]
214
+
215
+ if (before_column <= range.start.column) {
216
+ range.Shift(0, column_count);
217
+ }
218
+
219
+ // (3) it's an insert and we contain the insert point:
220
+ // increment [end] by [count]
221
+
222
+ else if (before_column > range.start.column && before_column <= range.end.column) {
223
+ range.ConsumeAddress({row: range.end.row, column: range.end.column + column_count});
224
+ }
225
+
226
+ else {
227
+ console.warn(`PNR X case 1`, before_column, column_count, JSON.stringify(range));
228
+ }
229
+
230
+ }
231
+ else if (column_count < 0) {
232
+
233
+ // (4) it's a delete and we are past the delete point (before+count):
234
+ // decrement [start] and [end] by [count]
235
+
236
+ if (before_column - column_count <= range.start.column) {
237
+ range.Shift(0, column_count);
238
+ }
239
+
240
+ // (5) it's a delete and contains the entire range
241
+
242
+ else if (before_column <= range.start.column && before_column - column_count > range.end.column) {
243
+ this.ClearName(key, false);
244
+ }
245
+
246
+ // (6) it's a delete and contains part of the range. clip the range.
247
+
248
+ else if (before_column <= range.start.column) {
249
+ const last_column = before_column - column_count - 1;
250
+ this.SetName(key, new Area({
251
+ row: range.start.row, column: last_column + 1 + column_count, sheet_id }, {
252
+ row: range.end.row, column: range.end.column + column_count }), false);
253
+ }
254
+
255
+ else if (before_column <= range.end.column) {
256
+ const last_column = before_column - column_count - 1;
257
+
258
+ if (last_column >= range.end.column) {
259
+ this.SetName(key, new Area({
260
+ row: range.start.row, column: range.start.column, sheet_id }, {
261
+ row: range.end.row, column: before_column - 1 }), false);
262
+ }
263
+ else {
264
+ this.SetName(key, new Area({
265
+ row: range.start.row, column: range.start.column, sheet_id }, {
266
+ row: range.end.row, column: range.start.column + range.columns + column_count - 1}), false);
267
+ }
268
+
269
+ }
270
+
271
+ else {
272
+ console.warn(`PNR X case 2`, before_column, column_count, JSON.stringify(range));
273
+ }
274
+
275
+ }
276
+ }
277
+
278
+
279
+ if (row_count && before_row <= range.end.row) {
280
+
281
+ /*
282
+ // (1) we are before the insert point, not affected
283
+
284
+ if (before_row > range.end.row) {
285
+ continue;
286
+ }
287
+ */
288
+
289
+ if (row_count > 0) {
290
+
291
+ // (2) it's an insert and we are past the insert point:
292
+ // increment [start] and [end] by [count]
293
+
294
+ if (before_row <= range.start.row) {
295
+ range.Shift(row_count, 0);
296
+ }
297
+
298
+ // (3) it's an insert and we contain the insert point:
299
+ // increment [end] by [count]
300
+
301
+ else if (before_row > range.start.row && before_row <= range.end.row) {
302
+ range.ConsumeAddress({row: range.end.row + row_count, column: range.end.column});
303
+ }
304
+
305
+ else {
306
+ console.warn(`PNR X case 3`, before_row, row_count, JSON.stringify(range));
307
+ }
308
+
309
+ }
310
+ else if (row_count < 0) {
311
+
312
+ // (4) it's a delete and we are past the delete point (before+count):
313
+ // decrement [start] and [end] by [count]
314
+
315
+ if (before_row - row_count <= range.start.row) {
316
+ range.Shift(row_count, 0);
317
+ }
318
+
319
+ // (5) it's a delete and contains the entire range
320
+
321
+ else if (before_row <= range.start.row && before_row - row_count > range.end.row) {
322
+ this.ClearName(key, false);
323
+ }
324
+
325
+ // (6) it's a delete and contains part of the range. clip the range.
326
+
327
+ else if (before_row <= range.start.row) {
328
+ const last_row = before_row - row_count - 1;
329
+ this.SetName(key, new Area({
330
+ column: range.start.column, row: last_row + 1 + row_count, sheet_id }, {
331
+ column: range.end.column, row: range.end.row + row_count }), false);
332
+ }
333
+
334
+ else if (before_row <= range.end.row) {
335
+ const last_row = before_row - row_count - 1;
336
+ if (last_row >= range.end.row) {
337
+ this.SetName(key, new Area({
338
+ column: range.start.column, row: range.start.row, sheet_id }, {
339
+ column: range.end.column, row: before_row - 1 }), false);
340
+ }
341
+ else {
342
+ this.SetName(key, new Area({
343
+ column: range.start.column, row: range.start.row, sheet_id }, {
344
+ column: range.end.column, row: range.start.row + range.rows + row_count - 1 }), false);
345
+ }
346
+
347
+ }
348
+
349
+ else {
350
+ console.warn(`PNR X case 4`, before_row, row_count, JSON.stringify(range));
351
+ }
352
+
353
+ }
354
+ }
355
+
356
+ }
357
+
358
+ this.RebuildList();
359
+
360
+ }
361
+
362
+ public RebuildList(): void {
363
+ this.backward = [];
364
+ for (const key of Object.keys(this.forward)) {
365
+ this.backward.push({ name: key, range: this.forward[key] });
366
+ }
367
+ }
368
+
369
+ }
@@ -0,0 +1,202 @@
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
+ import { DOMUtilities as DOM } from '../util/dom_utilities';
23
+ import { NumberFormat, NumberFormatCache, ValueParser } from 'treb-format';
24
+ import { ValueType } from 'treb-base-types';
25
+ import { EventSource } from 'treb-utils';
26
+
27
+ export interface ScaleEvent {
28
+ type: 'scale';
29
+ // action: 'increase'|'decrease'|number;
30
+ value: number;
31
+ keep_focus?: boolean;
32
+ }
33
+
34
+ /**
35
+ * updated scale control, broken out. this is based on what we did for
36
+ * project planning, which worked out rather nicely.
37
+ */
38
+
39
+ export class ScaleControl extends EventSource<ScaleEvent> {
40
+
41
+ private input: HTMLInputElement;
42
+ private slider: HTMLInputElement;
43
+ private scale = 0;
44
+ private format: NumberFormat;
45
+
46
+ private timeout = 0;
47
+
48
+ public constructor(public container: HTMLElement) {
49
+ super();
50
+
51
+ this.format = NumberFormatCache.Get('0.0');
52
+
53
+ // not sure what this extra div was for, we don't need it
54
+ // const div = DOM.CreateDiv('treb-scale-control-2', container);
55
+
56
+ this.input = DOM.Create('input', 'treb-scale-input', /* div */ container);
57
+ const popup = DOM.CreateDiv('treb-slider-container', /* div */ container);
58
+
59
+ /*
60
+ this.input.addEventListener('keyup', (event) => {
61
+ switch (event.key) {
62
+ case 'ArrowUp':
63
+ case 'ArrowDown':
64
+ event.stopPropagation();
65
+ event.preventDefault();
66
+ break;
67
+ }
68
+ });
69
+ */
70
+
71
+ // is this for some x-browser issue? or did we just not
72
+ // know which event to use and this is old junk?
73
+
74
+ this.input.addEventListener('keypress', (event) => {
75
+ switch (event.key) {
76
+ case 'ArrowUp':
77
+ case 'ArrowDown':
78
+ event.stopPropagation();
79
+ event.preventDefault();
80
+ console.info('mark?');
81
+ break;
82
+ }
83
+ })
84
+
85
+ // this is the one we want
86
+
87
+ this.input.addEventListener('keydown', (event) => {
88
+ switch (event.key) {
89
+ case 'Enter':
90
+ this.input.blur();
91
+ break;
92
+
93
+ case 'ArrowUp':
94
+ this.Tick(-1);
95
+ break;
96
+
97
+ case 'ArrowDown':
98
+ this.Tick(1);
99
+ break;
100
+
101
+ case 'Escape':
102
+ this.input.value = this.format.Format(this.scale) + '%';
103
+ this.input.blur();
104
+ break;
105
+
106
+ default:
107
+ return;
108
+
109
+ }
110
+
111
+ event.stopPropagation();
112
+ event.preventDefault();
113
+
114
+ });
115
+
116
+ // select text on click
117
+ this.input.addEventListener('focusin', () => this.input.select());
118
+
119
+ this.input.addEventListener('change', () => {
120
+
121
+ // what we're doing here is a little unusual. we always treat
122
+ // the value as a percent, even if there's no percent sign.
123
+
124
+ // for that to work, if there is a percent sign, we need to remove
125
+ // it before we continue. then try to parse as a number.
126
+
127
+ let text = this.input.value;
128
+ text = text.replace(/%/g, '');
129
+
130
+ const value = ValueParser.TryParse(text);
131
+ if (value.type === ValueType.number) {
132
+ this.UpdateScale(Number(value.value), true);
133
+ }
134
+ else {
135
+ this.input.value = this.format.Format(this.scale) + '%';
136
+ }
137
+
138
+ });
139
+
140
+ this.slider = DOM.Create<HTMLInputElement>('input', undefined, popup, undefined, {
141
+ type: 'range',
142
+ min: '50',
143
+ max: '200',
144
+ value: '100',
145
+ step: '2.5',
146
+ });
147
+
148
+ this.slider.addEventListener('input', () => {
149
+ this.UpdateScale(Number(this.slider.value), true);
150
+ });
151
+
152
+ /* div */ container.addEventListener('wheel', (event: WheelEvent) => {
153
+ event.stopPropagation();
154
+ event.preventDefault();
155
+ this.Tick(event.deltaY)
156
+ });
157
+
158
+ }
159
+
160
+ public Tick(value: number): void {
161
+
162
+ // not sure what alternate case I am worried about here,
163
+ // sideways wheel? shift key?
164
+
165
+ // normalize
166
+
167
+ const scale = Math.round(this.scale / 2.5) * 2.5;
168
+
169
+ if (value > 0) {
170
+ this.UpdateScale(scale - 2.5, true, true);
171
+ }
172
+ else if (value < 0){
173
+ this.UpdateScale(scale + 2.5, true, true);
174
+ }
175
+
176
+ }
177
+
178
+ public UpdateScale(scale: number, notify = false, keep_focus = false): void {
179
+
180
+ scale = Math.max(50, Math.min(200, scale));
181
+ if (scale !== this.scale) {
182
+ this.scale = scale;
183
+ this.input.value = this.format.Format(scale) + '%';
184
+ this.slider.value = scale.toFixed(1);
185
+
186
+ if (notify) {
187
+ if (!this.timeout) {
188
+ this.timeout = requestAnimationFrame(() => {
189
+ this.timeout = 0;
190
+ this.Publish({
191
+ type: 'scale',
192
+ value: this.scale / 100,
193
+ keep_focus,
194
+ });
195
+ });
196
+ }
197
+ }
198
+ }
199
+ }
200
+
201
+ }
202
+
@@ -0,0 +1,72 @@
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
+ * options for serializing data
24
+ *
25
+ * @privateRemarks
26
+ * essentially a placeholder for options; we only have one at the moment.
27
+ *
28
+ * note that the underlying cells container has its own set of options. we
29
+ * are explicitly not using that so we can add things that are beyond that
30
+ * scope.
31
+ *
32
+ * still, we might just wrap that object [FIXME/TODO].
33
+ */
34
+ export interface SerializeOptions {
35
+
36
+ /** optimize for size */
37
+ optimize?: 'size'|'speed';
38
+
39
+ /** include the rendered/calculated value in export */
40
+ rendered_values?: boolean;
41
+
42
+ /**
43
+ * preserve cell type
44
+ * @internal
45
+ */
46
+ preserve_type?: boolean;
47
+
48
+ /**
49
+ * expand arrays so cells have individual values
50
+ * @internal
51
+ */
52
+ expand_arrays?: boolean;
53
+
54
+ /** translate colors to xlsx-friendly values */
55
+ export_colors?: boolean;
56
+
57
+ /** export cells that have no value, but have a border or background color */
58
+ decorated_cells?: boolean;
59
+
60
+ /** prune unused rows/columns */
61
+ shrink?: boolean;
62
+
63
+ /**
64
+ * include tables. tables will be serialized in the model, so we can
65
+ * drop them from cells. but you can leave them in if that's useful.
66
+ */
67
+ tables?: boolean;
68
+
69
+ /** share resources (images, for now) to prevent writing data URIs more than once */
70
+ share_resources?: boolean;
71
+
72
+ }