svg-table 0.0.2 → 0.1.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/CHANGES.md +9 -0
- package/README.md +447 -1
- package/TableFormatter.ts +286 -5
- package/TableStyler.ts +74 -5
- package/dist/TableFormatter.d.ts +280 -0
- package/dist/TableFormatter.d.ts.map +1 -1
- package/dist/TableFormatter.js +286 -5
- package/dist/TableFormatter.js.map +1 -1
- package/dist/TableStyler.d.ts +56 -1
- package/dist/TableStyler.d.ts.map +1 -1
- package/dist/TableStyler.js +61 -2
- package/dist/TableStyler.js.map +1 -1
- package/dist/tableFormatter.test.js +41 -2
- package/dist/tableFormatter.test.js.map +1 -1
- package/dist/tableStyler.test.js +222 -6
- package/dist/tableStyler.test.js.map +1 -1
- package/dist/tableSvg.js +4 -2
- package/dist/tableSvg.js.map +1 -1
- package/package.json +1 -1
- package/tableFormatter.test.ts +46 -2
- package/tableStyler.test.ts +130 -7
- package/tableSvg.ts +4 -2
package/CHANGES.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# change log
|
|
2
|
+
|
|
3
|
+
## version 0.1.1
|
|
4
|
+
|
|
5
|
+
Fixed bug where the offset for the row was determined by the whether there was a row-header, rather than whether there was a column-header. And the offset for the column was determined by the whether there was a column-header, rather than whether there was a row-header.
|
|
6
|
+
|
|
7
|
+
## version 0.1.0
|
|
8
|
+
|
|
9
|
+
The initial release.
|
package/README.md
CHANGED
|
@@ -1,3 +1,449 @@
|
|
|
1
1
|
# SVG Table
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A tiny TypeScript library to turn tabular data into a styled SVG table. It separates three concerns:
|
|
4
|
+
- Data: describe your table structure (data, headers, footer) with TableData.
|
|
5
|
+
- Formatting: convert raw values into display strings with TableFormatter.
|
|
6
|
+
- Styling + Rendering: define look-and-feel with TableStyler and render into an SVG via createTable.
|
|
7
|
+
|
|
8
|
+
SVG Table is framework-agnostic and works with any environment where you can access an <svg> element (vanilla JS/TS, React, Svelte, etc.).
|
|
9
|
+
|
|
10
|
+
> See [the SVG table example](https://github.com/robphilipp/svg-table-example) for an example of creating a table with SVG Table.
|
|
11
|
+
|
|
12
|
+
## Table of Contents
|
|
13
|
+
- [Installation](#installation)
|
|
14
|
+
- [Quick Start](#quick-start)
|
|
15
|
+
- [Core Concepts](#core-concepts)
|
|
16
|
+
- [TableData](#tabledata)
|
|
17
|
+
- [TableFormatter](#tableformatter)
|
|
18
|
+
- [TableStyler](#tablestyler)
|
|
19
|
+
- [Rendering to SVG](#rendering-to-svg)
|
|
20
|
+
- [Examples](#examples)
|
|
21
|
+
- [1) Data with a column header](#1-data-with-a-column-header)
|
|
22
|
+
- [2) Column + row headers, custom formatters](#2-column--row-headers-custom-formatters)
|
|
23
|
+
- [3) Overriding specific cells](#3-overriding-specific-cells)
|
|
24
|
+
- [4) Styling the table](#4-styling-the-table)
|
|
25
|
+
- [API Surface (high level)](#api-surface-high-level)
|
|
26
|
+
- [Method Reference](#method-reference)
|
|
27
|
+
- [TableData methods](#tabledata-methods)
|
|
28
|
+
- [TableFormatter methods](#tableformatter-methods)
|
|
29
|
+
- [TableStyler methods](#tablestyler-methods)
|
|
30
|
+
- [Rendering methods](#rendering-methods)
|
|
31
|
+
- [Styling helpers](#styling-helpers)
|
|
32
|
+
- [FAQ](#faq)
|
|
33
|
+
- [License](#license)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
[(toc)](#table-of-contents)
|
|
39
|
+
|
|
40
|
+
Install from npm. TypeScript types are included.
|
|
41
|
+
|
|
42
|
+
- npm: npm install svg-table d3 data-frame-ts
|
|
43
|
+
- pnpm: pnpm add svg-table d3 data-frame-ts
|
|
44
|
+
- yarn: yarn add svg-table d3 data-frame-ts
|
|
45
|
+
|
|
46
|
+
Peer libraries used in examples:
|
|
47
|
+
- data-frame-ts: Simple immutable 2D data container with tagging.
|
|
48
|
+
- d3: Only the selection utilities are used when you need them; the renderer accepts a native SVG element.
|
|
49
|
+
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
[(toc)](#table-of-contents)
|
|
53
|
+
|
|
54
|
+
This example builds a small table, formats numbers and dates, styles it, and renders into an existing <svg id="app"> element.
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
// 1) Raw data (mixed types)
|
|
58
|
+
const data = DataFrame.from<(string | number | Date)>([
|
|
59
|
+
[new Date(2021, 1, 1, 1), 12345, 'gnm-f234', 123.45, 4],
|
|
60
|
+
[new Date(2021, 1, 2, 2), 23456, 'gnm-g234', 23.45, 5],
|
|
61
|
+
]).getOrThrow()
|
|
62
|
+
|
|
63
|
+
const columnHeader = ['Date-Time', 'Customer ID', 'Product ID', 'Purchase Price', 'Amount']
|
|
64
|
+
|
|
65
|
+
// 2) Describe the table structure
|
|
66
|
+
const withHeader = TableData.fromDataFrame(data)
|
|
67
|
+
.withColumnHeader(columnHeader)
|
|
68
|
+
.getOrThrow()
|
|
69
|
+
|
|
70
|
+
// 3) Format values for display
|
|
71
|
+
const formatted = TableFormatter.fromTableData(withHeader)
|
|
72
|
+
// ensure the header row uses the default formatter (highest priority)
|
|
73
|
+
.addRowFormatter(0, defaultFormatter, Infinity)
|
|
74
|
+
// column-wise formatters (note column indexes refer to the table, not just data)
|
|
75
|
+
.flatMap(tf => tf.addColumnFormatter(0, v => (v as Date).toLocaleDateString()))
|
|
76
|
+
.flatMap(tf => tf.addColumnFormatter(1, v => defaultFormatter(v)))
|
|
77
|
+
.flatMap(tf => tf.addColumnFormatter(3, v => `$ ${(v as number).toFixed(2)}`))
|
|
78
|
+
.flatMap(tf => tf.addColumnFormatter(4, v => `${(v as number).toFixed(0)}`))
|
|
79
|
+
.flatMap(tf => tf.formatTable())
|
|
80
|
+
.getOrThrow()
|
|
81
|
+
|
|
82
|
+
// 4) Style the table (use defaults or customize)
|
|
83
|
+
const styled = TableStyler.fromTableData(formatted)
|
|
84
|
+
.withDimensions(600, 200)
|
|
85
|
+
.styleTable()
|
|
86
|
+
.getOrThrow()
|
|
87
|
+
|
|
88
|
+
// 5) Render to SVG at position (x=20, y=20)
|
|
89
|
+
const svg = document.getElementById('app') as unknown as SVGSVGElement
|
|
90
|
+
createTable(styled, svg, 'example-1', (w, h) => [20, 20])
|
|
91
|
+
.getOrThrow()
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
## Core Concepts
|
|
96
|
+
|
|
97
|
+
[(toc)](#table-of-contents)
|
|
98
|
+
|
|
99
|
+
### TableData
|
|
100
|
+
|
|
101
|
+
[(toc)](#table-of-contents)
|
|
102
|
+
|
|
103
|
+
Represents your table’s structure over a DataFrame:
|
|
104
|
+
- Add column and row headers, and footers
|
|
105
|
+
- Ask for counts and sections of the table (data, headers, footer)
|
|
106
|
+
|
|
107
|
+
Key methods (return a Result so you can chain with .flatMap and finish with .getOrThrow()):
|
|
108
|
+
- TableData.fromDataFrame(df)
|
|
109
|
+
- withColumnHeader(header: string[], formatting = defaultFormatting)
|
|
110
|
+
- withRowHeader(header: (string|number)[], formatting = defaultFormatting, columnHeaderProvider?, footerProvider?)
|
|
111
|
+
- withFooter(footer: (string|number)[], formatting = defaultFormatting, rowHeaderProvider?)
|
|
112
|
+
- hasColumnHeader(), hasRowHeader(), hasFooter()
|
|
113
|
+
- tableRowCount(), tableColumnCount()
|
|
114
|
+
- data(), columnHeader(), rowHeader(), footer()
|
|
115
|
+
|
|
116
|
+
### TableFormatter
|
|
117
|
+
|
|
118
|
+
[(toc)](#table-of-contents)
|
|
119
|
+
|
|
120
|
+
Transforms raw cell values into display strings. You assign formatters at different scopes with optional priorities. Higher priority wins for a given cell.
|
|
121
|
+
|
|
122
|
+
Scopes:
|
|
123
|
+
- Row-level: addRowFormatter(rowIndex, formatter, priority?)
|
|
124
|
+
- Column-level: addColumnFormatter(columnIndex, formatter, priority?)
|
|
125
|
+
- Cell-level: addCellFormatter(rowIndex, columnIndex, formatter, priority?)
|
|
126
|
+
|
|
127
|
+
Utilities:
|
|
128
|
+
- defaultFormatter: converts anything to string sensibly
|
|
129
|
+
- formatTable(): Result<TableData<string>, string>
|
|
130
|
+
|
|
131
|
+
Tip: When both row and column headers exist, remember that indexes are for the full table including headers.
|
|
132
|
+
|
|
133
|
+
### TableStyler
|
|
134
|
+
|
|
135
|
+
[(toc)](#table-of-contents)
|
|
136
|
+
|
|
137
|
+
Assigns visual styles (font, padding, margins, borders, per-row/per-column/per-cell styles). Styling is also priority-based internally so the most specific style wins.
|
|
138
|
+
|
|
139
|
+
Useful entry points:
|
|
140
|
+
- TableStyler.fromTableData(tableData)
|
|
141
|
+
- withTableFont(font), withTableBackground(bg), withBorder(border)
|
|
142
|
+
- withDimensions(width, height), withPadding({top,left,bottom,right}), withMargin(...)
|
|
143
|
+
- withRowStyle(i, style, priority?), withColumnStyle(j, style, priority?), withCellStyle(i, j, style, priority?)
|
|
144
|
+
- withCellStyleWhen(predicate, style, priority?)
|
|
145
|
+
- withColumnHeaderStyle(style, priority?), withRowHeaderStyle(style, priority?), withFooterStyle(style, priority?)
|
|
146
|
+
- styleTable(): Result<StyledTable, string>
|
|
147
|
+
|
|
148
|
+
### Rendering to SVG
|
|
149
|
+
|
|
150
|
+
[(toc)](#table-of-contents)
|
|
151
|
+
|
|
152
|
+
Use createTable(styledTable, svgElement, uniqueTableId, coordinates)
|
|
153
|
+
|
|
154
|
+
- styledTable: result of TableStyler.styleTable().getOrThrow()
|
|
155
|
+
- svgElement: an existing SVGSVGElement
|
|
156
|
+
- uniqueTableId: used to generate element ids
|
|
157
|
+
- coordinates: either a fixed [x, y] or a function (width, height) => [x, y]
|
|
158
|
+
|
|
159
|
+
Helper:
|
|
160
|
+
- tableId(uniqueTableId) -> the id of the root <g> group added to your svg
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
## Examples
|
|
164
|
+
|
|
165
|
+
[(toc)](#table-of-contents)
|
|
166
|
+
|
|
167
|
+
### 1) Data with a column header
|
|
168
|
+
|
|
169
|
+
[(toc)](#table-of-contents)
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
const data = DataFrame.from<number | string>([
|
|
173
|
+
['Widget A', 12.34],
|
|
174
|
+
['Widget B', 56.7],
|
|
175
|
+
]).getOrThrow()
|
|
176
|
+
|
|
177
|
+
const td = TableData.fromDataFrame(data)
|
|
178
|
+
.withColumnHeader(['Product', 'Price'])
|
|
179
|
+
.getOrThrow()
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### 2) Column + row headers, custom formatters
|
|
183
|
+
|
|
184
|
+
[(toc)](#table-of-contents)
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
const df = DataFrame.from<(string | number | Date)>([
|
|
188
|
+
[new Date(2021, 1, 1), 12345, 123.45],
|
|
189
|
+
[new Date(2021, 1, 2), 23456, 23.45],
|
|
190
|
+
]).getOrThrow()
|
|
191
|
+
|
|
192
|
+
const tableData = TableData.fromDataFrame(df)
|
|
193
|
+
.withColumnHeader(['Date', 'Customer', 'Price'])
|
|
194
|
+
.flatMap(td => td.withRowHeader([1, 2]))
|
|
195
|
+
.getOrThrow()
|
|
196
|
+
|
|
197
|
+
const formatted = TableFormatter.fromTableData(tableData)
|
|
198
|
+
.addRowFormatters([0], defaultFormatter, Infinity)
|
|
199
|
+
.flatMap(tf => tf.addColumnFormatter(1, v => v.toString()))
|
|
200
|
+
.flatMap(tf => tf.addColumnFormatter(2, v => `$ ${(v as number).toFixed(2)}`))
|
|
201
|
+
.flatMap(tf => tf.formatTable())
|
|
202
|
+
.getOrThrow()
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### 3) Overriding specific cells
|
|
206
|
+
|
|
207
|
+
[(toc)](#table-of-contents)
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
const overridden = TableFormatter.fromTableData(formatted)
|
|
211
|
+
.addCellFormatter(1, 2, v => `${(v as number).toFixed(2)}`, 1000) // strong override
|
|
212
|
+
.flatMap(tf => tf.formatTable())
|
|
213
|
+
.getOrThrow()
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### 4) Styling the table
|
|
217
|
+
|
|
218
|
+
[(toc)](#table-of-contents)
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
const styled = TableStyler.fromTableData(overridden)
|
|
222
|
+
.withTableFont({ ...defaultTableFont(), size: '12px', weight: '600' })
|
|
223
|
+
.withTableBackground({ color: '#fff' })
|
|
224
|
+
.withPadding({ ...defaultTablePadding(), top: 8, left: 8, right: 8, bottom: 8 })
|
|
225
|
+
.withBorder({ ...defaultBorder(), color: '#999', width: 1 })
|
|
226
|
+
.withDimensions(480, 160)
|
|
227
|
+
.withRowStyle(0, { backgroundColor: '#f5f5f5' }) // header row, if present
|
|
228
|
+
.styleTable()
|
|
229
|
+
.getOrThrow()
|
|
230
|
+
|
|
231
|
+
// Render at (x, y) = (24, 24)
|
|
232
|
+
const svg = document.querySelector('svg#app') as unknown as SVGSVGElement
|
|
233
|
+
createTable(styled, svg, 'styled-demo', (w, h) => [24, 24])
|
|
234
|
+
.getOrThrow()
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
## API Surface (high level)
|
|
239
|
+
|
|
240
|
+
[(toc)](#table-of-contents)
|
|
241
|
+
|
|
242
|
+
This package re-exports the primary types and helpers from index.ts:
|
|
243
|
+
|
|
244
|
+
- TableData, TableTagType
|
|
245
|
+
- TableFormatter, defaultFormatter, isFormattingTag, defaultFormatting, TableFormatterType
|
|
246
|
+
- TableStyler, StyledTable
|
|
247
|
+
- createTable, elementInfoFrom, tableId
|
|
248
|
+
- Styling primitives and defaults: Styling, TableStylerProps, TableFont, Background, Padding, Margin,
|
|
249
|
+
BorderElement, Border, Dimension, ColumnStyle, RowStyle, CellStyle, ColumnHeaderStyle, RowHeaderStyle, FooterStyle,
|
|
250
|
+
TextAlignment, VerticalTextAlignment, Stylings, and their default* functions
|
|
251
|
+
- d3 type aliases: GroupSelection, TextSelection, RectSelection, LineSelection, BorderSelection
|
|
252
|
+
|
|
253
|
+
Use your editor’s type hints for full details, or read the source files:
|
|
254
|
+
- TableData.ts
|
|
255
|
+
- TableFormatter.ts
|
|
256
|
+
- TableStyler.ts
|
|
257
|
+
- tableSvg.ts
|
|
258
|
+
- stylings.ts
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
## Method Reference
|
|
262
|
+
|
|
263
|
+
[(toc)](#table-of-contents)
|
|
264
|
+
|
|
265
|
+
### TableData methods
|
|
266
|
+
|
|
267
|
+
[(toc)](#table-of-contents)
|
|
268
|
+
|
|
269
|
+
- fromDataFrame(df)
|
|
270
|
+
- Create a TableData from a DataFrame of values (strings, numbers, dates, etc.).
|
|
271
|
+
- Example:
|
|
272
|
+
```ts
|
|
273
|
+
const df = DataFrame.from([['A', 1], ['B', 2]]).getOrThrow()
|
|
274
|
+
const td = TableData.fromDataFrame(df)
|
|
275
|
+
```
|
|
276
|
+
- withColumnHeader(header: string[], formatting = defaultFormatting)
|
|
277
|
+
- Attach a column header row. Returns Result<TableData<...>, string>.
|
|
278
|
+
- Example:
|
|
279
|
+
```ts
|
|
280
|
+
const td2 = td.withColumnHeader(['Name', 'Qty']).getOrThrow()
|
|
281
|
+
```
|
|
282
|
+
- withRowHeader(header: (string|number)[], formatting = defaultFormatting, columnHeaderProvider?, footerProvider?)
|
|
283
|
+
- Attach a dedicated row header column. If a column header or footer already exists, use the providers so the new tags can reference each other under the hood.
|
|
284
|
+
- Example:
|
|
285
|
+
```ts
|
|
286
|
+
const td3 = td2.withRowHeader([1, 2]).getOrThrow()
|
|
287
|
+
```
|
|
288
|
+
- withFooter(footer: (string|number)[], formatting = defaultFormatting, rowHeaderProvider?)
|
|
289
|
+
- Attach a footer row. Works with or without row headers.
|
|
290
|
+
- Example:
|
|
291
|
+
```ts
|
|
292
|
+
const td4 = td3.withFooter(['Total', 3]).getOrThrow()
|
|
293
|
+
```
|
|
294
|
+
- hasColumnHeader() / hasRowHeader() / hasFooter()
|
|
295
|
+
- Booleans over the current table structure.
|
|
296
|
+
- Example:
|
|
297
|
+
```ts
|
|
298
|
+
if (td4.hasFooter()) { /* ... */ }
|
|
299
|
+
```
|
|
300
|
+
- dataRowCount() / dataColumnCount()
|
|
301
|
+
- The counts of the underlying data only (no headers/footers).
|
|
302
|
+
- tableRowCount() / tableColumnCount()
|
|
303
|
+
- The counts including any headers and/or footer.
|
|
304
|
+
- data()
|
|
305
|
+
- Returns Result<DataFrame<V>, string> of the data section only.
|
|
306
|
+
- columnHeader(includeRowHeader = false)
|
|
307
|
+
- Returns Result<string[]|number[], string> of the column header. When includeRowHeader is true and a row header exists, the left-most row header label(s) are included.
|
|
308
|
+
- rowHeader(includeColumnHeader = false, includeFooter = false)
|
|
309
|
+
- Returns Result<(string|number)[], string> of the row header column; optionally include the column header cell and/or footer cell for that column.
|
|
310
|
+
- footer(includeRowHeader = false)
|
|
311
|
+
- Returns Result<(string|number)[], string> of the footer row; optionally include the row header cell for that row.
|
|
312
|
+
- unwrapDataFrame()
|
|
313
|
+
- Returns the underlying DataFrame (unsafe; for advanced use where you manage tags yourself).
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
### TableFormatter methods
|
|
317
|
+
|
|
318
|
+
[(toc)](#table-of-contents)
|
|
319
|
+
|
|
320
|
+
- fromTableData(tableData) / fromDataFrame(dataFrame)
|
|
321
|
+
- Build a TableFormatter around an existing table or raw data.
|
|
322
|
+
- Example:
|
|
323
|
+
```ts
|
|
324
|
+
const tf = TableFormatter.fromTableData(td3)
|
|
325
|
+
```
|
|
326
|
+
- addColumnFormatter(columnIndex, formatter, priority = 0)
|
|
327
|
+
- Assign a formatter to a column index in the full table coordinate space (including headers). Higher priority wins.
|
|
328
|
+
- Example:
|
|
329
|
+
```ts
|
|
330
|
+
const tf2 = tf.addColumnFormatter(1, v => `$ ${(v as number).toFixed(2)}`)
|
|
331
|
+
```
|
|
332
|
+
- addColumnFormatters(columnIndexes: number[], formatter, priority = 0)
|
|
333
|
+
- Convenience for adding the same formatter to multiple columns.
|
|
334
|
+
- Example:
|
|
335
|
+
```ts
|
|
336
|
+
const tf3 = tf.flatMap(t => t.addColumnFormatters([1,2], v => v.toString()))
|
|
337
|
+
```
|
|
338
|
+
- addRowFormatter(rowIndex, formatter, priority = 0)
|
|
339
|
+
- Assign a formatter to a specific row (e.g., the column header row at index 0).
|
|
340
|
+
- Example:
|
|
341
|
+
```ts
|
|
342
|
+
const tfHdr = tf.addRowFormatter(0, defaultFormatter, Infinity)
|
|
343
|
+
```
|
|
344
|
+
- addRowFormatters(rowIndexes: number[], formatter, priority = 0)
|
|
345
|
+
- Convenience to format multiple rows.
|
|
346
|
+
- addCellFormatter(rowIndex, columnIndex, formatter, priority = 0)
|
|
347
|
+
- Most specific override for a single cell.
|
|
348
|
+
- Example:
|
|
349
|
+
```ts
|
|
350
|
+
const tfCell = tf.addCellFormatter(3, 2, v => (v as string).toUpperCase(), 1000)
|
|
351
|
+
```
|
|
352
|
+
- addCellFormatters(cellIndexes: [row, col][], formatter, priority = 0)
|
|
353
|
+
- Apply the same cell-override to a list of cells.
|
|
354
|
+
- formatTable()
|
|
355
|
+
- Applies all formatters and returns Result<TableData<string>, string>.
|
|
356
|
+
- Example:
|
|
357
|
+
```ts
|
|
358
|
+
const formatted = tfHdr.flatMap(t => t.formatTable()).getOrThrow()
|
|
359
|
+
```
|
|
360
|
+
- formatTableInto(mapper)
|
|
361
|
+
- Advanced: Format into a custom element type by mapping each text cell into your own structure.
|
|
362
|
+
|
|
363
|
+
Utilities (exported): defaultFormatter, defaultFormatting, isFormattingTag, TableFormatterType (enum-ish marker for tags).
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
### TableStyler methods
|
|
367
|
+
|
|
368
|
+
[(toc)](#table-of-contents)
|
|
369
|
+
|
|
370
|
+
- fromTableData(tableData) / fromDataFrame(dataFrame)
|
|
371
|
+
- Start configuring styles for a table.
|
|
372
|
+
- withTableFont(font) / withTableBackground(bg) / withBorder(border)
|
|
373
|
+
- Set global font, background, and border defaults.
|
|
374
|
+
- Example:
|
|
375
|
+
```ts
|
|
376
|
+
const ts = TableStyler.fromTableData(formatted)
|
|
377
|
+
.withTableFont({ ...defaultTableFont(), size: '12px' })
|
|
378
|
+
.withTableBackground({ color: '#fff' })
|
|
379
|
+
.withBorder({ ...defaultBorder(), color: '#ddd', width: 1 })
|
|
380
|
+
```
|
|
381
|
+
- withDimensions(width, height) / withPadding(padding) / withMargin(margin)
|
|
382
|
+
- Set overall layout metrics for the table and surrounding whitespace.
|
|
383
|
+
- withRowStyle(rowIndex, style, priority = 0) / withRowStyles(indexes, style, priority)
|
|
384
|
+
- Apply styles to header/data/footer rows (use table coordinates). Higher priority wins.
|
|
385
|
+
- withColumnStyle(columnIndex, style, priority = 0) / withColumnStyles(indexes, style, priority)
|
|
386
|
+
- Apply styles to whole columns.
|
|
387
|
+
- withCellStyle(rowIndex, columnIndex, style, priority = 0)
|
|
388
|
+
- Most specific style override for a single cell.
|
|
389
|
+
- withCellStyleWhen(predicate, style, priority = 0)
|
|
390
|
+
- Conditional styling; predicate receives (value, rowIndex, columnIndex) in table coordinates.
|
|
391
|
+
- Example:
|
|
392
|
+
```ts
|
|
393
|
+
const styled = ts
|
|
394
|
+
.withCellStyleWhen((v, i, j) => j === 2 && Number(v) > 100, { color: '#d00' }, 10)
|
|
395
|
+
.styleTable()
|
|
396
|
+
.getOrThrow()
|
|
397
|
+
```
|
|
398
|
+
- withColumnHeaderStyle(style, priority) / withRowHeaderStyle(style, priority) / withFooterStyle(style, priority)
|
|
399
|
+
- Section-specific styles that participate in the same priority system.
|
|
400
|
+
- styleTable()
|
|
401
|
+
- Finalize styles and produce Result<StyledTable, string>.
|
|
402
|
+
|
|
403
|
+
StyledTable (result) exposes getters used by the renderer: tableFont(), tableBackground(), tablePadding(), rowStyleFor(), columnStyleFor(), cellStyleFor(), and flags hasColumnHeader()/hasRowHeader()/hasFooter().
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
### Rendering methods
|
|
407
|
+
|
|
408
|
+
[(toc)](#table-of-contents)
|
|
409
|
+
|
|
410
|
+
- createTable(styledTable, svgElement, uniqueTableId, coordinates)
|
|
411
|
+
- Render the styled table into a provided SVGSVGElement, adding a <g id="svg-table-group-..."> group. Coordinates can be [x, y] or a function of (width, height).
|
|
412
|
+
- Example:
|
|
413
|
+
```ts
|
|
414
|
+
const svg = document.querySelector('svg#app') as unknown as SVGSVGElement
|
|
415
|
+
createTable(styled, svg, 'orders', (w, h) => [20, 20]).getOrThrow()
|
|
416
|
+
```
|
|
417
|
+
- tableId(uniqueTableId)
|
|
418
|
+
- Helper that returns the id of the root group for a given table name.
|
|
419
|
+
- elementInfoFrom(textSel, cellSel, borderSel, style)
|
|
420
|
+
- Low-level helper used internally; exposed for tooling/tests.
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
### Styling helpers
|
|
424
|
+
|
|
425
|
+
[(toc)](#table-of-contents)
|
|
426
|
+
|
|
427
|
+
- Defaults: defaultTableFont(), defaultTableBackground(), defaultTablePadding(), defaultTableMargin(), defaultBorder(), defaultDimension(), defaultColumnStyle(), defaultRowStyle(), defaultCellStyle(), defaultColumnHeaderStyle(), defaultRowHeaderStyle(), defaultFooterStyle().
|
|
428
|
+
- Example font override:
|
|
429
|
+
```ts
|
|
430
|
+
const font = { ...defaultTableFont(), family: 'Inter, sans-serif', size: '14px' }
|
|
431
|
+
```
|
|
432
|
+
- stylingFor(style)
|
|
433
|
+
- Wrap a plain style object into an internal Styling tag for use with tagRow/tagColumn APIs (you rarely need this directly; prefer withRowStyle/withColumnStyle/withCellStyle).
|
|
434
|
+
- TableStyleType
|
|
435
|
+
- Internal discriminator for style tags; useful if you explore raw tags.
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
## FAQ
|
|
439
|
+
|
|
440
|
+
[(toc)](#table-of-contents)
|
|
441
|
+
|
|
442
|
+
- Why Results? Methods return Result<T, string> so you can safely compose operations (.map/.flatMap) and collect errors instead of throwing immediately. Finish a chain with .getOrThrow() when you want to surface errors.
|
|
443
|
+
- Do I need d3 to render? createTable accepts a native SVGSVGElement. d3 is only used internally for convenient selection/manipulation; you don’t have to use d3 elsewhere in your app.
|
|
444
|
+
- How are indexes counted when headers exist? Row/column indexes are for the full table including headers. For example, if you add a row header, data columns shift by one in TableFormatter.
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
## License
|
|
448
|
+
|
|
449
|
+
MIT License. See LICENSE for details.
|