@martinomagnifico/tablechart 1.0.7 → 1.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/CHANGELOG.md +38 -0
- package/README.md +20 -2
- package/dist/tablechart-additional-types.d.mts +2 -0
- package/dist/tablechart-additional-types.js +1 -0
- package/dist/tablechart-additional-types.mjs +140 -0
- package/dist/tablechart-core.d.mts +2 -26
- package/dist/tablechart-core.mjs +1 -1
- package/dist/tablechart-shared.d.mts +122 -56
- package/dist/tablechart-shared.mjs +1074 -756
- package/dist/tablechart.css +1 -1
- package/dist/tablechart.d.mts +2 -2
- package/dist/tablechart.js +1 -1
- package/dist/tablechart.mjs +1 -1
- package/package.json +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.1.1] - 2026-10-23
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Columns and bars now grow in 0.8s with an ease-in-out, and overlap more to avoid stutter.
|
|
8
|
+
- Numbers now fade in as one group to avoid Safari issues.
|
|
9
|
+
- Gaps in lines and gridlines now switch on instead of fading.
|
|
10
|
+
- The mask under an annotation label is now set when the chart has built, not during the build.
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- A value of zero no longer shows a sliver of a column or bar under the axis.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## [1.1.0] - 2026-10-23
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- Scatter and bubble charts: `data-chart="scatter"`. The first additional type, in `@martinomagnifico/tablechart/additional-types` or `tablechart-additional-types.js`. It is in a script of its own, so a page without a scatter chart does not load it.
|
|
23
|
+
- `addType()`, to add an additional type.
|
|
24
|
+
- A value axis with `data-chart-axis`, and gridlines with `data-chart-grid`. Off by default, because the numbers on the bars already show the values. A scatter chart always has its axes.
|
|
25
|
+
- `data-chart-scale` for a scale of your own, such as 0 to 100%. On a scatter chart also `-x` and `-y`.
|
|
26
|
+
- Reference lines: `data-annotation="reference"`, at a value, the mean or the median. For a target, or the mean and median of a histogram.
|
|
27
|
+
- `data-chart-animate="false"`, for a chart that should just be there, without waiting to scroll into view.
|
|
28
|
+
- `--tablechart-axis-text-color` and `--tablechart-name-color`, so the numbers on an axis can be lighter or darker than the names.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- A line chart with three lines or more now shows its numbers where there is room, above or below the point. Before, they were all left out, so you only saw them in the tooltip.
|
|
33
|
+
|
|
34
|
+
### Removed
|
|
35
|
+
|
|
36
|
+
- The old CSS variable names from 1.0.4, and `up` and `across` for `animate`. Deprecated since 1.0.4.
|
|
37
|
+
- `hover` and `data-chart-hover`. Use `tooltip` and `data-chart-tooltip`. Deprecated since 1.0.5, when tooltips replaced the numbers that appeared on hover.
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
3
41
|
## [1.0.7] - 2026-10-16
|
|
4
42
|
|
|
5
43
|
### Added
|
package/README.md
CHANGED
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
|
|
12
12
|
Tablechart makes simple charts from a table: an HTML table, a Markdown table or a JSON file. You write the table, Tablechart shows it as a chart.
|
|
13
13
|
|
|
14
|
-
* **Chart types:** column, bar, line, area, waterfall and donut
|
|
14
|
+
* **Chart types:** column, bar, line, area, waterfall and donut, and scatter as an additional type
|
|
15
15
|
* **The table stays:** it is hidden from sight, but screen readers, search engines and translation scripts still read it. Without JavaScript, the table is all there is.
|
|
16
16
|
* **Real text:** names and numbers are HTML, so they use the font of the page and do not scale with the drawing.
|
|
17
17
|
* **CSS for the looks:** colours, sizes and animation are CSS variables. Light and dark mode follow the page.
|
|
18
|
-
* **Annotations:** badges, brackets, trend arrows and a break in the scale
|
|
18
|
+
* **Annotations:** badges, brackets, trend arrows, reference lines and a break in the scale
|
|
19
19
|
* **Tooltips:** when a chart leaves numbers out, point at a row, or tap it, to see all its values
|
|
20
20
|
* **Print and PDF:** every chart prints whole, and the table can be shown under a chart that leaves numbers out
|
|
21
21
|
* **Step by step:** show the rows one at a time, with Previous and Next buttons
|
|
@@ -50,6 +50,8 @@ Or with a script tag:
|
|
|
50
50
|
</script>
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
+
The scatter chart is an additional type, in a script of its own. To use it, see [Additional types](#additional-types).
|
|
54
|
+
|
|
53
55
|
## A chart
|
|
54
56
|
|
|
55
57
|
A chart is a `figure` with `data-chart` and a table in it. The first cell of a row is its name, the other cells are its values. The `figcaption` is the title; text after a `br` is the subtitle.
|
|
@@ -69,6 +71,20 @@ A chart is a `figure` with `data-chart` and a table in it. The first cell of a r
|
|
|
69
71
|
|
|
70
72
|
Use `bar`, `line`, `area`, `waterfall` or `donut` for the other types. With more than one value column, each column is a line, or a bar in each group. Add `data-chart-stack` to stack them.
|
|
71
73
|
|
|
74
|
+
### Additional types
|
|
75
|
+
|
|
76
|
+
The scatter chart is an additional type, in a script of its own. To use it, add it before `init()`:
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
import { addType, init } from "@martinomagnifico/tablechart";
|
|
80
|
+
import { scatter } from "@martinomagnifico/tablechart/additional-types";
|
|
81
|
+
|
|
82
|
+
addType("scatter", scatter);
|
|
83
|
+
init();
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
With a script tag, load `tablechart-additional-types.js` after `tablechart.js`. See [Additional types](https://martinomagnifico.github.io/tablechart/types/additional-types.html).
|
|
87
|
+
|
|
72
88
|
## Options
|
|
73
89
|
|
|
74
90
|
```js
|
|
@@ -79,6 +95,8 @@ init({
|
|
|
79
95
|
controls: true, // Previous and Next buttons on a chart that steps
|
|
80
96
|
tooltip: "auto", // Tooltips: "auto" only when a chart leaves numbers out, true or false
|
|
81
97
|
table: "never", // The table under the chart: "never", "auto" (in print, if numbers are left out), "print" or "always"
|
|
98
|
+
axis: false, // Numbers along the value axis
|
|
99
|
+
grid: false, // Gridlines at the numbers of the axis
|
|
82
100
|
locale: undefined, // Locale for numbers; the language of the page if not set
|
|
83
101
|
});
|
|
84
102
|
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(t){var e=["circle","triangle","square","diamond"],o=["right","left","above","below","right","left","right","left"],n=t=>{const e=t.flatMap((t,e)=>t.group?[]:[e]);return{x:e[0],y:e[1],size:e[2],group:t.findIndex(t=>t.group)}},r=(t,e)=>e<0?[]:[...new Set(t.map(t=>t.cells[e]?.raw??""))],a=(t,e,o)=>t.cells[e]?.missing||t.cells[o]?.missing?null:`${t.cells[e]?.value} ${t.cells[o]?.value}`,s={aspect:.62,categories:"beside",columns:!0,axes:!0,text({figure:o,plot:s,rows:c,series:i,config:l}){const{x:u,y:f,size:h,group:d}=n(i),g=s.querySelector(":scope > .tablechart-categories")?.children??[],p=new Map;c.forEach((t,e)=>{const o=a(t,u,f);o&&(p.get(o)?.push(e)??p.set(o,[e]))});const M=t=>void 0===h?0:Math.abs(c[t].cells[h]?.value??0);for(const t of p.values()){if(t.length<2)continue;const e=t.reduce((t,e)=>M(e)>M(t)?e:t);for(const o of t){const n=g[o];o===e?n?.setAttribute("data-more",String(t.length-1)):n?.setAttribute("data-same","")}}const b=r(c,d);if(b.length<2&&void 0===h)return;const m=document.createElement("div");m.className=t.LEGEND_CLASS,m.setAttribute("aria-hidden","true"),m.inert=!0;const v=Array.from(o.querySelectorAll(`tbody tr > td:nth-of-type(${d+1})`)),x=(e,o)=>{const n=(0,t.htmlEl)(t.NAME_CLASS,m);return n.dataset.place="legend",n.dataset.line="none",n.textContent=e,o&&l.langattribute&&n.setAttribute(l.langattribute,o),n};b.length>1&&b.forEach((t,o)=>{const n=l.langattribute?v.find(e=>e.textContent?.trim()===t)?.getAttribute(l.langattribute):null,r=x(t,n);r.dataset.marker=e[o%e.length],r.style.setProperty("--n",String(o)),r.style.setProperty("--palette",`var(--tablechart-color-${o+1})`)}),void 0!==h&&(x(i[h].name,i[h].key).dataset.marker="size"),o.appendChild(m)},draw(a){const{rows:s,series:c,x:i,y:l,frame:u,unit:f,svg:h,categories:d,seriesValues:g,height:p,config:M,plot:b}=a;if(!i||!u)return;const m=n(c),v=r(s,m.group),x=v.length>1;for(const t of g.flat())t.dataset.place="none";const w=(a.length("--tablechart-marker-size","10px")??10*f)/2,y=(a.length("--tablechart-bubble-max","24px")??24*f)/2,$=t=>void 0===m.size?void 0:t.cells[m.size],S=(0,t.largest)(s.map(t=>Math.abs($(t)?.value??0))),z=s.flatMap((t,e)=>{const o=t.cells[m.x],n=t.cells[m.y];if(!o||!n||o.missing||n.missing)return[];const r=$(t),a=r&&!r.missing&&S>0?Math.max(.6*w,Math.sqrt(Math.abs(r.value)/S)*y):w,s=x?v.indexOf(t.cells[m.group]?.raw??""):-1;return[{i:e,px:i(o.value),py:l(n.value),r:a,g:s}]}),k=Math.min(z.length-1,6);b.style.setProperty("--count",String(k+1));const q=new Map([...z].sort((t,e)=>t.px-e.px||t.i-e.i).map((e,o)=>[e.i,k?(0,t.short)(o*k/(z.length-1)):0])),A=[...z].sort((t,e)=>e.r-t.r||t.i-e.i);for(const o of A){const n=x?e[o.g%e.length]:"circle";h.appendChild((0,t.markerEl)(n,o.px,o.py,o.r,{class:t.POINT_CLASS,"data-row":o.i+1,"data-marker":n,style:`--i:${q.get(o.i)}; ${x?`--n:${o.g}; --palette:var(--tablechart-color-${o.g+1})`:""}`}))}const T=b.parentElement?.getAttribute("data-chart-names"),V=null==T?M.names:"false"!==T,j=4*f,B=[u[0]+1.5*j,u[1],u[2]-1.5*j,u[3]-1.5*j],[C,D,E,F]=B,G=A.map(({i:e,px:o,py:n,r:r})=>{if(d[e].hasAttribute("data-same"))return[];const{width:a,height:s}=(0,t.sizeOf)(d[e]),c=a*f,i=s*f,l=.1*i,u=.7*r+j/2,h=(t,e)=>[Math.max(C,Math.min(t,C+E-c)),Math.max(D,Math.min(e,D+F-i))+l,c,i-2*l];return[h(o+r+j,n-i/2),h(o-r-j-c,n-i/2),h(o-c/2,n-r-j-i),h(o-c/2,n+r+j),h(o+u,n-u-i),h(o-u-c,n-u-i),h(o+u,n+u),h(o-u-c,n+u)]}),H=V?(0,t.avoidCollisions)(G,z.map(({px:t,py:e,r:o})=>[t-o,e-o,2*o,2*o]),B):A.map(()=>null);for(const t of d)t.hidden=!0,t.dataset.missing="";A.forEach((e,n)=>{const r=d[e.i],a=H[n];if(r.hidden=!1,delete r.dataset.missing,r.style.setProperty("--i",String(q.get(e.i))),r.toggleAttribute("data-left-out",null===a),null===a)return;r.dataset.side=o[a];const[s,c,,i]=G[n][a];(0,t.placeAt)(r,s,c-((0,t.sizeOf)(r).height*f-i)/2,t.VIEWBOX_WIDTH,p)}),a.rowAt=(t,e)=>{let o=null,n=6*f;for(const r of z){const a=Math.max(Math.hypot(r.px-t*f,r.py-e*f)-r.r,0);(a<n||a===n&&o&&r.r<o.r)&&(n=a,o=r)}return o?o.i:null}},tooltip(t,e){const{x:o,y:r}=n(t.series),s=a(t.rows[e],o,r),c=t.rows.flatMap((t,n)=>n===e||null!==s&&a(t,o,r)===s?[n]:[]),i=c.filter(e=>t.categories[e]?.hasAttribute("data-more"));return[...i,...c.filter(t=>!i.includes(t))].map(e=>({name:t.categories[e]?.textContent??"",value:""}))}};window.Tablechart.addType("scatter",s)}(Tablechart.kit);
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { C as e, D as t, S as n, _ as r, b as i, g as a, j as o, v as s, w as c, x as l, y as u } from "./tablechart-shared.mjs";
|
|
2
|
+
//#region src/js/charts/scatter.ts
|
|
3
|
+
var d = [
|
|
4
|
+
"circle",
|
|
5
|
+
"triangle",
|
|
6
|
+
"square",
|
|
7
|
+
"diamond"
|
|
8
|
+
], f = [
|
|
9
|
+
"right",
|
|
10
|
+
"left",
|
|
11
|
+
"above",
|
|
12
|
+
"below",
|
|
13
|
+
"right",
|
|
14
|
+
"left",
|
|
15
|
+
"right",
|
|
16
|
+
"left"
|
|
17
|
+
], p = (e) => {
|
|
18
|
+
let t = e.flatMap((e, t) => e.group ? [] : [t]);
|
|
19
|
+
return {
|
|
20
|
+
x: t[0],
|
|
21
|
+
y: t[1],
|
|
22
|
+
size: t[2],
|
|
23
|
+
group: e.findIndex((e) => e.group)
|
|
24
|
+
};
|
|
25
|
+
}, m = (e, t) => t < 0 ? [] : [...new Set(e.map((e) => e.cells[t]?.raw ?? ""))], h = (e, t, n) => e.cells[t]?.missing || e.cells[n]?.missing ? null : `${e.cells[t]?.value} ${e.cells[n]?.value}`, g = {
|
|
26
|
+
aspect: .62,
|
|
27
|
+
categories: "beside",
|
|
28
|
+
columns: !0,
|
|
29
|
+
axes: !0,
|
|
30
|
+
text({ figure: t, plot: n, rows: r, series: a, config: o }) {
|
|
31
|
+
let { x: s, y: l, size: u, group: f } = p(a), g = n.querySelector(":scope > .tablechart-categories")?.children ?? [], _ = /* @__PURE__ */ new Map();
|
|
32
|
+
r.forEach((e, t) => {
|
|
33
|
+
let n = h(e, s, l);
|
|
34
|
+
n && (_.get(n)?.push(t) ?? _.set(n, [t]));
|
|
35
|
+
});
|
|
36
|
+
let v = (e) => u === void 0 ? 0 : Math.abs(r[e].cells[u]?.value ?? 0);
|
|
37
|
+
for (let e of _.values()) {
|
|
38
|
+
if (e.length < 2) continue;
|
|
39
|
+
let t = e.reduce((e, t) => v(t) > v(e) ? t : e);
|
|
40
|
+
for (let n of e) {
|
|
41
|
+
let r = g[n];
|
|
42
|
+
n === t ? r?.setAttribute("data-more", String(e.length - 1)) : r?.setAttribute("data-same", "");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
let y = m(r, f);
|
|
46
|
+
if (y.length < 2 && u === void 0) return;
|
|
47
|
+
let b = document.createElement("div");
|
|
48
|
+
b.className = e, b.setAttribute("aria-hidden", "true"), b.inert = !0;
|
|
49
|
+
let x = Array.from(t.querySelectorAll(`tbody tr > td:nth-of-type(${f + 1})`)), S = (e, t) => {
|
|
50
|
+
let n = i(c, b);
|
|
51
|
+
return n.dataset.place = "legend", n.dataset.line = "none", n.textContent = e, t && o.langattribute && n.setAttribute(o.langattribute, t), n;
|
|
52
|
+
};
|
|
53
|
+
y.length > 1 && y.forEach((e, t) => {
|
|
54
|
+
let n = o.langattribute ? x.find((t) => t.textContent?.trim() === e)?.getAttribute(o.langattribute) : null, r = S(e, n);
|
|
55
|
+
r.dataset.marker = d[t % d.length], r.style.setProperty("--n", String(t)), r.style.setProperty("--palette", `var(--tablechart-color-${t + 1})`);
|
|
56
|
+
}), u !== void 0 && (S(a[u].name, a[u].key).dataset.marker = "size"), t.appendChild(b);
|
|
57
|
+
},
|
|
58
|
+
draw(e) {
|
|
59
|
+
let { rows: i, series: c, x: h, y: g, frame: _, unit: v, svg: y, categories: b, seriesValues: x, height: S, config: C, plot: w } = e;
|
|
60
|
+
if (!h || !_) return;
|
|
61
|
+
let T = p(c), E = m(i, T.group), D = E.length > 1;
|
|
62
|
+
for (let e of x.flat()) e.dataset.place = "none";
|
|
63
|
+
let O = (e.length("--tablechart-marker-size", "10px") ?? 10 * v) / 2, k = (e.length("--tablechart-bubble-max", "24px") ?? 24 * v) / 2, A = (e) => T.size === void 0 ? void 0 : e.cells[T.size], j = u(i.map((e) => Math.abs(A(e)?.value ?? 0))), M = i.flatMap((e, t) => {
|
|
64
|
+
let n = e.cells[T.x], r = e.cells[T.y];
|
|
65
|
+
if (!n || !r || n.missing || r.missing) return [];
|
|
66
|
+
let i = A(e), a = i && !i.missing && j > 0 ? Math.max(O * .6, Math.sqrt(Math.abs(i.value) / j) * k) : O, o = D ? E.indexOf(e.cells[T.group]?.raw ?? "") : -1;
|
|
67
|
+
return [{
|
|
68
|
+
i: t,
|
|
69
|
+
px: h(n.value),
|
|
70
|
+
py: g(r.value),
|
|
71
|
+
r: a,
|
|
72
|
+
g: o
|
|
73
|
+
}];
|
|
74
|
+
}), N = Math.min(M.length - 1, 6);
|
|
75
|
+
w.style.setProperty("--count", String(N + 1));
|
|
76
|
+
let P = new Map([...M].sort((e, t) => e.px - t.px || e.i - t.i).map((e, t) => [e.i, N ? n(t * N / (M.length - 1)) : 0])), F = [...M].sort((e, t) => t.r - e.r || e.i - t.i);
|
|
77
|
+
for (let e of F) {
|
|
78
|
+
let n = D ? d[e.g % d.length] : "circle";
|
|
79
|
+
y.appendChild(a(n, e.px, e.py, e.r, {
|
|
80
|
+
class: t,
|
|
81
|
+
"data-row": e.i + 1,
|
|
82
|
+
"data-marker": n,
|
|
83
|
+
style: `--i:${P.get(e.i)}; ${D ? `--n:${e.g}; --palette:var(--tablechart-color-${e.g + 1})` : ""}`
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
let I = w.parentElement?.getAttribute("data-chart-names"), L = I == null ? C.names : I !== "false", R = 4 * v, z = [
|
|
87
|
+
_[0] + 1.5 * R,
|
|
88
|
+
_[1],
|
|
89
|
+
_[2] - 1.5 * R,
|
|
90
|
+
_[3] - 1.5 * R
|
|
91
|
+
], [B, V, H, U] = z, W = F.map(({ i: e, px: t, py: n, r: i }) => {
|
|
92
|
+
if (b[e].hasAttribute("data-same")) return [];
|
|
93
|
+
let { width: a, height: o } = r(b[e]), s = a * v, c = o * v, l = c * .1, u = i * .7 + R / 2, d = (e, t) => [
|
|
94
|
+
Math.max(B, Math.min(e, B + H - s)),
|
|
95
|
+
Math.max(V, Math.min(t, V + U - c)) + l,
|
|
96
|
+
s,
|
|
97
|
+
c - 2 * l
|
|
98
|
+
];
|
|
99
|
+
return [
|
|
100
|
+
d(t + i + R, n - c / 2),
|
|
101
|
+
d(t - i - R - s, n - c / 2),
|
|
102
|
+
d(t - s / 2, n - i - R - c),
|
|
103
|
+
d(t - s / 2, n + i + R),
|
|
104
|
+
d(t + u, n - u - c),
|
|
105
|
+
d(t - u - s, n - u - c),
|
|
106
|
+
d(t + u, n + u),
|
|
107
|
+
d(t - u - s, n + u)
|
|
108
|
+
];
|
|
109
|
+
}), G = L ? s(W, M.map(({ px: e, py: t, r: n }) => [
|
|
110
|
+
e - n,
|
|
111
|
+
t - n,
|
|
112
|
+
2 * n,
|
|
113
|
+
2 * n
|
|
114
|
+
]), z) : F.map(() => null);
|
|
115
|
+
for (let e of b) e.hidden = !0, e.dataset.missing = "";
|
|
116
|
+
F.forEach((e, t) => {
|
|
117
|
+
let n = b[e.i], i = G[t];
|
|
118
|
+
if (n.hidden = !1, delete n.dataset.missing, n.style.setProperty("--i", String(P.get(e.i))), n.toggleAttribute("data-left-out", i === null), i === null) return;
|
|
119
|
+
n.dataset.side = f[i];
|
|
120
|
+
let [a, s, , c] = W[t][i];
|
|
121
|
+
l(n, a, s - (r(n).height * v - c) / 2, o, S);
|
|
122
|
+
}), e.rowAt = (e, t) => {
|
|
123
|
+
let n = null, r = 6 * v;
|
|
124
|
+
for (let i of M) {
|
|
125
|
+
let a = Math.max(Math.hypot(i.px - e * v, i.py - t * v) - i.r, 0);
|
|
126
|
+
(a < r || a === r && n && i.r < n.r) && (r = a, n = i);
|
|
127
|
+
}
|
|
128
|
+
return n ? n.i : null;
|
|
129
|
+
};
|
|
130
|
+
},
|
|
131
|
+
tooltip(e, t) {
|
|
132
|
+
let { x: n, y: r } = p(e.series), i = h(e.rows[t], n, r), a = e.rows.flatMap((e, a) => a === t || i !== null && h(e, n, r) === i ? [a] : []), o = a.filter((t) => e.categories[t]?.hasAttribute("data-more"));
|
|
133
|
+
return [...o, ...a.filter((e) => !o.includes(e))].map((t) => ({
|
|
134
|
+
name: e.categories[t]?.textContent ?? "",
|
|
135
|
+
value: ""
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
//#endregion
|
|
140
|
+
export { g as scatter };
|
|
@@ -1,26 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
/** Pass 2: everything a reader will read, before a translation script looks. */
|
|
4
|
-
export declare const build: (figure: HTMLElement, config: Config, asKind?: string | null) => ChartState | null;
|
|
5
|
-
/** Pass 3. Needs layout; makes no text, only places it. */
|
|
6
|
-
export declare const layout: (state: ChartState, config: Config) => boolean;
|
|
7
|
-
/** Numbers are reformatted in place, so a language change costs no redraw. */
|
|
8
|
-
export declare const relabel: (state: ChartState, config: Config) => void;
|
|
9
|
-
/** Removes what `build` added, so the chart can be built again. */
|
|
10
|
-
export declare const unbuild: (state: ChartState) => void;
|
|
11
|
-
/** One class, `is-shown`, starts the whole build. */
|
|
12
|
-
export declare const setShown: (state: ChartState, shown: boolean) => void;
|
|
13
|
-
//#endregion
|
|
14
|
-
//#region src/js/functions/sources.d.ts
|
|
15
|
-
/** A Markdown table, or a caption with chart attributes, is wrapped in a figure with the caption and annotations beside it. */
|
|
16
|
-
export declare const adoptTables: (figures: HTMLElement[]) => HTMLElement[];
|
|
17
|
-
/** `data-chart-src` fills the figure's table with the rows of a JSON file, keeping a header row the author wrote; a file that fails is reported. */
|
|
18
|
-
export declare const loadSources: (figures: HTMLElement[]) => Promise<void>;
|
|
19
|
-
/** In a Markdown table, a bold label makes the row a total, and a bold header puts that series in focus. */
|
|
20
|
-
export declare const readMarkdownRows: (figures: HTMLElement[]) => void;
|
|
21
|
-
//#endregion
|
|
22
|
-
//#region src/js/functions/read-table.d.ts
|
|
23
|
-
/** Writes translation keys such as `harvest-row1` onto a figure with `data-chart-keys`; a duplicate prefix gets a number. */
|
|
24
|
-
export declare const assignKeys: (figures: HTMLElement[], langattribute: string | false) => void;
|
|
25
|
-
//#endregion
|
|
26
|
-
export { type ChartState, type Config, PLACED_CLASS, PLOT_CLASS, PRINTING_CLASS, QUEUED_CLASS, type Row, SHOWN_CLASS, type Series, type StepPlan, defaultConfig, entranceOf, prepare, stepTo };
|
|
1
|
+
import { A as defaultConfig, C as stepTo, D as PRINTING_CLASS, E as PLOT_CLASS, O as QUEUED_CLASS, S as StepPlan, T as PLACED_CLASS, b as Row, c as entranceOf, d as addType, f as build, g as unbuild, h as setShown, i as readMarkdownRows, k as SHOWN_CLASS, m as relabel, n as adoptTables, p as layout, r as loadSources, t as assignKeys, u as prepare, v as ChartState, w as Config, x as Series, y as ChartType } from "./tablechart-shared.mjs";
|
|
2
|
+
export { 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, defaultConfig, entranceOf, layout, loadSources, prepare, readMarkdownRows, relabel, setShown, stepTo, unbuild };
|
package/dist/tablechart-core.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { T as PLACED_CLASS, E as PLOT_CLASS, O as PRINTING_CLASS, k as QUEUED_CLASS, A as SHOWN_CLASS, c as addType, a as adoptTables, h as assignKeys, l as build, M as defaultConfig, n as entranceOf, u as layout, o as loadSources, i as prepare, s as readMarkdownRows, d as relabel, f as setShown, m as stepTo, p as unbuild } from "./tablechart-shared.mjs";
|
|
@@ -1,3 +1,63 @@
|
|
|
1
|
+
//#region src/js/config.d.ts
|
|
2
|
+
declare const PLOT_CLASS = "tablechart-plot";
|
|
3
|
+
declare const PLACED_CLASS = "is-placed";
|
|
4
|
+
declare const SHOWN_CLASS = "is-shown";
|
|
5
|
+
declare const PRINTING_CLASS = "is-printing";
|
|
6
|
+
declare const QUEUED_CLASS = "tablechart-queued";
|
|
7
|
+
interface Config {
|
|
8
|
+
/** Which elements Tablechart turns into charts. */
|
|
9
|
+
selector: string;
|
|
10
|
+
/** Height of the plot as a share of its width. */
|
|
11
|
+
aspect: number;
|
|
12
|
+
/** Share of a band that a bar fills. */
|
|
13
|
+
barfill: number;
|
|
14
|
+
/** Share of a donut's radius that the ring itself takes. */
|
|
15
|
+
ringfill: number;
|
|
16
|
+
/** Locale for numbers. Unset, the document's language is used and followed when it changes. */
|
|
17
|
+
locale?: string;
|
|
18
|
+
/** Animate a chart when it builds. `"grow"` grows each element from zero, `"sweep"` reveals the chart in one movement; a figure overrides it with `data-chart-animate`, also with `"false"`. */
|
|
19
|
+
animate: boolean | Motion;
|
|
20
|
+
/** How far an animated parent is in before its chart builds: 0 when it starts moving, 1 when it is in. A figure overrides it with `data-chart-entrance`. */
|
|
21
|
+
entrance: number;
|
|
22
|
+
/** Where a column's number goes: on the bar, or inside it. A figure overrides it with `data-chart-labels`. */
|
|
23
|
+
labels: "outside" | "inside";
|
|
24
|
+
/** How a line or area runs between points: `straight`, `step` or `smooth`. A figure overrides it with `data-chart-shape`. */
|
|
25
|
+
shape: "straight" | "step" | "smooth";
|
|
26
|
+
/** Names of several lines in a legend instead of at the end of each line. A figure overrides it with `data-chart-legend`. */
|
|
27
|
+
legend: boolean;
|
|
28
|
+
/** Numbers along the value axis of a column, bar, line, area or waterfall chart. A figure overrides it with `data-chart-axis`. */
|
|
29
|
+
axis: boolean;
|
|
30
|
+
/** Gridlines across the plot at each number of the axis. A figure overrides it with `data-chart-grid`. */
|
|
31
|
+
grid: boolean;
|
|
32
|
+
/** The name of each marker beside it, on a scatter chart. A figure overrides it with `data-chart-names`. */
|
|
33
|
+
names: boolean;
|
|
34
|
+
/** A tooltip with the values of a row that is pointed at or tapped: `"auto"`, the default, only on a chart that does not show all its numbers; `true` always; `false` never. A figure overrides it with `data-chart-tooltip`. */
|
|
35
|
+
tooltip: boolean | "auto";
|
|
36
|
+
/** Where the tooltip goes in the page: an element or a selector, `body` by default. In a scaled element, such as the slides of a presentation, the tooltip has their scale. */
|
|
37
|
+
tooltipparent: HTMLElement | string | null;
|
|
38
|
+
/** The table under the chart: `"always"`, only in `"print"`, in print when numbers are left out (`"auto"`), or `"never"`. A figure overrides it with `data-chart-table`. */
|
|
39
|
+
table: "never" | "auto" | "print" | "always";
|
|
40
|
+
/** The name of the total that a donut without a total row works out, for screen readers. */
|
|
41
|
+
totallabel: string;
|
|
42
|
+
/** Previous and Next buttons under a chart that steps (`data-fragment`). `false` leaves them out, for buttons of your own. */
|
|
43
|
+
controls: boolean;
|
|
44
|
+
/** The text of the Previous button. */
|
|
45
|
+
previouslabel: string;
|
|
46
|
+
/** The text of the Next button. */
|
|
47
|
+
nextlabel: string;
|
|
48
|
+
/** Read by screen readers after the text of each button, so they know it only changes the chart. */
|
|
49
|
+
stephint: string;
|
|
50
|
+
/** How much of a chart must be in view before it builds, from 0 to 1. */
|
|
51
|
+
threshold: number;
|
|
52
|
+
/** Build again each time a chart scrolls back into view, not only the first time. */
|
|
53
|
+
replay: boolean;
|
|
54
|
+
/** The attribute for translation keys, for a translation script. `false` turns keys off. */
|
|
55
|
+
langattribute: string | false;
|
|
56
|
+
/** Show messages in the console for whoever is working on the page. */
|
|
57
|
+
debug?: boolean;
|
|
58
|
+
}
|
|
59
|
+
declare const defaultConfig: Config;
|
|
60
|
+
//#endregion
|
|
1
61
|
//#region src/js/functions/scale.d.ts
|
|
2
62
|
/** A break in the scale: values from `lo` to `hi` get `share` of the length, and the cut is at `gap`. */
|
|
3
63
|
interface Squeeze {
|
|
@@ -70,6 +130,8 @@ interface Series {
|
|
|
70
130
|
/** `data-marker` on the header, such as `square` or `diamond open`. */
|
|
71
131
|
marker: string | null;
|
|
72
132
|
line: "dashed" | "dotted" | null;
|
|
133
|
+
/** `data-group` on the header: the cells name a group, such as "Predefined". */
|
|
134
|
+
group: boolean;
|
|
73
135
|
}
|
|
74
136
|
interface Segment extends Row {
|
|
75
137
|
from: number;
|
|
@@ -82,6 +144,14 @@ interface Geometry {
|
|
|
82
144
|
segments: Segment[];
|
|
83
145
|
cx: (index: number) => number;
|
|
84
146
|
y: (value: number) => number;
|
|
147
|
+
/** Across: on a chart with two axes, and the value scale of a bar chart, set by its drawing. */
|
|
148
|
+
x?: (value: number) => number;
|
|
149
|
+
/** The plot inside the axes, on a chart with axes. */
|
|
150
|
+
frame?: [number, number, number, number];
|
|
151
|
+
/** A chart that knows better which row is pointed at sets this, in screen pixels from the plot's corner. */
|
|
152
|
+
rowAt?: (x: number, y: number) => number | null;
|
|
153
|
+
/** A CSS length set on the figure, such as `--tablechart-marker-size`, in viewBox units. */
|
|
154
|
+
length: (name: string, fallback: string) => number | null;
|
|
85
155
|
barWidth: number;
|
|
86
156
|
barMax: number;
|
|
87
157
|
height: number;
|
|
@@ -99,6 +169,8 @@ interface Geometry {
|
|
|
99
169
|
squeeze: Squeeze | null;
|
|
100
170
|
/** The empty space where the scale jumps, in viewBox units. */
|
|
101
171
|
breakGap: number;
|
|
172
|
+
/** The range of the value axis, on a chart with an axis or gridlines; a chart that makes its own scale reaches it. */
|
|
173
|
+
domain: [number, number] | null;
|
|
102
174
|
/** Where a bar chart is cut across, in viewBox units; set by its drawing. */
|
|
103
175
|
breakX?: number;
|
|
104
176
|
labels: "outside" | "inside";
|
|
@@ -122,6 +194,8 @@ interface Geometry {
|
|
|
122
194
|
config: Config;
|
|
123
195
|
/** Numbers an annotation worked out, against the ones the author wrote. */
|
|
124
196
|
checks: Check[];
|
|
197
|
+
/** The labels of annotations placed so far, as left, top, width and height, so the next one finds room. */
|
|
198
|
+
taken: [number, number, number, number][];
|
|
125
199
|
}
|
|
126
200
|
interface Check {
|
|
127
201
|
label: string;
|
|
@@ -143,6 +217,18 @@ interface ChartType {
|
|
|
143
217
|
swatch?: "box";
|
|
144
218
|
categories?: "under" | "beside";
|
|
145
219
|
series?: boolean;
|
|
220
|
+
/** The value columns are the fields of one mark, such as x and y, rather than series: no names for them. */
|
|
221
|
+
columns?: boolean;
|
|
222
|
+
/** An axis across and an axis up, from the first two value columns, with their headers as titles. */
|
|
223
|
+
axes?: boolean;
|
|
224
|
+
/** Text of its own, made with the rest of the text so a translation script finds it, such as a legend. */
|
|
225
|
+
text?: (input: {
|
|
226
|
+
figure: HTMLElement;
|
|
227
|
+
plot: HTMLElement;
|
|
228
|
+
rows: Row[];
|
|
229
|
+
series: Series[];
|
|
230
|
+
config: Config;
|
|
231
|
+
}) => void;
|
|
146
232
|
/** With several series, always a legend, with a sample of this shape. */
|
|
147
233
|
legend?: "box";
|
|
148
234
|
headroom?: (geo: HeadroomInput) => number;
|
|
@@ -204,6 +290,12 @@ interface ChartState {
|
|
|
204
290
|
names: HTMLElement[];
|
|
205
291
|
categories: HTMLElement[];
|
|
206
292
|
centre: HTMLElement | null;
|
|
293
|
+
/** The axis titles and the place for the numbers along the axes. Without `numbers`, only for gridlines. */
|
|
294
|
+
axes: {
|
|
295
|
+
titles: HTMLElement[];
|
|
296
|
+
ticks: HTMLElement;
|
|
297
|
+
numbers: boolean;
|
|
298
|
+
} | null;
|
|
207
299
|
stacked: boolean;
|
|
208
300
|
totals: HTMLElement[];
|
|
209
301
|
totalCell: HTMLElement | null;
|
|
@@ -228,61 +320,23 @@ interface ChartState {
|
|
|
228
320
|
checks: Check[];
|
|
229
321
|
}
|
|
230
322
|
//#endregion
|
|
231
|
-
//#region src/js/
|
|
232
|
-
|
|
233
|
-
declare const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
/** Animate a chart when it builds. `"grow"` grows each element from zero, `"sweep"` reveals the chart in one movement; a figure overrides it with `data-chart-animate`. `"up"` and `"across"` are their old names. */
|
|
249
|
-
animate: boolean | Motion | "across" | "up";
|
|
250
|
-
/** How far an animated parent is in before its chart builds: 0 when it starts moving, 1 when it is in. A figure overrides it with `data-chart-entrance`. */
|
|
251
|
-
entrance: number;
|
|
252
|
-
/** Where a column's number goes: on the bar, or inside it. A figure overrides it with `data-chart-labels`. */
|
|
253
|
-
labels: "outside" | "inside";
|
|
254
|
-
/** How a line or area runs between points: `straight`, `step` or `smooth`. A figure overrides it with `data-chart-shape`. */
|
|
255
|
-
shape: "straight" | "step" | "smooth";
|
|
256
|
-
/** Names of several lines in a legend instead of at the end of each line. A figure overrides it with `data-chart-legend`. */
|
|
257
|
-
legend: boolean;
|
|
258
|
-
/** A tooltip with the values of a row that is pointed at or tapped: `"auto"`, the default, only on a chart that does not show all its numbers; `true` always; `false` never. A figure overrides it with `data-chart-tooltip`. */
|
|
259
|
-
tooltip: boolean | "auto";
|
|
260
|
-
/** The old name of `tooltip`, until the next minor version. */
|
|
261
|
-
hover?: boolean;
|
|
262
|
-
/** Where the tooltip goes in the page: an element or a selector, `body` by default. In a scaled element, such as the slides of a presentation, the tooltip has their scale. */
|
|
263
|
-
tooltipparent: HTMLElement | string | null;
|
|
264
|
-
/** The table under the chart: `"always"`, only in `"print"`, in print when numbers are left out (`"auto"`), or `"never"`. A figure overrides it with `data-chart-table`. */
|
|
265
|
-
table: "never" | "auto" | "print" | "always";
|
|
266
|
-
/** The name of the total that a donut without a total row works out, for screen readers. */
|
|
267
|
-
totallabel: string;
|
|
268
|
-
/** Previous and Next buttons under a chart that steps (`data-fragment`). `false` leaves them out, for buttons of your own. */
|
|
269
|
-
controls: boolean;
|
|
270
|
-
/** The text of the Previous button. */
|
|
271
|
-
previouslabel: string;
|
|
272
|
-
/** The text of the Next button. */
|
|
273
|
-
nextlabel: string;
|
|
274
|
-
/** Read by screen readers after the text of each button, so they know it only changes the chart. */
|
|
275
|
-
stephint: string;
|
|
276
|
-
/** How much of a chart must be in view before it builds, from 0 to 1. */
|
|
277
|
-
threshold: number;
|
|
278
|
-
/** Build again each time a chart scrolls back into view, not only the first time. */
|
|
279
|
-
replay: boolean;
|
|
280
|
-
/** The attribute for translation keys, for a translation script. `false` turns keys off. */
|
|
281
|
-
langattribute: string | false;
|
|
282
|
-
/** Show messages in the console for whoever is working on the page. */
|
|
283
|
-
debug?: boolean;
|
|
284
|
-
}
|
|
285
|
-
declare const defaultConfig: Config;
|
|
323
|
+
//#region src/js/charts/scatter.d.ts
|
|
324
|
+
/** One marker per row, across by its first value and up by its second; a third value makes it a bubble. */
|
|
325
|
+
declare const scatter: ChartType;
|
|
326
|
+
//#endregion
|
|
327
|
+
//#region src/js/core.d.ts
|
|
328
|
+
/** Adds a chart type for `data-chart="name"`, such as one from `@martinomagnifico/tablechart/additional-types`, before `init()`. */
|
|
329
|
+
declare const addType: (name: string, type: ChartType) => void;
|
|
330
|
+
/** Pass 2: everything a reader will read, before a translation script looks. */
|
|
331
|
+
declare const build: (figure: HTMLElement, config: Config, asKind?: string | null) => ChartState | null;
|
|
332
|
+
/** Pass 3. Needs layout; makes no text, only places it. */
|
|
333
|
+
declare const layout: (state: ChartState, config: Config) => boolean;
|
|
334
|
+
/** Numbers are reformatted in place, so a language change costs no redraw. */
|
|
335
|
+
declare const relabel: (state: ChartState, config: Config) => void;
|
|
336
|
+
/** Removes what `build` added, so the chart can be built again. */
|
|
337
|
+
declare const unbuild: (state: ChartState) => void;
|
|
338
|
+
/** One class, `is-shown`, starts the whole build. */
|
|
339
|
+
declare const setShown: (state: ChartState, shown: boolean) => void;
|
|
286
340
|
//#endregion
|
|
287
341
|
//#region src/js/init.d.ts
|
|
288
342
|
interface TablechartChart {
|
|
@@ -323,4 +377,16 @@ declare const create: (element: HTMLElement, options?: Partial<Config>) => Promi
|
|
|
323
377
|
/** Makes a chart of every figure in `root` that matches the selector, skipping existing charts. */
|
|
324
378
|
declare const init: (options?: Partial<Config>, root?: ParentNode) => Promise<TablechartInstance>;
|
|
325
379
|
//#endregion
|
|
326
|
-
|
|
380
|
+
//#region src/js/functions/sources.d.ts
|
|
381
|
+
/** A Markdown table, or a caption with chart attributes, is wrapped in a figure with the caption and annotations beside it. */
|
|
382
|
+
declare const adoptTables: (figures: HTMLElement[]) => HTMLElement[];
|
|
383
|
+
/** `data-chart-src` fills the figure's table with the rows of a JSON file, keeping a header row the author wrote; a file that fails is reported. */
|
|
384
|
+
declare const loadSources: (figures: HTMLElement[]) => Promise<void>;
|
|
385
|
+
/** In a Markdown table, a bold label makes the row a total, and a bold header puts that series in focus. */
|
|
386
|
+
declare const readMarkdownRows: (figures: HTMLElement[]) => void;
|
|
387
|
+
//#endregion
|
|
388
|
+
//#region src/js/functions/read-table.d.ts
|
|
389
|
+
/** Writes translation keys such as `harvest-row1` onto a figure with `data-chart-keys`; a duplicate prefix gets a number. */
|
|
390
|
+
declare const assignKeys: (figures: HTMLElement[], langattribute: string | false) => void;
|
|
391
|
+
//#endregion
|
|
392
|
+
export { defaultConfig as A, stepTo as C, PRINTING_CLASS as D, PLOT_CLASS as E, QUEUED_CLASS as O, StepPlan as S, PLACED_CLASS as T, scatter as _, TablechartChart as a, Row as b, entranceOf as c, addType as d, build as f, unbuild as g, setShown as h, readMarkdownRows as i, SHOWN_CLASS as k, init as l, relabel as m, adoptTables as n, TablechartInstance as o, layout as p, loadSources as r, create as s, assignKeys as t, prepare as u, ChartState as v, Config as w, Series as x, ChartType as y };
|