@martinomagnifico/tablechart 1.2.6 → 1.3.0
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/CHANGELOG.md +25 -0
- package/dist/tablechart-additional-types.mjs +60 -60
- package/dist/tablechart-core.d.mts +1 -1
- package/dist/tablechart-core.mjs +1 -1
- package/dist/tablechart-shared.d.mts +23 -4
- package/dist/tablechart-shared.mjs +2661 -2538
- package/dist/tablechart-summary.js +1 -1
- package/dist/tablechart-summary.mjs +149 -130
- package/dist/tablechart.css +1 -1
- package/dist/tablechart.d.mts +1 -1
- package/dist/tablechart.js +1 -1
- package/dist/tablechart.mjs +1 -1
- package/package.json +8 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.3.0] - 2026-11-10
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `data-series="total"` in a summary, for the totals of the rows, such as the stacks of a stacked chart.
|
|
8
|
+
- `{highest.share}`, `{lowest.share}` and `{total}` in a summary.
|
|
9
|
+
- `chart.replay()`, builds a chart again with its animation.
|
|
10
|
+
- `chart.reset()`, takes a chart back to its start, to build when it scrolls into view.
|
|
11
|
+
- `data-chart-group-scale`, one scale for the charts of a group, so the same value is the same height.
|
|
12
|
+
- `data-chart-group`, so the baselines of charts side by side line up when their names take a different number of lines.
|
|
13
|
+
- `--tablechart-max-height` and `--tablechart-height`, so a chart stops getting higher on a wide screen.
|
|
14
|
+
- `data-tablechart-ready` and `data-summary-ready` on `html`, with the events `tablechart:ready` and `tablechart:summary-ready`, for scripts that print the page to PDF.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- A chart that builds once stops watching the scroll.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- Brackets and numbers keep clear of each other in print to PDF flows..
|
|
23
|
+
- A chart keeps the room of its `data-chart-aspect` until it is laid out.
|
|
24
|
+
- In a tagged PDF, the summary and the table are outside the figure of the chart, so a screen reader reads them.
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
3
28
|
## [1.2.6] - 2026-11-08
|
|
4
29
|
|
|
5
30
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { A as e,
|
|
1
|
+
import { A as e, D as t, E as n, F as r, I as i, K as a, L as o, M as s, N as c, O as l, R as u, S as d, U as f, V as p, j as m, k as h, w as g } from "./tablechart-shared.mjs";
|
|
2
2
|
// src/js/annotations/quadrant.ts
|
|
3
|
-
var _ = `${
|
|
3
|
+
var _ = `${f}-name`, v = [
|
|
4
4
|
"top left",
|
|
5
5
|
"top right",
|
|
6
6
|
"bottom left",
|
|
@@ -30,13 +30,13 @@ var _ = `${p}-name`, v = [
|
|
|
30
30
|
}
|
|
31
31
|
return null;
|
|
32
32
|
},
|
|
33
|
-
draw(
|
|
34
|
-
let { frame: u, x: d, y:
|
|
33
|
+
draw(n, i, s) {
|
|
34
|
+
let { frame: u, x: d, y: g, rows: v, series: b, height: x, unit: S, svg: C, plot: w, categories: T } = s;
|
|
35
35
|
if (!u || !d) {
|
|
36
36
|
console.warn(`[${o}] A quadrant works on a scatter chart, which has an axis across and an axis up.`);
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
|
-
let [E, D, O, k] = u, A = b.flatMap((e, t) => e.group ? [] : [t]), j = (e) => v.flatMap((t) => t.cells[A[e]] && !t.cells[A[e]].missing ? [t.cells[A[e]].value] : []), M = y(
|
|
39
|
+
let [E, D, O, k] = u, A = b.flatMap((e, t) => e.group ? [] : [t]), j = (e) => v.flatMap((t) => t.cells[A[e]] && !t.cells[A[e]].missing ? [t.cells[A[e]].value] : []), M = y(n.getAttribute("data-x"), j(0)), N = y(n.getAttribute("data-y"), j(1)), P = M === null ? E + O / 2 : Math.min(Math.max(d(M), E), E + O), F = N === null ? D + k / 2 : Math.min(Math.max(g(N), D), D + k), I = C.querySelector(`:scope > .${r}`);
|
|
40
40
|
if (I) {
|
|
41
41
|
let e = (e, t) => Math.abs(e - t) < S / 2, t = (I.getAttribute("d") ?? "").match(/M[^M]+/g) ?? [];
|
|
42
42
|
I.setAttribute("d", t.filter((t) => {
|
|
@@ -44,27 +44,27 @@ var _ = `${p}-name`, v = [
|
|
|
44
44
|
return !(i === "V" && e(Number(n), P)) && !(i === "H" && e(Number(r), F));
|
|
45
45
|
}).join(""));
|
|
46
46
|
}
|
|
47
|
-
C.insertBefore(
|
|
48
|
-
class:
|
|
49
|
-
d: `M${
|
|
50
|
-
}), C.querySelector(`:scope > .${
|
|
47
|
+
C.insertBefore(h("path", {
|
|
48
|
+
class: f,
|
|
49
|
+
d: `M${l(P)},${l(D)}V${l(D + k)}M${l(E)},${l(F)}H${l(E + O)}`
|
|
50
|
+
}), C.querySelector(`:scope > .${p}`));
|
|
51
51
|
let L = 6 * S, R = [];
|
|
52
52
|
for (let e of w.querySelectorAll(`:scope > .${_}`)) {
|
|
53
|
-
let
|
|
54
|
-
|
|
55
|
-
let
|
|
53
|
+
let n = e.dataset.corner ?? "", r = n.includes("right"), i = n.includes("bottom"), o = r ? E + O - L : E + L, s = i ? D + k - L : D + L;
|
|
54
|
+
t(e, o, s, a, x);
|
|
55
|
+
let c = m(e).width * S, l = m(e).height * S;
|
|
56
56
|
R.push([
|
|
57
|
-
n ? i - s : i,
|
|
58
57
|
r ? o - c : o,
|
|
59
|
-
s,
|
|
60
|
-
c
|
|
58
|
+
i ? s - l : s,
|
|
59
|
+
c,
|
|
60
|
+
l
|
|
61
61
|
]);
|
|
62
62
|
}
|
|
63
|
-
|
|
64
|
-
for (let
|
|
65
|
-
if (
|
|
66
|
-
let
|
|
67
|
-
R.some((e) =>
|
|
63
|
+
s.taken.push(...R);
|
|
64
|
+
for (let t of T) {
|
|
65
|
+
if (t.hidden || t.hasAttribute("data-left-out") || !t.style.left) continue;
|
|
66
|
+
let n = e(t, S, a, x, [0, 0]);
|
|
67
|
+
R.some((e) => c(e, n)) && t.setAttribute("data-left-out", "");
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
}, x = [
|
|
@@ -96,8 +96,8 @@ var _ = `${p}-name`, v = [
|
|
|
96
96
|
axes: !0,
|
|
97
97
|
numbers: !1,
|
|
98
98
|
annotations: { quadrant: b },
|
|
99
|
-
text({ figure:
|
|
100
|
-
let { x: s, y: c, size: l, group: d } = C(a), f =
|
|
99
|
+
text({ figure: e, plot: t, rows: r, series: a, config: o }) {
|
|
100
|
+
let { x: s, y: c, size: l, group: d } = C(a), f = t.querySelector(":scope > .tablechart-categories")?.children ?? [], p = /* @__PURE__ */ new Map();
|
|
101
101
|
r.forEach((e, t) => {
|
|
102
102
|
let n = T(e, s, c);
|
|
103
103
|
n && (p.get(n)?.push(t) ?? p.set(n, [t]));
|
|
@@ -115,81 +115,81 @@ var _ = `${p}-name`, v = [
|
|
|
115
115
|
if (h.length < 2 && l === void 0) return;
|
|
116
116
|
let g = document.createElement("div");
|
|
117
117
|
g.className = i, g.setAttribute("aria-hidden", "true"), g.inert = !0;
|
|
118
|
-
let _ = Array.from(
|
|
119
|
-
let r =
|
|
120
|
-
return r.dataset.place = "legend", r.dataset.line = "none", r.textContent =
|
|
118
|
+
let _ = Array.from(e.querySelectorAll(`tbody tr > td:nth-of-type(${d + 1})`)), v = (e, t) => {
|
|
119
|
+
let r = n(u, g);
|
|
120
|
+
return r.dataset.place = "legend", r.dataset.line = "none", r.textContent = e, t && o.langattribute && r.setAttribute(o.langattribute, t), r;
|
|
121
121
|
};
|
|
122
122
|
h.length > 1 && h.forEach((e, t) => {
|
|
123
123
|
let n = o.langattribute ? _.find((t) => t.textContent?.trim() === e)?.getAttribute(o.langattribute) : null, r = v(e, n);
|
|
124
124
|
r.dataset.marker = x[t % x.length], r.style.setProperty("--n", String(t)), r.style.setProperty("--palette", `var(--tablechart-color-${t + 1})`);
|
|
125
|
-
}), l !== void 0 && (v(a[l].name, a[l].key).dataset.marker = "size"),
|
|
125
|
+
}), l !== void 0 && (v(a[l].name, a[l].key).dataset.marker = "size"), t.after(g);
|
|
126
126
|
},
|
|
127
127
|
draw(e) {
|
|
128
|
-
let { rows:
|
|
129
|
-
if (!
|
|
130
|
-
let b = C(
|
|
131
|
-
let n = e.cells[b.x],
|
|
132
|
-
if (!n || !
|
|
133
|
-
let
|
|
128
|
+
let { rows: n, series: r, x: i, y: o, frame: c, unit: u, svg: f, categories: h, height: _, config: v, plot: y } = e;
|
|
129
|
+
if (!i || !c) return;
|
|
130
|
+
let b = C(r), T = w(n, b.group), E = T.length > 1, D = (e.length("--tablechart-marker-size", "10px") ?? 10 * u) / 2, O = (e.length("--tablechart-bubble-max", "24px") ?? 24 * u) / 2, k = (e.length("--tablechart-bubble-min", "") ?? D * 1.2) / 2, A = (e) => b.size === void 0 ? void 0 : e.cells[b.size], j = g(n.map((e) => Math.abs(A(e)?.value ?? 0))), M = n.flatMap((e, t) => {
|
|
131
|
+
let n = e.cells[b.x], r = e.cells[b.y];
|
|
132
|
+
if (!n || !r || n.missing || r.missing) return [];
|
|
133
|
+
let a = A(e), s = a && !a.missing && j > 0 ? Math.max(k, Math.sqrt(Math.abs(a.value) / j) * O) : D, c = E ? T.indexOf(e.cells[b.group]?.raw ?? "") : -1;
|
|
134
134
|
return [{
|
|
135
135
|
i: t,
|
|
136
|
-
px:
|
|
137
|
-
py:
|
|
136
|
+
px: i(n.value),
|
|
137
|
+
py: o(r.value),
|
|
138
138
|
r: s,
|
|
139
139
|
g: c
|
|
140
140
|
}];
|
|
141
141
|
}), N = Math.min(M.length - 1, 6);
|
|
142
142
|
y.style.setProperty("--count", String(N + 1));
|
|
143
|
-
let P = new Map([...M].sort((e, t) => e.px - t.px || e.i - t.i).map((e, t) => [e.i, N ?
|
|
143
|
+
let P = new Map([...M].sort((e, t) => e.px - t.px || e.i - t.i).map((e, t) => [e.i, N ? l(t * N / (M.length - 1)) : 0])), F = [...M].sort((e, t) => t.r - e.r || e.i - t.i);
|
|
144
144
|
for (let e of F) {
|
|
145
145
|
let t = E ? x[e.g % x.length] : "circle";
|
|
146
|
-
|
|
147
|
-
class:
|
|
146
|
+
f.appendChild(d(t, e.px, e.py, e.r, {
|
|
147
|
+
class: p,
|
|
148
148
|
"data-row": e.i + 1,
|
|
149
149
|
"data-marker": t,
|
|
150
150
|
style: `--i:${P.get(e.i)}; ${E ? `--n:${e.g}; --palette:var(--tablechart-color-${e.g + 1})` : ""}`
|
|
151
151
|
}));
|
|
152
152
|
}
|
|
153
|
-
let I = y.parentElement?.getAttribute("data-chart-names"), L = I == null ? v.names : I !== "false", R = 4 *
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
153
|
+
let I = y.parentElement?.getAttribute("data-chart-names"), L = I == null ? v.names : I !== "false", R = 4 * u, z = [
|
|
154
|
+
c[0] + 1.5 * R,
|
|
155
|
+
c[1],
|
|
156
|
+
c[2] - 1.5 * R,
|
|
157
|
+
c[3] - 1.5 * R
|
|
158
158
|
], [B, V, H, U] = z, W = F.map(({ i: e, px: t, py: n, r }) => {
|
|
159
|
-
if (
|
|
160
|
-
let { width: i, height: a } =
|
|
159
|
+
if (h[e].hasAttribute("data-same")) return [];
|
|
160
|
+
let { width: i, height: a } = m(h[e]), o = i * u, s = a * u, c = s * .1, l = r * .7 + R / 2, d = (e, t) => [
|
|
161
161
|
Math.max(B, Math.min(e, B + H - o)),
|
|
162
|
-
Math.max(V, Math.min(t, V + U - s)) +
|
|
162
|
+
Math.max(V, Math.min(t, V + U - s)) + c,
|
|
163
163
|
o,
|
|
164
|
-
s - 2 *
|
|
164
|
+
s - 2 * c
|
|
165
165
|
];
|
|
166
166
|
return [
|
|
167
167
|
d(t + r + R, n - s / 2),
|
|
168
168
|
d(t - r - R - o, n - s / 2),
|
|
169
169
|
d(t - o / 2, n - r - R - s),
|
|
170
170
|
d(t - o / 2, n + r + R),
|
|
171
|
-
d(t +
|
|
172
|
-
d(t -
|
|
173
|
-
d(t +
|
|
174
|
-
d(t -
|
|
171
|
+
d(t + l, n - l - s),
|
|
172
|
+
d(t - l - o, n - l - s),
|
|
173
|
+
d(t + l, n + l),
|
|
174
|
+
d(t - l - o, n + l)
|
|
175
175
|
];
|
|
176
|
-
}), G = L ?
|
|
176
|
+
}), G = L ? s(W, M.map(({ px: e, py: t, r: n }) => [
|
|
177
177
|
e - n,
|
|
178
178
|
t - n,
|
|
179
179
|
2 * n,
|
|
180
180
|
2 * n
|
|
181
181
|
]), z) : F.map(() => null);
|
|
182
|
-
for (let e of
|
|
183
|
-
F.forEach((e,
|
|
184
|
-
let
|
|
185
|
-
if (
|
|
186
|
-
|
|
187
|
-
let [
|
|
188
|
-
|
|
182
|
+
for (let e of h) e.hidden = !0, e.dataset.missing = "";
|
|
183
|
+
F.forEach((e, n) => {
|
|
184
|
+
let r = h[e.i], i = G[n];
|
|
185
|
+
if (r.hidden = !1, delete r.dataset.missing, r.style.setProperty("--i", String(P.get(e.i))), r.toggleAttribute("data-left-out", i === null), i === null) return;
|
|
186
|
+
r.dataset.side = S[i];
|
|
187
|
+
let [o, s, , c] = W[n][i];
|
|
188
|
+
t(r, o, s - (m(r).height * u - c) / 2, a, _);
|
|
189
189
|
}), e.rowAt = (e, t) => {
|
|
190
|
-
let n = null, r = 6 *
|
|
190
|
+
let n = null, r = 6 * u;
|
|
191
191
|
for (let i of M) {
|
|
192
|
-
let a = Math.max(Math.hypot(i.px - e *
|
|
192
|
+
let a = Math.max(Math.hypot(i.px - e * u, i.py - t * u) - i.r, 0);
|
|
193
193
|
(a < r || a === r && n && i.r < n.r) && (r = a, n = i);
|
|
194
194
|
}
|
|
195
195
|
return n ? n.i : null;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as PRINTING_CLASS, C as Series, D as Config, E as AT_ONCE_CLASS, M as SHOWN_CLASS, N as defaultConfig, O as PLACED_CLASS, S as Row, T as stepTo, _ as
|
|
1
|
+
import { A as PRINTING_CLASS, C as Series, D as Config, E as AT_ONCE_CLASS, M as SHOWN_CLASS, N as defaultConfig, O as PLACED_CLASS, S as Row, T as stepTo, _ as unbuild, a as loadSources, b as ChartState, f as prepare, g as relabel, h as build, i as adoptTables, j as QUEUED_CLASS, k as PLOT_CLASS, m as layout, n as checkTextContrast, o as readMarkdownRows, p as setShown, r as assignKeys, t as checkContrast, u as entranceOf, v as addType, w as StepPlan, x as ChartType } from "./tablechart-shared.mjs";
|
|
2
2
|
export { AT_ONCE_CLASS, type ChartState, type ChartType, type Config, PLACED_CLASS, PLOT_CLASS, PRINTING_CLASS, QUEUED_CLASS, type Row, SHOWN_CLASS, type Series, type StepPlan, addType, adoptTables, assignKeys, build, checkContrast, checkTextContrast, defaultConfig, entranceOf, layout, loadSources, prepare, readMarkdownRows, relabel, setShown, stepTo, unbuild };
|
package/dist/tablechart-core.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { P as AT_ONCE_CLASS, z as PLACED_CLASS, B as PLOT_CLASS, H as PRINTING_CLASS, W as QUEUED_CLASS, G as SHOWN_CLASS,
|
|
1
|
+
export { P as AT_ONCE_CLASS, z as PLACED_CLASS, B as PLOT_CLASS, H as PRINTING_CLASS, W as QUEUED_CLASS, G as SHOWN_CLASS, h as addType, a as adoptTables, y as assignKeys, d as build, c as checkContrast, l as checkTextContrast, q as defaultConfig, n as entranceOf, u as layout, o as loadSources, i as prepare, s as readMarkdownRows, f as relabel, m as setShown, v as stepTo, p as unbuild } from "./tablechart-shared.mjs";
|
|
@@ -330,6 +330,22 @@ interface AnnotationType {
|
|
|
330
330
|
draw: (spec: HTMLElement, badge: HTMLElement | null, geo: Geometry) => void;
|
|
331
331
|
}
|
|
332
332
|
interface ChartState {
|
|
333
|
+
/** What the chart needs by itself, for a group that shares a scale; null for a chart that cannot share one. */
|
|
334
|
+
measured?: {
|
|
335
|
+
height: number;
|
|
336
|
+
room: number;
|
|
337
|
+
floor: number;
|
|
338
|
+
ceiling: number;
|
|
339
|
+
bottom: number;
|
|
340
|
+
} | null;
|
|
341
|
+
/** What its group with `data-chart-group-scale` agreed on. */
|
|
342
|
+
agreed?: {
|
|
343
|
+
height: number;
|
|
344
|
+
room: number;
|
|
345
|
+
floor: number;
|
|
346
|
+
ceiling: number;
|
|
347
|
+
bottom: number;
|
|
348
|
+
};
|
|
333
349
|
figure: HTMLElement;
|
|
334
350
|
plot: HTMLElement;
|
|
335
351
|
svg: SVGSVGElement;
|
|
@@ -379,12 +395,12 @@ declare const scatter: ChartType;
|
|
|
379
395
|
declare const addType: (name: string, type: ChartType) => void;
|
|
380
396
|
/** Pass 2: everything a reader will read, before a translation script looks. */
|
|
381
397
|
declare const build: (figure: HTMLElement, config: Config, asKind?: string | null) => ChartState | null;
|
|
382
|
-
/** Pass 3. Needs layout; makes no text, only places it. */
|
|
383
|
-
declare const layout: (state: ChartState, config: Config) => boolean;
|
|
384
398
|
/** Numbers are reformatted in place, so a language change costs no redraw. */
|
|
385
399
|
declare const relabel: (state: ChartState, config: Config) => void;
|
|
386
400
|
/** Removes what `build` added, so the chart can be built again. */
|
|
387
401
|
declare const unbuild: (state: ChartState) => void;
|
|
402
|
+
/** Pass 3. Needs layout; makes no text, only places it. */
|
|
403
|
+
declare const layout: (state: ChartState, config: Config) => boolean;
|
|
388
404
|
/**
|
|
389
405
|
* One class, `is-shown`, starts the whole build. `atOnce` skips it: the chart lands at its end, or back at its start,
|
|
390
406
|
* without transitions, such as a chart in view when the page opens, or one hidden where nobody sees it.
|
|
@@ -402,6 +418,10 @@ interface TablechartChart {
|
|
|
402
418
|
previous(): void;
|
|
403
419
|
/** On a chart that steps: shows the chart up to `step`, from 0 to `steps`. */
|
|
404
420
|
stepTo(step: number): void;
|
|
421
|
+
/** Builds the chart again, with its animation. A chart with steps goes back to its first step. */
|
|
422
|
+
replay(): void;
|
|
423
|
+
/** Takes the chart back to its start, to build when it scrolls into view. */
|
|
424
|
+
reset(): void;
|
|
405
425
|
/** How many steps are shown. */
|
|
406
426
|
readonly step: number;
|
|
407
427
|
/** How many steps the chart has; 0 for a chart that does not step. */
|
|
@@ -425,7 +445,6 @@ declare const entranceOf: (figure: HTMLElement, config: Config) => number;
|
|
|
425
445
|
declare const prepare: (found: HTMLElement[], config: Config) => Promise<HTMLElement[]>;
|
|
426
446
|
/** Makes a chart of one figure; returns the existing chart if there is one, or null without data. */
|
|
427
447
|
declare const create: (element: HTMLElement, options?: Partial<Config>) => Promise<TablechartChart | null>;
|
|
428
|
-
/** Makes a chart of every figure in `root` that matches the selector, skipping existing charts. */
|
|
429
448
|
declare const init: (options?: Partial<Config>, root?: ParentNode) => Promise<TablechartInstance>;
|
|
430
449
|
/** A Markdown table, or a caption with chart attributes, is wrapped in a figure with the caption and annotations beside it. */
|
|
431
450
|
declare const adoptTables: (figures: HTMLElement[]) => HTMLElement[];
|
|
@@ -439,4 +458,4 @@ declare const assignKeys: (figures: HTMLElement[], langattribute: string | false
|
|
|
439
458
|
declare const checkContrast: (figure: HTMLElement) => void;
|
|
440
459
|
/** Warns about text that does not stand out enough: a number inside a bar from that bar, other text from the background, once the chart is built. */
|
|
441
460
|
declare const checkTextContrast: (figure: HTMLElement) => void;
|
|
442
|
-
export { PRINTING_CLASS as A, Series as C, Config as D, AT_ONCE_CLASS as E, SHOWN_CLASS as M, defaultConfig as N, PLACED_CLASS as O, Row as S, stepTo as T,
|
|
461
|
+
export { PRINTING_CLASS as A, Series as C, Config as D, AT_ONCE_CLASS as E, SHOWN_CLASS as M, defaultConfig as N, PLACED_CLASS as O, Row as S, stepTo as T, unbuild as _, loadSources as a, ChartState as b, TablechartInstance as c, init as d, prepare as f, relabel as g, build as h, adoptTables as i, QUEUED_CLASS as j, PLOT_CLASS as k, create as l, layout as m, checkTextContrast as n, readMarkdownRows as o, setShown as p, assignKeys as r, TablechartChart as s, checkContrast as t, entranceOf as u, addType as v, StepPlan as w, ChartType as x, scatter as y };
|