@jackens/nnn 2024.2.19 → 2024.2.20
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/chartable.d.ts +17 -15
- package/chartable.js +33 -31
- package/package.json +3 -1
- package/readme.md +18 -16
package/chartable.d.ts
CHANGED
|
@@ -5,27 +5,29 @@
|
|
|
5
5
|
* - `table`: `HTMLTableElement` to extract data, data series labels and X axis labels
|
|
6
6
|
* - `headerColumn`: flag indicating that `table` has a header column with X axis labels
|
|
7
7
|
* - `xGap`: X axis spacing
|
|
8
|
-
* - `
|
|
8
|
+
* - `xLabelsMinHeight`: minimal height of X axis labels
|
|
9
9
|
* - `xLabelsRotate`: flag to rotate X axis labels
|
|
10
10
|
* - `xReverse`: flag to reverse all data series
|
|
11
11
|
* - `yGap`: Y axis spacing
|
|
12
|
-
* - `
|
|
13
|
-
* - `
|
|
12
|
+
* - `yLabelsLeftMinWidth`: minimal width of Y axis left labels
|
|
13
|
+
* - `yLabelsRightMinWidth`: minimal width of Y axis right labels
|
|
14
14
|
* - `yMax`: number of Y axis lines
|
|
15
|
-
* - `
|
|
15
|
+
* - `zLabelsMinWidth`: minimal width of data series labels
|
|
16
|
+
* - `zyMappings`: mappings per data series
|
|
16
17
|
*/
|
|
17
|
-
export function chartable({ table, headerColumn, xGap,
|
|
18
|
+
export function chartable({ table, headerColumn, xGap, xLabelsMinHeight, xLabelsRotate, xReverse, yGap, yLabelsLeftMinWidth, yLabelsRightMinWidth, yMax, zLabelsMinWidth, zyMappings }: {
|
|
18
19
|
table: HTMLTableElement;
|
|
19
|
-
headerColumn?: boolean;
|
|
20
|
-
xGap?: number;
|
|
21
|
-
|
|
22
|
-
xLabelsRotate?: boolean;
|
|
23
|
-
xReverse?: boolean;
|
|
24
|
-
yGap?: number;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
yMax?: number;
|
|
28
|
-
|
|
20
|
+
headerColumn?: boolean | undefined;
|
|
21
|
+
xGap?: number | undefined;
|
|
22
|
+
xLabelsMinHeight?: number | undefined;
|
|
23
|
+
xLabelsRotate?: boolean | undefined;
|
|
24
|
+
xReverse?: boolean | undefined;
|
|
25
|
+
yGap?: number | undefined;
|
|
26
|
+
yLabelsLeftMinWidth?: number | undefined;
|
|
27
|
+
yLabelsRightMinWidth?: number | undefined;
|
|
28
|
+
yMax?: number | undefined;
|
|
29
|
+
zLabelsMinWidth?: number | undefined;
|
|
30
|
+
zyMappings?: [(label: string) => number, (value: number) => string][] | undefined;
|
|
29
31
|
}): SVGSVGElement;
|
|
30
32
|
|
|
31
33
|
export const tests: {};
|
package/chartable.js
CHANGED
|
@@ -7,6 +7,8 @@ const _svg = s('svg', { viewBox: '0 0 0 0', width: 0, height: 0 })
|
|
|
7
7
|
|
|
8
8
|
h(document.body, ['div', { $style: { width: 0, height: 0 } }, _svg])
|
|
9
9
|
|
|
10
|
+
const toFixed2 = (/** @type {number} */ value) => value.toFixed(2)
|
|
11
|
+
|
|
10
12
|
/**
|
|
11
13
|
* A helper for creating a chart based on a table (conf. <https://jackens.github.io/nnn/chartable/>).
|
|
12
14
|
*
|
|
@@ -14,41 +16,44 @@ h(document.body, ['div', { $style: { width: 0, height: 0 } }, _svg])
|
|
|
14
16
|
* - `table`: `HTMLTableElement` to extract data, data series labels and X axis labels
|
|
15
17
|
* - `headerColumn`: flag indicating that `table` has a header column with X axis labels
|
|
16
18
|
* - `xGap`: X axis spacing
|
|
17
|
-
* - `
|
|
19
|
+
* - `xLabelsMinHeight`: minimal height of X axis labels
|
|
18
20
|
* - `xLabelsRotate`: flag to rotate X axis labels
|
|
19
21
|
* - `xReverse`: flag to reverse all data series
|
|
20
22
|
* - `yGap`: Y axis spacing
|
|
21
|
-
* - `
|
|
22
|
-
* - `
|
|
23
|
+
* - `yLabelsLeftMinWidth`: minimal width of Y axis left labels
|
|
24
|
+
* - `yLabelsRightMinWidth`: minimal width of Y axis right labels
|
|
23
25
|
* - `yMax`: number of Y axis lines
|
|
24
|
-
* - `
|
|
26
|
+
* - `zLabelsMinWidth`: minimal width of data series labels
|
|
27
|
+
* - `zyMappings`: mappings per data series
|
|
25
28
|
*
|
|
26
29
|
* @param {{
|
|
27
30
|
* table: HTMLTableElement;
|
|
28
31
|
* headerColumn?: boolean;
|
|
29
32
|
* xGap?: number;
|
|
30
|
-
*
|
|
33
|
+
* xLabelsMinHeight?: number;
|
|
31
34
|
* xLabelsRotate?: boolean;
|
|
32
35
|
* xReverse?: boolean;
|
|
33
36
|
* yGap?: number;
|
|
34
|
-
*
|
|
35
|
-
*
|
|
37
|
+
* yLabelsLeftMinWidth?: number;
|
|
38
|
+
* yLabelsRightMinWidth?: number;
|
|
36
39
|
* yMax?: number;
|
|
37
|
-
*
|
|
40
|
+
* zLabelsMinWidth?: number;
|
|
41
|
+
* zyMappings?: [(label: string) => number, (value: number) => string][];
|
|
38
42
|
* }} options
|
|
39
43
|
*/
|
|
40
44
|
export const chartable = ({
|
|
41
45
|
table,
|
|
42
46
|
headerColumn = false,
|
|
43
47
|
xGap = 70,
|
|
44
|
-
|
|
48
|
+
xLabelsMinHeight = 0,
|
|
45
49
|
xLabelsRotate = false,
|
|
46
50
|
xReverse = false,
|
|
47
51
|
yGap = 30,
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
yLabelsLeftMinWidth = 100,
|
|
53
|
+
yLabelsRightMinWidth = 100,
|
|
50
54
|
yMax = 10,
|
|
51
|
-
|
|
55
|
+
zLabelsMinWidth = 0,
|
|
56
|
+
zyMappings = []
|
|
52
57
|
}) => {
|
|
53
58
|
const /** @type {number[][]} */ zxValues = []
|
|
54
59
|
const /** @type {string[]} */ xLabels = []
|
|
@@ -63,7 +68,7 @@ export const chartable = ({
|
|
|
63
68
|
|
|
64
69
|
if (x >= 0 && z >= 0) {
|
|
65
70
|
zxValues[z] = zxValues[z] ?? []
|
|
66
|
-
zxValues[z][x] = parseFloat(value)
|
|
71
|
+
zxValues[z][x] = (zyMappings?.[z]?.[0] ?? parseFloat)(value)
|
|
67
72
|
} else if (x >= 0 && z < 0) {
|
|
68
73
|
xLabels[x] = value
|
|
69
74
|
} else if (x < 0 && z >= 0) {
|
|
@@ -104,17 +109,14 @@ export const chartable = ({
|
|
|
104
109
|
const maxValue = Math.max(...values.filter(value => !isNaN(value)))
|
|
105
110
|
|
|
106
111
|
yPx.forEach((yp, y) => {
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const textR = s('text',
|
|
111
|
-
{ x: 0, y: yp, 'text-anchor': 'start', 'alignment-baseline': 'middle' },
|
|
112
|
-
(maxValue - (maxValue - minValue) / yMax * (y + 1)).toFixed(2))
|
|
112
|
+
const value = (zyMappings?.[z]?.[1] ?? toFixed2)(maxValue - (maxValue - minValue) / yMax * (y + 1))
|
|
113
|
+
const textL = s('text', { x: 0, y: yp, 'text-anchor': 'end', 'alignment-baseline': 'middle' }, value)
|
|
114
|
+
const textR = s('text', { x: 0, y: yp, 'text-anchor': 'start', 'alignment-baseline': 'middle' }, value)
|
|
113
115
|
|
|
114
116
|
s(_svg, textL, textR)
|
|
115
117
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
+
yLabelsLeftMinWidth = Math.max(yLabelsLeftMinWidth, textL.getBBox().width)
|
|
119
|
+
yLabelsRightMinWidth = Math.max(yLabelsRightMinWidth, textR.getBBox().width)
|
|
118
120
|
|
|
119
121
|
s(gYLabelsL[z], textL)
|
|
120
122
|
s(gYLabelsR[z], textR)
|
|
@@ -132,7 +134,7 @@ export const chartable = ({
|
|
|
132
134
|
|
|
133
135
|
s(_svg, text)
|
|
134
136
|
|
|
135
|
-
|
|
137
|
+
zLabelsMinWidth = Math.max(zLabelsMinWidth, text.getBBox().width)
|
|
136
138
|
|
|
137
139
|
gZLabels[z] = text
|
|
138
140
|
|
|
@@ -161,22 +163,22 @@ export const chartable = ({
|
|
|
161
163
|
|
|
162
164
|
s(_svg, text)
|
|
163
165
|
|
|
164
|
-
|
|
166
|
+
xLabelsMinHeight = Math.max(xLabelsMinHeight, xLabelsRotate ? text.getBBox().width : text.getBBox().height)
|
|
165
167
|
|
|
166
168
|
s(gXLabels, text)
|
|
167
169
|
})
|
|
168
170
|
}
|
|
169
171
|
|
|
170
|
-
const svgW = width +
|
|
171
|
-
const svgH = height +
|
|
172
|
+
const svgW = width + yLabelsLeftMinWidth + yLabelsRightMinWidth + zLabelsMinWidth + 4 * PADDING
|
|
173
|
+
const svgH = height + xLabelsMinHeight + (xLabels.length > 0 ? 3 : 2) * PADDING
|
|
172
174
|
|
|
173
|
-
s(gGraph, { transform: `translate(${
|
|
175
|
+
s(gGraph, { transform: `translate(${yLabelsLeftMinWidth + PADDING} ${PADDING})` })
|
|
174
176
|
|
|
175
|
-
gYLabelsL.forEach(g => s(g, { transform: `translate(${
|
|
176
|
-
gYLabelsR.forEach(g => s(g, { transform: `translate(${width +
|
|
177
|
+
gYLabelsL.forEach(g => s(g, { transform: `translate(${yLabelsLeftMinWidth} ${PADDING})` }))
|
|
178
|
+
gYLabelsR.forEach(g => s(g, { transform: `translate(${width + yLabelsLeftMinWidth + 2 * PADDING} ${PADDING})` }))
|
|
177
179
|
|
|
178
|
-
s(gZColors, { transform: `translate(${width +
|
|
179
|
-
s(gXLabels, { transform: `translate(${
|
|
180
|
+
s(gZColors, { transform: `translate(${width + yLabelsLeftMinWidth + yLabelsRightMinWidth + 3 * PADDING} ${PADDING})` })
|
|
181
|
+
s(gXLabels, { transform: `translate(${yLabelsLeftMinWidth + PADDING} ${height + 2 * PADDING})` })
|
|
180
182
|
|
|
181
183
|
onclick(0)
|
|
182
184
|
|
|
@@ -187,7 +189,7 @@ export const chartable = ({
|
|
|
187
189
|
...gYLabelsL,
|
|
188
190
|
...gYLabelsR,
|
|
189
191
|
gZColors,
|
|
190
|
-
['g', { transform: `translate(${width +
|
|
192
|
+
['g', { transform: `translate(${width + yLabelsLeftMinWidth + yLabelsRightMinWidth + 4 * PADDING} ${PADDING})` }, ...gZLabels])
|
|
191
193
|
}
|
|
192
194
|
|
|
193
195
|
export const tests = {}
|
package/package.json
CHANGED
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
"localization",
|
|
28
28
|
"nanolight",
|
|
29
29
|
"nnn",
|
|
30
|
+
"omit",
|
|
31
|
+
"pick",
|
|
30
32
|
"RWD",
|
|
31
33
|
"SVG",
|
|
32
34
|
"translation",
|
|
@@ -40,5 +42,5 @@
|
|
|
40
42
|
"types": "nnn.d.ts",
|
|
41
43
|
"name": "@jackens/nnn",
|
|
42
44
|
"type": "module",
|
|
43
|
-
"version": "2024.2.
|
|
45
|
+
"version": "2024.2.20"
|
|
44
46
|
}
|
package/readme.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Jackens’ JavaScript helpers.
|
|
4
4
|
|
|
5
|
-
<sub>Version: <code class="version">2024.2.
|
|
5
|
+
<sub>Version: <code class="version">2024.2.20</code></sub>
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
@@ -103,18 +103,19 @@ The type of arguments of the `jcss` helper.
|
|
|
103
103
|
### chartable
|
|
104
104
|
|
|
105
105
|
```ts
|
|
106
|
-
export function chartable({ table, headerColumn, xGap,
|
|
106
|
+
export function chartable({ table, headerColumn, xGap, xLabelsMinHeight, xLabelsRotate, xReverse, yGap, yLabelsLeftMinWidth, yLabelsRightMinWidth, yMax, zLabelsMinWidth, zyMappings }: {
|
|
107
107
|
table: HTMLTableElement;
|
|
108
|
-
headerColumn?: boolean;
|
|
109
|
-
xGap?: number;
|
|
110
|
-
|
|
111
|
-
xLabelsRotate?: boolean;
|
|
112
|
-
xReverse?: boolean;
|
|
113
|
-
yGap?: number;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
yMax?: number;
|
|
117
|
-
|
|
108
|
+
headerColumn?: boolean | undefined;
|
|
109
|
+
xGap?: number | undefined;
|
|
110
|
+
xLabelsMinHeight?: number | undefined;
|
|
111
|
+
xLabelsRotate?: boolean | undefined;
|
|
112
|
+
xReverse?: boolean | undefined;
|
|
113
|
+
yGap?: number | undefined;
|
|
114
|
+
yLabelsLeftMinWidth?: number | undefined;
|
|
115
|
+
yLabelsRightMinWidth?: number | undefined;
|
|
116
|
+
yMax?: number | undefined;
|
|
117
|
+
zLabelsMinWidth?: number | undefined;
|
|
118
|
+
zyMappings?: [(label: string) => number, (value: number) => string][] | undefined;
|
|
118
119
|
}): SVGSVGElement;
|
|
119
120
|
```
|
|
120
121
|
|
|
@@ -124,14 +125,15 @@ Options:
|
|
|
124
125
|
- `table`: `HTMLTableElement` to extract data, data series labels and X axis labels
|
|
125
126
|
- `headerColumn`: flag indicating that `table` has a header column with X axis labels
|
|
126
127
|
- `xGap`: X axis spacing
|
|
127
|
-
- `
|
|
128
|
+
- `xLabelsMinHeight`: minimal height of X axis labels
|
|
128
129
|
- `xLabelsRotate`: flag to rotate X axis labels
|
|
129
130
|
- `xReverse`: flag to reverse all data series
|
|
130
131
|
- `yGap`: Y axis spacing
|
|
131
|
-
- `
|
|
132
|
-
- `
|
|
132
|
+
- `yLabelsLeftMinWidth`: minimal width of Y axis left labels
|
|
133
|
+
- `yLabelsRightMinWidth`: minimal width of Y axis right labels
|
|
133
134
|
- `yMax`: number of Y axis lines
|
|
134
|
-
- `
|
|
135
|
+
- `zLabelsMinWidth`: minimal width of data series labels
|
|
136
|
+
- `zyMappings`: mappings per data series
|
|
135
137
|
|
|
136
138
|
### eq
|
|
137
139
|
|