@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 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,2 @@
1
+ import { _ as scatter } from "./tablechart-shared.mjs";
2
+ export { scatter };
@@ -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 { _ as StepPlan, c as PLACED_CLASS, d as QUEUED_CLASS, f as SHOWN_CLASS, g as Series, h as Row, i as entranceOf, l as PLOT_CLASS, m as ChartState, o as prepare, p as defaultConfig, s as Config, u as PRINTING_CLASS, v as stepTo } from "./tablechart-shared.mjs";
2
- //#region src/js/core.d.ts
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 };
@@ -1 +1 @@
1
- export { h as PLACED_CLASS, g as PLOT_CLASS, _ as PRINTING_CLASS, v as QUEUED_CLASS, y as SHOWN_CLASS, a as adoptTables, m as assignKeys, c as build, b as defaultConfig, n as entranceOf, l as layout, o as loadSources, i as prepare, s as readMarkdownRows, u as relabel, d as setShown, p as stepTo, f as unbuild } from "./tablechart-shared.mjs";
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/config.d.ts
232
- declare const PLOT_CLASS = "tablechart-plot";
233
- declare const PLACED_CLASS = "is-placed";
234
- declare const SHOWN_CLASS = "is-shown";
235
- declare const PRINTING_CLASS = "is-printing";
236
- declare const QUEUED_CLASS = "tablechart-queued";
237
- interface Config {
238
- /** Which elements Tablechart turns into charts. */
239
- selector: string;
240
- /** Height of the plot as a share of its width. */
241
- aspect: number;
242
- /** Share of a band that a bar fills. */
243
- barfill: number;
244
- /** Share of a donut's radius that the ring itself takes. */
245
- ringfill: number;
246
- /** Locale for numbers. Unset, the document's language is used and followed when it changes. */
247
- locale?: string;
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
- export { StepPlan as _, init as a, PLACED_CLASS as c, QUEUED_CLASS as d, SHOWN_CLASS as f, Series as g, Row as h, entranceOf as i, PLOT_CLASS as l, ChartState as m, TablechartInstance as n, prepare as o, defaultConfig as p, create as r, Config as s, TablechartChart as t, PRINTING_CLASS as u, stepTo as v };
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 };