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
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import {TableData} from "./tableData";
|
|
2
|
+
import {DataFrame} from "data-frame-ts"
|
|
3
|
+
import {defaultFormatter, TableFormatter} from "./tableFormatter";
|
|
4
|
+
import {
|
|
5
|
+
type Border,
|
|
6
|
+
type CellStyle,
|
|
7
|
+
type ColumnHeaderStyle,
|
|
8
|
+
defaultBorder,
|
|
9
|
+
defaultCellStyle,
|
|
10
|
+
defaultColumnHeaderStyle,
|
|
11
|
+
defaultColumnStyle,
|
|
12
|
+
defaultDimension,
|
|
13
|
+
defaultFooterStyle,
|
|
14
|
+
defaultRowHeaderStyle,
|
|
15
|
+
defaultTableFont,
|
|
16
|
+
defaultTableMargin,
|
|
17
|
+
defaultTablePadding,
|
|
18
|
+
type FooterStyle,
|
|
19
|
+
type RowHeaderStyle,
|
|
20
|
+
type Styling,
|
|
21
|
+
} from "./stylings";
|
|
22
|
+
import {type StyledTable, TableStyler} from "./tableStyler";
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
describe('styling data tables', () => {
|
|
26
|
+
function dateTimeFor(day: number, hour: number): Date {
|
|
27
|
+
return new Date(2021, 1, day, hour, 0, 0, 0);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const data = DataFrame.from<string | number | Date>([
|
|
31
|
+
[dateTimeFor(1, 1), 12345, 'gnm-f234', 123.45, 4],
|
|
32
|
+
[dateTimeFor(2, 2), 23456, 'gnm-g234', 23.45, 5],
|
|
33
|
+
[dateTimeFor(3, 3), 34567, 'gnm-h234', 3.65, 40],
|
|
34
|
+
[dateTimeFor(4, 4), 45678, 'gnm-i234', 314.15, 9],
|
|
35
|
+
]).getOrThrow()
|
|
36
|
+
const columnHeader = ['Date-Time', 'Customer ID', 'Product ID', 'Purchase Price', 'Amount']
|
|
37
|
+
const rowHeader = [1, 2, 3, 4]
|
|
38
|
+
const footer = ['A', 'B', 'C', 'D', 'E']
|
|
39
|
+
|
|
40
|
+
describe('adding basic table styles', () => {
|
|
41
|
+
const formattedTableData = TableData.fromDataFrame<string | number | Date>(data)
|
|
42
|
+
.withColumnHeader(columnHeader)
|
|
43
|
+
.flatMap(td => td.withRowHeader(rowHeader))
|
|
44
|
+
.flatMap(td => td.withFooter(footer))
|
|
45
|
+
.flatMap(td => TableFormatter.fromTableData(td)
|
|
46
|
+
// add the default formatter for the column header, at the highest priority so that
|
|
47
|
+
// it is the one that applies to the row representing the column header
|
|
48
|
+
.addRowFormatter(0, defaultFormatter, 100)
|
|
49
|
+
// formatter for the footer
|
|
50
|
+
.flatMap(tf => tf.addRowFormatter(5, defaultFormatter, 100))
|
|
51
|
+
.flatMap(tf => tf.addColumnFormatter(0, defaultFormatter, 100))
|
|
52
|
+
// add the column formatters for each column at the default (lowest) priority
|
|
53
|
+
.flatMap(tf => tf.addColumnFormatter(1, value => (value as Date).toLocaleDateString()))
|
|
54
|
+
.flatMap(tf => tf.addColumnFormatter(2, value => defaultFormatter(value)))
|
|
55
|
+
.flatMap(tf => tf.addColumnFormatter(4, value => `$ ${(value as number).toFixed(2)}`))
|
|
56
|
+
.flatMap(tf => tf.addColumnFormatter(5, value => `${(value as number).toFixed(0)}`))
|
|
57
|
+
.flatMap(tf => tf.addCellFormatter(3, 3, value => (value as string).toUpperCase(), 1))
|
|
58
|
+
// format the table into a new TableData object
|
|
59
|
+
.flatMap(tf => tf.formatTable())
|
|
60
|
+
)
|
|
61
|
+
.getOrThrow()
|
|
62
|
+
|
|
63
|
+
describe('set and retrieve global table styles', () => {
|
|
64
|
+
|
|
65
|
+
const styledTable: StyledTable<string> = TableStyler.fromTableData(formattedTableData)
|
|
66
|
+
.withTableBackground({color: 'grey', opacity: 0.15})
|
|
67
|
+
.withTableFont({color: 'blue', size: 13.5})
|
|
68
|
+
.withBorder({top: {opacity: 0}} as Border)
|
|
69
|
+
.withDimensions(1300, 500)
|
|
70
|
+
.withPadding({top: 10})
|
|
71
|
+
.withMargin({left: 10, right: 10})
|
|
72
|
+
.styleTable()
|
|
73
|
+
|
|
74
|
+
test('should be able to retrieve the background', () => {
|
|
75
|
+
expect(styledTable.tableBackground()).toEqual({color: 'grey', opacity: 0.15})
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
test('should be able to retrieve the font', () => {
|
|
79
|
+
expect(styledTable.tableFont()).toEqual({...defaultTableFont, color: 'blue', size: 13.5})
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
test('should be able to retrieve the border', () => {
|
|
83
|
+
expect(styledTable.tableBorder()).toEqual({...defaultBorder, top: {opacity: 0}})
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test('should be able to retrieve the dimensions', () => {
|
|
87
|
+
expect(styledTable.tableDimensions()).toEqual({width: 1300, height: 500})
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
test('should be able to retrieve the padding', () => {
|
|
91
|
+
expect(styledTable.tablePadding()).toEqual({...defaultTablePadding, top: 10})
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
test('should be able to retrieve the margin', () => {
|
|
95
|
+
expect(styledTable.tableMargin()).toEqual({...defaultTableMargin, left: 10, right: 10})
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test('should be able to set and retrieve style for the column header', () => {
|
|
100
|
+
const styledTable: StyledTable<string> = TableStyler.fromTableData(formattedTableData)
|
|
101
|
+
.withColumnHeaderStyle({font: {...defaultTableFont, size: 16, weight: 800}})
|
|
102
|
+
.styleTable()
|
|
103
|
+
|
|
104
|
+
expect(styledTable.columnHeaderStyle().getOrThrow()).toEqual({
|
|
105
|
+
style: {
|
|
106
|
+
...defaultColumnHeaderStyle,
|
|
107
|
+
font: {...defaultTableFont, size: 16, weight: 800},
|
|
108
|
+
},
|
|
109
|
+
priority: Infinity
|
|
110
|
+
} as Styling<ColumnHeaderStyle>)
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
test('should be able to set and retrieve style for the row header', () => {
|
|
114
|
+
const styledTable: StyledTable<string> = TableStyler.fromTableData(formattedTableData)
|
|
115
|
+
.withRowHeaderStyle({font: {...defaultTableFont, size: 16, weight: 800}})
|
|
116
|
+
.styleTable()
|
|
117
|
+
|
|
118
|
+
expect(styledTable.rowHeaderStyle().getOrThrow()).toEqual({
|
|
119
|
+
style: {
|
|
120
|
+
...defaultRowHeaderStyle,
|
|
121
|
+
font: {...defaultTableFont, size: 16, weight: 800},
|
|
122
|
+
},
|
|
123
|
+
priority: Infinity
|
|
124
|
+
} as Styling<RowHeaderStyle>)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
test('should be able to set and retrieve style for the footer', () => {
|
|
128
|
+
const styledTable: StyledTable<string> = TableStyler.fromTableData(formattedTableData)
|
|
129
|
+
.withFooterStyle({font: {...defaultTableFont, size: 16, weight: 800}})
|
|
130
|
+
.styleTable()
|
|
131
|
+
|
|
132
|
+
expect(styledTable.footerStyle().getOrThrow()).toEqual({
|
|
133
|
+
style: {
|
|
134
|
+
...defaultFooterStyle,
|
|
135
|
+
font: {...defaultTableFont, size: 16, weight: 800},
|
|
136
|
+
},
|
|
137
|
+
priority: Infinity
|
|
138
|
+
} as Styling<FooterStyle>)
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
describe('retrieve the cell style with highest priority', () => {
|
|
142
|
+
const styledTable: StyledTable<string> = TableStyler.fromTableData(formattedTableData)
|
|
143
|
+
.withColumnHeaderStyle({font: {...defaultTableFont, size: 16, weight: 800}})
|
|
144
|
+
.withCellStyle(2, 3, {font: {...defaultTableFont, size: 12, weight: 600}}, 100)
|
|
145
|
+
.withRowStyle(2, {font: {...defaultTableFont, size: 14, weight: 700}}, 50)
|
|
146
|
+
.withRowHeaderStyle({font: {...defaultTableFont, size: 15, weight: 650}})
|
|
147
|
+
.withColumnStyle(4, {padding: {left: 1000, right: 1111}}, 75)
|
|
148
|
+
.styleTable()
|
|
149
|
+
|
|
150
|
+
function expectDefaultCellStyleFor(row: number, column: number) {
|
|
151
|
+
expect(styledTable.stylesForTableCoordinates(row, column).getOrThrow()).toEqual(defaultCellStyle)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
test('should get the default cell style for cells with no available style', () => {
|
|
155
|
+
const unstyledRows = [1, 3, 4, 5] // row 0 is the column header, row 2 has a row-style
|
|
156
|
+
const unstyledColumns = [1, 2, 3, 5] // column 0 is the row header, column 4 has a column-style
|
|
157
|
+
for (const row of unstyledRows) {
|
|
158
|
+
for (const column of unstyledColumns) {
|
|
159
|
+
expectDefaultCellStyleFor(row, column)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
test('should get cell style for (2, 3) is the highest priority', () => {
|
|
165
|
+
expect(styledTable.stylesForTableCoordinates(2, 3).getOrThrow()).toEqual({
|
|
166
|
+
...defaultCellStyle,
|
|
167
|
+
font: {...defaultTableFont, size: 12, weight: 600},
|
|
168
|
+
} as CellStyle)
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
test('should get column header style for (0, 3) is the highest priority', () => {
|
|
172
|
+
// column header style for (0, 3) is the highest priority
|
|
173
|
+
expect(styledTable.stylesForTableCoordinates(0, 3).getOrThrow()).toEqual({
|
|
174
|
+
...defaultCellStyle,
|
|
175
|
+
...defaultColumnStyle,
|
|
176
|
+
// these come from the default column header style
|
|
177
|
+
dimension: {...defaultDimension, height: 20, minHeight: 15},
|
|
178
|
+
// these come from setting the column header style
|
|
179
|
+
font: {...defaultTableFont, size: 16, weight: 800},
|
|
180
|
+
} as CellStyle)
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
test('should return a failure when getting a style for a column index that is too large', () => {
|
|
184
|
+
const result = styledTable.stylesForTableCoordinates(1, 6)
|
|
185
|
+
expect(result.failed).toBeTruthy()
|
|
186
|
+
expect(result.error).toEqual("(StyledTable::stylesFor) Invalid row and/or column index; row_index: 1; column_index: 6; valid_row_index: [0, 6); valid_column_index: [0, 6)")
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
test('should return a failure when getting a style for a column index that is less than 0', () => {
|
|
190
|
+
const result = styledTable.stylesForTableCoordinates(3, -1)
|
|
191
|
+
expect(result.failed).toBeTruthy()
|
|
192
|
+
expect(result.error).toEqual("(StyledTable::stylesFor) Invalid row and/or column index; row_index: 3; column_index: -1; valid_row_index: [0, 6); valid_column_index: [0, 6)")
|
|
193
|
+
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
test('should return a failure when getting a style for a row index that is less than 0', () => {
|
|
197
|
+
const result = styledTable.stylesForTableCoordinates(-1, 3)
|
|
198
|
+
expect(result.failed).toBeTruthy()
|
|
199
|
+
expect(result.error).toEqual("(StyledTable::stylesFor) Invalid row and/or column index; row_index: -1; column_index: 3; valid_row_index: [0, 6); valid_column_index: [0, 6)")
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
test('should return a failure when getting a style for a row index that is too large', () => {
|
|
203
|
+
const result = styledTable.stylesForTableCoordinates(6, 3)
|
|
204
|
+
expect(result.failed).toBeTruthy()
|
|
205
|
+
expect(result.error).toEqual("(StyledTable::stylesFor) Invalid row and/or column index; row_index: 6; column_index: 3; valid_row_index: [0, 6); valid_column_index: [0, 6)")
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
test('should get the row header style for (1, 0) because table has row header style', () => {
|
|
209
|
+
expect(styledTable.stylesForTableCoordinates(1, 0).getOrThrow()).toEqual({
|
|
210
|
+
...defaultCellStyle,
|
|
211
|
+
...defaultRowHeaderStyle,
|
|
212
|
+
font: {...defaultTableFont, size: 15, weight: 650}
|
|
213
|
+
} as CellStyle)
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
test('should get column header style for (0, 4) because table has column header style', () => {
|
|
217
|
+
expect(styledTable.stylesForTableCoordinates(0, 4).getOrThrow()).toEqual({
|
|
218
|
+
...defaultCellStyle,
|
|
219
|
+
// these come from the default column header style rather than the column style for
|
|
220
|
+
// the 4th column because the column header style has a higher priority
|
|
221
|
+
dimension: {...defaultDimension, height: 20, minHeight: 15},
|
|
222
|
+
// these come from setting the column header style
|
|
223
|
+
font: {...defaultTableFont, size: 16, weight: 800}
|
|
224
|
+
} as CellStyle)
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
test('should get column style for (1, 4) because table has column style', () => {
|
|
228
|
+
expect(styledTable.stylesForTableCoordinates(1, 4).getOrThrow()).toEqual({
|
|
229
|
+
...defaultCellStyle,
|
|
230
|
+
...defaultColumnStyle,
|
|
231
|
+
padding: {...defaultTablePadding, left: 1000, right: 1111}
|
|
232
|
+
} as CellStyle)
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
test('should get column style for (2, 4) because table has column style with higher priority than row-style', () => {
|
|
236
|
+
expect(styledTable.stylesForTableCoordinates(2, 4).getOrThrow()).toEqual({
|
|
237
|
+
// the default cell style is the base style
|
|
238
|
+
...defaultCellStyle,
|
|
239
|
+
// the column style overwrites the row style for this cell
|
|
240
|
+
...defaultColumnStyle,
|
|
241
|
+
// the row style sets the font (column style doesn't) have font, and so the column style
|
|
242
|
+
// that overrides the row style doesn't change the font
|
|
243
|
+
font: {...defaultTableFont, size: 14, weight: 700},
|
|
244
|
+
// and the column style sets the padding
|
|
245
|
+
padding: {...defaultTablePadding, left: 1000, right: 1111}
|
|
246
|
+
} as CellStyle)
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
test('should get column style for (3, 4) because table has column style with higher priority than row-style', () => {
|
|
250
|
+
expect(styledTable.stylesForTableCoordinates(3, 4).getOrThrow()).toEqual({
|
|
251
|
+
...defaultCellStyle,
|
|
252
|
+
...defaultColumnStyle,
|
|
253
|
+
padding: {...defaultTablePadding, left: 1000, right: 1111}
|
|
254
|
+
} as CellStyle)
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
test('should be able to retrieve cell styles using data row and column indices', () => {
|
|
258
|
+
// cell (2 ,3) in table coordinates translates to cell (1, 2) in data coordinates because
|
|
259
|
+
// the table has a column header and a row header. in this case the data coordinates are
|
|
260
|
+
// (table_row - 1, table_column - 1).
|
|
261
|
+
expect(styledTable.stylesForDataCoordinates(2 - 1, 3 - 1).getOrThrow()).toEqual({
|
|
262
|
+
...defaultCellStyle,
|
|
263
|
+
font: {...defaultTableFont, size: 12, weight: 600},
|
|
264
|
+
} as CellStyle)
|
|
265
|
+
})
|
|
266
|
+
})
|
|
267
|
+
})
|
|
268
|
+
})
|