@trebco/treb 28.5.1 → 28.7.0

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 (162) hide show
  1. package/dist/treb-spreadsheet-light.mjs +15 -15
  2. package/dist/treb-spreadsheet.mjs +15 -15
  3. package/dist/treb.d.ts +1 -1
  4. package/package.json +1 -1
  5. package/treb-base-types/src/api_types.ts +1 -1
  6. package/treb-base-types/src/area.ts +1 -1
  7. package/treb-base-types/src/basic_types.ts +21 -21
  8. package/treb-base-types/src/cell.ts +1 -1
  9. package/treb-base-types/src/cells.ts +1 -1
  10. package/treb-base-types/src/color.ts +1 -1
  11. package/treb-base-types/src/dom-utilities.ts +1 -1
  12. package/treb-base-types/src/import.ts +1 -1
  13. package/treb-base-types/src/index-standalone.ts +9 -9
  14. package/treb-base-types/src/index.ts +1 -1
  15. package/treb-base-types/src/layout.ts +21 -21
  16. package/treb-base-types/src/localization.ts +21 -21
  17. package/treb-base-types/src/rectangle.ts +1 -1
  18. package/treb-base-types/src/render_text.ts +1 -1
  19. package/treb-base-types/src/style.ts +1 -1
  20. package/treb-base-types/src/table.ts +1 -1
  21. package/treb-base-types/src/text_part.ts +21 -21
  22. package/treb-base-types/src/theme.ts +1 -1
  23. package/treb-base-types/src/union.ts +1 -1
  24. package/treb-base-types/src/value-type.ts +1 -1
  25. package/treb-base-types/style/resizable.css +21 -21
  26. package/treb-calculator/src/calculator.ts +1 -1
  27. package/treb-calculator/src/complex-math.ts +1 -1
  28. package/treb-calculator/src/dag/array-vertex.ts +1 -1
  29. package/treb-calculator/src/dag/calculation_leaf_vertex.ts +1 -1
  30. package/treb-calculator/src/dag/graph.ts +1 -1
  31. package/treb-calculator/src/dag/spreadsheet_vertex.ts +1 -1
  32. package/treb-calculator/src/dag/spreadsheet_vertex_base.ts +21 -21
  33. package/treb-calculator/src/dag/state_leaf_vertex.ts +1 -1
  34. package/treb-calculator/src/dag/vertex.ts +21 -21
  35. package/treb-calculator/src/descriptors.ts +1 -1
  36. package/treb-calculator/src/expression-calculator.ts +1 -1
  37. package/treb-calculator/src/function-error.ts +1 -1
  38. package/treb-calculator/src/function-library.ts +1 -1
  39. package/treb-calculator/src/functions/base-functions.ts +1 -1
  40. package/treb-calculator/src/functions/checkbox.ts +1 -1
  41. package/treb-calculator/src/functions/complex-functions.ts +1 -1
  42. package/treb-calculator/src/functions/finance-functions.ts +1 -1
  43. package/treb-calculator/src/functions/information-functions.ts +1 -1
  44. package/treb-calculator/src/functions/matrix-functions.ts +1 -1
  45. package/treb-calculator/src/functions/sparkline.ts +1 -1
  46. package/treb-calculator/src/functions/statistics-functions.ts +1 -1
  47. package/treb-calculator/src/functions/text-functions.ts +1 -1
  48. package/treb-calculator/src/index.ts +1 -1
  49. package/treb-calculator/src/notifier-types.ts +1 -1
  50. package/treb-calculator/src/primitives.ts +1 -1
  51. package/treb-calculator/src/utilities.ts +1 -1
  52. package/treb-charts/src/chart-functions.ts +1 -1
  53. package/treb-charts/src/chart-types.ts +21 -21
  54. package/treb-charts/src/chart-utils.ts +696 -0
  55. package/treb-charts/src/chart.ts +92 -1291
  56. package/treb-charts/src/default-chart-renderer.ts +535 -0
  57. package/treb-charts/src/index.ts +5 -4
  58. package/treb-charts/src/main.ts +17 -17
  59. package/treb-charts/src/rectangle.ts +21 -21
  60. package/treb-charts/src/renderer-type.ts +32 -0
  61. package/treb-charts/src/renderer.ts +1 -1
  62. package/treb-charts/src/util.ts +1 -1
  63. package/treb-charts/style/charts.scss +1 -1
  64. package/treb-charts/style/old-charts.scss +21 -21
  65. package/treb-embed/src/embedded-spreadsheet.ts +15 -12
  66. package/treb-embed/src/language-model.ts +1 -1
  67. package/treb-embed/src/options.ts +30 -1
  68. package/treb-embed/src/progress-dialog.ts +1 -1
  69. package/treb-embed/src/spinner.ts +1 -1
  70. package/treb-embed/src/types.ts +1 -1
  71. package/treb-embed/style/autocomplete.scss +1 -1
  72. package/treb-embed/style/dark-theme.scss +1 -1
  73. package/treb-embed/style/defaults.scss +1 -1
  74. package/treb-embed/style/dialog.scss +1 -1
  75. package/treb-embed/style/dropdown-select.scss +1 -1
  76. package/treb-embed/style/formula-bar.scss +1 -1
  77. package/treb-embed/style/grid.scss +1 -1
  78. package/treb-embed/style/mouse-mask.scss +1 -1
  79. package/treb-embed/style/note.scss +1 -1
  80. package/treb-embed/style/overlay-editor.scss +1 -1
  81. package/treb-embed/style/spinner.scss +1 -1
  82. package/treb-embed/style/tab-bar.scss +1 -1
  83. package/treb-embed/style/table.scss +1 -1
  84. package/treb-embed/style/theme-defaults.scss +1 -1
  85. package/treb-embed/style/tooltip.scss +1 -1
  86. package/treb-embed/style/z-index.scss +1 -1
  87. package/treb-export/src/address-type.ts +21 -21
  88. package/treb-export/src/base-template.ts +1 -1
  89. package/treb-export/src/column-width.ts +1 -1
  90. package/treb-export/src/drawing2/chart-template-components2.ts +1 -1
  91. package/treb-export/src/drawing2/chart2.ts +1 -1
  92. package/treb-export/src/drawing2/column-chart-template2.ts +1 -1
  93. package/treb-export/src/drawing2/donut-chart-template2.ts +1 -1
  94. package/treb-export/src/drawing2/drawing2.ts +1 -1
  95. package/treb-export/src/drawing2/embedded-image.ts +1 -1
  96. package/treb-export/src/drawing2/scatter-chart-template2.ts +1 -1
  97. package/treb-export/src/export-worker/export-worker.ts +1 -1
  98. package/treb-export/src/export-worker/index.worker.ts +1 -1
  99. package/treb-export/src/export2.ts +1 -1
  100. package/treb-export/src/import2.ts +1 -1
  101. package/treb-export/src/relationship.ts +1 -1
  102. package/treb-export/src/shared-strings2.ts +1 -1
  103. package/treb-export/src/template-2.ts +2 -2
  104. package/treb-export/src/workbook-sheet2.ts +1 -1
  105. package/treb-export/src/workbook-style2.ts +1 -1
  106. package/treb-export/src/workbook-theme2.ts +1 -1
  107. package/treb-export/src/workbook2.ts +1 -1
  108. package/treb-export/src/xml-utils.ts +1 -1
  109. package/treb-format/src/format.test.ts +21 -21
  110. package/treb-format/src/format.ts +1 -1
  111. package/treb-format/src/format_cache.ts +21 -21
  112. package/treb-format/src/format_parser.ts +1 -1
  113. package/treb-format/src/index.ts +4 -4
  114. package/treb-format/src/number_format_section.ts +21 -21
  115. package/treb-format/src/value_parser.ts +1 -1
  116. package/treb-grid/src/editors/autocomplete.ts +1 -1
  117. package/treb-grid/src/editors/autocomplete_matcher.ts +21 -21
  118. package/treb-grid/src/editors/editor.ts +1 -1
  119. package/treb-grid/src/editors/formula_bar.ts +1 -1
  120. package/treb-grid/src/editors/overlay_editor.ts +1 -1
  121. package/treb-grid/src/index.ts +1 -1
  122. package/treb-grid/src/layout/base_layout.ts +1 -1
  123. package/treb-grid/src/layout/grid_layout.ts +1 -1
  124. package/treb-grid/src/layout/rectangle_cache.ts +21 -21
  125. package/treb-grid/src/render/selection-renderer.ts +1 -1
  126. package/treb-grid/src/render/svg_header_overlay.ts +1 -1
  127. package/treb-grid/src/render/svg_selection_block.ts +1 -1
  128. package/treb-grid/src/render/tile_renderer.ts +1 -1
  129. package/treb-grid/src/types/annotation.ts +1 -1
  130. package/treb-grid/src/types/border_constants.ts +1 -1
  131. package/treb-grid/src/types/clipboard_data.ts +1 -1
  132. package/treb-grid/src/types/data_model.ts +1 -1
  133. package/treb-grid/src/types/drag_mask.ts +21 -21
  134. package/treb-grid/src/types/grid.ts +1 -1
  135. package/treb-grid/src/types/grid_base.ts +1 -1
  136. package/treb-grid/src/types/grid_command.ts +1 -1
  137. package/treb-grid/src/types/grid_events.ts +1 -1
  138. package/treb-grid/src/types/grid_options.ts +1 -1
  139. package/treb-grid/src/types/grid_selection.ts +1 -1
  140. package/treb-grid/src/types/named_range.ts +1 -1
  141. package/treb-grid/src/types/scale-control.ts +1 -1
  142. package/treb-grid/src/types/serialize_options.ts +1 -1
  143. package/treb-grid/src/types/set_range_options.ts +1 -1
  144. package/treb-grid/src/types/sheet.ts +1 -1
  145. package/treb-grid/src/types/sheet_types.ts +1 -1
  146. package/treb-grid/src/types/tab_bar.ts +1 -1
  147. package/treb-grid/src/types/tile.ts +21 -21
  148. package/treb-grid/src/types/update_flags.ts +1 -1
  149. package/treb-grid/src/util/fontmetrics2.ts +1 -1
  150. package/treb-grid/src/util/ua.ts +21 -21
  151. package/treb-parser/src/csv-parser.ts +21 -21
  152. package/treb-parser/src/index.ts +5 -5
  153. package/treb-parser/src/md-parser.ts +1 -1
  154. package/treb-parser/src/parser-types.ts +1 -1
  155. package/treb-parser/src/parser.test.ts +21 -21
  156. package/treb-parser/src/parser.ts +1 -1
  157. package/treb-utils/src/event_source.ts +1 -1
  158. package/treb-utils/src/ievent_source.ts +13 -13
  159. package/treb-utils/src/index.ts +1 -1
  160. package/treb-utils/src/measurement.ts +1 -1
  161. package/treb-utils/src/scale.ts +21 -21
  162. package/treb-utils/src/serialize_html.ts +1 -1
@@ -0,0 +1,535 @@
1
+
2
+ import type { ChartRenderer as ChartRendererType } from './renderer-type';
3
+
4
+ import type { Metrics } from './renderer';
5
+ import { ChartRenderer } from './renderer';
6
+ import { Area } from './rectangle';
7
+ import { Util } from './util';
8
+ import type { ChartData } from './chart-types';
9
+ import { LegendLayout, LegendPosition } from './chart-types';
10
+
11
+ /**
12
+ * this class contains the original chart rendering functions, mapped
13
+ * to the new interface.
14
+ */
15
+ export class DefaultChartRenderer implements ChartRendererType {
16
+
17
+ private renderer = new ChartRenderer();
18
+
19
+ // not chart-specific, so leave outside (FIXME: layout options?)
20
+
21
+ // FIXME: change depending on whether there are y-axis labels
22
+ // FIXME: different for donut charts...
23
+
24
+ private margin = { top: 0.025, left: 0.05, bottom: 0.025, right: 0.075 };
25
+
26
+ public Resize(target: HTMLElement, data: ChartData) {
27
+ this.renderer.Resize();
28
+ }
29
+
30
+ public Initialize(target: HTMLElement) {
31
+ this.renderer.Initialize(target);
32
+ }
33
+
34
+ /**
35
+ * redraw
36
+ */
37
+ public Update(target: HTMLElement, chart_data: ChartData) {
38
+
39
+ // reset
40
+ this.renderer.Resize(); // just too many problems
41
+ this.renderer.Prerender();
42
+ this.renderer.Clear(chart_data.class_name);
43
+
44
+ // get usable area [FIXME: method]
45
+ const area = new Area(0, 0, this.renderer.size.width, this.renderer.size.height);
46
+
47
+ // chart margin
48
+ const chart_margin = {
49
+ top: Math.round(area.height) * this.margin.top,
50
+ bottom: Math.round(area.height) * this.margin.bottom,
51
+ left: Math.round(area.width) * this.margin.left,
52
+ right: Math.round(area.width) * this.margin.right,
53
+ };
54
+
55
+ // title, top or bottom
56
+ const title = chart_data.title;
57
+
58
+ if (title) {
59
+ this.renderer.RenderTitle(title, area, chart_margin.top,
60
+ chart_data.title_layout||'top');
61
+ }
62
+
63
+ // pad
64
+ area.top += chart_margin.top;
65
+ area.left += chart_margin.left;
66
+ area.bottom -= chart_margin.bottom;
67
+ area.right -= chart_margin.right;
68
+
69
+ if (chart_data.legend && chart_data.legend.length) {
70
+
71
+ let default_position = LegendPosition.top;
72
+ if (chart_data.title) {
73
+ if (!chart_data.title_layout || chart_data.title_layout === 'top') {
74
+ default_position = LegendPosition.bottom;
75
+ }
76
+ }
77
+
78
+ const position = chart_data.legend_position || default_position;
79
+
80
+ this.renderer.Legend({
81
+ labels: chart_data.legend,
82
+ position,
83
+ style: chart_data.legend_style,
84
+ layout: (position === LegendPosition.top || position === LegendPosition.bottom) ?
85
+ LegendLayout.horizontal : LegendLayout.vertical,
86
+ area,
87
+ });
88
+
89
+ }
90
+
91
+ if (chart_data.type === 'histogram'
92
+ || chart_data.type === 'line'
93
+ || chart_data.type === 'area'
94
+ || chart_data.type === 'column'
95
+ || chart_data.type === 'histogram2'
96
+ || chart_data.type === 'bar'
97
+ || chart_data.type === 'scatter2'
98
+ ) {
99
+
100
+ // we need to measure first, then lay out the other axis, then we
101
+ // can come back and render. it doesn't really matter which one you
102
+ // do first.
103
+
104
+ // measure x axis (height)
105
+
106
+ let x_metrics: Metrics[] = [];
107
+ let max_x_height = 0;
108
+
109
+ if (chart_data.x_labels && chart_data.x_labels.length) {
110
+ x_metrics = chart_data.x_labels.map((text) => {
111
+ const metrics = this.renderer.MeasureText(text, ['axis-label', 'x-axis-label'], true);
112
+ max_x_height = Math.max(max_x_height, metrics.height);
113
+ return metrics;
114
+ });
115
+ }
116
+
117
+ // measure & render y axis
118
+
119
+ if (chart_data.y_labels && chart_data.y_labels.length) {
120
+
121
+ const y_labels: Array<{label: string; metrics: Metrics}> = [];
122
+ let max_width = 0;
123
+ let max_height = 0;
124
+
125
+ const scale = (chart_data.type === 'scatter2') ? chart_data.y_scale : chart_data.scale;
126
+
127
+ const count = (chart_data.type === 'bar') ?
128
+ chart_data.y_labels.length :
129
+ /* chart_data. */
130
+ scale.count + 1;
131
+
132
+ for (let i = 0; i < count; i++ ){
133
+ const metrics = this.renderer.MeasureText(chart_data.y_labels[i], ['axis-label', 'y-axis-label']);
134
+ y_labels.push({ label: chart_data.y_labels[i], metrics });
135
+ max_width = Math.max(max_width, metrics.width);
136
+ max_height = Math.max(max_height, metrics.height);
137
+ }
138
+
139
+ area.bottom = Math.round(area.bottom - max_height / 2);
140
+ area.top = Math.round(area.top + max_height / 2);
141
+
142
+ if (x_metrics.length) {
143
+ area.bottom -= (max_x_height + chart_margin.bottom);
144
+ }
145
+
146
+ if (chart_data.type === 'bar') {
147
+ this.renderer.RenderYAxisBar(area, area.left + max_width, y_labels, ['axis-label', 'y-axis-label']);
148
+ }
149
+ else {
150
+ this.renderer.RenderYAxis(area, area.left + max_width, y_labels, ['axis-label', 'y-axis-label']);
151
+ }
152
+ area.left += (max_width + chart_margin.left);
153
+
154
+ }
155
+
156
+ // now render x axis
157
+
158
+ if (x_metrics.length && chart_data.x_labels && chart_data.x_labels.length) {
159
+
160
+ const tick = (chart_data.type === 'histogram2');
161
+ const offset_tick = (
162
+ chart_data.type !== 'line' &&
163
+ chart_data.type !== 'area' &&
164
+ chart_data.type !== 'bar' &&
165
+ chart_data.type !== 'scatter2' &&
166
+ chart_data.type !== 'histogram2'
167
+ );
168
+
169
+ // do this before you fix the offset
170
+
171
+ if (tick) {
172
+ this.renderer.RenderXAxisTicks(area, offset_tick, chart_data.x_labels.length);
173
+ }
174
+
175
+
176
+ if (chart_data.y_labels) {
177
+ // undo, temp
178
+ area.bottom += (max_x_height + chart_margin.bottom);
179
+ }
180
+
181
+ // render
182
+ this.renderer.RenderXAxis(area,
183
+ offset_tick,
184
+ chart_data.x_labels,
185
+ x_metrics,
186
+ ['axis-label', 'x-axis-label']);
187
+
188
+ // update bottom (either we unwound for labels, or we need to do it the first time)
189
+ area.bottom -= (max_x_height + chart_margin.bottom);
190
+
191
+ }
192
+
193
+ }
194
+
195
+ // now do type-specific rendering
196
+
197
+ switch (chart_data.type) {
198
+ case 'scatter':
199
+ this.renderer.RenderPoints(area, chart_data.x, chart_data.y, 'mc mc-correlation series-1');
200
+ break;
201
+
202
+ case 'scatter2':
203
+
204
+ this.renderer.RenderGrid(area,
205
+ chart_data.y_scale.count,
206
+ chart_data.x_scale.count + 1, // (sigh)
207
+ 'chart-grid');
208
+
209
+ if (chart_data.series) {
210
+ for (let i = 0; i < chart_data.series.length; i++) {
211
+ const series = chart_data.series[i];
212
+
213
+ let lines = !!chart_data.lines;
214
+ let points = !!chart_data.points;
215
+
216
+ if (series.subtype === 'plot') {
217
+ points = true;
218
+ lines = false;
219
+ }
220
+ else if (series.subtype === 'line') {
221
+ points = false;
222
+ lines = true;
223
+ }
224
+
225
+ const index = typeof series.index === 'number' ? series.index : i + 1;
226
+ this.renderer.RenderScatterSeries(area,
227
+ series.x.data,
228
+ series.y.data,
229
+ chart_data.x_scale,
230
+ chart_data.y_scale,
231
+ lines,
232
+ points,
233
+ !!chart_data.filled,
234
+ !!chart_data.markers,
235
+ !!chart_data.smooth,
236
+ `scatter-plot series-${index}`);
237
+ }
238
+ if (chart_data.data_labels) {
239
+ for (let i = 0; i < chart_data.series.length; i++) {
240
+ const series = chart_data.series[i];
241
+ if (series.y.labels) {
242
+ this.renderer.RenderDataLabels(
243
+ area,
244
+ series.x.data,
245
+ series.y.data,
246
+ chart_data.x_scale,
247
+ chart_data.y_scale,
248
+ series.y.labels,
249
+ i + 1);
250
+ }
251
+ }
252
+ }
253
+ }
254
+ break;
255
+
256
+ case 'pie':
257
+ case 'donut':
258
+ {
259
+ const outer = (Math.min(area.height, area.width) / 2) * .9;
260
+ const inner = chart_data.type === 'pie' ? 0 : outer * .8;
261
+ this.renderer.RenderDonut(chart_data.slices, area.center, outer, inner, area,
262
+ true, 'donut');
263
+ }
264
+ break;
265
+
266
+ case 'line':
267
+ case 'area':
268
+ {
269
+ const scale = chart_data.scale;
270
+ if (chart_data.series) {
271
+
272
+ const points = chart_data.x_scale ?
273
+ chart_data.x_scale.max :
274
+ Math.max.apply(0, chart_data.series.map(x => x.length));
275
+
276
+ const func = chart_data.smooth ?
277
+ this.renderer.RenderSmoothLine : this.renderer.RenderLine;
278
+
279
+ // gridlines
280
+ this.renderer.RenderGrid(area,
281
+ chart_data.scale.count,
282
+ chart_data.x_scale ? chart_data.x_scale.count + 1 : points,
283
+ 'chart-grid');
284
+
285
+ // series
286
+ let series_index = 0;
287
+ for (const series of chart_data.series) {
288
+
289
+
290
+
291
+ const y = series.map((point) => {
292
+ if (typeof point === 'undefined') { return undefined; }
293
+ return Util.ApplyScale(point, area.height, scale);
294
+ });
295
+
296
+ if (y.length < points) {
297
+ for (let i = y.length; i < points; i++) {
298
+ y.push(undefined);
299
+ }
300
+ }
301
+
302
+ const styles = [
303
+ chart_data.type === 'area' ? 'chart-area' : 'chart-line',
304
+ `series-${series_index + 1}`]
305
+
306
+ func.call(this.renderer, area, y, (chart_data.type === 'area'), chart_data.titles, styles);
307
+ series_index++;
308
+ }
309
+ }
310
+
311
+ // TODO: callouts
312
+
313
+ }
314
+ break;
315
+
316
+ case 'bar':
317
+ {
318
+ let corners: number[]|undefined;
319
+
320
+ // gridlines
321
+ this.renderer.RenderBarGrid(area, chart_data.scale.count, 'chart-grid');
322
+ if (chart_data.series2) {
323
+
324
+ let count = 0;
325
+ const series_count = chart_data.series2.length;
326
+
327
+ for (const series of chart_data.series2) {
328
+ count = Math.max(count, series.y.data.length);
329
+ }
330
+
331
+ const row_height = area.height / count;
332
+ let row_pct = .7;
333
+ if (typeof chart_data.space === 'number') {
334
+ row_pct = Math.max(0, Math.min(1, 1 - (chart_data.space)));
335
+ }
336
+
337
+ const space = row_height * (1 - row_pct) / 2;
338
+ const height = (row_height - space * 2) / series_count;
339
+
340
+ let zero = 0;
341
+ if (chart_data.scale.min < 0) { // && chart_data.scale.max >= 0) {
342
+ zero = Util.ApplyScale(0, area.width, chart_data.scale);
343
+ }
344
+
345
+ if (chart_data.round) {
346
+ const half_height = Math.floor(height / 2);
347
+ corners = [0, half_height, half_height, 0];
348
+ }
349
+
350
+ for (let s = 0; s < series_count; s++) {
351
+ const series = chart_data.series2[s];
352
+ const color_index = typeof series.index === 'number' ? series.index : s + 1;
353
+
354
+ for (let i = 0; i < series.y.data.length; i++ ){
355
+ const value = series.y.data[i];
356
+ if (typeof value === 'number') {
357
+
358
+ const y = Math.round(area.top + i * row_height + space) + s * height;
359
+
360
+ let x = 0;
361
+ let width = 0;
362
+ let negative = false;
363
+
364
+ if (zero) {
365
+ if (value > 0) {
366
+ width = Util.ApplyScale(value + chart_data.scale.min, area.width, chart_data.scale);
367
+ x = area.left + zero;
368
+ }
369
+ else {
370
+ width = Util.ApplyScale(chart_data.scale.min - value, area.width, chart_data.scale);
371
+ x = area.left + zero - width;
372
+ negative = true;
373
+ }
374
+ }
375
+ else {
376
+ width = Util.ApplyScale(value, area.width, chart_data.scale);
377
+ x = area.left;
378
+ }
379
+
380
+ // const bar_title = chart_data.titles ? chart_data.titles[i] : undefined;
381
+ const bar_title = undefined;
382
+
383
+ if (width) {
384
+ this.renderer.RenderRectangle(new Area(
385
+ x, y, x + width, y + height,
386
+ ), corners, ['chart-column', `series-${color_index}`], bar_title || undefined);
387
+ }
388
+ }
389
+ }
390
+ }
391
+
392
+ }
393
+
394
+ }
395
+ break;
396
+
397
+ case 'column':
398
+ case 'histogram2':
399
+ {
400
+
401
+ // gridlines
402
+ this.renderer.RenderGrid(area, chart_data.scale.count, 0, 'chart-grid');
403
+
404
+ if (chart_data.series2) {
405
+
406
+ let count = 0;
407
+ const series_count = chart_data.series2.length;
408
+
409
+ for (const series of chart_data.series2) {
410
+ count = Math.max(count, series.y.data.length);
411
+ }
412
+
413
+ // columns
414
+ const column_width = area.width / count;
415
+ let column_pct = .7;
416
+ if (typeof chart_data.space === 'number') {
417
+ column_pct = Math.max(0, Math.min(1, 1 - (chart_data.space)));
418
+ }
419
+
420
+ const space = column_width * (1 - column_pct) / 2;
421
+ const width = (column_width - space * 2) / series_count;
422
+
423
+ let zero = 0;
424
+ if (chart_data.scale.min < 0) { // && chart_data.scale.max >= 0) {
425
+ zero = Util.ApplyScale(0, area.height, chart_data.scale);
426
+ }
427
+
428
+ if (chart_data.callouts && chart_data.x_scale) {
429
+ const scale = chart_data.x_scale;
430
+ const lines = chart_data.callouts.map((callout, index) => {
431
+ const x = Math.round(area.left + Util.ApplyScale(callout.value, area.width, scale)) + .5;
432
+ return {
433
+ x1: x, y1: area.bottom - area.height, x2: x, y2: area.bottom,
434
+ classes: `callout-${index + 1}`,
435
+ }
436
+ });
437
+ this.renderer.RenderCalloutLines(lines);
438
+ }
439
+
440
+ let corners: number[]|undefined;
441
+
442
+ if (chart_data.round) {
443
+ const half_width = Math.floor(width/2);
444
+ corners = [half_width, half_width, 0, 0];
445
+ }
446
+
447
+ for (let s = 0; s < series_count; s++) {
448
+ const series = chart_data.series2[s];
449
+ const color_index = typeof series.index === 'number' ? series.index : s + 1;
450
+
451
+ for (let i = 0; i < series.y.data.length; i++ ){
452
+ const value = series.y.data[i];
453
+ // const format = NumberFormatCache.Get(series.y.format || '0.00');
454
+
455
+ if (typeof value === 'number') {
456
+
457
+ // const x = Math.round(area.left + i * column_width + space) + s * width;
458
+ const x = (area.left + i * column_width + space) + s * width;
459
+
460
+ let height = 0;
461
+ let y = 0;
462
+ let negative = false;
463
+
464
+ if (zero) {
465
+ if (value > 0) {
466
+ height = Util.ApplyScale(value + chart_data.scale.min, area.height, chart_data.scale);
467
+ y = area.bottom - height - zero;
468
+ }
469
+ else {
470
+ height = Util.ApplyScale(chart_data.scale.min - value, area.height, chart_data.scale);
471
+ y = area.bottom - zero; // // area.bottom - height - zero;
472
+ negative = true;
473
+ }
474
+ }
475
+ else {
476
+ height = Util.ApplyScale(value, area.height, chart_data.scale);
477
+ y = area.bottom - height;
478
+ }
479
+
480
+ // const bar_title = chart_data.titles ? chart_data.titles[i] : undefined;
481
+ const bar_title = undefined;
482
+
483
+ if (height) {
484
+
485
+ const label = (chart_data.data_labels && !!series.y.labels) ? series.y.labels[i] : '';
486
+ const label_point = {
487
+ x: Math.round(x + width / 2),
488
+ y: Math.round(y - 10),
489
+ };
490
+
491
+ this.renderer.RenderRectangle(new Area(
492
+ x, y, x + width, y + height,
493
+ ), corners, ['chart-column', `series-${color_index}`], bar_title || undefined, label, label_point);
494
+ }
495
+ }
496
+ }
497
+
498
+ }
499
+
500
+ }
501
+
502
+ }
503
+ break;
504
+
505
+ case 'histogram':
506
+ {
507
+ // gridlines
508
+ this.renderer.RenderGrid(area, chart_data.scale.count, 0, 'chart-grid');
509
+
510
+ // columns
511
+ const column_width = area.width / chart_data.count;
512
+ const column_pct = chart_data.column_width;
513
+
514
+ const space = column_width * (1 - column_pct) / 2;
515
+
516
+ for (let i = 0; i < chart_data.count; i++ ){
517
+ const x = Math.round(area.left + i * column_width + space);
518
+ const width = column_width - space * 2;
519
+ const height = Util.ApplyScale(chart_data.bins[i], area.height, chart_data.scale);
520
+ const y = area.bottom - height;
521
+ const bar_title = chart_data.titles ? chart_data.titles[i] : undefined;
522
+
523
+ this.renderer.RenderRectangle(new Area(
524
+ x, y, x + width, y + height,
525
+ ), undefined, 'chart-column series-1', bar_title || undefined);
526
+ }
527
+
528
+ }
529
+ break;
530
+ }
531
+
532
+ }
533
+
534
+
535
+ }
@@ -14,11 +14,12 @@
14
14
  * You should have received a copy of the GNU General Public License along
15
15
  * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
16
  *
17
- * Copyright 2022-2023 trebco, llc.
17
+ * Copyright 2022-2024 trebco, llc.
18
18
  * info@treb.app
19
19
  *
20
20
  */
21
21
 
22
- export { Chart } from './chart';
23
- export { ChartFunctions } from './chart-functions';
24
- export { Util } from './util';
22
+ export { Chart } from './chart';
23
+ export { ChartFunctions } from './chart-functions';
24
+ export { Util } from './util';
25
+ export type { ChartRenderer } from './renderer-type';
@@ -14,24 +14,24 @@
14
14
  * You should have received a copy of the GNU General Public License along
15
15
  * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
16
  *
17
- * Copyright 2022-2023 trebco, llc.
17
+ * Copyright 2022-2024 trebco, llc.
18
18
  * info@treb.app
19
19
  *
20
20
  */
21
21
 
22
- import { Chart } from './';
23
-
24
- // tslint:disable-next-line: no-var-requires
25
- require('../style/charts.pcss');
26
-
27
- if (!(self as any).TREB) {
28
- (self as any).TREB = {};
29
- }
30
-
31
- // (temporarily, atm) switching name to prevent overlap
32
-
33
- (self as any).TREB.CreateChart2 = (node?: HTMLElement) => {
34
- const chart = new Chart();
35
- if (node) chart.Initialize(node);
36
- return chart;
37
- };
22
+ import { Chart } from './';
23
+
24
+ // tslint:disable-next-line: no-var-requires
25
+ require('../style/charts.pcss');
26
+
27
+ if (!(self as any).TREB) {
28
+ (self as any).TREB = {};
29
+ }
30
+
31
+ // (temporarily, atm) switching name to prevent overlap
32
+
33
+ (self as any).TREB.CreateChart2 = (node?: HTMLElement) => {
34
+ const chart = new Chart();
35
+ if (node) chart.Initialize(node);
36
+ return chart;
37
+ };
@@ -1,24 +1,24 @@
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
-
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-2024 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
22
  export interface Point {
23
23
  x: number;
24
24
  y: number;
@@ -0,0 +1,32 @@
1
+
2
+ import type { ChartData } from './chart-types'
3
+
4
+ /**
5
+ * interface type for renderer
6
+ */
7
+ export interface ChartRenderer {
8
+
9
+ /**
10
+ * set the target node. this is separate from rendering in the
11
+ * event you want to cache or precalculate anything. it will be
12
+ * called any time the node changes.
13
+ */
14
+ Initialize: (target: HTMLElement) => void;
15
+
16
+ /**
17
+ * called when the data has updated, you need to repaint the chart.
18
+ * the node is passed as a conveniece, but you can cache the node
19
+ * from Initialize().
20
+ */
21
+ Update: (target: HTMLElement, data: ChartData) => void;
22
+
23
+ /**
24
+ * called when the chart is resized. data has not changed. if you cached
25
+ * the data previously, then you can reuse that. the node is passed as a
26
+ * conveniece, but you can cache the node from Initialize().
27
+ */
28
+ Resize: (target: HTMLElement, data: ChartData) => void;
29
+
30
+ }
31
+
32
+
@@ -14,7 +14,7 @@
14
14
  * You should have received a copy of the GNU General Public License along
15
15
  * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
16
  *
17
- * Copyright 2022-2023 trebco, llc.
17
+ * Copyright 2022-2024 trebco, llc.
18
18
  * info@treb.app
19
19
  *
20
20
  */
@@ -14,7 +14,7 @@
14
14
  * You should have received a copy of the GNU General Public License along
15
15
  * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
16
  *
17
- * Copyright 2022-2023 trebco, llc.
17
+ * Copyright 2022-2024 trebco, llc.
18
18
  * info@treb.app
19
19
  *
20
20
  */
@@ -14,7 +14,7 @@
14
14
  * You should have received a copy of the GNU General Public License along
15
15
  * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
16
  *
17
- * Copyright 2022-2023 trebco, llc.
17
+ * Copyright 2022-2024 trebco, llc.
18
18
  * info@treb.app
19
19
  *
20
20
  */