svg-table 0.0.1

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 (62) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -0
  3. package/d3types.ts +17 -0
  4. package/dist/d3types.d.ts +12 -0
  5. package/dist/d3types.d.ts.map +1 -0
  6. package/dist/d3types.js +3 -0
  7. package/dist/d3types.js.map +1 -0
  8. package/dist/index.d.ts +10 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +36 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/stylings.d.ts +206 -0
  13. package/dist/stylings.d.ts.map +1 -0
  14. package/dist/stylings.js +123 -0
  15. package/dist/stylings.js.map +1 -0
  16. package/dist/tableData.d.ts +168 -0
  17. package/dist/tableData.d.ts.map +1 -0
  18. package/dist/tableData.js +329 -0
  19. package/dist/tableData.js.map +1 -0
  20. package/dist/tableData.test.d.ts +2 -0
  21. package/dist/tableData.test.d.ts.map +1 -0
  22. package/dist/tableData.test.js +259 -0
  23. package/dist/tableData.test.js.map +1 -0
  24. package/dist/tableFormatter.d.ts +179 -0
  25. package/dist/tableFormatter.d.ts.map +1 -0
  26. package/dist/tableFormatter.js +298 -0
  27. package/dist/tableFormatter.js.map +1 -0
  28. package/dist/tableFormatter.test.d.ts +2 -0
  29. package/dist/tableFormatter.test.d.ts.map +1 -0
  30. package/dist/tableFormatter.test.js +101 -0
  31. package/dist/tableFormatter.test.js.map +1 -0
  32. package/dist/tableStyler.d.ts +310 -0
  33. package/dist/tableStyler.d.ts.map +1 -0
  34. package/dist/tableStyler.js +665 -0
  35. package/dist/tableStyler.js.map +1 -0
  36. package/dist/tableStyler.test.d.ts +2 -0
  37. package/dist/tableStyler.test.d.ts.map +1 -0
  38. package/dist/tableStyler.test.js +225 -0
  39. package/dist/tableStyler.test.js.map +1 -0
  40. package/dist/tableSvg.d.ts +41 -0
  41. package/dist/tableSvg.d.ts.map +1 -0
  42. package/dist/tableSvg.js +634 -0
  43. package/dist/tableSvg.js.map +1 -0
  44. package/dist/tableUtils.d.ts +14 -0
  45. package/dist/tableUtils.d.ts.map +1 -0
  46. package/dist/tableUtils.js +18 -0
  47. package/dist/tableUtils.js.map +1 -0
  48. package/eslint.config.js +23 -0
  49. package/index.ts +82 -0
  50. package/jest.config.js +5 -0
  51. package/package.json +44 -0
  52. package/stylings.ts +311 -0
  53. package/svg-table-0.0.1-snapshot.tgz +0 -0
  54. package/tableData.test.ts +290 -0
  55. package/tableData.ts +359 -0
  56. package/tableFormatter.test.ts +122 -0
  57. package/tableFormatter.ts +306 -0
  58. package/tableStyler.test.ts +268 -0
  59. package/tableStyler.ts +798 -0
  60. package/tableSvg.ts +820 -0
  61. package/tableUtils.ts +20 -0
  62. package/tsconfig.json +102 -0
@@ -0,0 +1,634 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __read = (this && this.__read) || function (o, n) {
14
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
15
+ if (!m) return o;
16
+ var i = m.call(o), r, ar = [], e;
17
+ try {
18
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
19
+ }
20
+ catch (error) { e = { error: error }; }
21
+ finally {
22
+ try {
23
+ if (r && !r.done && (m = i["return"])) m.call(i);
24
+ }
25
+ finally { if (e) throw e.error; }
26
+ }
27
+ return ar;
28
+ };
29
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
30
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
31
+ if (ar || !(i in from)) {
32
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
33
+ ar[i] = from[i];
34
+ }
35
+ }
36
+ return to.concat(ar || Array.prototype.slice.call(from));
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.elementInfoFrom = elementInfoFrom;
40
+ exports.createTable = createTable;
41
+ exports.tableId = tableId;
42
+ var d3_1 = require("d3");
43
+ var tableUtils_1 = require("./tableUtils");
44
+ var tableData_1 = require("./tableData");
45
+ var stylings_1 = require("./stylings");
46
+ var data_frame_ts_1 = require("data-frame-ts");
47
+ var tableFormatter_1 = require("./tableFormatter");
48
+ function textAnchorFrom(align) {
49
+ switch (align) {
50
+ case "left":
51
+ return "start";
52
+ case "center":
53
+ return "middle";
54
+ case "right":
55
+ return "end";
56
+ }
57
+ }
58
+ function dominantBaselineFrom(align) {
59
+ switch (align) {
60
+ case "top":
61
+ return "hanging";
62
+ case "middle":
63
+ return "central";
64
+ case "bottom":
65
+ return "auto";
66
+ }
67
+ }
68
+ function elementInfoFrom(textSelection, cellSelection, borderSelection, cellStyle) {
69
+ return {
70
+ cellSelection: cellSelection,
71
+ textSelection: textSelection,
72
+ borderSelection: borderSelection,
73
+ textWidth: (0, tableUtils_1.textWidthOf)(textSelection),
74
+ textHeight: (0, tableUtils_1.textHeightOf)(textSelection),
75
+ cellStyle: cellStyle
76
+ };
77
+ }
78
+ // export class SvgTable<V> {
79
+ // private constructor(
80
+ // private readonly uniqueTableId: string,
81
+ // private readonly tableSelection: GSelection,
82
+ // private readonly renderingInfo: TableRenderingInfo,
83
+ // private readonly styledTable: StyledTable<V>,
84
+ // private readonly container: SVGSVGElement,
85
+ // private readonly coordinates: [x: number, y: number] | ((width: number, height: number) => [x: number, y: number])
86
+ // ) {
87
+ // }
88
+ //
89
+ // static createTable<V>(
90
+ // styledTable: StyledTable<V>,
91
+ // container: SVGSVGElement,
92
+ // uniqueTableId: string,
93
+ // coordinates: [x: number, y: number] | ((width: number, height: number) => [x: number, y: number])
94
+ // ): Result<SvgTable<V>, string> {
95
+ // // return new SvgTable(styledTable, container, uniqueTableId, coordinates)
96
+ // // grab a copy of the data as a data-frame
97
+ // const tableData = styledTable.tableData()
98
+ //
99
+ // // add the group <g> representing the table, to which all the elements will be added, and
100
+ // // the group will be translated to the mouse (x, y) coordinates as appropriate
101
+ // const tableSelection = select<SVGSVGElement | null, any>(container)
102
+ // .append('g')
103
+ // .attr('id', tableId(uniqueTableId))
104
+ // .attr('class', 'tooltip')
105
+ // .style('fill', styledTable.tableBackground().color)
106
+ // .style('font-family', styledTable.tableFont().family)
107
+ // .style('font-size', styledTable.tableFont().size)
108
+ // .style('font-weight', styledTable.tableFont().weight)
109
+ //
110
+ // // creates an SVG group to hold the column header (if there is one), and
111
+ // // then add a cell for each column header element
112
+ // const {data: columnHeaders} = createColumnHeaderPlacementInfo(tableData, tableSelection, uniqueTableId, styledTable)
113
+ // const {columnHeader, data: rowHeaders, footer} = createRowHeaderPlacementInfo(tableData, tableSelection, uniqueTableId, styledTable)
114
+ // const {rowHeader, data: footers} = createFooterPlacementInfo(tableData, tableSelection, uniqueTableId, styledTable)
115
+ // const data = createDataPlacementInfo(tableData, tableSelection, uniqueTableId, styledTable)
116
+ //
117
+ // const {top, left} = styledTable.tablePadding()
118
+ //
119
+ // return TableData
120
+ // .fromDataFrame<ElementPlacementInfo>(data)
121
+ // // the column header doesn't need to deal with the value providers, because it is
122
+ // // the first one added and so there are no row-headers or footers yet.
123
+ // .withColumnHeader(columnHeaders)
124
+ // .flatMap(td => td.withRowHeader(
125
+ // rowHeaders,
126
+ // defaultFormatting<ElementPlacementInfo>(),
127
+ // () => columnHeader,
128
+ // () => footer
129
+ // ))
130
+ // .flatMap(td => td.withFooter(
131
+ // footers,
132
+ // defaultFormatting<ElementPlacementInfo>(),
133
+ // () => rowHeader
134
+ // ))
135
+ // .map(td => {
136
+ // const info = calculateRenderingInfo(td, styledTable, coordinates)
137
+ // tableSelection.attr('transform', `translate(${info.tableX + left}, ${info.tableY + top})`)
138
+ // return info
139
+ // })
140
+ // .map(renderingInfo => placeTextInTable(renderingInfo))
141
+ // .map(renderingInfo => new SvgTable(uniqueTableId, tableSelection, renderingInfo, styledTable, container, coordinates))
142
+ // }
143
+ //
144
+ // private static updateTable<V>(
145
+ // styledTable: StyledTable<V>,
146
+ // container: SVGSVGElement,
147
+ // uniqueTableId: string,
148
+ // coordinates: [x: number, y: number] | ((width: number, height: number) => [x: number, y: number])
149
+ // ): Result<SvgTable<V>, string> {
150
+ // const {top, left} = styledTable.tablePadding()
151
+ //
152
+ // return TableData
153
+ // .fromDataFrame<ElementPlacementInfo>(data)
154
+ // // the column header doesn't need to deal with the value providers, because it is
155
+ // // the first one added and so there are no row-headers or footers yet.
156
+ // .withColumnHeader(columnHeaders)
157
+ // .flatMap(td => td.withRowHeader(
158
+ // rowHeaders,
159
+ // defaultFormatting<ElementPlacementInfo>(),
160
+ // () => columnHeader,
161
+ // () => footer
162
+ // ))
163
+ // .flatMap(td => td.withFooter(
164
+ // footers,
165
+ // defaultFormatting<ElementPlacementInfo>(),
166
+ // () => rowHeader
167
+ // ))
168
+ // .map(td => {
169
+ // const info = calculateRenderingInfo(td, styledTable, coordinates)
170
+ // tableSelection.attr('transform', `translate(${info.tableX + left}, ${info.tableY + top})`)
171
+ // return info
172
+ // })
173
+ // .map(renderingInfo => placeTextInTable(renderingInfo))
174
+ // .map(renderingInfo => new SvgTable(uniqueTableId, tableSelection, renderingInfo, styledTable, container, coordinates))
175
+ // }
176
+ // }
177
+ /**
178
+ * Creates the table
179
+ * @param styledTable
180
+ * @param container
181
+ * @param uniqueTableId
182
+ * @param coordinates
183
+ */
184
+ function createTable(styledTable, container, uniqueTableId, coordinates) {
185
+ // grab a copy of the data as a data-frame
186
+ var tableData = styledTable.tableData();
187
+ // add the group <g> representing the table, to which all the elements will be added, and
188
+ // the group will be translated to the mouse (x, y) coordinates as appropriate
189
+ var tableSelection = (0, d3_1.select)(container)
190
+ .append('g')
191
+ .attr('id', tableId(uniqueTableId))
192
+ .attr('class', 'tooltip')
193
+ .style('fill', styledTable.tableBackground().color)
194
+ .style('font-family', styledTable.tableFont().family)
195
+ .style('font-size', styledTable.tableFont().size)
196
+ .style('font-weight', styledTable.tableFont().weight);
197
+ // creates an SVG group to hold the column header (if there is one), and
198
+ // then add a cell for each column header element
199
+ var columnHeaders = createColumnHeaderPlacementInfo(tableData, tableSelection, uniqueTableId, styledTable).data;
200
+ var _a = createRowHeaderPlacementInfo(tableData, tableSelection, uniqueTableId, styledTable), columnHeader = _a.columnHeader, rowHeaders = _a.data, footer = _a.footer;
201
+ var _b = createFooterPlacementInfo(tableData, tableSelection, uniqueTableId, styledTable), rowHeader = _b.rowHeader, footers = _b.data;
202
+ var data = createDataPlacementInfo(tableData, tableSelection, uniqueTableId, styledTable);
203
+ var _c = styledTable.tablePadding(), top = _c.top, left = _c.left;
204
+ return tableData_1.TableData
205
+ .fromDataFrame(data)
206
+ // the column header doesn't need to deal with the value providers, because it is
207
+ // the first one added and so there are no row-headers or footers yet.
208
+ .withColumnHeader(columnHeaders)
209
+ .flatMap(function (td) { return td.withRowHeader(rowHeaders, (0, tableFormatter_1.defaultFormatting)(), function () { return columnHeader; }, function () { return footer; }); })
210
+ .flatMap(function (td) { return td.withFooter(footers, (0, tableFormatter_1.defaultFormatting)(), function () { return rowHeader; }); })
211
+ .map(function (td) {
212
+ var info = calculateRenderingInfo(td, styledTable, coordinates);
213
+ tableSelection.attr('transform', "translate(".concat(info.tableX + left, ", ").concat(info.tableY + top, ")"));
214
+ return info;
215
+ })
216
+ .map(function (renderingInfo) { return placeTextInTable(renderingInfo); });
217
+ }
218
+ /*
219
+ HELPER STUFF
220
+ */
221
+ /*
222
+ Add all the SVG elements representing the table and then update the
223
+ coordinates for each of those elements to make a table
224
+ */
225
+ var ELEMENT_TYPE_ID;
226
+ (function (ELEMENT_TYPE_ID) {
227
+ ELEMENT_TYPE_ID["ROW_HEADER"] = "row-header";
228
+ ELEMENT_TYPE_ID["COLUMN_HEADER"] = "column-header";
229
+ ELEMENT_TYPE_ID["DATA"] = "data";
230
+ ELEMENT_TYPE_ID["FOOTER"] = "footer";
231
+ ELEMENT_TYPE_ID["CELL_TEXT"] = "cell-data";
232
+ ELEMENT_TYPE_ID["CELL"] = "cell";
233
+ })(ELEMENT_TYPE_ID || (ELEMENT_TYPE_ID = {}));
234
+ function tableId(uniqueTableId) {
235
+ return "svg-table-group-".concat(uniqueTableId);
236
+ }
237
+ function columnHeaderGroupId(uniqueTableId) {
238
+ return "svg-table-".concat(ELEMENT_TYPE_ID.COLUMN_HEADER, "-group-").concat(uniqueTableId);
239
+ }
240
+ function rowHeaderGroupId(uniqueTableId) {
241
+ return "svg-table-".concat(ELEMENT_TYPE_ID.ROW_HEADER, "-group-").concat(uniqueTableId);
242
+ }
243
+ function footerGroupId(uniqueTableId) {
244
+ return "svg-table-".concat(ELEMENT_TYPE_ID.FOOTER, "-group-").concat(uniqueTableId);
245
+ }
246
+ function dataGroupId(uniqueTableId) {
247
+ return "svg-table-".concat(ELEMENT_TYPE_ID.DATA, "-group-").concat(uniqueTableId);
248
+ }
249
+ function cellTextId(uniqueTableId, rowIndex, columnIndex) {
250
+ return "svg-table-".concat(ELEMENT_TYPE_ID.CELL_TEXT, "-").concat(rowIndex, "-").concat(columnIndex, "-").concat(uniqueTableId);
251
+ }
252
+ function cellId(uniqueTableId, rowIndex, columnIndex) {
253
+ return "svg-table-".concat(ELEMENT_TYPE_ID.CELL, "-").concat(rowIndex, "-").concat(columnIndex, "-").concat(uniqueTableId);
254
+ }
255
+ function borderId(uniqueTableId, location, rowIndex, columnIndex) {
256
+ return "svg-table-".concat(ELEMENT_TYPE_ID.CELL, "-").concat(rowIndex, "-").concat(columnIndex, "-border-").concat(location, "-").concat(uniqueTableId);
257
+ }
258
+ function createCellSelection(uniqueTableId, rowIndex, columnIndex, groupSelection, style) {
259
+ return groupSelection
260
+ .append("rect")
261
+ .attr('id', cellId(uniqueTableId, rowIndex, columnIndex))
262
+ .style('fill', style.background.color)
263
+ .style('fill-opacity', style.background.opacity);
264
+ }
265
+ function createBorderSelection(uniqueTableId, rowIndex, columnIndex, groupSelection, style) {
266
+ var borderSelection = {};
267
+ if (style.border.top) {
268
+ borderSelection.top = groupSelection
269
+ .append("line")
270
+ .attr('id', borderId(uniqueTableId, stylings_1.BorderLocation.TOP, rowIndex, columnIndex))
271
+ .style('stroke', style.border.top.color)
272
+ .style('stroke-width', style.border.top.width);
273
+ }
274
+ if (style.border.bottom) {
275
+ borderSelection.bottom = groupSelection
276
+ .append("line")
277
+ .attr('id', borderId(uniqueTableId, stylings_1.BorderLocation.BOTTOM, rowIndex, columnIndex))
278
+ .style('stroke', style.border.bottom.color)
279
+ .style('stroke-width', style.border.bottom.width);
280
+ }
281
+ if (style.border.left) {
282
+ borderSelection.left = groupSelection
283
+ .append("line")
284
+ .attr('id', borderId(uniqueTableId, stylings_1.BorderLocation.LEFT, rowIndex, columnIndex))
285
+ .style('stroke', style.border.left.color)
286
+ .style('stroke-width', style.border.left.width);
287
+ }
288
+ if (style.border.right) {
289
+ borderSelection.right = groupSelection
290
+ .append("line")
291
+ .attr('id', borderId(uniqueTableId, stylings_1.BorderLocation.RIGHT, rowIndex, columnIndex))
292
+ .style('stroke', style.border.right.color)
293
+ .style('stroke-width', style.border.right.width);
294
+ }
295
+ return borderSelection;
296
+ }
297
+ function createTextSelection(uniqueTableId, rowIndex, columnIndex, groupSelection, style, element) {
298
+ return groupSelection
299
+ .append("text")
300
+ .attr('id', cellTextId(uniqueTableId, rowIndex, columnIndex))
301
+ .style('font-family', style.font.family)
302
+ .style('font-size', style.font.size)
303
+ .style('font-weight', style.font.weight)
304
+ .style('fill', style.font.color)
305
+ .text(function () { return "".concat(element); });
306
+ }
307
+ function createColumnHeaderPlacementInfo(tableData, tableSelection, uniqueTableId, styledTable) {
308
+ return tableData.columnHeader(true)
309
+ .map(function (columnHeader) {
310
+ var groupSelection = tableSelection
311
+ .append('g')
312
+ .attr('id', columnHeaderGroupId(uniqueTableId))
313
+ .attr('class', 'tooltip-table-header');
314
+ return columnHeader.map(function (header, columnIndex) {
315
+ // the style with the highest priority for the cell
316
+ var style = styledTable
317
+ .stylesForTableCoordinates(0, columnIndex)
318
+ .getOrElse(__assign({}, stylings_1.defaultCellStyle));
319
+ var cellSelection = createCellSelection(uniqueTableId, 0, columnIndex, groupSelection, style);
320
+ var borderSelection = createBorderSelection(uniqueTableId, 0, columnIndex, groupSelection, style);
321
+ var textSelection = createTextSelection(uniqueTableId, 0, columnIndex, groupSelection, style, header);
322
+ return elementInfoFrom(textSelection, cellSelection, borderSelection, __assign({}, style));
323
+ });
324
+ })
325
+ .map(function (columnHeader) {
326
+ var rowHeaderElem = tableData.hasRowHeader() ? columnHeader.shift() : undefined;
327
+ return { rowHeader: rowHeaderElem, data: columnHeader };
328
+ })
329
+ .getOrElse({ rowHeader: undefined, data: [] });
330
+ }
331
+ /**
332
+ *
333
+ * @param tableData
334
+ * @param tableSelection
335
+ * @param uniqueTableId
336
+ * @param styledTable
337
+ */
338
+ function createRowHeaderPlacementInfo(tableData, tableSelection, uniqueTableId, styledTable) {
339
+ return tableData
340
+ .rowHeader(true, true)
341
+ .map(function (rowHeader) {
342
+ var groupSelection = tableSelection
343
+ .append('g')
344
+ .attr('id', rowHeaderGroupId(uniqueTableId))
345
+ .attr('class', 'tooltip-table-row-header')
346
+ .style('fill', styledTable.rowHeaderStyle()
347
+ .map(function (styling) { return styling.style.background.color; })
348
+ .getOrElse(stylings_1.defaultRowHeaderStyle.background.color));
349
+ return rowHeader.map(function (header, rowIndex) {
350
+ // the style with the highest priority for the cell
351
+ var style = styledTable
352
+ .stylesForTableCoordinates(rowIndex, 0)
353
+ .getOrElse(__assign({}, stylings_1.defaultCellStyle));
354
+ var cellSelection = createCellSelection(uniqueTableId, rowIndex, 0, groupSelection, style);
355
+ var borderSelection = createBorderSelection(uniqueTableId, rowIndex, 0, groupSelection, style);
356
+ var textSelection = createTextSelection(uniqueTableId, rowIndex, 0, groupSelection, style, header);
357
+ return elementInfoFrom(textSelection, cellSelection, borderSelection, __assign({}, style));
358
+ });
359
+ })
360
+ .map(function (rowHeader) {
361
+ var columnHeaderElem = tableData.hasRowHeader() ? rowHeader.shift() : undefined;
362
+ var footerElem = tableData.hasFooter() ? rowHeader.pop() : undefined;
363
+ return { columnHeader: columnHeaderElem, data: rowHeader, footer: footerElem };
364
+ })
365
+ .getOrElse({ columnHeader: undefined, data: [], footer: undefined });
366
+ }
367
+ /**
368
+ *
369
+ * @param tableData
370
+ * @param tableSelection
371
+ * @param uniqueTableId
372
+ * @param styledTable
373
+ */
374
+ function createFooterPlacementInfo(tableData, tableSelection, uniqueTableId, styledTable) {
375
+ return tableData
376
+ .footer(true)
377
+ .map(function (footer) {
378
+ var groupSelection = tableSelection
379
+ .append('g')
380
+ .attr('id', footerGroupId(uniqueTableId))
381
+ .attr('class', 'tooltip-table-footer')
382
+ .style('fill', styledTable.columnHeaderStyle()
383
+ .map(function (styling) { return styling.style.background.color; })
384
+ .getOrElse(stylings_1.defaultFooterStyle.background.color));
385
+ return footer.map(function (ftr, columnIndex) {
386
+ // the style with the highest priority for the cell
387
+ var style = styledTable
388
+ .stylesForTableCoordinates(footer.length - 1, columnIndex)
389
+ .getOrElse(__assign({}, stylings_1.defaultCellStyle));
390
+ var cellSelection = createCellSelection(uniqueTableId, footer.length - 1, columnIndex, groupSelection, style);
391
+ var borderSelection = createBorderSelection(uniqueTableId, footer.length - 1, columnIndex, groupSelection, style);
392
+ var textSelection = createTextSelection(uniqueTableId, footer.length - 1, columnIndex, groupSelection, style, ftr);
393
+ return elementInfoFrom(textSelection, cellSelection, borderSelection, __assign({}, style));
394
+ });
395
+ })
396
+ .map(function (footer) {
397
+ var rowHeaderElem = tableData.hasRowHeader() ? footer.shift() : undefined;
398
+ return { rowHeader: rowHeaderElem, data: footer };
399
+ })
400
+ .getOrElse({ rowHeader: undefined, data: [] });
401
+ }
402
+ /**
403
+ *
404
+ * @param tableData
405
+ * @param tableSelection
406
+ * @param uniqueTableId
407
+ * @param styledTable
408
+ */
409
+ function createDataPlacementInfo(tableData, tableSelection, uniqueTableId, styledTable) {
410
+ // when the table has a column header, then the data starts at row 1
411
+ // otherwise, the data starts at row 0
412
+ var rowOffset = tableData.hasRowHeader() ? 1 : 0;
413
+ var columnOffset = tableData.hasColumnHeader() ? 1 : 0;
414
+ return tableData
415
+ .data()
416
+ .map(function (df) {
417
+ var groupSelection = tableSelection
418
+ .append('g')
419
+ .attr('class', 'tooltip-table-data')
420
+ .attr('id', dataGroupId(uniqueTableId));
421
+ //
422
+ return df.mapElements(function (element, rowIndex, columnIndex) {
423
+ // the style with the highest priority for the cell
424
+ var style = styledTable
425
+ .stylesForTableCoordinates(rowIndex + rowOffset, columnIndex + columnOffset)
426
+ .getOrElse(__assign({}, stylings_1.defaultCellStyle));
427
+ var cellSelection = createCellSelection(uniqueTableId, rowIndex + rowOffset, columnIndex + columnOffset, groupSelection, style);
428
+ var borderSelection = createBorderSelection(uniqueTableId, rowIndex + rowOffset, columnIndex + columnOffset, groupSelection, style);
429
+ var textSelection = createTextSelection(uniqueTableId, rowIndex + rowOffset, columnIndex + columnOffset, groupSelection, style, element);
430
+ return elementInfoFrom(textSelection, cellSelection, borderSelection, __assign({}, style));
431
+ });
432
+ })
433
+ .getOrElse(data_frame_ts_1.DataFrame.empty());
434
+ }
435
+ /**
436
+ * Calculates the
437
+ * 1. table width and height,
438
+ * 2. width of each column in the table,
439
+ * 3. height of each row in the table,
440
+ * 4.
441
+ *
442
+ * @param tableData
443
+ * @param styledTable
444
+ * @param coordinates
445
+ */
446
+ function calculateRenderingInfo(tableData, styledTable, coordinates) {
447
+ /**
448
+ * Calculates the min and max values for the extracted value from the cell
449
+ * @param elements An array of rows (data frame row slices) or columns (data
450
+ * frame column slices)
451
+ * @param extractor
452
+ */
453
+ function minMaxFor(elements, extractor) {
454
+ return elements.reduce(function (minMax, row) {
455
+ var cellValue = row.map(function (cell) { return Math.ceil(extractor(cell)); });
456
+ var min = minMax.min, max = minMax.max, minValues = minMax.minValues, maxValues = minMax.maxValues;
457
+ var mins = Math.min.apply(Math, __spreadArray([], __read(cellValue), false));
458
+ minValues.push(mins);
459
+ var maxes = Math.max.apply(Math, __spreadArray([], __read(cellValue), false));
460
+ maxValues.push(maxes);
461
+ return {
462
+ minValues: minValues,
463
+ min: Math.min(min, mins),
464
+ maxValues: maxValues,
465
+ max: Math.max(max, maxes)
466
+ };
467
+ }, { min: Infinity, max: -Infinity, minValues: [], maxValues: [] });
468
+ }
469
+ var df = tableData.unwrapDataFrame();
470
+ // 1. calculate the bounding box for the element
471
+ // 2. calculate the cell width/height using the bounding width/height and the
472
+ // maximum and minimum cell width/height from the styling
473
+ var whdf = df.mapElements(function (element, rowIndex, columnIndex) {
474
+ // grab the style for the cell
475
+ var style = styledTable
476
+ .stylesForTableCoordinates(rowIndex, columnIndex)
477
+ .getOrElse(__assign({}, stylings_1.defaultCellStyle));
478
+ // calculate the actual width and height of the cell
479
+ var _a = calculateCellDimensions(style, element.textWidth, element.textHeight), width = _a.width, height = _a.height;
480
+ return __assign(__assign({}, element), { cellWidth: width, cellHeight: height });
481
+ });
482
+ // 3. calculate the cell width for each column based on the max and min width of
483
+ // all the cells in the column
484
+ // 4. calculate the cell height for each row based on the max and min height of
485
+ // all the cells in the row
486
+ // 5. calculate the table width/height by adding up all the column-widths/row-heights
487
+ // 6. calculate the (x, y)-coordinates of the text for each cell
488
+ // 7. update each cell's coordinates (here we need to update the header groups, footer
489
+ // groups, and then the cell's coordinates relative to their group.. :()
490
+ var minMaxColumnWidths = minMaxFor(whdf.columnSlices(), function (cell) { return cell.cellWidth; });
491
+ var minMaxRowHeights = minMaxFor(whdf.rowSlices(), function (cell) { return cell.cellHeight; });
492
+ var columnWidths = df.columnSlices().map(function (_, index) {
493
+ if (index === 0 && tableData.hasRowHeader()) {
494
+ return styledTable.rowHeaderStyle()
495
+ // todo update the styling for the row-headers to include the width and the min and max width
496
+ .map(function (_) { return minMaxColumnWidths.maxValues[index]; })
497
+ .getOrElse(Math.max(stylings_1.defaultColumnStyle.dimension.minWidth, Math.min(stylings_1.defaultColumnStyle.dimension.maxWidth, minMaxColumnWidths.maxValues[index])));
498
+ }
499
+ return styledTable.columnStyleFor(index)
500
+ .map(function (styling) { return Math.max(styling.style.dimension.minWidth, Math.min(styling.style.dimension.maxWidth, minMaxColumnWidths.maxValues[index])); })
501
+ .getOrElse(Math.max(stylings_1.defaultColumnStyle.dimension.minWidth, Math.min(stylings_1.defaultColumnStyle.dimension.maxWidth, minMaxColumnWidths.maxValues[index])));
502
+ });
503
+ var rowHeights = df.rowSlices().map(function (_, index) {
504
+ if (index === 0 && tableData.hasColumnHeader()) {
505
+ return styledTable.columnHeaderStyle()
506
+ .map(function (styling) { return Math.max(styling.style.dimension.minHeight, Math.min(styling.style.dimension.maxHeight, minMaxRowHeights.maxValues[index])); })
507
+ .getOrElse(Math.max(stylings_1.defaultRowStyle.dimension.minHeight, Math.min(stylings_1.defaultRowStyle.dimension.maxHeight, minMaxRowHeights.maxValues[index])));
508
+ }
509
+ return styledTable.rowStyleFor(index)
510
+ .map(function (styling) { return Math.max(styling.style.dimension.minHeight, Math.min(styling.style.dimension.maxHeight, minMaxRowHeights.maxValues[index])); })
511
+ .getOrElse(Math.max(stylings_1.defaultRowStyle.dimension.minHeight, Math.min(stylings_1.defaultRowStyle.dimension.maxHeight, minMaxRowHeights.maxValues[index])));
512
+ });
513
+ var dimAdjustedDf = df
514
+ .mapElements(function (element, rowIndex, columnIndex) {
515
+ return (__assign(__assign({}, element), { cellStyle: __assign(__assign({}, element.cellStyle), { dimension: __assign(__assign({}, element.cellStyle.dimension), { width: columnWidths[columnIndex], height: rowHeights[rowIndex] }) }) }));
516
+ });
517
+ // todo gross as shit, is there a better way
518
+ var cumColumnWidths = columnWidths.reduce(function (sum, curr, index) {
519
+ sum.push(Math.ceil(curr) + sum[index]);
520
+ return sum;
521
+ }, [0]);
522
+ var cumRowHeights = rowHeights.reduce(function (sum, curr, index) {
523
+ sum.push(Math.ceil(curr) + sum[index]);
524
+ return sum;
525
+ }, [0]);
526
+ var positionAdjustedDf = dimAdjustedDf
527
+ .mapElements(function (element, rowIndex, columnIndex) {
528
+ var cellWidth = element.cellStyle.dimension.width;
529
+ var cellHeight = element.cellStyle.dimension.height;
530
+ return __assign(__assign({}, element), { width: cellWidth, height: cellHeight, x: cumColumnWidths[columnIndex] + textXOffset(element, cellWidth), y: cumRowHeights[rowIndex] + textYOffset(element, cellHeight), cellX: cumColumnWidths[columnIndex], cellY: cumRowHeights[rowIndex] });
531
+ });
532
+ var tableWidth = columnWidths.reduce(function (sum, width) { return sum + width; }, 0);
533
+ var tableHeight = rowHeights.reduce(function (sum, height) { return sum + height; }, 0);
534
+ var _a = __read((Array.isArray(coordinates)) ? coordinates : coordinates(tableWidth, tableWidth), 2), x = _a[0], y = _a[1];
535
+ return {
536
+ tableWidth: tableWidth,
537
+ tableHeight: tableHeight,
538
+ tableX: x,
539
+ tableY: y,
540
+ renderingInfo: tableData_1.TableData.fromDataFrame(positionAdjustedDf)
541
+ };
542
+ }
543
+ /**
544
+ * Calculates the row and column dimensions based on the min and max width and hieght of
545
+ * the cells.
546
+ * @param style
547
+ * @param width
548
+ * @param height
549
+ */
550
+ function calculateCellDimensions(style, width, height) {
551
+ return {
552
+ width: Math.max(Math.min(width + style.padding.left + style.padding.right, style.dimension.maxWidth), style.dimension.minWidth),
553
+ height: Math.max(Math.min(height + style.padding.top + style.padding.bottom, style.dimension.maxHeight), style.dimension.minHeight)
554
+ };
555
+ }
556
+ /**
557
+ * Calculates the x-offset of the text with the cell
558
+ * @param element The element to render
559
+ * @param cellWidth The width of the cell into which the text is rendered
560
+ */
561
+ function textXOffset(element, cellWidth) {
562
+ switch (element.cellStyle.alignText) {
563
+ case "left":
564
+ return element.cellStyle.padding.left;
565
+ case "center":
566
+ return cellWidth / 2;
567
+ case "right":
568
+ return cellWidth - element.cellStyle.padding.right;
569
+ default:
570
+ return cellWidth / 2;
571
+ }
572
+ }
573
+ function textYOffset(element, cellHeight) {
574
+ switch (element.cellStyle.verticalAlignText) {
575
+ case "top":
576
+ return element.cellStyle.padding.top;
577
+ case "middle":
578
+ return cellHeight / 2;
579
+ case "bottom":
580
+ return cellHeight - element.cellStyle.padding.bottom;
581
+ default:
582
+ return cellHeight / 2;
583
+ }
584
+ }
585
+ /**
586
+ * Places the text into the table at its (x, y) coordinates, and returns the {@link TableData} holding
587
+ * the updated values.
588
+ * @param tableRenderingInfo The information for rendering the text as a table
589
+ * @return A {@link TableData} holding the updated values.
590
+ */
591
+ function placeTextInTable(tableRenderingInfo) {
592
+ var updatedDf = tableRenderingInfo.renderingInfo.unwrapDataFrame()
593
+ .mapElements(function (info) {
594
+ info.cellSelection
595
+ .attr('width', info.width)
596
+ .attr('height', info.height)
597
+ .attr('transform', "translate(".concat(info.cellX, ", ").concat(info.cellY, ")"));
598
+ info.textSelection
599
+ .attr('text-anchor', textAnchorFrom(info.cellStyle.alignText))
600
+ .attr('dominant-baseline', dominantBaselineFrom(info.cellStyle.verticalAlignText))
601
+ .attr('transform', "translate(".concat(info.x, ", ").concat(info.y, ")"));
602
+ if (info.borderSelection.top) {
603
+ info.borderSelection.top
604
+ .attr('x1', info.cellX)
605
+ .attr('y1', info.cellY)
606
+ .attr('x2', info.cellX + info.width)
607
+ .attr('y2', info.cellY);
608
+ }
609
+ if (info.borderSelection.bottom) {
610
+ info.borderSelection.bottom
611
+ .attr('x1', info.cellX)
612
+ .attr('y1', info.cellY + info.height)
613
+ .attr('x2', info.cellX + info.width)
614
+ .attr('y2', info.cellY + info.height);
615
+ }
616
+ if (info.borderSelection.right) {
617
+ info.borderSelection.right
618
+ .attr('x1', info.cellX + info.width)
619
+ .attr('y1', info.cellY)
620
+ .attr('x2', info.cellX + info.width)
621
+ .attr('y2', info.cellY + info.height);
622
+ }
623
+ if (info.borderSelection.left) {
624
+ info.borderSelection.left
625
+ .attr('x1', info.cellX)
626
+ .attr('y1', info.cellY)
627
+ .attr('x2', info.cellX)
628
+ .attr('y2', info.cellY + info.height);
629
+ }
630
+ return info;
631
+ });
632
+ return __assign(__assign({}, tableRenderingInfo), { renderingInfo: tableData_1.TableData.fromDataFrame(updatedDf) });
633
+ }
634
+ //# sourceMappingURL=tableSvg.js.map