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.
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/d3types.ts +17 -0
- package/dist/d3types.d.ts +12 -0
- package/dist/d3types.d.ts.map +1 -0
- package/dist/d3types.js +3 -0
- package/dist/d3types.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/stylings.d.ts +206 -0
- package/dist/stylings.d.ts.map +1 -0
- package/dist/stylings.js +123 -0
- package/dist/stylings.js.map +1 -0
- package/dist/tableData.d.ts +168 -0
- package/dist/tableData.d.ts.map +1 -0
- package/dist/tableData.js +329 -0
- package/dist/tableData.js.map +1 -0
- package/dist/tableData.test.d.ts +2 -0
- package/dist/tableData.test.d.ts.map +1 -0
- package/dist/tableData.test.js +259 -0
- package/dist/tableData.test.js.map +1 -0
- package/dist/tableFormatter.d.ts +179 -0
- package/dist/tableFormatter.d.ts.map +1 -0
- package/dist/tableFormatter.js +298 -0
- package/dist/tableFormatter.js.map +1 -0
- package/dist/tableFormatter.test.d.ts +2 -0
- package/dist/tableFormatter.test.d.ts.map +1 -0
- package/dist/tableFormatter.test.js +101 -0
- package/dist/tableFormatter.test.js.map +1 -0
- package/dist/tableStyler.d.ts +310 -0
- package/dist/tableStyler.d.ts.map +1 -0
- package/dist/tableStyler.js +665 -0
- package/dist/tableStyler.js.map +1 -0
- package/dist/tableStyler.test.d.ts +2 -0
- package/dist/tableStyler.test.d.ts.map +1 -0
- package/dist/tableStyler.test.js +225 -0
- package/dist/tableStyler.test.js.map +1 -0
- package/dist/tableSvg.d.ts +41 -0
- package/dist/tableSvg.d.ts.map +1 -0
- package/dist/tableSvg.js +634 -0
- package/dist/tableSvg.js.map +1 -0
- package/dist/tableUtils.d.ts +14 -0
- package/dist/tableUtils.d.ts.map +1 -0
- package/dist/tableUtils.js +18 -0
- package/dist/tableUtils.js.map +1 -0
- package/eslint.config.js +23 -0
- package/index.ts +82 -0
- package/jest.config.js +5 -0
- package/package.json +44 -0
- package/stylings.ts +311 -0
- package/svg-table-0.0.1-snapshot.tgz +0 -0
- package/tableData.test.ts +290 -0
- package/tableData.ts +359 -0
- package/tableFormatter.test.ts +122 -0
- package/tableFormatter.ts +306 -0
- package/tableStyler.test.ts +268 -0
- package/tableStyler.ts +798 -0
- package/tableSvg.ts +820 -0
- package/tableUtils.ts +20 -0
- package/tsconfig.json +102 -0
package/dist/tableSvg.js
ADDED
|
@@ -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
|