vvplot 0.1.2 → 0.2.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/dist/theme.d.ts DELETED
@@ -1 +0,0 @@
1
- export { }
package/dist/theme.js DELETED
@@ -1,251 +0,0 @@
1
- import { obj_merge } from "./utils.js";
2
- const theme_base = {
3
- axis: {
4
- line_width: 1,
5
- tick_width: 1,
6
- tick_length: 5,
7
- label_size: 12,
8
- title_size: 18
9
- },
10
- axis_h: {
11
- title_offset: 20
12
- },
13
- axis_v: {
14
- title_offset: 30,
15
- title_angle: 90
16
- },
17
- axis_left: {
18
- tick_position: "left",
19
- title_position: "left"
20
- },
21
- axis_right: {
22
- tick_position: "right",
23
- title_position: "right"
24
- },
25
- axis_top: {
26
- tick_position: "top",
27
- title_position: "top"
28
- },
29
- axis_bottom: {
30
- tick_position: "bottom",
31
- title_position: "bottom"
32
- },
33
- grid: {
34
- line_width: 1,
35
- line_width_major: 2
36
- },
37
- plot: {
38
- margin: 20,
39
- padding_h: 50,
40
- padding_v: 20
41
- },
42
- legend: {
43
- spacing: 4
44
- }
45
- };
46
- const theme_default = {
47
- axis: {
48
- line_color: "black",
49
- tick_color: "black",
50
- label_color: "black",
51
- title_color: "black"
52
- },
53
- grid: {
54
- line_color: "#eeeeee"
55
- }
56
- };
57
- const theme_light = {
58
- axis: {
59
- line_color: "gray",
60
- tick_color: "gray",
61
- label_color: "gray",
62
- title_color: "gray"
63
- },
64
- grid: {
65
- line_color: "#eeeeee"
66
- }
67
- };
68
- const theme_gray = {
69
- axis: {
70
- tick_color: "black",
71
- label_color: "black",
72
- title_color: "black"
73
- },
74
- grid: {
75
- line_color: "white"
76
- },
77
- plot: {
78
- background: "#eeeeee"
79
- }
80
- };
81
- const theme_dark = {
82
- axis: {
83
- tick_color: "#333333",
84
- label_color: "#555555",
85
- title_color: "black"
86
- },
87
- grid: {
88
- line_color: "#666666"
89
- },
90
- plot: {
91
- background: "#888888"
92
- }
93
- };
94
- const theme_linedraw = {
95
- axis: {
96
- line_color: "black",
97
- tick_color: "black",
98
- label_color: "black",
99
- title_color: "black"
100
- },
101
- grid: {
102
- line_color: "black",
103
- line_width_major: 1,
104
- line_width_minor: 0.5
105
- }
106
- };
107
- const theme_classic = {
108
- axis: {
109
- line_color: "black",
110
- tick_color: "black",
111
- label_color: "black",
112
- title_color: "black"
113
- },
114
- grid: null
115
- };
116
- const theme_void = {
117
- axis: null,
118
- grid: null
119
- };
120
- function themeMerge(...themes) {
121
- return themes.reduce((acc, t) => {
122
- for (let k in t) {
123
- if (t[k] === null) {
124
- acc[k] = null;
125
- } else {
126
- acc[k] = Object.assign(acc[k] || {}, t[k]);
127
- }
128
- }
129
- return acc ?? void 0;
130
- }, {});
131
- }
132
- function themePreprocess(theme2, flip = false) {
133
- let {
134
- axis_h,
135
- axis_v,
136
- axis_x,
137
- axis_y,
138
- grid_h,
139
- grid_v,
140
- grid_x,
141
- grid_y,
142
- plot: {
143
- margin_x,
144
- margin_y,
145
- margin_h,
146
- margin_v,
147
- padding_x,
148
- padding_y,
149
- padding_h,
150
- padding_v,
151
- ...plot
152
- } = {},
153
- ...rest
154
- } = theme2;
155
- if (flip) {
156
- axis_h = obj_merge([axis_h, axis_y]);
157
- axis_v = obj_merge([axis_v, axis_x]);
158
- grid_h = obj_merge([grid_h, grid_x]);
159
- grid_v = obj_merge([grid_v, grid_y]);
160
- plot.margin_h = margin_y === void 0 ? margin_h : margin_y;
161
- plot.margin_v = margin_x === void 0 ? margin_v : margin_x;
162
- plot.padding_h = padding_y === void 0 ? padding_h : padding_y;
163
- plot.padding_v = padding_x === void 0 ? padding_v : padding_x;
164
- } else {
165
- axis_h = obj_merge([axis_h, axis_x]);
166
- axis_v = obj_merge([axis_v, axis_y]);
167
- grid_h = obj_merge([grid_h, grid_y]);
168
- grid_v = obj_merge([grid_v, grid_x]);
169
- plot.margin_h = margin_x === void 0 ? margin_h : margin_x;
170
- plot.margin_v = margin_y === void 0 ? margin_v : margin_y;
171
- plot.padding_h = padding_x === void 0 ? padding_h : padding_x;
172
- plot.padding_v = padding_y === void 0 ? padding_v : padding_y;
173
- }
174
- return {
175
- axis_h,
176
- axis_v,
177
- grid_h,
178
- grid_v,
179
- plot,
180
- ...rest
181
- };
182
- }
183
- function themeBuild(theme2) {
184
- function _grid_build(grid_theme) {
185
- return {
186
- line_color_major: ["line_color", "line_color_major"].map((k) => grid_theme?.[k]).findLast((x) => x !== void 0),
187
- line_color_minor: ["line_color", "line_color_minor"].map((k) => grid_theme?.[k]).findLast((x) => x !== void 0),
188
- line_width_major: ["line_width", "line_width_major"].map((k) => grid_theme?.[k]).findLast((x) => x !== void 0),
189
- line_width_minor: ["line_width", "line_width_minor"].map((k) => grid_theme?.[k]).findLast((x) => x !== void 0)
190
- };
191
- }
192
- return {
193
- axis: {
194
- h: obj_merge(["axis", "axis_h"].map((k) => theme2?.[k])),
195
- v: obj_merge(["axis", "axis_v"].map((k) => theme2?.[k])),
196
- left: obj_merge(
197
- ["axis", "axis_v", "axis_left"].map((k) => theme2?.[k])
198
- ),
199
- right: obj_merge(
200
- ["axis", "axis_v", "axis_right"].map((k) => theme2?.[k])
201
- ),
202
- top: obj_merge(
203
- ["axis", "axis_h", "axis_top"].map((k) => theme2?.[k])
204
- ),
205
- bottom: obj_merge(
206
- ["axis", "axis_h", "axis_bottom"].map((k) => theme2?.[k])
207
- )
208
- },
209
- grid: {
210
- h: _grid_build(obj_merge(["grid", "grid_h"].map((k) => theme2?.[k]))),
211
- v: _grid_build(obj_merge(["grid", "grid_v"].map((k) => theme2?.[k])))
212
- },
213
- plot: {
214
- margin: {
215
- left: ["margin", "margin_h", "margin_left"].map((k) => theme2?.plot?.[k]).findLast((x) => x !== void 0) ?? 0,
216
- right: ["margin", "margin_h", "margin_right"].map((k) => theme2?.plot?.[k]).findLast((x) => x !== void 0) ?? 0,
217
- top: ["margin", "margin_v", "margin_top"].map((k) => theme2?.plot?.[k]).findLast((x) => x !== void 0) ?? 0,
218
- bottom: ["margin", "margin_v", "margin_bottom"].map((k) => theme2?.plot?.[k]).findLast((x) => x !== void 0) ?? 0
219
- },
220
- padding: {
221
- left: ["padding", "padding_h", "padding_left"].map((k) => theme2?.plot?.[k]).findLast((x) => x !== void 0) ?? 0,
222
- right: ["padding", "padding_h", "padding_right"].map((k) => theme2?.plot?.[k]).findLast((x) => x !== void 0) ?? 0,
223
- top: ["padding", "padding_v", "padding_top"].map((k) => theme2?.plot?.[k]).findLast((x) => x !== void 0) ?? 0,
224
- bottom: ["padding", "padding_v", "padding_bottom"].map((k) => theme2?.plot?.[k]).findLast((x) => x !== void 0) ?? 0
225
- },
226
- background: theme2?.plot?.background
227
- },
228
- selection: theme2?.selection ?? {},
229
- legend: {
230
- spacing: theme2?.legend?.spacing ?? 0
231
- }
232
- };
233
- }
234
- const theme = {
235
- base: theme_base,
236
- default: theme_default,
237
- light: theme_light,
238
- classic: theme_classic,
239
- gray: theme_gray,
240
- dark: theme_dark,
241
- linedraw: theme_linedraw,
242
- void: theme_void
243
- };
244
- export {
245
- theme as default,
246
- themeBuild,
247
- themeMerge,
248
- themePreprocess,
249
- theme_base,
250
- theme_default
251
- };
package/dist/utils.js DELETED
@@ -1,333 +0,0 @@
1
- class GEnumElement {
2
- constructor(label, value, level) {
3
- this.label = label;
4
- this.value = value;
5
- this.level = level;
6
- }
7
- toString() {
8
- return this.label;
9
- }
10
- valueOf() {
11
- return this.value;
12
- }
13
- toJSON() {
14
- return this.label;
15
- }
16
- }
17
- class GEnumLevel extends Array {
18
- /**
19
- * return:
20
- * x if x is a GEnumLevel
21
- * new GEnumLevel from distinct values of x, ordered by natural order, if x is iterable
22
- * new GEnumLevel from keys of x, orderd by coresponing values, if x is an object
23
- * @param {*} x
24
- * @param {function} [sortkey]
25
- * @returns {GEnumLevel}
26
- */
27
- static from(x) {
28
- if (x instanceof this) return x;
29
- if (x[Symbol.iterator]) {
30
- let lvl = unique(Array.from(x).map((x2) => String(x2))).sort((a, b) => compare(a, b, { numeric: true }));
31
- return new this(...lvl);
32
- } else if (typeof x === "object") {
33
- let lvl = Object.keys(x).map((x2) => String(x2)).sort((a, b) => compare(x[a], x[b]));
34
- return new this(...lvl);
35
- }
36
- throw new Error(`Invalid level values: ${x}`);
37
- }
38
- /**
39
- * build a GEnumLevel
40
- * @param {string[]} level
41
- */
42
- constructor(...level) {
43
- level = level.map((x, i) => new GEnumElement(String(x), i));
44
- level.forEach((l) => l.level = level);
45
- level.mapping = Object.fromEntries(level.map((fct) => [fct, fct]));
46
- Object.setPrototypeOf(level, GEnumLevel.prototype);
47
- return level;
48
- }
49
- /**
50
- * get the level instance by index or key
51
- * @param {(number|string)} idx
52
- * @returns {GEnumElement}
53
- */
54
- getItem(idx) {
55
- if (typeof idx === "number" || idx instanceof Number) {
56
- return this[idx];
57
- } else {
58
- return this.mapping[idx];
59
- }
60
- }
61
- /**
62
- * convert an array to a GEnum array
63
- * @param {string[]} arr array to be converted, preferably a string array (items of other types will be converted to string)
64
- * @returns {GEnumElement[]}
65
- */
66
- apply(arr) {
67
- let result = arr.map((x) => this.mapping[x]);
68
- result.level = this;
69
- return result;
70
- }
71
- }
72
- function isContinuous(x) {
73
- return typeof x === "number" || x instanceof Number || x instanceof Date;
74
- }
75
- function plus(a, b = 0) {
76
- if (b == 0 || a == null) return a;
77
- if (a instanceof Date) return new a.constructor(+a + b);
78
- return +a + b;
79
- }
80
- const numutils = {
81
- min(arr, { na_rm = true, infinity_rm = true } = {}) {
82
- if (na_rm) arr = arr.filter(isContinuous);
83
- if (infinity_rm) arr = arr.filter((x) => isFinite(x));
84
- return Array.from(arr).reduce((a, b) => a < b ? a : b, Infinity);
85
- },
86
- max(arr, { na_rm = true, infinity_rm = true } = {}) {
87
- if (na_rm) arr = arr.filter(isContinuous);
88
- if (infinity_rm) arr = arr.filter((x) => isFinite(x));
89
- return Array.from(arr).reduce((a, b) => a > b ? a : b, -Infinity);
90
- },
91
- mean(arr, { na_rm = true, infinity_rm = true } = {}) {
92
- if (na_rm) arr = arr.filter(isContinuous);
93
- if (infinity_rm) arr = arr.filter((x) => isFinite(x));
94
- if (arr.length == 0) return NaN;
95
- return Array.from(arr).reduce((a, v) => a + v, 0) / arr.length;
96
- },
97
- sd(arr, { na_rm = true, infinity_rm = true } = {}) {
98
- if (na_rm) arr = arr.filter(isContinuous);
99
- if (infinity_rm) arr = arr.filter((x) => isFinite(x));
100
- if (arr.length <= 1) return NaN;
101
- let mean = Array.from(arr).reduce((a, v) => a + v, 0) / arr.length;
102
- return Math.sqrt(Array.from(arr).reduce((a, v) => a + (v - mean) ** 2, 0) / (arr.length - 1));
103
- },
104
- quantile(arr, p, { na_rm = true, infinity_rm = true } = {}) {
105
- if (na_rm) arr = arr.filter(isContinuous);
106
- if (infinity_rm) arr = arr.filter((x) => isFinite(x));
107
- if (arr.length == 0) return NaN;
108
- arr = Array.from(arr).sort((a, b) => a - b);
109
- let idx = (arr.length - 1) * p, lo = Math.floor(idx), hi = Math.ceil(idx);
110
- if (lo == hi) return arr[lo];
111
- return arr[lo] * (hi - idx) + arr[hi] * (idx - lo);
112
- },
113
- extent(arr, { na_rm = true, infinity_rm = true } = {}) {
114
- if (na_rm) arr = arr.filter(isContinuous);
115
- if (infinity_rm) arr = arr.filter((x) => isFinite(x));
116
- if (arr.length == 0) return new Array(2);
117
- let min = Array.from(arr).reduce((a, b) => a < b ? a : b, Infinity), max = Array.from(arr).reduce((a, b) => a > b ? a : b, -Infinity);
118
- return Object.assign([min, max], { min, max });
119
- }
120
- };
121
- const vecutils = {
122
- /* vectorized summation of numbers */
123
- sum(...values) {
124
- if (values.some((x) => x == null)) return null;
125
- if (values.some((x) => !Array.isArray(x) && typeof x != "number"))
126
- throw new Error("Arguments must be numbers or arrays");
127
- let nums = values.filter((x) => !Array.isArray(x)).reduce((s, a) => +a + s, 0);
128
- values = values.filter((x) => Array.isArray(x));
129
- if (values.length == 0)
130
- return [nums];
131
- if (values.some((v) => v.length == 0))
132
- return [];
133
- let length = values[0].length;
134
- if (values.some((v) => v.length != length))
135
- throw new Error("Arrays must have the same length");
136
- return Array.from({ length }, (_, i) => values.reduce((s, a) => +a[i] + s, nums));
137
- }
138
- };
139
- function obj_merge(arr) {
140
- arr = arr.filter((x) => x !== void 0);
141
- if (arr.length == 0) return void 0;
142
- arr = arr.slice(arr.findIndex((x) => x == null) + 1);
143
- if (arr.length == 0) return null;
144
- return arr.reduce((a, c) => Object.assign(a, c), {});
145
- }
146
- function str_c(...args) {
147
- if (args.some((x) => x === void 0)) return void 0;
148
- if (args.some((x) => x === null)) return null;
149
- return args.join("");
150
- }
151
- function unique(arr, mapper = null) {
152
- let map = /* @__PURE__ */ new Map();
153
- for (let i in arr) {
154
- let key = mapper ? mapper(arr[i]) : arr[i];
155
- if (!map.has(key)) map.set(key, arr[i]);
156
- }
157
- return Array.from(map.values());
158
- }
159
- function compare(a, b, { numeric = false } = {}) {
160
- if (typeof a != "number" || typeof b != "number")
161
- return String(a).localeCompare(String(b), void 0, { numeric });
162
- return a - b;
163
- }
164
- function emitEvent(handlers, ...args) {
165
- if (Array.isArray(handlers)) {
166
- handlers = handlers.filter((h) => typeof h === "function");
167
- if (handlers.length === 0) return false;
168
- handlers.forEach((h) => h(...args));
169
- return true;
170
- }
171
- if (typeof handlers !== "function") return false;
172
- handlers(...args);
173
- return true;
174
- }
175
- function oob_censor(value, { min, max }) {
176
- if (value < min || value > max) return NaN;
177
- return value;
178
- }
179
- function oob_squish_any(value, { min, max }) {
180
- if (value < min) return min;
181
- if (value > max) return max;
182
- return value;
183
- }
184
- function oob_squish_infinite(value, { min, max }) {
185
- if (value == -Infinity) return min;
186
- if (value == Infinity) return max;
187
- return value;
188
- }
189
- function dropNull(obj) {
190
- if (typeof obj !== "object" || obj == null) return obj;
191
- return Object.fromEntries(Object.entries(obj).filter(([k, v]) => v != null));
192
- }
193
- function deepEqual(a, b) {
194
- if (a === b) return true;
195
- if (typeof a !== "object" || typeof b !== "object" || a == null || b == null) return false;
196
- let aKeys = Object.keys(a), bKeys = Object.keys(b);
197
- if (aKeys.length !== bKeys.length) return false;
198
- for (let key of aKeys) {
199
- if (!deepEqual(a[key], b[key])) return false;
200
- }
201
- return true;
202
- }
203
- function categorize(array) {
204
- if (!Array.isArray(array)) throw new Error("Argument must be an array");
205
- let categories = [], result = [];
206
- for (let i = 0; i < array.length; i++) {
207
- let obj = array[i];
208
- let idx = categories.findIndex((cat) => deepEqual(cat, obj));
209
- if (idx === -1) {
210
- categories.push(obj);
211
- idx = categories.length - 1;
212
- }
213
- result.push(idx);
214
- }
215
- result.categories = categories;
216
- return result;
217
- }
218
- function interaction(...arrays) {
219
- if (arrays.length == 0) return null;
220
- let length = arrays.filter((x) => Array.isArray(x)).reduce((l, arr) => {
221
- if (Array.isArray(arr)) {
222
- if (l == null) return arr.length;
223
- if (l != arr.length) throw new Error("Arrays must have the same length");
224
- }
225
- return l;
226
- }, null) ?? 0;
227
- let categories = [], result = [];
228
- for (let i = 0; i < length; i++) {
229
- let arr = arrays.map((x) => Array.isArray(x) ? x[i] : x);
230
- let idx = categories.findIndex((x) => x.every((v, j) => v === arr[j]));
231
- if (idx === -1) {
232
- categories.push(arr);
233
- idx = categories.length - 1;
234
- }
235
- result.push(idx);
236
- }
237
- result.categories = categories;
238
- return result;
239
- }
240
- function intraaction(arrays) {
241
- if (Object.keys(arrays).length == 0) return null;
242
- let length = Object.values(arrays).filter((x) => Array.isArray(x)).reduce((l, arr) => {
243
- if (Array.isArray(arr)) {
244
- if (l == null) return arr.length;
245
- if (l != arr.length) throw new Error("Arrays must have the same length");
246
- }
247
- return l;
248
- }, null) ?? 0;
249
- let keys = Object.keys(arrays);
250
- let categories = [], result = [];
251
- for (let i = 0; i < length; i++) {
252
- let arr = Object.fromEntries(keys.map((k) => [k, Array.isArray(arrays[k]) ? arrays[k][i] : arrays[k]]));
253
- let idx = categories.findIndex((x) => keys.every((k) => x[k] === arr[k]));
254
- if (idx === -1) {
255
- categories.push(arr);
256
- idx = categories.length - 1;
257
- }
258
- result.push(idx);
259
- }
260
- result.categories = categories;
261
- return result;
262
- }
263
- function intrazip(arrays) {
264
- if (Object.keys(arrays).length == 0) return [];
265
- let length = Object.values(arrays).filter((x) => Array.isArray(x)).reduce((l, arr) => {
266
- if (Array.isArray(arr)) {
267
- if (l == null) return arr.length;
268
- if (l != arr.length) throw new Error("Arrays must have the same length");
269
- }
270
- return l;
271
- }, null) ?? 0;
272
- return Array.from({ length }, (_, i) => Object.fromEntries(Object.keys(arrays).map((k) => [k, Array.isArray(arrays[k]) ? arrays[k][i] : arrays[k]])));
273
- }
274
- function serializeSVG(svgElement) {
275
- if (!(svgElement instanceof SVGElement)) return null;
276
- function removeComments(node) {
277
- let i = node.childNodes.length;
278
- while (i--) {
279
- const child = node.childNodes[i];
280
- if (child.nodeType === Node.COMMENT_NODE) {
281
- node.removeChild(child);
282
- } else if (child.nodeType === Node.ELEMENT_NODE) {
283
- removeComments(child);
284
- if (child.getAttribute("style") == "") child.removeAttribute("style");
285
- if (child.getAttribute("class") == "") child.removeAttribute("class");
286
- }
287
- }
288
- }
289
- let svgClone = svgElement.cloneNode(true);
290
- let foreignElements = Array.from(svgElement.querySelectorAll("foreignObject")), foreignClones = Array.from(svgClone.querySelectorAll("foreignObject"));
291
- for (let i = 0; i < foreignElements.length; i++) {
292
- let foreignElement = foreignElements[i], foreignClone = foreignClones[i];
293
- let canvas = foreignElements[i].querySelector("canvas");
294
- if (!canvas) continue;
295
- let img = svgClone.ownerDocument.createElementNS("http://www.w3.org/2000/svg", "image");
296
- img.setAttribute("href", canvas.toDataURL());
297
- img.setAttribute("x", foreignElement.getAttribute("x"));
298
- img.setAttribute("y", foreignElement.getAttribute("y"));
299
- img.setAttribute("width", foreignElement.getAttribute("width"));
300
- img.setAttribute("height", foreignElement.getAttribute("height"));
301
- foreignClone.parentNode.replaceChild(img, foreignClone);
302
- }
303
- for (let node of svgClone.querySelectorAll(".vvplot-interactive")) node.remove();
304
- removeComments(svgClone);
305
- svgClone.setAttribute("xmlns", "http://www.w3.org/2000/svg");
306
- svgClone.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
307
- svgClone.setAttribute("version", "1.1");
308
- svgClone.setAttribute("width", svgElement.scrollWidth);
309
- svgClone.setAttribute("height", svgElement.scrollHeight);
310
- svgClone.setAttribute("viewBox", `0 0 ${svgElement.scrollWidth} ${svgElement.scrollHeight}`);
311
- const serializer = new XMLSerializer();
312
- return serializer.serializeToString(svgClone);
313
- }
314
- export {
315
- GEnumElement,
316
- GEnumLevel,
317
- categorize,
318
- dropNull,
319
- emitEvent,
320
- interaction,
321
- intraaction,
322
- intrazip,
323
- numutils,
324
- obj_merge,
325
- oob_censor,
326
- oob_squish_any,
327
- oob_squish_infinite,
328
- plus,
329
- serializeSVG,
330
- str_c,
331
- unique,
332
- vecutils
333
- };