@vanduo-oss/vd3-cbun 1.0.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.
Files changed (45) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/LICENSE +22 -0
  3. package/README.md +160 -0
  4. package/SKILL.md +119 -0
  5. package/dist/charts/core.d.ts +273 -0
  6. package/dist/charts/index.cjs +1828 -0
  7. package/dist/charts/index.cjs.map +7 -0
  8. package/dist/charts/index.d.ts +65 -0
  9. package/dist/charts/index.js +1805 -0
  10. package/dist/charts/index.js.map +7 -0
  11. package/dist/charts/vd3-charts.css +51 -0
  12. package/dist/charts/vue.d.ts +86 -0
  13. package/dist/flowchart/core.d.ts +288 -0
  14. package/dist/flowchart/index.cjs +3447 -0
  15. package/dist/flowchart/index.cjs.map +7 -0
  16. package/dist/flowchart/index.d.ts +54 -0
  17. package/dist/flowchart/index.js +3424 -0
  18. package/dist/flowchart/index.js.map +7 -0
  19. package/dist/flowchart/vd3-flowchart.css +600 -0
  20. package/dist/flowchart/vue.d.ts +66 -0
  21. package/dist/hex-grid/core.d.ts +200 -0
  22. package/dist/hex-grid/hex-math.cjs +162 -0
  23. package/dist/hex-grid/hex-math.cjs.map +7 -0
  24. package/dist/hex-grid/hex-math.d.ts +119 -0
  25. package/dist/hex-grid/hex-math.js +141 -0
  26. package/dist/hex-grid/hex-math.js.map +7 -0
  27. package/dist/hex-grid/index.cjs +915 -0
  28. package/dist/hex-grid/index.cjs.map +7 -0
  29. package/dist/hex-grid/index.d.ts +15 -0
  30. package/dist/hex-grid/index.js +894 -0
  31. package/dist/hex-grid/index.js.map +7 -0
  32. package/dist/hex-grid/vue.d.ts +14 -0
  33. package/dist/index.d.ts +13 -0
  34. package/dist/index.js +11 -0
  35. package/dist/index.js.map +7 -0
  36. package/dist/meta.json +551 -0
  37. package/dist/music-player/core.d.ts +88 -0
  38. package/dist/music-player/index.cjs +1227 -0
  39. package/dist/music-player/index.cjs.map +7 -0
  40. package/dist/music-player/index.d.ts +12 -0
  41. package/dist/music-player/index.js +1204 -0
  42. package/dist/music-player/index.js.map +7 -0
  43. package/dist/music-player/vd3-music-player.css +829 -0
  44. package/dist/music-player/vue.d.ts +32 -0
  45. package/package.json +105 -0
@@ -0,0 +1,1805 @@
1
+ // src/charts/vue.js
2
+ import { defineComponent, h, ref, onMounted, onBeforeUnmount, watch } from "vue";
3
+
4
+ // src/charts/core.js
5
+ var SVG_NS = "http://www.w3.org/2000/svg";
6
+ var TAU = Math.PI * 2;
7
+ var ARC_EPSILON = 1e-4;
8
+ var DEFAULT_WIDTH = 640;
9
+ var DEFAULT_HEIGHT = 360;
10
+ var DEFAULT_MARGIN = { top: 28, right: 24, bottom: 46, left: 56 };
11
+ var POLAR_MARGIN = { top: 32, right: 24, bottom: 28, left: 24 };
12
+ var DEFAULT_COLORS = [
13
+ "#5c7cfa",
14
+ "#228be6",
15
+ "#40c057",
16
+ "#fab005",
17
+ "#fa5252",
18
+ "#12b886",
19
+ "#be4bdb",
20
+ "#fd7e14"
21
+ ];
22
+ var VD_CHARTS_VERSION = "1.0.0";
23
+ var chartId = 0;
24
+ function nextId(prefix) {
25
+ chartId += 1;
26
+ return `${prefix}-${chartId}`;
27
+ }
28
+ function hasWindow() {
29
+ return typeof window !== "undefined" && typeof document !== "undefined";
30
+ }
31
+ function isElement(value) {
32
+ return hasWindow() && value instanceof Element;
33
+ }
34
+ function resolveTarget(target) {
35
+ if (!hasWindow()) {
36
+ throw new Error("Vanduo Charts requires a browser DOM target.");
37
+ }
38
+ if (typeof target === "string") {
39
+ const el = document.querySelector(target);
40
+ if (!el) throw new Error(`Chart target not found: ${target}`);
41
+ return el;
42
+ }
43
+ if (isElement(target)) return target;
44
+ throw new Error("Chart target must be an Element or selector string.");
45
+ }
46
+ function svgEl(name, attrs = {}) {
47
+ const el = document.createElementNS(SVG_NS, name);
48
+ Object.entries(attrs).forEach(([key, value]) => {
49
+ if (value !== null && typeof value !== "undefined") {
50
+ el.setAttribute(key, String(value));
51
+ }
52
+ });
53
+ return el;
54
+ }
55
+ function append(parent, child) {
56
+ parent.appendChild(child);
57
+ return child;
58
+ }
59
+ function setText(parent, text) {
60
+ parent.textContent = text == null ? "" : String(text);
61
+ return parent;
62
+ }
63
+ function toArray(value) {
64
+ return Array.isArray(value) ? value : [];
65
+ }
66
+ function unique(values) {
67
+ const seen = /* @__PURE__ */ new Set();
68
+ const result = [];
69
+ values.forEach((value) => {
70
+ const key = String(value);
71
+ if (seen.has(key)) return;
72
+ seen.add(key);
73
+ result.push(value);
74
+ });
75
+ return result;
76
+ }
77
+ function isFiniteNumber(value) {
78
+ return typeof value === "number" && Number.isFinite(value);
79
+ }
80
+ function toNumber(value) {
81
+ if (value instanceof Date) return Number.isFinite(value.getTime()) ? value.getTime() : null;
82
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
83
+ if (typeof value === "string" && value.trim() !== "") {
84
+ const parsed = Number(value);
85
+ return Number.isFinite(parsed) ? parsed : null;
86
+ }
87
+ return null;
88
+ }
89
+ function toTime(value) {
90
+ if (value instanceof Date) return Number.isFinite(value.getTime()) ? value.getTime() : null;
91
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
92
+ if (typeof value === "string" && value.trim() !== "") {
93
+ const parsed = Date.parse(value);
94
+ return Number.isFinite(parsed) ? parsed : null;
95
+ }
96
+ return null;
97
+ }
98
+ function isDateLike(value) {
99
+ if (value instanceof Date) return Number.isFinite(value.getTime());
100
+ if (typeof value !== "string") return false;
101
+ const trimmed = value.trim();
102
+ if (!trimmed || /^-?\d+(\.\d+)?$/.test(trimmed)) return false;
103
+ return Number.isFinite(Date.parse(trimmed));
104
+ }
105
+ function readPathValue(source, path) {
106
+ if (source == null) return void 0;
107
+ if (!String(path).includes(".")) return source[path];
108
+ return String(path).split(".").reduce((value, key) => {
109
+ if (value == null) return void 0;
110
+ return value[key];
111
+ }, source);
112
+ }
113
+ function createAccessor(accessor, fallback) {
114
+ const resolved = accessor == null ? fallback : accessor;
115
+ if (typeof resolved === "function") return resolved;
116
+ if (typeof resolved === "string" && resolved.length) {
117
+ return (datum) => readPathValue(datum, resolved);
118
+ }
119
+ return (datum) => datum;
120
+ }
121
+ function normalizeMargin(value, fallback = DEFAULT_MARGIN) {
122
+ if (typeof value === "number") {
123
+ return { top: value, right: value, bottom: value, left: value };
124
+ }
125
+ return {
126
+ top: Number(value?.top ?? fallback.top),
127
+ right: Number(value?.right ?? fallback.right),
128
+ bottom: Number(value?.bottom ?? fallback.bottom),
129
+ left: Number(value?.left ?? fallback.left)
130
+ };
131
+ }
132
+ function measureTarget(target, options) {
133
+ const width = Number(options.width) || Math.round(target.clientWidth) || DEFAULT_WIDTH;
134
+ const height = Number(options.height) || Math.round(target.clientHeight) || DEFAULT_HEIGHT;
135
+ return {
136
+ width: Math.max(160, width),
137
+ height: Math.max(140, height)
138
+ };
139
+ }
140
+ function getPlotBox(width, height, margin) {
141
+ return {
142
+ left: margin.left,
143
+ top: margin.top,
144
+ right: Math.max(margin.left + 1, width - margin.right),
145
+ bottom: Math.max(margin.top + 1, height - margin.bottom)
146
+ };
147
+ }
148
+ function readToken(style, names, fallback) {
149
+ for (const name of names) {
150
+ const value = style.getPropertyValue(name).trim();
151
+ if (value) return value;
152
+ }
153
+ return fallback;
154
+ }
155
+ function resolveTheme(target, overrides = {}) {
156
+ if (!hasWindow()) {
157
+ return {
158
+ fontFamily: "inherit",
159
+ textColor: "#1a1d20",
160
+ mutedTextColor: "#868e96",
161
+ gridColor: "#e9ecef",
162
+ axisColor: "#ced4da",
163
+ backgroundColor: "#ffffff",
164
+ colors: DEFAULT_COLORS.slice(),
165
+ ...overrides
166
+ };
167
+ }
168
+ const styleTarget = isElement(target) ? target : document.documentElement;
169
+ const style = getComputedStyle(styleTarget);
170
+ const rootStyle = getComputedStyle(document.documentElement);
171
+ const tokenStyle = {
172
+ getPropertyValue(name) {
173
+ return style.getPropertyValue(name) || rootStyle.getPropertyValue(name);
174
+ }
175
+ };
176
+ const colors = DEFAULT_COLORS.map(
177
+ (fallback, index) => readToken(
178
+ tokenStyle,
179
+ [
180
+ `--vd-chart-${index + 1}`,
181
+ index === 0 ? "--vd-color-primary" : "",
182
+ index === 1 ? "--vd-color-info" : "",
183
+ index === 2 ? "--vd-color-success" : "",
184
+ index === 3 ? "--vd-color-warning" : "",
185
+ index === 4 ? "--vd-color-error" : "",
186
+ index === 0 ? "--color-primary" : "",
187
+ index === 1 ? "--color-info" : "",
188
+ index === 2 ? "--color-success" : ""
189
+ ].filter(Boolean),
190
+ fallback
191
+ )
192
+ );
193
+ return {
194
+ fontFamily: readToken(tokenStyle, ["--vd-font-family-base"], "inherit"),
195
+ textColor: readToken(tokenStyle, ["--vd-text-primary", "--text-primary"], "#1a1d20"),
196
+ mutedTextColor: readToken(tokenStyle, ["--vd-text-muted", "--text-muted"], "#868e96"),
197
+ gridColor: readToken(
198
+ tokenStyle,
199
+ ["--vd-border-color-light", "--border-color-light", "--vd-border-color"],
200
+ "#e9ecef"
201
+ ),
202
+ axisColor: readToken(tokenStyle, ["--vd-border-color", "--border-color"], "#ced4da"),
203
+ backgroundColor: readToken(tokenStyle, ["--vd-bg-primary", "--bg-primary"], "#ffffff"),
204
+ ...overrides,
205
+ colors: overrides.colors || colors
206
+ };
207
+ }
208
+ function tickStep(min, max, count) {
209
+ const span = Math.abs(max - min);
210
+ if (!span || !Number.isFinite(span)) return 1;
211
+ const raw = span / Math.max(1, count);
212
+ const power = Math.pow(10, Math.floor(Math.log10(raw)));
213
+ const error = raw / power;
214
+ const factor = error >= 7.5 ? 10 : error >= 3.5 ? 5 : error >= 1.5 ? 2 : 1;
215
+ return factor * power;
216
+ }
217
+ function ticks(min, max, count = 5) {
218
+ if (!Number.isFinite(min) || !Number.isFinite(max)) return [];
219
+ if (min === max) return [min];
220
+ const reverse = max < min;
221
+ const start = reverse ? max : min;
222
+ const stop = reverse ? min : max;
223
+ const step = tickStep(start, stop, count);
224
+ const first = Math.ceil(start / step) * step;
225
+ const values = [];
226
+ for (let value = first; value <= stop + step / 2; value += step) {
227
+ values.push(Number(value.toFixed(12)));
228
+ }
229
+ return reverse ? values.reverse() : values;
230
+ }
231
+ function niceDomain(values, options = false) {
232
+ const opts = typeof options === "boolean" ? { includeZero: options } : options || {};
233
+ const nums = values.map(toNumber).filter(isFiniteNumber);
234
+ if (!nums.length) {
235
+ return [isFiniteNumber(opts.min) ? opts.min : 0, isFiniteNumber(opts.max) ? opts.max : 1];
236
+ }
237
+ let min = Math.min(...nums);
238
+ let max = Math.max(...nums);
239
+ if (opts.includeZero) {
240
+ min = Math.min(0, min);
241
+ max = Math.max(0, max);
242
+ }
243
+ if (isFiniteNumber(opts.min)) min = opts.min;
244
+ if (isFiniteNumber(opts.max)) max = opts.max;
245
+ if (min === max) {
246
+ const pad = Math.abs(min || 1) * 0.1;
247
+ min -= pad;
248
+ max += pad;
249
+ }
250
+ const step = tickStep(min, max, opts.tickCount || 5);
251
+ return [
252
+ isFiniteNumber(opts.min) ? opts.min : Math.floor(min / step) * step,
253
+ isFiniteNumber(opts.max) ? opts.max : Math.ceil(max / step) * step
254
+ ];
255
+ }
256
+ function scaleLinear(config = {}) {
257
+ const domain = config.domain || [0, 1];
258
+ const range = config.range || [0, 1];
259
+ let d0 = Number(domain[0]);
260
+ let d1 = Number(domain[1]);
261
+ const r0 = Number(range[0]);
262
+ const r1 = Number(range[1]);
263
+ if (!Number.isFinite(d0)) d0 = 0;
264
+ if (!Number.isFinite(d1)) d1 = 1;
265
+ if (d0 === d1) {
266
+ d0 -= 0.5;
267
+ d1 += 0.5;
268
+ }
269
+ const scale = (value) => {
270
+ const n = Number(value);
271
+ if (!Number.isFinite(n)) return null;
272
+ return r0 + (n - d0) / (d1 - d0) * (r1 - r0);
273
+ };
274
+ scale.domain = () => [d0, d1];
275
+ scale.range = () => [r0, r1];
276
+ scale.ticks = (count = 5) => ticks(d0, d1, count);
277
+ return scale;
278
+ }
279
+ function scaleTime(config = {}) {
280
+ const domain = (config.domain || [/* @__PURE__ */ new Date(0), /* @__PURE__ */ new Date(1)]).map(toTime);
281
+ const linear = scaleLinear({
282
+ domain: [domain[0] ?? 0, domain[1] ?? 1],
283
+ range: config.range || [0, 1]
284
+ });
285
+ const scale = (value) => linear(toTime(value));
286
+ scale.domain = () => linear.domain().map((value) => new Date(value));
287
+ scale.range = linear.range;
288
+ scale.ticks = (count = 5) => linear.ticks(count).map((value) => new Date(value));
289
+ return scale;
290
+ }
291
+ function scaleBand(config = {}) {
292
+ const domain = unique(config.domain || []).map(String);
293
+ const range = config.range || [0, 1];
294
+ const paddingInner = Number(config.paddingInner ?? config.padding ?? 0.16);
295
+ const paddingOuter = Number(config.paddingOuter ?? config.padding ?? 0.16);
296
+ const r0 = Number(range[0]);
297
+ const r1 = Number(range[1]);
298
+ const span = r1 - r0;
299
+ const denominator = Math.max(1, domain.length - paddingInner + paddingOuter * 2);
300
+ const step = span / denominator;
301
+ const bandwidth = Math.abs(step * Math.max(0, 1 - paddingInner));
302
+ const scale = (value) => {
303
+ const index = domain.indexOf(String(value));
304
+ if (index < 0) return null;
305
+ return r0 + (paddingOuter + index) * step;
306
+ };
307
+ scale.domain = () => domain.slice();
308
+ scale.range = () => [r0, r1];
309
+ scale.bandwidth = () => bandwidth;
310
+ scale.step = () => Math.abs(step);
311
+ return scale;
312
+ }
313
+ function scalePoint(config = {}) {
314
+ const domain = unique(config.domain || []).map(String);
315
+ const range = config.range || [0, 1];
316
+ const padding = Number(config.padding ?? 0.5);
317
+ const r0 = Number(range[0]);
318
+ const r1 = Number(range[1]);
319
+ const span = r1 - r0;
320
+ const step = domain.length <= 1 ? 0 : span / Math.max(1, domain.length - 1 + padding * 2);
321
+ const start = domain.length <= 1 ? r0 + span / 2 : r0 + padding * step;
322
+ const scale = (value) => {
323
+ const index = domain.indexOf(String(value));
324
+ if (index < 0) return null;
325
+ return start + index * step;
326
+ };
327
+ scale.domain = () => domain.slice();
328
+ scale.range = () => [r0, r1];
329
+ scale.step = () => Math.abs(step);
330
+ scale.bandwidth = () => 0;
331
+ return scale;
332
+ }
333
+ function scaleOrdinal(config = {}) {
334
+ const domain = unique(config.domain || []).map(String);
335
+ const range = config.range || DEFAULT_COLORS;
336
+ const scale = (value) => {
337
+ const key = String(value);
338
+ let index = domain.indexOf(key);
339
+ if (index < 0) {
340
+ domain.push(key);
341
+ index = domain.length - 1;
342
+ }
343
+ return range[index % range.length];
344
+ };
345
+ scale.domain = () => domain.slice();
346
+ scale.range = () => range.slice();
347
+ return scale;
348
+ }
349
+ function linePath(points) {
350
+ const clean = points.filter((point) => isFiniteNumber(point.x) && isFiniteNumber(point.y));
351
+ if (!clean.length) return "";
352
+ return clean.map((point, index) => `${index === 0 ? "M" : "L"}${point.x},${point.y}`).join(" ");
353
+ }
354
+ function areaPath(points, baselineY) {
355
+ const clean = points.filter((point) => isFiniteNumber(point.x) && isFiniteNumber(point.y));
356
+ if (!clean.length || !isFiniteNumber(baselineY)) return "";
357
+ const line = linePath(clean);
358
+ const last = clean[clean.length - 1];
359
+ const first = clean[0];
360
+ return `${line} L${last.x},${baselineY} L${first.x},${baselineY} Z`;
361
+ }
362
+ function polarPoint(cx, cy, radius, angle) {
363
+ return {
364
+ x: cx + radius * Math.cos(angle),
365
+ y: cy + radius * Math.sin(angle)
366
+ };
367
+ }
368
+ function arcPath(cx, cy, outerRadius, innerRadius, startAngle, endAngle) {
369
+ if (!isFiniteNumber(outerRadius) || outerRadius <= 0 || endAngle <= startAngle) return "";
370
+ const safeEnd = endAngle - startAngle >= TAU ? startAngle + TAU - ARC_EPSILON : endAngle;
371
+ const largeArc = safeEnd - startAngle > Math.PI ? 1 : 0;
372
+ const outerStart = polarPoint(cx, cy, outerRadius, startAngle);
373
+ const outerEnd = polarPoint(cx, cy, outerRadius, safeEnd);
374
+ const inner = Math.max(0, Number(innerRadius) || 0);
375
+ if (inner <= 0) {
376
+ return [
377
+ `M${cx},${cy}`,
378
+ `L${outerStart.x},${outerStart.y}`,
379
+ `A${outerRadius},${outerRadius} 0 ${largeArc} 1 ${outerEnd.x},${outerEnd.y}`,
380
+ "Z"
381
+ ].join(" ");
382
+ }
383
+ const innerEnd = polarPoint(cx, cy, inner, safeEnd);
384
+ const innerStart = polarPoint(cx, cy, inner, startAngle);
385
+ return [
386
+ `M${outerStart.x},${outerStart.y}`,
387
+ `A${outerRadius},${outerRadius} 0 ${largeArc} 1 ${outerEnd.x},${outerEnd.y}`,
388
+ `L${innerEnd.x},${innerEnd.y}`,
389
+ `A${inner},${inner} 0 ${largeArc} 0 ${innerStart.x},${innerStart.y}`,
390
+ "Z"
391
+ ].join(" ");
392
+ }
393
+ function formatNumber(value) {
394
+ if (!Number.isFinite(value)) return "";
395
+ return Math.abs(value) >= 1e3 ? value.toLocaleString() : String(Number(value.toFixed(3)));
396
+ }
397
+ function formatTick(value, formatter) {
398
+ if (typeof formatter === "function") return formatter(value);
399
+ if (value instanceof Date) {
400
+ return new Intl.DateTimeFormat(void 0, { month: "short", day: "numeric" }).format(value);
401
+ }
402
+ return formatNumber(Number(value));
403
+ }
404
+ function formatCategory(value) {
405
+ return value == null ? "" : String(value);
406
+ }
407
+ function attachTooltip(instance, mark, options, context, fallback) {
408
+ const tooltip = options.tooltip;
409
+ if (tooltip === false) return;
410
+ const getContent = () => {
411
+ if (typeof tooltip === "function") {
412
+ const result = tooltip(context.datum, context);
413
+ return result === false ? null : result;
414
+ }
415
+ if (typeof tooltip === "string") return tooltip;
416
+ return fallback;
417
+ };
418
+ const show = (event) => {
419
+ const content = getContent();
420
+ if (content == null || content === "") return;
421
+ instance.showTooltip(content, event);
422
+ };
423
+ const hide = () => instance.hideTooltip();
424
+ mark.addEventListener("pointerenter", show);
425
+ mark.addEventListener("pointermove", show);
426
+ mark.addEventListener("pointerleave", hide);
427
+ mark.addEventListener("focus", show);
428
+ mark.addEventListener("blur", hide);
429
+ }
430
+ function attachClick(mark, callback, datum, index) {
431
+ if (typeof callback !== "function") return;
432
+ const fire = (event) => callback({ event, datum, index });
433
+ mark.addEventListener("click", fire);
434
+ mark.addEventListener("keydown", (event) => {
435
+ if (event.key === "Enter" || event.key === " ") {
436
+ event.preventDefault();
437
+ fire(event);
438
+ }
439
+ });
440
+ }
441
+ function makeInteractive(mark, hasClick, hasTooltip) {
442
+ if (hasClick || hasTooltip) {
443
+ mark.setAttribute("tabindex", "0");
444
+ mark.setAttribute("focusable", "true");
445
+ }
446
+ }
447
+ function createSvgShell(instance) {
448
+ const { target, options } = instance;
449
+ const size = measureTarget(target, options);
450
+ const theme = resolveTheme(target, options.theme);
451
+ const margin = normalizeMargin(options.margin, options.polar ? POLAR_MARGIN : DEFAULT_MARGIN);
452
+ const plot = getPlotBox(size.width, size.height, margin);
453
+ target.innerHTML = "";
454
+ target.classList.add("vd-chart-root", `vd-chart-${instance.kind}`);
455
+ if (getComputedStyle(target).position === "static") {
456
+ target.style.position = "relative";
457
+ }
458
+ const svg = svgEl("svg", {
459
+ class: "vd-chart-svg",
460
+ width: size.width,
461
+ height: size.height,
462
+ viewBox: `0 0 ${size.width} ${size.height}`,
463
+ role: "img"
464
+ });
465
+ const titleId = nextId("vd-chart-title");
466
+ const descId = nextId("vd-chart-desc");
467
+ const labelledBy = [];
468
+ if (options.title) {
469
+ labelledBy.push(titleId);
470
+ append(svg, setText(svgEl("title", { id: titleId }), options.title));
471
+ }
472
+ if (options.description) {
473
+ labelledBy.push(descId);
474
+ append(svg, setText(svgEl("desc", { id: descId }), options.description));
475
+ }
476
+ if (labelledBy.length) {
477
+ svg.setAttribute("aria-labelledby", labelledBy.join(" "));
478
+ } else {
479
+ svg.setAttribute("aria-label", options.ariaLabel || `${instance.kind} chart`);
480
+ }
481
+ if (options.title) {
482
+ append(
483
+ svg,
484
+ setText(
485
+ svgEl("text", {
486
+ x: margin.left,
487
+ y: 18,
488
+ fill: theme.textColor,
489
+ "font-size": 14,
490
+ "font-weight": 600
491
+ }),
492
+ options.title
493
+ )
494
+ );
495
+ }
496
+ target.appendChild(svg);
497
+ instance.theme = theme;
498
+ instance.size = size;
499
+ instance.plot = plot;
500
+ instance.tooltipEl = null;
501
+ return { svg, size, theme, plot, margin };
502
+ }
503
+ function renderEmpty(svg, size, theme, message = "No data") {
504
+ append(
505
+ svg,
506
+ setText(
507
+ svgEl("text", {
508
+ class: "vd-chart-empty",
509
+ x: size.width / 2,
510
+ y: size.height / 2,
511
+ fill: theme.mutedTextColor,
512
+ "text-anchor": "middle"
513
+ }),
514
+ message
515
+ )
516
+ );
517
+ }
518
+ function drawAxisLine(svg, x1, y1, x2, y2, theme) {
519
+ append(
520
+ svg,
521
+ svgEl("line", {
522
+ x1,
523
+ y1,
524
+ x2,
525
+ y2,
526
+ stroke: theme.axisColor,
527
+ "stroke-width": 1,
528
+ "shape-rendering": "crispEdges"
529
+ })
530
+ );
531
+ }
532
+ function drawCartesianAxes(svg, config) {
533
+ const { plot, xScale, yScale, xTicks, yTicks, theme, options, categoricalX } = config;
534
+ const axisGroup = append(svg, svgEl("g", { class: "vd-chart-axes" }));
535
+ yTicks.forEach((tick) => {
536
+ const y = yScale(tick);
537
+ if (!isFiniteNumber(y)) return;
538
+ append(
539
+ axisGroup,
540
+ svgEl("line", {
541
+ x1: plot.left,
542
+ y1: y,
543
+ x2: plot.right,
544
+ y2: y,
545
+ stroke: theme.gridColor,
546
+ "stroke-width": 1,
547
+ "shape-rendering": "crispEdges"
548
+ })
549
+ );
550
+ append(
551
+ axisGroup,
552
+ setText(
553
+ svgEl("text", {
554
+ x: plot.left - 10,
555
+ y: y + 4,
556
+ fill: theme.mutedTextColor,
557
+ "font-size": 11,
558
+ "text-anchor": "end"
559
+ }),
560
+ formatTick(tick, options.yFormat)
561
+ )
562
+ );
563
+ });
564
+ drawAxisLine(axisGroup, plot.left, plot.bottom, plot.right, plot.bottom, theme);
565
+ drawAxisLine(axisGroup, plot.left, plot.top, plot.left, plot.bottom, theme);
566
+ xTicks.forEach((tick) => {
567
+ let x = xScale(tick);
568
+ if (categoricalX && typeof xScale.bandwidth === "function") {
569
+ x += xScale.bandwidth() / 2;
570
+ }
571
+ if (!isFiniteNumber(x)) return;
572
+ append(
573
+ axisGroup,
574
+ svgEl("line", {
575
+ x1: x,
576
+ y1: plot.bottom,
577
+ x2: x,
578
+ y2: plot.bottom + 5,
579
+ stroke: theme.axisColor,
580
+ "stroke-width": 1
581
+ })
582
+ );
583
+ append(
584
+ axisGroup,
585
+ setText(
586
+ svgEl("text", {
587
+ x,
588
+ y: plot.bottom + 20,
589
+ fill: theme.mutedTextColor,
590
+ "font-size": 11,
591
+ "text-anchor": "middle"
592
+ }),
593
+ categoricalX ? formatCategory(tick) : formatTick(tick, options.xFormat)
594
+ )
595
+ );
596
+ });
597
+ if (options.xAxis?.label) {
598
+ append(
599
+ axisGroup,
600
+ setText(
601
+ svgEl("text", {
602
+ x: (plot.left + plot.right) / 2,
603
+ y: plot.bottom + 40,
604
+ fill: theme.mutedTextColor,
605
+ "font-size": 12,
606
+ "text-anchor": "middle"
607
+ }),
608
+ options.xAxis.label
609
+ )
610
+ );
611
+ }
612
+ if (options.yAxis?.label) {
613
+ append(
614
+ axisGroup,
615
+ setText(
616
+ svgEl("text", {
617
+ x: -((plot.top + plot.bottom) / 2),
618
+ y: 15,
619
+ fill: theme.mutedTextColor,
620
+ "font-size": 12,
621
+ "text-anchor": "middle",
622
+ transform: "rotate(-90)"
623
+ }),
624
+ options.yAxis.label
625
+ )
626
+ );
627
+ }
628
+ }
629
+ function inferXScale(rows, plot, options) {
630
+ const values = rows.map((row) => row.x);
631
+ const explicitType = options.xScale;
632
+ const allNumeric = values.every((value) => toNumber(value) !== null);
633
+ const allDates = values.every(isDateLike);
634
+ if (explicitType === "time" || !explicitType && allDates) {
635
+ const times = values.map(toTime).filter(isFiniteNumber);
636
+ return {
637
+ scale: scaleTime({ domain: niceDomain(times), range: [plot.left, plot.right] }),
638
+ values: times,
639
+ ticks: scaleLinear({ domain: niceDomain(times), range: [plot.left, plot.right] }).ticks(5).map((value) => new Date(value)),
640
+ type: "time",
641
+ mapValue: toTime
642
+ };
643
+ }
644
+ if (explicitType === "linear" || !explicitType && allNumeric) {
645
+ const nums = values.map(toNumber).filter(isFiniteNumber);
646
+ const domain2 = niceDomain(nums, { min: options.xMin, max: options.xMax });
647
+ const scale = scaleLinear({ domain: domain2, range: [plot.left, plot.right] });
648
+ return {
649
+ scale,
650
+ values: nums,
651
+ ticks: scale.ticks(5),
652
+ type: "linear",
653
+ mapValue: toNumber
654
+ };
655
+ }
656
+ const domain = unique(values).map(String);
657
+ return {
658
+ scale: scalePoint({ domain, range: [plot.left, plot.right], padding: 0.5 }),
659
+ values: domain,
660
+ ticks: domain,
661
+ type: "point",
662
+ mapValue: (value) => String(value)
663
+ };
664
+ }
665
+ function getColorScale(rows, colorOption, theme) {
666
+ if (colorOption == null) return null;
667
+ if (typeof colorOption === "function") {
668
+ return { direct: colorOption };
669
+ }
670
+ const colorAccessor = createAccessor(colorOption);
671
+ const domain = unique(rows.map((row) => colorAccessor(row.raw))).map(String);
672
+ return {
673
+ accessor: colorAccessor,
674
+ scale: scaleOrdinal({ domain, range: theme.colors })
675
+ };
676
+ }
677
+ function colorForRow(color, row, theme) {
678
+ if (color) {
679
+ if (typeof color.direct === "function") return color.direct(row.raw);
680
+ if (color.scale) return color.scale(color.accessor(row.raw));
681
+ }
682
+ return theme.colors[row.index % theme.colors.length];
683
+ }
684
+ function buildSeriesList(options) {
685
+ const xAccessor = createAccessor(options.x, "x");
686
+ const sharedData = toArray(options.data);
687
+ const buildRows = (data, yAccessor) => data.map((datum, index) => ({
688
+ raw: datum,
689
+ index,
690
+ x: xAccessor(datum),
691
+ y: toNumber(yAccessor(datum))
692
+ })).filter((row) => row.x != null && isFiniteNumber(row.y));
693
+ if (Array.isArray(options.series) && options.series.length) {
694
+ return options.series.map((series, seriesIndex) => {
695
+ const data = Array.isArray(series.data) && series.data.length ? series.data : sharedData;
696
+ const yAccessor = createAccessor(series.y ?? options.y, "y");
697
+ return {
698
+ name: series.name ?? `Series ${seriesIndex + 1}`,
699
+ color: series.color,
700
+ seriesIndex,
701
+ rows: buildRows(data, yAccessor)
702
+ };
703
+ });
704
+ }
705
+ return [
706
+ {
707
+ name: options.name ?? null,
708
+ color: options.stroke,
709
+ seriesIndex: 0,
710
+ rows: buildRows(sharedData, createAccessor(options.y, "y"))
711
+ }
712
+ ];
713
+ }
714
+ function seriesColor(series, theme) {
715
+ return series.color || theme.colors[series.seriesIndex % theme.colors.length];
716
+ }
717
+ function renderTopLegend(svg, items, theme, plot) {
718
+ if (!items.length) return;
719
+ const shown = items.slice(0, 8);
720
+ const widths = shown.map((item) => 14 + String(item.label).length * 6.5 + 14);
721
+ const total = widths.reduce((sum, w) => sum + w, 0);
722
+ let x = Math.max(plot.left, plot.right - total);
723
+ const y = 14;
724
+ const legend = append(svg, svgEl("g", { class: "vd-chart-legend" }));
725
+ shown.forEach((item, index) => {
726
+ append(
727
+ legend,
728
+ svgEl("rect", {
729
+ x,
730
+ y: y - 8,
731
+ width: 10,
732
+ height: 10,
733
+ rx: 2,
734
+ fill: item.color
735
+ })
736
+ );
737
+ append(
738
+ legend,
739
+ setText(
740
+ svgEl("text", {
741
+ x: x + 14,
742
+ y,
743
+ fill: theme.mutedTextColor,
744
+ "font-size": 11
745
+ }),
746
+ formatCategory(item.label)
747
+ )
748
+ );
749
+ x += widths[index];
750
+ });
751
+ }
752
+ function dataLabelConfig(options) {
753
+ const dl = options.dataLabels;
754
+ if (!dl) return null;
755
+ return typeof dl === "object" ? dl : {};
756
+ }
757
+ function drawDataLabel(svg, x, y, value, cfg, theme, anchor = "middle") {
758
+ if (!isFiniteNumber(x) || !isFiniteNumber(y)) return;
759
+ append(
760
+ svg,
761
+ setText(
762
+ svgEl("text", {
763
+ class: "vd-chart-data-label",
764
+ x,
765
+ y,
766
+ fill: cfg.color || theme.textColor,
767
+ "font-size": 10,
768
+ "text-anchor": anchor
769
+ }),
770
+ typeof cfg.format === "function" ? cfg.format(value) : formatNumber(value)
771
+ )
772
+ );
773
+ }
774
+ function drawAnnotations(svg, options, plot, xScale, yScale, theme) {
775
+ const annotations = toArray(options.annotations);
776
+ if (!annotations.length) return;
777
+ const group = append(svg, svgEl("g", { class: "vd-chart-annotations" }));
778
+ annotations.forEach((ann) => {
779
+ const color = ann.color || theme.mutedTextColor;
780
+ const dash = ann.dash === false ? null : "4 3";
781
+ if (isFiniteNumber(ann.y) && yScale) {
782
+ const y = yScale(ann.y);
783
+ if (!isFiniteNumber(y)) return;
784
+ append(
785
+ group,
786
+ svgEl("line", {
787
+ class: "vd-chart-annotation-line",
788
+ x1: plot.left,
789
+ y1: y,
790
+ x2: plot.right,
791
+ y2: y,
792
+ stroke: color,
793
+ "stroke-width": 1,
794
+ "stroke-dasharray": dash
795
+ })
796
+ );
797
+ if (ann.label) {
798
+ append(
799
+ group,
800
+ setText(
801
+ svgEl("text", {
802
+ x: plot.right - 4,
803
+ y: y - 4,
804
+ fill: color,
805
+ "font-size": 10,
806
+ "text-anchor": "end"
807
+ }),
808
+ ann.label
809
+ )
810
+ );
811
+ }
812
+ }
813
+ if (ann.x != null && xScale) {
814
+ let x = xScale(ann.x);
815
+ if (typeof xScale.bandwidth === "function" && isFiniteNumber(x)) {
816
+ x += xScale.bandwidth() / 2;
817
+ }
818
+ if (!isFiniteNumber(x)) return;
819
+ append(
820
+ group,
821
+ svgEl("line", {
822
+ class: "vd-chart-annotation-line",
823
+ x1: x,
824
+ y1: plot.top,
825
+ x2: x,
826
+ y2: plot.bottom,
827
+ stroke: color,
828
+ "stroke-width": 1,
829
+ "stroke-dasharray": dash
830
+ })
831
+ );
832
+ if (ann.label) {
833
+ append(
834
+ group,
835
+ setText(
836
+ svgEl("text", {
837
+ x: x + 4,
838
+ y: plot.top + 10,
839
+ fill: color,
840
+ "font-size": 10
841
+ }),
842
+ ann.label
843
+ )
844
+ );
845
+ }
846
+ }
847
+ });
848
+ }
849
+ function renderBarChart(instance) {
850
+ if (instance.options.series?.length) return renderMultiBarChart(instance);
851
+ const shell = createSvgShell(instance);
852
+ const { svg, size, theme, plot } = shell;
853
+ const options = instance.options;
854
+ const data = toArray(options.data);
855
+ const xAccessor = createAccessor(options.x, "x");
856
+ const yAccessor = createAccessor(options.y, "y");
857
+ const rows = data.map((datum, index) => ({
858
+ raw: datum,
859
+ index,
860
+ x: xAccessor(datum),
861
+ y: toNumber(yAccessor(datum))
862
+ })).filter((row) => row.x != null && isFiniteNumber(row.y));
863
+ if (!rows.length) {
864
+ renderEmpty(svg, size, theme);
865
+ return;
866
+ }
867
+ const categories = unique(rows.map((row) => row.x)).map(String);
868
+ const xScale = scaleBand({
869
+ domain: categories,
870
+ range: [plot.left, plot.right],
871
+ padding: options.barPadding ?? 0.18
872
+ });
873
+ const yDomain = niceDomain(
874
+ rows.map((row) => row.y),
875
+ {
876
+ includeZero: true,
877
+ min: options.yMin,
878
+ max: options.yMax,
879
+ tickCount: options.yTickCount
880
+ }
881
+ );
882
+ const yScale = scaleLinear({ domain: yDomain, range: [plot.bottom, plot.top] });
883
+ const yTicks = yScale.ticks(options.yTickCount ?? 5);
884
+ const color = getColorScale(rows, options.color, theme);
885
+ drawCartesianAxes(svg, {
886
+ plot,
887
+ xScale,
888
+ yScale,
889
+ xTicks: categories,
890
+ yTicks,
891
+ theme,
892
+ options,
893
+ categoricalX: true
894
+ });
895
+ drawAnnotations(svg, options, plot, xScale, yScale, theme);
896
+ const labels = dataLabelConfig(options);
897
+ const markGroup = append(svg, svgEl("g", { class: "vd-chart-marks vd-chart-bars" }));
898
+ const baseline = yScale(0);
899
+ rows.forEach((row) => {
900
+ const x = xScale(row.x);
901
+ const y = yScale(row.y);
902
+ if (!isFiniteNumber(x) || !isFiniteNumber(y) || !isFiniteNumber(baseline)) return;
903
+ const rectY = Math.min(y, baseline);
904
+ const rectHeight = Math.max(1, Math.abs(baseline - y));
905
+ const fill = colorForRow(color, row, theme);
906
+ const rect = svgEl("rect", {
907
+ class: "vd-chart-bar",
908
+ x,
909
+ y: rectY,
910
+ width: xScale.bandwidth(),
911
+ height: rectHeight,
912
+ rx: 3,
913
+ fill,
914
+ role: "graphics-symbol",
915
+ "aria-label": `${formatCategory(row.x)}: ${formatNumber(row.y)}`
916
+ });
917
+ makeInteractive(rect, typeof options.onBarClick === "function", options.tooltip !== false);
918
+ attachTooltip(
919
+ instance,
920
+ rect,
921
+ options,
922
+ {
923
+ datum: row.raw,
924
+ x: row.x,
925
+ y: row.y,
926
+ value: row.y,
927
+ label: row.x,
928
+ index: row.index
929
+ },
930
+ `${formatCategory(row.x)}: ${formatNumber(row.y)}`
931
+ );
932
+ attachClick(rect, options.onBarClick, row.raw, row.index);
933
+ if (labels) drawDataLabel(svg, x + xScale.bandwidth() / 2, rectY - 4, row.y, labels, theme);
934
+ append(markGroup, rect);
935
+ });
936
+ if (options.legend && color && color.scale) {
937
+ renderTopLegend(
938
+ svg,
939
+ color.scale.domain().map((cat) => ({ label: cat, color: color.scale(cat) })),
940
+ theme,
941
+ plot
942
+ );
943
+ }
944
+ }
945
+ function renderMultiBarChart(instance) {
946
+ const shell = createSvgShell(instance);
947
+ const { svg, size, theme, plot } = shell;
948
+ const options = instance.options;
949
+ const seriesList = buildSeriesList(options);
950
+ const allRows = seriesList.flatMap((series) => series.rows);
951
+ if (!allRows.length) {
952
+ renderEmpty(svg, size, theme);
953
+ return;
954
+ }
955
+ const categories = unique(allRows.map((row) => String(row.x)));
956
+ const xScale = scaleBand({
957
+ domain: categories,
958
+ range: [plot.left, plot.right],
959
+ padding: options.barPadding ?? 0.18
960
+ });
961
+ const innerScale = scaleBand({
962
+ domain: seriesList.map((series) => series.name),
963
+ range: [0, xScale.bandwidth()],
964
+ padding: 0.08
965
+ });
966
+ const yDomain = niceDomain(
967
+ allRows.map((row) => row.y),
968
+ {
969
+ includeZero: true,
970
+ min: options.yMin,
971
+ max: options.yMax,
972
+ tickCount: options.yTickCount
973
+ }
974
+ );
975
+ const yScale = scaleLinear({ domain: yDomain, range: [plot.bottom, plot.top] });
976
+ const yTicks = yScale.ticks(options.yTickCount ?? 5);
977
+ drawCartesianAxes(svg, {
978
+ plot,
979
+ xScale,
980
+ yScale,
981
+ xTicks: categories,
982
+ yTicks,
983
+ theme,
984
+ options,
985
+ categoricalX: true
986
+ });
987
+ drawAnnotations(svg, options, plot, xScale, yScale, theme);
988
+ const labels = dataLabelConfig(options);
989
+ const markGroup = append(svg, svgEl("g", { class: "vd-chart-marks vd-chart-bars" }));
990
+ const baseline = yScale(0);
991
+ seriesList.forEach((series) => {
992
+ const fill = seriesColor(series, theme);
993
+ series.rows.forEach((row) => {
994
+ const groupX = xScale(String(row.x));
995
+ const offset = innerScale(series.name);
996
+ const y = yScale(row.y);
997
+ if (![groupX, offset, y, baseline].every(isFiniteNumber)) return;
998
+ const rectY = Math.min(y, baseline);
999
+ const rectHeight = Math.max(1, Math.abs(baseline - y));
1000
+ const rect = svgEl("rect", {
1001
+ class: "vd-chart-bar",
1002
+ x: groupX + offset,
1003
+ y: rectY,
1004
+ width: innerScale.bandwidth(),
1005
+ height: rectHeight,
1006
+ rx: 3,
1007
+ fill,
1008
+ role: "graphics-symbol",
1009
+ "aria-label": `${series.name} \u2014 ${formatCategory(row.x)}: ${formatNumber(row.y)}`
1010
+ });
1011
+ makeInteractive(rect, typeof options.onBarClick === "function", options.tooltip !== false);
1012
+ attachTooltip(
1013
+ instance,
1014
+ rect,
1015
+ options,
1016
+ {
1017
+ datum: row.raw,
1018
+ x: row.x,
1019
+ y: row.y,
1020
+ value: row.y,
1021
+ label: row.x,
1022
+ index: row.index,
1023
+ seriesIndex: series.seriesIndex,
1024
+ seriesName: series.name
1025
+ },
1026
+ `${series.name} \u2014 ${formatCategory(row.x)}: ${formatNumber(row.y)}`
1027
+ );
1028
+ attachClick(rect, options.onBarClick, row.raw, row.index);
1029
+ if (labels)
1030
+ drawDataLabel(
1031
+ svg,
1032
+ groupX + offset + innerScale.bandwidth() / 2,
1033
+ rectY - 4,
1034
+ row.y,
1035
+ labels,
1036
+ theme
1037
+ );
1038
+ append(markGroup, rect);
1039
+ });
1040
+ });
1041
+ if (options.legend !== false) {
1042
+ renderTopLegend(
1043
+ svg,
1044
+ seriesList.map((series) => ({ label: series.name, color: seriesColor(series, theme) })),
1045
+ theme,
1046
+ plot
1047
+ );
1048
+ }
1049
+ }
1050
+ function renderLineLikeChart(instance, mode) {
1051
+ if (instance.options.series?.length) return renderMultiLineChart(instance, mode);
1052
+ const shell = createSvgShell(instance);
1053
+ const { svg, size, theme, plot } = shell;
1054
+ const options = instance.options;
1055
+ const data = toArray(options.data);
1056
+ const xAccessor = createAccessor(options.x, "x");
1057
+ const yAccessor = createAccessor(options.y, "y");
1058
+ const rows = data.map((datum, index) => ({
1059
+ raw: datum,
1060
+ index,
1061
+ x: xAccessor(datum),
1062
+ y: toNumber(yAccessor(datum))
1063
+ })).filter((row) => row.x != null && isFiniteNumber(row.y));
1064
+ if (!rows.length) {
1065
+ renderEmpty(svg, size, theme);
1066
+ return;
1067
+ }
1068
+ const xInfo = inferXScale(rows, plot, options);
1069
+ const yDomain = niceDomain(
1070
+ rows.map((row) => row.y),
1071
+ {
1072
+ includeZero: mode === "area" || options.yIncludeZero === true,
1073
+ min: options.yMin,
1074
+ max: options.yMax,
1075
+ tickCount: options.yTickCount
1076
+ }
1077
+ );
1078
+ const yScale = scaleLinear({ domain: yDomain, range: [plot.bottom, plot.top] });
1079
+ const yTicks = yScale.ticks(options.yTickCount ?? 5);
1080
+ const color = options.stroke || theme.colors[0];
1081
+ const points = rows.map((row) => ({
1082
+ raw: row.raw,
1083
+ index: row.index,
1084
+ xValue: row.x,
1085
+ yValue: row.y,
1086
+ x: xInfo.scale(xInfo.mapValue(row.x)),
1087
+ y: yScale(row.y)
1088
+ })).filter((point) => isFiniteNumber(point.x) && isFiniteNumber(point.y));
1089
+ drawCartesianAxes(svg, {
1090
+ plot,
1091
+ xScale: xInfo.scale,
1092
+ yScale,
1093
+ xTicks: xInfo.ticks,
1094
+ yTicks,
1095
+ theme,
1096
+ options,
1097
+ categoricalX: xInfo.type === "point"
1098
+ });
1099
+ drawAnnotations(svg, options, plot, xInfo.scale, yScale, theme);
1100
+ const labels = dataLabelConfig(options);
1101
+ const markGroup = append(svg, svgEl("g", { class: `vd-chart-marks vd-chart-${mode}` }));
1102
+ if (mode === "area") {
1103
+ const baseline = yScale(Math.max(0, yDomain[0]));
1104
+ append(
1105
+ markGroup,
1106
+ svgEl("path", {
1107
+ class: "vd-chart-area-path",
1108
+ d: areaPath(points, baseline),
1109
+ fill: options.fill || color,
1110
+ opacity: options.fillOpacity ?? 0.18,
1111
+ stroke: "none"
1112
+ })
1113
+ );
1114
+ }
1115
+ append(
1116
+ markGroup,
1117
+ svgEl("path", {
1118
+ class: "vd-chart-line-path",
1119
+ d: linePath(points),
1120
+ fill: "none",
1121
+ stroke: color,
1122
+ "stroke-width": options.strokeWidth || 2,
1123
+ "stroke-linecap": "round",
1124
+ "stroke-linejoin": "round"
1125
+ })
1126
+ );
1127
+ if (options.points !== false) {
1128
+ points.forEach((point) => {
1129
+ const circle = svgEl("circle", {
1130
+ class: "vd-chart-point",
1131
+ cx: point.x,
1132
+ cy: point.y,
1133
+ r: options.pointRadius || 3.5,
1134
+ fill: options.pointFill || theme.backgroundColor,
1135
+ stroke: color,
1136
+ "stroke-width": 2,
1137
+ role: "graphics-symbol",
1138
+ "aria-label": `${formatCategory(point.xValue)}: ${formatNumber(point.yValue)}`
1139
+ });
1140
+ makeInteractive(
1141
+ circle,
1142
+ typeof options.onPointClick === "function",
1143
+ options.tooltip !== false
1144
+ );
1145
+ attachTooltip(
1146
+ instance,
1147
+ circle,
1148
+ options,
1149
+ {
1150
+ datum: point.raw,
1151
+ x: point.xValue,
1152
+ y: point.yValue,
1153
+ value: point.yValue,
1154
+ index: point.index
1155
+ },
1156
+ `${formatCategory(point.xValue)}: ${formatNumber(point.yValue)}`
1157
+ );
1158
+ attachClick(circle, options.onPointClick, point.raw, point.index);
1159
+ append(markGroup, circle);
1160
+ });
1161
+ }
1162
+ if (labels) {
1163
+ points.forEach(
1164
+ (point) => drawDataLabel(svg, point.x, point.y - 8, point.yValue, labels, theme)
1165
+ );
1166
+ }
1167
+ }
1168
+ function renderMultiLineChart(instance, mode) {
1169
+ const shell = createSvgShell(instance);
1170
+ const { svg, size, theme, plot } = shell;
1171
+ const options = instance.options;
1172
+ const seriesList = buildSeriesList(options);
1173
+ const allRows = seriesList.flatMap((series) => series.rows);
1174
+ if (!allRows.length) {
1175
+ renderEmpty(svg, size, theme);
1176
+ return;
1177
+ }
1178
+ const xInfo = inferXScale(allRows, plot, options);
1179
+ const yDomain = niceDomain(
1180
+ allRows.map((row) => row.y),
1181
+ {
1182
+ includeZero: mode === "area" || options.yIncludeZero === true,
1183
+ min: options.yMin,
1184
+ max: options.yMax,
1185
+ tickCount: options.yTickCount
1186
+ }
1187
+ );
1188
+ const yScale = scaleLinear({ domain: yDomain, range: [plot.bottom, plot.top] });
1189
+ const yTicks = yScale.ticks(options.yTickCount ?? 5);
1190
+ drawCartesianAxes(svg, {
1191
+ plot,
1192
+ xScale: xInfo.scale,
1193
+ yScale,
1194
+ xTicks: xInfo.ticks,
1195
+ yTicks,
1196
+ theme,
1197
+ options,
1198
+ categoricalX: xInfo.type === "point"
1199
+ });
1200
+ drawAnnotations(svg, options, plot, xInfo.scale, yScale, theme);
1201
+ const labels = dataLabelConfig(options);
1202
+ const markGroup = append(svg, svgEl("g", { class: `vd-chart-marks vd-chart-${mode}` }));
1203
+ const baseline = yScale(Math.max(0, yDomain[0]));
1204
+ seriesList.forEach((series) => {
1205
+ const stroke = seriesColor(series, theme);
1206
+ const points = series.rows.map((row) => ({
1207
+ raw: row.raw,
1208
+ index: row.index,
1209
+ xValue: row.x,
1210
+ yValue: row.y,
1211
+ x: xInfo.scale(xInfo.mapValue(row.x)),
1212
+ y: yScale(row.y)
1213
+ })).filter((point) => isFiniteNumber(point.x) && isFiniteNumber(point.y));
1214
+ if (mode === "area") {
1215
+ append(
1216
+ markGroup,
1217
+ svgEl("path", {
1218
+ class: "vd-chart-area-path",
1219
+ d: areaPath(points, baseline),
1220
+ fill: series.color || stroke,
1221
+ opacity: options.fillOpacity ?? 0.18,
1222
+ stroke: "none"
1223
+ })
1224
+ );
1225
+ }
1226
+ append(
1227
+ markGroup,
1228
+ svgEl("path", {
1229
+ class: "vd-chart-line-path",
1230
+ d: linePath(points),
1231
+ fill: "none",
1232
+ stroke,
1233
+ "stroke-width": options.strokeWidth || 2,
1234
+ "stroke-linecap": "round",
1235
+ "stroke-linejoin": "round"
1236
+ })
1237
+ );
1238
+ if (options.points !== false) {
1239
+ points.forEach((point) => {
1240
+ const circle = svgEl("circle", {
1241
+ class: "vd-chart-point",
1242
+ cx: point.x,
1243
+ cy: point.y,
1244
+ r: options.pointRadius || 3.5,
1245
+ fill: options.pointFill || theme.backgroundColor,
1246
+ stroke,
1247
+ "stroke-width": 2,
1248
+ role: "graphics-symbol",
1249
+ "aria-label": `${series.name} ${formatCategory(point.xValue)}: ${formatNumber(point.yValue)}`
1250
+ });
1251
+ makeInteractive(
1252
+ circle,
1253
+ typeof options.onPointClick === "function",
1254
+ options.tooltip !== false
1255
+ );
1256
+ attachTooltip(
1257
+ instance,
1258
+ circle,
1259
+ options,
1260
+ {
1261
+ datum: point.raw,
1262
+ x: point.xValue,
1263
+ y: point.yValue,
1264
+ value: point.yValue,
1265
+ index: point.index,
1266
+ seriesIndex: series.seriesIndex,
1267
+ seriesName: series.name
1268
+ },
1269
+ `${series.name} \u2014 ${formatCategory(point.xValue)}: ${formatNumber(point.yValue)}`
1270
+ );
1271
+ attachClick(circle, options.onPointClick, point.raw, point.index);
1272
+ append(markGroup, circle);
1273
+ });
1274
+ }
1275
+ if (labels) {
1276
+ points.forEach(
1277
+ (point) => drawDataLabel(svg, point.x, point.y - 8, point.yValue, labels, theme)
1278
+ );
1279
+ }
1280
+ });
1281
+ if (options.legend !== false) {
1282
+ renderTopLegend(
1283
+ svg,
1284
+ seriesList.map((series) => ({ label: series.name, color: seriesColor(series, theme) })),
1285
+ theme,
1286
+ plot
1287
+ );
1288
+ }
1289
+ }
1290
+ function renderScatterChart(instance) {
1291
+ const shell = createSvgShell(instance);
1292
+ const { svg, size, theme, plot } = shell;
1293
+ const options = instance.options;
1294
+ const data = toArray(options.data);
1295
+ const xAccessor = createAccessor(options.x, "x");
1296
+ const yAccessor = createAccessor(options.y, "y");
1297
+ const rows = data.map((datum, index) => ({
1298
+ raw: datum,
1299
+ index,
1300
+ x: xAccessor(datum),
1301
+ y: toNumber(yAccessor(datum))
1302
+ })).filter((row) => row.x != null && isFiniteNumber(row.y));
1303
+ if (!rows.length) {
1304
+ renderEmpty(svg, size, theme);
1305
+ return;
1306
+ }
1307
+ const xInfo = inferXScale(rows, plot, options);
1308
+ const yDomain = niceDomain(
1309
+ rows.map((row) => row.y),
1310
+ {
1311
+ includeZero: options.yIncludeZero === true,
1312
+ min: options.yMin,
1313
+ max: options.yMax,
1314
+ tickCount: options.yTickCount
1315
+ }
1316
+ );
1317
+ const yScale = scaleLinear({ domain: yDomain, range: [plot.bottom, plot.top] });
1318
+ const yTicks = yScale.ticks(options.yTickCount ?? 5);
1319
+ const color = getColorScale(rows, options.color, theme);
1320
+ drawCartesianAxes(svg, {
1321
+ plot,
1322
+ xScale: xInfo.scale,
1323
+ yScale,
1324
+ xTicks: xInfo.ticks,
1325
+ yTicks,
1326
+ theme,
1327
+ options,
1328
+ categoricalX: xInfo.type === "point"
1329
+ });
1330
+ drawAnnotations(svg, options, plot, xInfo.scale, yScale, theme);
1331
+ const labels = dataLabelConfig(options);
1332
+ const markGroup = append(svg, svgEl("g", { class: "vd-chart-marks vd-chart-scatter" }));
1333
+ rows.forEach((row) => {
1334
+ const cx = xInfo.scale(xInfo.mapValue(row.x));
1335
+ const cy = yScale(row.y);
1336
+ if (!isFiniteNumber(cx) || !isFiniteNumber(cy)) return;
1337
+ const fill = colorForRow(color, row, theme);
1338
+ const circle = svgEl("circle", {
1339
+ class: "vd-chart-scatter-point",
1340
+ cx,
1341
+ cy,
1342
+ r: options.pointRadius || 4,
1343
+ fill,
1344
+ opacity: options.pointOpacity ?? 0.88,
1345
+ role: "graphics-symbol",
1346
+ "aria-label": `${formatCategory(row.x)}: ${formatNumber(row.y)}`
1347
+ });
1348
+ makeInteractive(circle, typeof options.onPointClick === "function", options.tooltip !== false);
1349
+ attachTooltip(
1350
+ instance,
1351
+ circle,
1352
+ options,
1353
+ {
1354
+ datum: row.raw,
1355
+ x: row.x,
1356
+ y: row.y,
1357
+ value: row.y,
1358
+ index: row.index
1359
+ },
1360
+ `${formatCategory(row.x)}: ${formatNumber(row.y)}`
1361
+ );
1362
+ attachClick(circle, options.onPointClick, row.raw, row.index);
1363
+ if (labels) drawDataLabel(svg, cx, cy - 8, row.y, labels, theme);
1364
+ append(markGroup, circle);
1365
+ });
1366
+ if (options.legend && color && color.scale) {
1367
+ renderTopLegend(
1368
+ svg,
1369
+ color.scale.domain().map((cat) => ({ label: cat, color: color.scale(cat) })),
1370
+ theme,
1371
+ plot
1372
+ );
1373
+ }
1374
+ }
1375
+ function renderLegend(svg, rows, colorScale, theme, x, y) {
1376
+ const legend = append(svg, svgEl("g", { class: "vd-chart-legend" }));
1377
+ rows.slice(0, 8).forEach((row, index) => {
1378
+ const itemY = y + index * 20;
1379
+ append(
1380
+ legend,
1381
+ svgEl("rect", {
1382
+ x,
1383
+ y: itemY - 9,
1384
+ width: 10,
1385
+ height: 10,
1386
+ rx: 2,
1387
+ fill: colorScale(row.label)
1388
+ })
1389
+ );
1390
+ append(
1391
+ legend,
1392
+ setText(
1393
+ svgEl("text", {
1394
+ x: x + 16,
1395
+ y: itemY,
1396
+ fill: theme.mutedTextColor,
1397
+ "font-size": 11
1398
+ }),
1399
+ formatCategory(row.label)
1400
+ )
1401
+ );
1402
+ });
1403
+ }
1404
+ function renderDonutChart(instance) {
1405
+ instance.options.polar = true;
1406
+ const shell = createSvgShell(instance);
1407
+ const { svg, size, theme, plot } = shell;
1408
+ const options = instance.options;
1409
+ const data = toArray(options.data);
1410
+ const labelAccessor = createAccessor(options.label, "label");
1411
+ const valueAccessor = createAccessor(options.value, "value");
1412
+ const rows = data.map((datum, index) => ({
1413
+ raw: datum,
1414
+ index,
1415
+ label: labelAccessor(datum),
1416
+ value: toNumber(valueAccessor(datum))
1417
+ })).filter((row) => row.label != null && isFiniteNumber(row.value) && row.value > 0);
1418
+ const total = rows.reduce((sum, row) => sum + row.value, 0);
1419
+ if (!rows.length || total <= 0) {
1420
+ renderEmpty(svg, size, theme);
1421
+ return;
1422
+ }
1423
+ const legendSpace = options.legend === false || size.width < 520 ? 0 : 128;
1424
+ const cx = (plot.left + plot.right - legendSpace) / 2;
1425
+ const cy = (plot.top + plot.bottom) / 2 + 5;
1426
+ const outerRadius = Math.max(
1427
+ 28,
1428
+ Math.min(plot.right - plot.left - legendSpace, plot.bottom - plot.top) / 2
1429
+ );
1430
+ const ratio = Math.max(0, Math.min(0.9, Number(options.innerRadiusRatio ?? 0.62)));
1431
+ const innerRadius = outerRadius * ratio;
1432
+ const colorScale = scaleOrdinal({ domain: rows.map((row) => row.label), range: theme.colors });
1433
+ const labels = dataLabelConfig(options);
1434
+ const markGroup = append(svg, svgEl("g", { class: "vd-chart-marks vd-chart-slices" }));
1435
+ let cursor = -Math.PI / 2;
1436
+ rows.forEach((row) => {
1437
+ const angle = row.value / total * TAU;
1438
+ const start = cursor;
1439
+ const end = cursor + angle;
1440
+ cursor = end;
1441
+ const path = svgEl("path", {
1442
+ class: "vd-chart-slice",
1443
+ d: arcPath(cx, cy, outerRadius, innerRadius, start, end),
1444
+ fill: colorScale(row.label),
1445
+ stroke: theme.backgroundColor,
1446
+ "stroke-width": 2,
1447
+ role: "graphics-symbol",
1448
+ "aria-label": `${formatCategory(row.label)}: ${formatNumber(row.value)}`
1449
+ });
1450
+ makeInteractive(path, typeof options.onSliceClick === "function", options.tooltip !== false);
1451
+ attachTooltip(
1452
+ instance,
1453
+ path,
1454
+ options,
1455
+ {
1456
+ datum: row.raw,
1457
+ label: row.label,
1458
+ value: row.value,
1459
+ y: row.value,
1460
+ index: row.index
1461
+ },
1462
+ `${formatCategory(row.label)}: ${formatNumber(row.value)}`
1463
+ );
1464
+ attachClick(path, options.onSliceClick, row.raw, row.index);
1465
+ if (labels) {
1466
+ const mid = (start + end) / 2;
1467
+ const point = polarPoint(cx, cy, (innerRadius + outerRadius) / 2, mid);
1468
+ drawDataLabel(svg, point.x, point.y, row.value, labels, theme);
1469
+ }
1470
+ append(markGroup, path);
1471
+ });
1472
+ if (innerRadius > 16 && options.centerLabel !== false) {
1473
+ append(
1474
+ svg,
1475
+ setText(
1476
+ svgEl("text", {
1477
+ x: cx,
1478
+ y: cy - 2,
1479
+ fill: theme.textColor,
1480
+ "font-size": 18,
1481
+ "font-weight": 700,
1482
+ "text-anchor": "middle"
1483
+ }),
1484
+ options.centerLabel || formatNumber(total)
1485
+ )
1486
+ );
1487
+ append(
1488
+ svg,
1489
+ setText(
1490
+ svgEl("text", {
1491
+ x: cx,
1492
+ y: cy + 16,
1493
+ fill: theme.mutedTextColor,
1494
+ "font-size": 11,
1495
+ "text-anchor": "middle"
1496
+ }),
1497
+ options.centerSubLabel || "total"
1498
+ )
1499
+ );
1500
+ }
1501
+ if (legendSpace) {
1502
+ renderLegend(svg, rows, colorScale, theme, plot.right - legendSpace + 8, plot.top + 28);
1503
+ }
1504
+ }
1505
+ var ChartInstance = class {
1506
+ constructor(kind, options, renderer) {
1507
+ this.kind = kind;
1508
+ this.options = { ...options };
1509
+ this.target = resolveTarget(options.target);
1510
+ this.renderer = renderer;
1511
+ this.resizeObserver = null;
1512
+ this.destroyed = false;
1513
+ this.theme = null;
1514
+ this.size = null;
1515
+ this.plot = null;
1516
+ this.tooltipEl = null;
1517
+ this.render();
1518
+ this.setupResizeObserver();
1519
+ }
1520
+ render() {
1521
+ if (this.destroyed) return this;
1522
+ this.renderer(this);
1523
+ return this;
1524
+ }
1525
+ update(nextOptions = {}) {
1526
+ if (this.destroyed) return this;
1527
+ this.options = { ...this.options, ...nextOptions };
1528
+ return this.render();
1529
+ }
1530
+ resize() {
1531
+ return this.render();
1532
+ }
1533
+ setupResizeObserver() {
1534
+ if (this.options.responsive === false || !hasWindow() || typeof ResizeObserver === "undefined")
1535
+ return;
1536
+ let lastWidth = this.target.clientWidth;
1537
+ let lastHeight = this.target.clientHeight;
1538
+ this.resizeObserver = new ResizeObserver(() => {
1539
+ const width = this.target.clientWidth;
1540
+ const height = this.target.clientHeight;
1541
+ if (width === lastWidth && height === lastHeight) return;
1542
+ lastWidth = width;
1543
+ lastHeight = height;
1544
+ this.resize();
1545
+ });
1546
+ this.resizeObserver.observe(this.target);
1547
+ }
1548
+ ensureTooltip() {
1549
+ if (this.tooltipEl && this.tooltipEl.isConnected) return this.tooltipEl;
1550
+ const tooltip = document.createElement("div");
1551
+ tooltip.className = "vd-chart-tooltip";
1552
+ tooltip.setAttribute("role", "status");
1553
+ tooltip.setAttribute("aria-live", "polite");
1554
+ this.target.appendChild(tooltip);
1555
+ this.tooltipEl = tooltip;
1556
+ return tooltip;
1557
+ }
1558
+ showTooltip(content, event) {
1559
+ const tooltip = this.ensureTooltip();
1560
+ tooltip.textContent = String(content);
1561
+ const rect = this.target.getBoundingClientRect();
1562
+ let x = rect.width / 2;
1563
+ let y = rect.height / 2;
1564
+ if (event && isFiniteNumber(event.clientX) && isFiniteNumber(event.clientY)) {
1565
+ x = event.clientX - rect.left;
1566
+ y = event.clientY - rect.top;
1567
+ } else if (event && event.target && typeof event.target.getBoundingClientRect === "function") {
1568
+ const markRect = event.target.getBoundingClientRect();
1569
+ x = markRect.left + markRect.width / 2 - rect.left;
1570
+ y = markRect.top - rect.top;
1571
+ }
1572
+ tooltip.style.left = `${Math.max(8, Math.min(rect.width - 8, x))}px`;
1573
+ tooltip.style.top = `${Math.max(18, Math.min(rect.height - 8, y))}px`;
1574
+ tooltip.classList.add("is-visible");
1575
+ }
1576
+ hideTooltip() {
1577
+ if (this.tooltipEl) {
1578
+ this.tooltipEl.classList.remove("is-visible");
1579
+ }
1580
+ }
1581
+ destroy() {
1582
+ if (this.destroyed) return;
1583
+ if (this.resizeObserver) {
1584
+ this.resizeObserver.disconnect();
1585
+ this.resizeObserver = null;
1586
+ }
1587
+ this.target.innerHTML = "";
1588
+ this.target.classList.remove("vd-chart-root", `vd-chart-${this.kind}`);
1589
+ this.destroyed = true;
1590
+ }
1591
+ };
1592
+ function createChartFactory(kind, renderer, defaults = {}) {
1593
+ return function chartFactory(options = {}) {
1594
+ return new ChartInstance(kind, { ...defaults, ...options }, renderer);
1595
+ };
1596
+ }
1597
+ var BarChart = createChartFactory("bar", renderBarChart);
1598
+ var LineChart = createChartFactory(
1599
+ "line",
1600
+ (instance) => renderLineLikeChart(instance, "line")
1601
+ );
1602
+ var AreaChart = createChartFactory(
1603
+ "area",
1604
+ (instance) => renderLineLikeChart(instance, "area")
1605
+ );
1606
+ var ScatterChart = createChartFactory("scatter", renderScatterChart);
1607
+ var DonutChart = createChartFactory("donut", renderDonutChart, { innerRadiusRatio: 0.62 });
1608
+ var PieChart = createChartFactory("pie", renderDonutChart, { innerRadiusRatio: 0 });
1609
+
1610
+ // src/charts/vue.js
1611
+ var FACTORIES = {
1612
+ bar: BarChart,
1613
+ line: LineChart,
1614
+ area: AreaChart,
1615
+ scatter: ScatterChart,
1616
+ donut: DonutChart,
1617
+ pie: PieChart
1618
+ };
1619
+ var CHART_PROPS = {
1620
+ type: { type: String, default: "bar" },
1621
+ data: { type: Array, default: () => [] },
1622
+ x: { type: [String, Function], default: void 0 },
1623
+ y: { type: [String, Function], default: void 0 },
1624
+ label: { type: [String, Function], default: void 0 },
1625
+ value: { type: [String, Function], default: void 0 },
1626
+ // CSS color, category-field name, or per-datum function `(row) => color`.
1627
+ color: { type: [String, Function], default: void 0 },
1628
+ title: { type: String, default: void 0 },
1629
+ description: { type: String, default: void 0 },
1630
+ width: { type: Number, default: void 0 },
1631
+ height: { type: Number, default: 300 },
1632
+ innerRadiusRatio: { type: Number, default: void 0 },
1633
+ theme: { type: Object, default: void 0 },
1634
+ tooltip: { type: [Function, String, Boolean], default: void 0 },
1635
+ responsive: { type: Boolean, default: true },
1636
+ // Multi-series (bar → grouped, line/area → one path each).
1637
+ series: { type: Array, default: void 0 },
1638
+ // `true` / `false` / `{ position }`.
1639
+ legend: { type: [Boolean, Object], default: void 0 },
1640
+ // Value labels on marks: `true` / `false` / `{ format, color }`.
1641
+ dataLabels: { type: [Boolean, Object], default: void 0 },
1642
+ // Reference lines: `[{ y?, x?, label?, color?, dash? }]`.
1643
+ annotations: { type: Array, default: void 0 },
1644
+ // Axis range + ticks.
1645
+ xMin: { type: Number, default: void 0 },
1646
+ xMax: { type: Number, default: void 0 },
1647
+ yMin: { type: Number, default: void 0 },
1648
+ yMax: { type: Number, default: void 0 },
1649
+ yTickCount: { type: Number, default: void 0 },
1650
+ yIncludeZero: { type: Boolean, default: void 0 },
1651
+ xFormat: { type: Function, default: void 0 },
1652
+ yFormat: { type: Function, default: void 0 },
1653
+ xAxis: { type: Object, default: void 0 },
1654
+ yAxis: { type: Object, default: void 0 }
1655
+ };
1656
+ function optionsFrom(target, props) {
1657
+ return {
1658
+ target,
1659
+ type: props.type,
1660
+ data: props.data,
1661
+ x: props.x,
1662
+ y: props.y,
1663
+ label: props.label,
1664
+ value: props.value,
1665
+ color: props.color,
1666
+ title: props.title,
1667
+ description: props.description,
1668
+ width: props.width,
1669
+ height: props.height,
1670
+ innerRadiusRatio: props.innerRadiusRatio,
1671
+ theme: props.theme,
1672
+ tooltip: props.tooltip,
1673
+ responsive: props.responsive,
1674
+ series: props.series,
1675
+ legend: props.legend,
1676
+ dataLabels: props.dataLabels,
1677
+ annotations: props.annotations,
1678
+ xMin: props.xMin,
1679
+ xMax: props.xMax,
1680
+ yMin: props.yMin,
1681
+ yMax: props.yMax,
1682
+ yTickCount: props.yTickCount,
1683
+ yIncludeZero: props.yIncludeZero,
1684
+ xFormat: props.xFormat,
1685
+ yFormat: props.yFormat,
1686
+ xAxis: props.xAxis,
1687
+ yAxis: props.yAxis
1688
+ };
1689
+ }
1690
+ var VdChart = defineComponent({
1691
+ name: "VdChart",
1692
+ props: CHART_PROPS,
1693
+ setup(props) {
1694
+ const el = ref(null);
1695
+ let instance = null;
1696
+ let currentType = props.type;
1697
+ const create = () => {
1698
+ const factory = FACTORIES[props.type] || BarChart;
1699
+ currentType = props.type;
1700
+ instance = factory(optionsFrom(el.value, props));
1701
+ };
1702
+ onMounted(() => {
1703
+ if (typeof window === "undefined" || !el.value) return;
1704
+ create();
1705
+ });
1706
+ watch(
1707
+ () => [
1708
+ props.type,
1709
+ props.data,
1710
+ props.x,
1711
+ props.y,
1712
+ props.label,
1713
+ props.value,
1714
+ props.color,
1715
+ props.title,
1716
+ props.description,
1717
+ props.width,
1718
+ props.height,
1719
+ props.innerRadiusRatio,
1720
+ props.theme,
1721
+ props.tooltip,
1722
+ props.responsive,
1723
+ props.series,
1724
+ props.legend,
1725
+ props.dataLabels,
1726
+ props.annotations,
1727
+ props.xMin,
1728
+ props.xMax,
1729
+ props.yMin,
1730
+ props.yMax,
1731
+ props.yTickCount,
1732
+ props.yIncludeZero,
1733
+ props.xFormat,
1734
+ props.yFormat,
1735
+ props.xAxis,
1736
+ props.yAxis
1737
+ ],
1738
+ () => {
1739
+ if (!instance) return;
1740
+ if (props.type !== currentType) {
1741
+ instance.destroy();
1742
+ create();
1743
+ } else {
1744
+ instance.update(optionsFrom(el.value, props));
1745
+ }
1746
+ },
1747
+ { deep: true }
1748
+ );
1749
+ onBeforeUnmount(() => {
1750
+ if (instance) {
1751
+ instance.destroy();
1752
+ instance = null;
1753
+ }
1754
+ });
1755
+ return () => h("div", {
1756
+ ref: el,
1757
+ class: "vd-chart",
1758
+ style: props.height ? { minHeight: `${props.height}px` } : void 0
1759
+ });
1760
+ }
1761
+ });
1762
+ function typed(name, type) {
1763
+ return defineComponent({
1764
+ name,
1765
+ props: CHART_PROPS,
1766
+ setup(props) {
1767
+ return () => h(VdChart, { ...props, type });
1768
+ }
1769
+ });
1770
+ }
1771
+ var VdBarChart = typed("VdBarChart", "bar");
1772
+ var VdLineChart = typed("VdLineChart", "line");
1773
+ var VdAreaChart = typed("VdAreaChart", "area");
1774
+ var VdScatterChart = typed("VdScatterChart", "scatter");
1775
+ var VdDonutChart = typed("VdDonutChart", "donut");
1776
+ var VdPieChart = typed("VdPieChart", "pie");
1777
+ export {
1778
+ AreaChart,
1779
+ BarChart,
1780
+ DonutChart,
1781
+ LineChart,
1782
+ PieChart,
1783
+ ScatterChart,
1784
+ VD_CHARTS_VERSION,
1785
+ VdAreaChart,
1786
+ VdBarChart,
1787
+ VdChart,
1788
+ VdDonutChart,
1789
+ VdLineChart,
1790
+ VdPieChart,
1791
+ VdScatterChart,
1792
+ arcPath,
1793
+ areaPath,
1794
+ createAccessor,
1795
+ linePath,
1796
+ niceDomain,
1797
+ resolveTheme,
1798
+ scaleBand,
1799
+ scaleLinear,
1800
+ scaleOrdinal,
1801
+ scalePoint,
1802
+ scaleTime,
1803
+ ticks
1804
+ };
1805
+ //# sourceMappingURL=index.js.map