@jackens/nnn 2024.3.5 → 2024.3.8

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.
Files changed (4) hide show
  1. package/nnn.d.ts +0 -32
  2. package/nnn.js +40 -152
  3. package/package.json +1 -1
  4. package/readme.md +1 -38
package/nnn.d.ts CHANGED
@@ -1,35 +1,3 @@
1
- /**
2
- * A helper for creating a chart based on a table (conf. <https://jackens.github.io/nnn/chartable/>).
3
- *
4
- * Options:
5
- * - `table`: `HTMLTableElement` to extract data, data series labels and X axis labels
6
- * - `headerColumn`: flag indicating that `table` has a header column with X axis labels
7
- * - `xGap`: X axis spacing
8
- * - `xLabelsMinHeight`: minimal height of X axis labels
9
- * - `xLabelsRotate`: flag to rotate X axis labels
10
- * - `xReverse`: flag to reverse all data series
11
- * - `yGap`: Y axis spacing
12
- * - `yLabelsLeftMinWidth`: minimal width of Y axis left labels
13
- * - `yLabelsRightMinWidth`: minimal width of Y axis right labels
14
- * - `yMax`: number of Y axis lines
15
- * - `zLabelsMinWidth`: minimal width of data series labels
16
- * - `zyMappings`: mappings per data series
17
- */
18
- export declare const chartable: ({ table, headerColumn, xGap, xLabelsMinHeight, xLabelsRotate, xReverse, yGap, yLabelsLeftMinWidth, yLabelsRightMinWidth, yMax, zLabelsMinWidth, zyMappings }: {
19
- table: HTMLTableElement;
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;
31
- }) => SVGSVGElement;
32
-
33
1
  /**
34
2
  * A helper that checks equality of the given arguments.
35
3
  */
package/nnn.js CHANGED
@@ -1,3 +1,42 @@
1
+ // src/nnn/eq.ts
2
+ var eq = (x, y) => {
3
+ if (x === y) {
4
+ return true;
5
+ }
6
+ const xConstructor = x?.constructor;
7
+ if (xConstructor === y?.constructor) {
8
+ if (xConstructor === Number) {
9
+ return isNaN(x) && isNaN(y) || +x === +y;
10
+ }
11
+ if (xConstructor === Date) {
12
+ return +x === +y;
13
+ }
14
+ if (xConstructor === String || xConstructor === RegExp) {
15
+ return "" + x === "" + y;
16
+ }
17
+ if (xConstructor === Array) {
18
+ return x.length === y.length && x.every((item, index) => eq(item, y[index]));
19
+ }
20
+ if (xConstructor === Object) {
21
+ const keysOfX = Object.keys(x);
22
+ return keysOfX.length === Object.keys(y).length && keysOfX.every((key) => eq(x[key], y[key]));
23
+ }
24
+ if (xConstructor === Set || xConstructor === Map) {
25
+ if (x.size !== y.size) {
26
+ return false;
27
+ }
28
+ const xa = [...x];
29
+ const ya = [...y];
30
+ return xa.every((xv) => ya.find((yv) => eq(xv, yv)));
31
+ }
32
+ }
33
+ return false;
34
+ };
35
+
36
+ // src/nnn/escape.ts
37
+ var escapeValues = (escapeMap, values) => values.map((value) => (escapeMap.get(value?.constructor) ?? escapeMap.get(undefined))?.(value) ?? "");
38
+ var escape = (escapeMap, template, ...values) => String.raw(template, ...escapeValues(escapeMap, values));
39
+
1
40
  // src/nnn/is.ts
2
41
  var is = (type, arg) => arg?.constructor === type;
3
42
 
@@ -66,156 +105,6 @@ var h = _h();
66
105
  var s = _h("http://www.w3.org/2000/svg");
67
106
  var svgUse = (id, ...args) => s("svg", ["use", { "xlink:href": "#" + id }], ...args);
68
107
 
69
- // src/nnn/chartable.ts
70
- var COLORS = ["#e22", "#e73", "#fc3", "#ad4", "#4d9", "#3be", "#45d", "#c3e"];
71
- var PADDING = 15;
72
- var _svg = s("svg", { viewBox: "0 0 0 0", width: 0, height: 0 });
73
- h(document.body, ["div", { $style: { width: 0, height: 0 } }, _svg]);
74
- var toFixed2 = (value) => value.toFixed(2);
75
- var chartable = ({
76
- table,
77
- headerColumn = false,
78
- xGap = 70,
79
- xLabelsMinHeight = 0,
80
- xLabelsRotate = false,
81
- xReverse = false,
82
- yGap = 30,
83
- yLabelsLeftMinWidth = 100,
84
- yLabelsRightMinWidth = 100,
85
- yMax = 10,
86
- zLabelsMinWidth = 0,
87
- zyMappings = []
88
- }) => {
89
- const zxValues = [];
90
- const xLabels = [];
91
- const zLabels = [];
92
- table.querySelectorAll("tr").forEach((row, r) => row.querySelectorAll("td,th").forEach((col, c) => {
93
- const x = r - 1;
94
- const z = c - +headerColumn;
95
- const value = col.innerText;
96
- if (x >= 0 && z >= 0) {
97
- zxValues[z] = zxValues[z] ?? [];
98
- zxValues[z][x] = (zyMappings?.[z]?.[0] ?? parseFloat)(value);
99
- } else if (x >= 0 && z < 0) {
100
- xLabels[x] = value;
101
- } else if (x < 0 && z >= 0) {
102
- zLabels[z] = value;
103
- }
104
- }));
105
- if (xReverse) {
106
- xLabels.reverse();
107
- zxValues.forEach((xValues) => xValues.reverse());
108
- }
109
- const xMax = zxValues[0].length;
110
- const xPx = Array.from({ length: xMax }, (_, x) => x * xGap);
111
- const yPx = Array.from({ length: yMax }, (_, y) => y * yGap);
112
- const width = xGap * (xMax - 1);
113
- const height = yGap * (yMax - 1);
114
- const gGraph = s("g", ...yPx.map((px) => ["line", { x1: 0, x2: width, y1: px, y2: px, stroke: "#8888" }]), ...xPx.map((px) => ["line", { x1: px, x2: px, y1: 0, y2: height, stroke: "#8888" }]));
115
- const gXLabels = s("g");
116
- const gYLabelsL = zxValues.map((_) => s("g"));
117
- const gYLabelsR = zxValues.map((_) => s("g"));
118
- const gZColors = s("g");
119
- const gZLabels = [];
120
- const onclick = (z) => {
121
- gYLabelsL.forEach((g, z2) => s(g, { $style: { display: z2 === z ? "block" : "none" } }));
122
- gYLabelsR.forEach((g, z2) => s(g, { $style: { display: z2 === z ? "block" : "none" } }));
123
- gZLabels.forEach((text, z2) => s(text, { $style: { fontWeight: z2 === z ? "bold" : "normal", cursor: "pointer" } }));
124
- };
125
- zxValues.forEach((values, z) => {
126
- const fill = COLORS[z % COLORS.length];
127
- const minValue = Math.min(...values.filter((value) => !isNaN(value)));
128
- const maxValue = Math.max(...values.filter((value) => !isNaN(value)));
129
- yPx.forEach((yp, y) => {
130
- const value = (zyMappings?.[z]?.[1] ?? toFixed2)(maxValue - (maxValue - minValue) / yMax * (y + 1));
131
- const textL = s("text", { x: 0, y: yp, "text-anchor": "end", "alignment-baseline": "middle" }, value);
132
- const textR = s("text", { x: 0, y: yp, "text-anchor": "start", "alignment-baseline": "middle" }, value);
133
- s(_svg, textL, textR);
134
- yLabelsLeftMinWidth = Math.max(yLabelsLeftMinWidth, textL.getBBox().width);
135
- yLabelsRightMinWidth = Math.max(yLabelsRightMinWidth, textR.getBBox().width);
136
- s(gYLabelsL[z], textL);
137
- s(gYLabelsR[z], textR);
138
- });
139
- const text = s("text", {
140
- x: 0,
141
- y: yGap * z,
142
- "text-anchor": "start",
143
- "alignment-baseline": "middle",
144
- $onclick: () => onclick(z),
145
- $style: { fontWeight: "bold" }
146
- }, zLabels[z]);
147
- s(_svg, text);
148
- zLabelsMinWidth = Math.max(zLabelsMinWidth, text.getBBox().width);
149
- gZLabels[z] = text;
150
- s(gZColors, ["circle", { cx: 0, cy: yGap * z, r: 5, fill }]);
151
- const valuesPx = values.map((value) => isNaN(value) ? value : height * (maxValue - value) / (maxValue - minValue));
152
- xPx.forEach((px, x) => {
153
- if (!isNaN(valuesPx[x])) {
154
- s(gGraph, ["g", ["circle", { cx: px, cy: valuesPx[x], r: 5, fill }]]);
155
- if (!isNaN(valuesPx[x - 1])) {
156
- s(gGraph, ["line", { x1: px, x2: xPx[x - 1], y1: valuesPx[x], y2: valuesPx[x - 1], stroke: fill }]);
157
- }
158
- }
159
- });
160
- });
161
- if (xLabels.length > 0) {
162
- xPx.forEach((xp, x) => {
163
- const text = s("text", xLabelsRotate ? { x: 0, y: -xp, "text-anchor": "start", "alignment-baseline": "middle", transform: "rotate(90)" } : { x: xp, y: PADDING, "text-anchor": "middle", "alignment-baseline": "middle" }, xLabels[x]);
164
- s(_svg, text);
165
- xLabelsMinHeight = Math.max(xLabelsMinHeight, xLabelsRotate ? text.getBBox().width : text.getBBox().height);
166
- s(gXLabels, text);
167
- });
168
- }
169
- const svgW = width + yLabelsLeftMinWidth + yLabelsRightMinWidth + zLabelsMinWidth + 4 * PADDING;
170
- const svgH = height + xLabelsMinHeight + (xLabels.length > 0 ? 3 : 2) * PADDING;
171
- s(gGraph, { transform: `translate(${yLabelsLeftMinWidth + PADDING} ${PADDING})` });
172
- gYLabelsL.forEach((g) => s(g, { transform: `translate(${yLabelsLeftMinWidth} ${PADDING})` }));
173
- gYLabelsR.forEach((g) => s(g, { transform: `translate(${width + yLabelsLeftMinWidth + 2 * PADDING} ${PADDING})` }));
174
- s(gZColors, { transform: `translate(${width + yLabelsLeftMinWidth + yLabelsRightMinWidth + 3 * PADDING} ${PADDING})` });
175
- s(gXLabels, { transform: `translate(${yLabelsLeftMinWidth + PADDING} ${height + 2 * PADDING})` });
176
- onclick(0);
177
- return s("svg", { viewBox: `0 0 ${svgW} ${svgH}`, width: `${svgW}px`, height: `${svgH}px`, class: "chartable" }, gGraph, gXLabels, ...gYLabelsL, ...gYLabelsR, gZColors, ["g", { transform: `translate(${width + yLabelsLeftMinWidth + yLabelsRightMinWidth + 4 * PADDING} ${PADDING})` }, ...gZLabels]);
178
- };
179
-
180
- // src/nnn/eq.ts
181
- var eq = (x, y) => {
182
- if (x === y) {
183
- return true;
184
- }
185
- const xConstructor = x?.constructor;
186
- if (xConstructor === y?.constructor) {
187
- if (xConstructor === Number) {
188
- return isNaN(x) && isNaN(y) || +x === +y;
189
- }
190
- if (xConstructor === Date) {
191
- return +x === +y;
192
- }
193
- if (xConstructor === String || xConstructor === RegExp) {
194
- return "" + x === "" + y;
195
- }
196
- if (xConstructor === Array) {
197
- return x.length === y.length && x.every((item, index) => eq(item, y[index]));
198
- }
199
- if (xConstructor === Object) {
200
- const keysOfX = Object.keys(x);
201
- return keysOfX.length === Object.keys(y).length && keysOfX.every((key) => eq(x[key], y[key]));
202
- }
203
- if (xConstructor === Set || xConstructor === Map) {
204
- if (x.size !== y.size) {
205
- return false;
206
- }
207
- const xa = [...x];
208
- const ya = [...y];
209
- return xa.every((xv) => ya.find((yv) => eq(xv, yv)));
210
- }
211
- }
212
- return false;
213
- };
214
-
215
- // src/nnn/escape.ts
216
- var escapeValues = (escapeMap, values) => values.map((value) => (escapeMap.get(value?.constructor) ?? escapeMap.get(undefined))?.(value) ?? "");
217
- var escape = (escapeMap, template, ...values) => String.raw(template, ...escapeValues(escapeMap, values));
218
-
219
108
  // src/nnn/fixTypography.ts
220
109
  var TAGS_TO_SKIP = ["IFRAME", "NOSCRIPT", "PRE", "SCRIPT", "STYLE", "TEXTAREA"];
221
110
  var fixTypography = (node) => {
@@ -417,6 +306,5 @@ export {
417
306
  fixTypography,
418
307
  escapeValues,
419
308
  escape,
420
- eq,
421
- chartable
309
+ eq
422
310
  };
package/package.json CHANGED
@@ -43,5 +43,5 @@
43
43
  "types": "nnn.d.ts",
44
44
  "name": "@jackens/nnn",
45
45
  "type": "module",
46
- "version": "2024.3.5"
46
+ "version": "2024.3.8"
47
47
  }
package/readme.md CHANGED
@@ -2,11 +2,10 @@
2
2
 
3
3
  Jackens’ JavaScript helpers.
4
4
 
5
- <sub>Version: <code class="version">2024.3.5</code></sub>
5
+ <sub>Version: <code class="version">2024.3.8</code></sub>
6
6
 
7
7
  ## Examples
8
8
 
9
- - [Chartable Demo](https://jackens.github.io/nnn/chartable/)
10
9
  - [Chessboard Demo](https://jackens.github.io/nnn/chessboard/)
11
10
  - [Documentation](https://jackens.github.io/nnn/doc/)
12
11
  - [Gant Chart Demo](https://jackens.github.io/nnn/gantt/)
@@ -45,7 +44,6 @@ import { «something» } from './node_modules/@jackens/nnn/nnn.js'
45
44
  - `HArgs1`: The type of arguments of the `h` and `s` helpers.
46
45
  - `JcNode`: The type of arguments of the `jc` helper.
47
46
  - `JcRoot`: The type of arguments of the `jc` helper.
48
- - `chartable`: A helper for creating a chart based on a table (conf. <https://jackens.github.io/nnn/chartable/>).
49
47
  - `eq`: A helper that checks equality of the given arguments.
50
48
  - `escape`: A generic helper for escaping `values` by given `escapeMap` (in *TemplateStrings* flavor).
51
49
  - `escapeValues`: A generic helper for escaping `values` by given `escapeMap`.
@@ -109,41 +107,6 @@ type JcRoot = Partial<Record<PropertyKey, JcNode>>;
109
107
 
110
108
  The type of arguments of the `jc` helper.
111
109
 
112
- ### chartable
113
-
114
- ```ts
115
- const chartable: ({ table, headerColumn, xGap, xLabelsMinHeight, xLabelsRotate, xReverse, yGap, yLabelsLeftMinWidth, yLabelsRightMinWidth, yMax, zLabelsMinWidth, zyMappings }: {
116
- table: HTMLTableElement;
117
- headerColumn?: boolean | undefined;
118
- xGap?: number | undefined;
119
- xLabelsMinHeight?: number | undefined;
120
- xLabelsRotate?: boolean | undefined;
121
- xReverse?: boolean | undefined;
122
- yGap?: number | undefined;
123
- yLabelsLeftMinWidth?: number | undefined;
124
- yLabelsRightMinWidth?: number | undefined;
125
- yMax?: number | undefined;
126
- zLabelsMinWidth?: number | undefined;
127
- zyMappings?: [(label: string) => number, (value: number) => string][] | undefined;
128
- }) => SVGSVGElement;
129
- ```
130
-
131
- A helper for creating a chart based on a table (conf. <https://jackens.github.io/nnn/chartable/>).
132
-
133
- Options:
134
- - `table`: `HTMLTableElement` to extract data, data series labels and X axis labels
135
- - `headerColumn`: flag indicating that `table` has a header column with X axis labels
136
- - `xGap`: X axis spacing
137
- - `xLabelsMinHeight`: minimal height of X axis labels
138
- - `xLabelsRotate`: flag to rotate X axis labels
139
- - `xReverse`: flag to reverse all data series
140
- - `yGap`: Y axis spacing
141
- - `yLabelsLeftMinWidth`: minimal width of Y axis left labels
142
- - `yLabelsRightMinWidth`: minimal width of Y axis right labels
143
- - `yMax`: number of Y axis lines
144
- - `zLabelsMinWidth`: minimal width of data series labels
145
- - `zyMappings`: mappings per data series
146
-
147
110
  ### eq
148
111
 
149
112
  ```ts