@cfasim-ui/charts 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,6 +14,21 @@ type __VLS_Props = {
14
14
  maxRows?: number;
15
15
  columnConfig?: Record<string, ColumnConfig>;
16
16
  menu?: boolean | string;
17
+ /**
18
+ * Custom CSV content for the Download CSV menu item and download link.
19
+ * Can be a raw CSV string or a function returning one. When omitted, CSV
20
+ * is generated from the table data.
21
+ */
22
+ csv?: string | (() => string);
23
+ /** Filename (without extension) for downloaded CSV files. */
24
+ filename?: string;
25
+ /**
26
+ * Show a plain text link below the table to download the CSV data.
27
+ * Pass `true` for the default label ("Download data (CSV)") or a string
28
+ * to customize the link text. When set, the Download CSV menu item is
29
+ * hidden.
30
+ */
31
+ downloadLink?: boolean | string;
17
32
  };
18
33
  declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
19
34
  menu: boolean | string;
@@ -39,6 +39,20 @@ type __VLS_Props = {
39
39
  tooltipData?: unknown[];
40
40
  /** Tooltip activation mode. Default: 'hover' */
41
41
  tooltipTrigger?: "hover" | "click";
42
+ /**
43
+ * Custom CSV content for the Download CSV menu item. Can be a raw CSV
44
+ * string or a function returning one. When omitted, CSV is generated
45
+ * from the chart series.
46
+ */
47
+ csv?: string | (() => string);
48
+ /** Filename (without extension) for downloaded SVG, PNG and CSV files. */
49
+ filename?: string;
50
+ /**
51
+ * Show a plain text link below the chart to download the CSV data.
52
+ * Pass `true` for the default label ("Download data (CSV)") or a string
53
+ * to customize the link text.
54
+ */
55
+ downloadLink?: boolean | string;
42
56
  };
43
57
  declare function __VLS_template(): {
44
58
  attrs: Partial<{}>;
package/dist/index.css CHANGED
@@ -1,2 +1,2 @@
1
- .chart-menu-trigger-area[data-v-fe2f6904]{z-index:1;position:absolute;top:0;right:0}.chart-menu-button[data-v-fe2f6904]{border:1px solid var(--color-border);background:var(--color-bg-0,#fff);width:28px;height:28px;color:var(--color-text-secondary);cursor:pointer;opacity:0;border-radius:.25em;justify-content:center;align-items:center;transition:opacity .15s;display:flex}.chart-menu-button[data-state=open][data-v-fe2f6904]{opacity:1}.chart-menu-button[data-v-fe2f6904]:hover{background:var(--color-bg-1,#0000000d);color:var(--color-text)}.chart-menu-content{z-index:100;background:var(--color-bg-0);border:1px solid var(--color-border);border-radius:.25em;min-width:140px;padding:.25em;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.chart-menu-item{font-size:var(--font-size-sm);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;border-radius:.25em;outline:none;align-items:center;padding:.375em .5em;display:flex}.chart-menu-item[data-highlighted]{background:var(--color-primary);color:#fff}.line-chart-wrapper[data-v-4ea55781]{width:100%;position:relative}.line-chart-wrapper[data-v-4ea55781]:hover .chart-menu-button{opacity:1}.line-chart-tooltip-label[data-v-4ea55781]{margin-bottom:.25em;font-weight:600}.line-chart-tooltip-row[data-v-4ea55781]{align-items:center;gap:.375em;display:flex}.line-chart-tooltip-swatch[data-v-4ea55781]{border-radius:50%;flex-shrink:0;width:.625em;height:.625em;display:inline-block}.choropleth-wrapper[data-v-ffaf1671]{width:100%;position:relative}.choropleth-wrapper.pannable svg[data-v-ffaf1671]{cursor:grab}.choropleth-wrapper.pannable svg[data-v-ffaf1671]:active{cursor:grabbing}.choropleth-wrapper[data-v-ffaf1671]:hover .chart-menu-button{opacity:1}.state-path[data-v-ffaf1671]{cursor:pointer}.chart-tooltip-anchor[data-v-44377f70]{pointer-events:none;width:1px;height:1px;position:absolute}.chart-tooltip-content{z-index:100;background:var(--color-bg-0,#fff);border:1px solid var(--color-border,#e5e7eb);font-size:var(--font-size-sm,.875rem);pointer-events:none;border-radius:.375em;padding:.5em .75em;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.TableOuter[data-v-dbfb7c84]{display:inline-block;position:relative}.TableOuter.has-menu[data-v-dbfb7c84]{padding-top:32px}.TableOuter[data-v-dbfb7c84]:hover .chart-menu-button{opacity:1}.TableWrapper[data-v-dbfb7c84]{font-size:var(--font-size-sm);overflow-x:auto}.Table[data-v-dbfb7c84]{border-collapse:collapse;font-variant-numeric:tabular-nums;border:1px solid var(--color-border)}.Table tr[data-v-dbfb7c84],.Table th[data-v-dbfb7c84],.Table td[data-v-dbfb7c84]{background:0 0;border:none}.Table th[data-v-dbfb7c84],.Table td[data-v-dbfb7c84]{white-space:nowrap;padding:.75em 1.25em}.Table th[data-v-dbfb7c84]{border-bottom:1px solid var(--color-border-header);font-weight:600;position:sticky;top:0}.Table tbody td[data-v-dbfb7c84]{border-bottom:1px solid var(--color-border)}.Table tbody tr:last-child td[data-v-dbfb7c84]{border-bottom:none}
1
+ .chart-menu-trigger-area[data-v-fe2f6904]{z-index:1;position:absolute;top:0;right:0}.chart-menu-button[data-v-fe2f6904]{border:1px solid var(--color-border);background:var(--color-bg-0,#fff);width:28px;height:28px;color:var(--color-text-secondary);cursor:pointer;opacity:0;border-radius:.25em;justify-content:center;align-items:center;transition:opacity .15s;display:flex}.chart-menu-button[data-state=open][data-v-fe2f6904]{opacity:1}.chart-menu-button[data-v-fe2f6904]:hover{background:var(--color-bg-1,#0000000d);color:var(--color-text)}.chart-menu-content{z-index:100;background:var(--color-bg-0);border:1px solid var(--color-border);border-radius:.25em;min-width:140px;padding:.25em;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.chart-menu-item{font-size:var(--font-size-sm);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;border-radius:.25em;outline:none;align-items:center;padding:.375em .5em;display:flex}.chart-menu-item[data-highlighted]{background:var(--color-primary);color:#fff}.line-chart-wrapper[data-v-61fdeef2]{width:100%;position:relative}.line-chart-wrapper[data-v-61fdeef2]:hover .chart-menu-button{opacity:1}.line-chart-tooltip-label[data-v-61fdeef2]{margin-bottom:.25em;font-weight:600}.line-chart-tooltip-row[data-v-61fdeef2]{align-items:center;gap:.375em;display:flex}.line-chart-download-link[data-v-61fdeef2]{text-align:right;font-size:var(--font-size-sm);margin-top:.25em;display:block}.line-chart-tooltip-swatch[data-v-61fdeef2]{border-radius:50%;flex-shrink:0;width:.625em;height:.625em;display:inline-block}.choropleth-wrapper[data-v-ffaf1671]{width:100%;position:relative}.choropleth-wrapper.pannable svg[data-v-ffaf1671]{cursor:grab}.choropleth-wrapper.pannable svg[data-v-ffaf1671]:active{cursor:grabbing}.choropleth-wrapper[data-v-ffaf1671]:hover .chart-menu-button{opacity:1}.state-path[data-v-ffaf1671]{cursor:pointer}.chart-tooltip-anchor[data-v-44377f70]{pointer-events:none;width:1px;height:1px;position:absolute}.chart-tooltip-content{z-index:100;background:var(--color-bg-0,#fff);border:1px solid var(--color-border,#e5e7eb);font-size:var(--font-size-sm,.875rem);pointer-events:none;border-radius:.375em;padding:.5em .75em;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.TableOuter[data-v-505e2187]{display:inline-block;position:relative}.TableOuter.has-menu[data-v-505e2187]{margin-top:32px}.TableOuter[data-v-505e2187] .chart-menu-trigger-area{top:-32px;right:0}.TableOuter[data-v-505e2187]:hover .chart-menu-button{opacity:1}.TableWrapper[data-v-505e2187]{font-size:var(--font-size-sm);overflow-x:auto}.Table[data-v-505e2187]{border-collapse:collapse;font-variant-numeric:tabular-nums;border:1px solid var(--color-border);margin:0;display:table}.Table tr[data-v-505e2187],.Table th[data-v-505e2187],.Table td[data-v-505e2187]{background:0 0;border:none}.Table th[data-v-505e2187],.Table td[data-v-505e2187]{white-space:nowrap;padding:.75em 1.25em}.Table th[data-v-505e2187]{border-bottom:1px solid var(--color-border-header);font-weight:600;position:sticky;top:0}.Table tbody td[data-v-505e2187]{border-bottom:1px solid var(--color-border)}.Table tbody tr:last-child td[data-v-505e2187]{border-bottom:none}.data-table-download-link[data-v-505e2187]{text-align:right;font-size:var(--font-size-sm);margin-top:.25em;display:block}
2
2
  /*$vite$:1*/
package/dist/index.js CHANGED
@@ -166,7 +166,7 @@ var ce = ["width", "height"], le = ["x"], U = [
166
166
  ], ye = { class: "line-chart-tooltip" }, be = {
167
167
  key: 0,
168
168
  class: "line-chart-tooltip-label"
169
- }, xe = 50, J = /* @__PURE__ */ B(/* @__PURE__ */ c({
169
+ }, xe = ["href", "download"], Se = 50, J = /* @__PURE__ */ B(/* @__PURE__ */ c({
170
170
  __name: "LineChart",
171
171
  props: {
172
172
  data: {},
@@ -189,7 +189,10 @@ var ce = ["width", "height"], le = ["x"], U = [
189
189
  xGrid: { type: Boolean },
190
190
  yGrid: { type: Boolean },
191
191
  tooltipData: {},
192
- tooltipTrigger: {}
192
+ tooltipTrigger: {},
193
+ csv: {},
194
+ filename: {},
195
+ downloadLink: { type: [Boolean, String] }
193
196
  },
194
197
  emits: ["hover"],
195
198
  setup(s, { emit: c }) {
@@ -313,12 +316,14 @@ var ce = ["width", "height"], le = ["x"], U = [
313
316
  return a;
314
317
  });
315
318
  function B() {
316
- return typeof u.menu == "string" ? u.menu : "chart";
319
+ return u.filename ? u.filename : typeof u.menu == "string" ? u.menu : "chart";
317
320
  }
318
321
  function V() {
319
322
  return x.value;
320
323
  }
321
324
  function J() {
325
+ if (typeof u.csv == "function") return u.csv();
326
+ if (typeof u.csv == "string") return u.csv;
322
327
  let e = j.value;
323
328
  if (e.length === 0) return "";
324
329
  let t = N.value, n = [(e.length === 1 ? ["index", "value"] : ["index", ...e.map((e, t) => `series_${t}`)]).join(",")];
@@ -329,20 +334,20 @@ var ce = ["width", "height"], le = ["x"], U = [
329
334
  }
330
335
  return n.join("\n");
331
336
  }
332
- let Y = h(null), X = h(!1), Se = h(null), Z = t(() => !!u.tooltipData || !!u.tooltipTrigger), Ce = t(() => {
337
+ let Y = h(null), X = h(!1), Ce = h(null), we = t(() => !!u.tooltipData || !!u.tooltipTrigger), Te = t(() => {
333
338
  if (Y.value === null) return 0;
334
339
  let e = N.value, t = k.value / (e - 1 || 1);
335
340
  return O.value.left + Y.value * t;
336
- }), we = t(() => {
341
+ }), Ee = t(() => {
337
342
  let e = Y.value;
338
343
  if (e === null) return [];
339
344
  let { min: t, range: n } = P.value, r = A.value / n, i = O.value.top + A.value;
340
345
  return j.value.filter((t) => e < t.data.length && isFinite(t.data[e])).map((n) => ({
341
- x: Ce.value,
346
+ x: Te.value,
342
347
  y: i - (n.data[e] - t) * r,
343
348
  color: n.color ?? "currentColor"
344
349
  }));
345
- }), Q = t(() => {
350
+ }), Z = t(() => {
346
351
  let e = Y.value;
347
352
  return e === null ? null : {
348
353
  index: e,
@@ -355,10 +360,10 @@ var ce = ["width", "height"], le = ["x"], U = [
355
360
  data: u.tooltipData?.[e] ?? null
356
361
  };
357
362
  });
358
- function Te(e) {
363
+ function De(e) {
359
364
  return "touches" in e ? e.touches[0] ?? null : e;
360
365
  }
361
- function Ee(e) {
366
+ function Oe(e) {
362
367
  let t = b.value?.getBoundingClientRect();
363
368
  if (!t) return null;
364
369
  let n = N.value;
@@ -366,62 +371,58 @@ var ce = ["width", "height"], le = ["x"], U = [
366
371
  let r = e - t.left, i = k.value / (n - 1 || 1), a = (r - O.value.left) / i;
367
372
  return Math.round(Math.max(0, Math.min(n - 1, a)));
368
373
  }
369
- function De(e, t) {
370
- let n = Se.value;
374
+ function ke(e, t) {
375
+ let n = Ce.value;
371
376
  if (!n) return;
372
- let r = b.value.getBoundingClientRect(), i = X.value ? xe : 0, a = e - r.left, o = Math.max(0, t - r.top - i);
377
+ let r = b.value.getBoundingClientRect(), i = X.value ? Se : 0, a = e - r.left, o = Math.max(0, t - r.top - i);
373
378
  n.style.left = `${a + 16}px`, n.style.top = `${o}px`;
374
379
  }
375
- function Oe(e) {
376
- let t = Te(e);
380
+ function Ae(e) {
381
+ let t = De(e);
377
382
  if (!t) return;
378
- let n = Ee(t.clientX);
379
- n !== null && (Y.value = n, De(t.clientX, t.clientY), y("hover", { index: n }));
383
+ let n = Oe(t.clientX);
384
+ n !== null && (Y.value = n, ke(t.clientX, t.clientY), y("hover", { index: n }));
380
385
  }
381
- function ke(e) {
382
- Oe(e);
386
+ function je(e) {
387
+ Ae(e);
383
388
  }
384
- function Ae() {
389
+ function Me() {
385
390
  u.tooltipTrigger !== "click" && (Y.value = null, y("hover", null));
386
391
  }
387
- function je(e) {
392
+ function Ne(e) {
388
393
  if (u.tooltipTrigger !== "click") return;
389
- let t = Te(e);
394
+ let t = De(e);
390
395
  if (!t) return;
391
- let n = Ee(t.clientX);
396
+ let n = Oe(t.clientX);
392
397
  n !== null && (Y.value = Y.value === n ? null : n, y("hover", Y.value === null ? null : { index: n }));
393
398
  }
394
- function Me(e) {
395
- X.value = !0, Oe(e);
399
+ function Pe(e) {
400
+ X.value = !0, Ae(e);
396
401
  }
397
- function Ne(e) {
398
- Oe(e);
402
+ function Fe(e) {
403
+ Ae(e);
399
404
  }
400
- function Pe() {
405
+ function Q() {
401
406
  X.value = !1, Y.value = null, y("hover", null);
402
407
  }
403
- let $ = t(() => {
404
- let e = B();
405
- return [
406
- {
407
- label: "Save as SVG",
408
- action: () => {
409
- let t = V();
410
- t && oe(t, e);
411
- }
412
- },
413
- {
414
- label: "Save as PNG",
415
- action: () => {
416
- let t = V();
417
- t && se(t, e);
418
- }
419
- },
420
- {
421
- label: "Download CSV",
422
- action: () => H(J(), e)
408
+ let $ = t(() => u.downloadLink ? typeof u.downloadLink == "string" ? u.downloadLink : "Download data (CSV)" : null), Ie = t(() => u.downloadLink ? `data:text/csv;charset=utf-8,${encodeURIComponent(J())}` : null), Le = t(() => {
409
+ let e = B(), t = [{
410
+ label: "Save as SVG",
411
+ action: () => {
412
+ let t = V();
413
+ t && oe(t, e);
423
414
  }
424
- ];
415
+ }, {
416
+ label: "Save as PNG",
417
+ action: () => {
418
+ let t = V();
419
+ t && se(t, e);
420
+ }
421
+ }];
422
+ return u.downloadLink || t.push({
423
+ label: "Download CSV",
424
+ action: () => H(J(), e)
425
+ }), t;
425
426
  });
426
427
  return (t, c) => (m(), i("div", {
427
428
  ref_key: "containerRef",
@@ -430,7 +431,7 @@ var ce = ["width", "height"], le = ["x"], U = [
430
431
  }, [
431
432
  s.menu ? (m(), n(ae, {
432
433
  key: 0,
433
- items: $.value
434
+ items: Le.value
434
435
  }, null, 8, ["items"])) : r("", !0),
435
436
  (m(), i("svg", {
436
437
  ref_key: "svgRef",
@@ -541,18 +542,18 @@ var ce = ["width", "height"], le = ["x"], U = [
541
542
  "fill-opacity": t.dotOpacity ?? t.opacity ?? s.lineOpacity,
542
543
  stroke: t.dotStroke ?? "none"
543
544
  }, null, 8, _e))), 128)) : r("", !0)], 64))), 128)),
544
- Z.value && Y.value !== null ? (m(), i("line", {
545
+ we.value && Y.value !== null ? (m(), i("line", {
545
546
  key: 5,
546
- x1: I(Ce.value),
547
+ x1: I(Te.value),
547
548
  y1: O.value.top,
548
- x2: I(Ce.value),
549
+ x2: I(Te.value),
549
550
  y2: O.value.top + A.value,
550
551
  stroke: "currentColor",
551
552
  "stroke-opacity": "0.3",
552
553
  "stroke-dasharray": "4 2",
553
554
  "pointer-events": "none"
554
555
  }, null, 8, ve)) : r("", !0),
555
- (m(!0), i(e, null, g(we.value, (e, t) => (m(), i("circle", {
556
+ (m(!0), i(e, null, g(Ee.value, (e, t) => (m(), i("circle", {
556
557
  key: "hd" + t,
557
558
  cx: e.x,
558
559
  cy: e.y,
@@ -562,7 +563,7 @@ var ce = ["width", "height"], le = ["x"], U = [
562
563
  "stroke-width": "2",
563
564
  "pointer-events": "none"
564
565
  }, null, 8, K))), 128)),
565
- Z.value ? (m(), i("rect", {
566
+ we.value ? (m(), i("rect", {
566
567
  key: 6,
567
568
  x: O.value.left,
568
569
  y: O.value.top,
@@ -573,33 +574,39 @@ var ce = ["width", "height"], le = ["x"], U = [
573
574
  cursor: "crosshair",
574
575
  "touch-action": "none"
575
576
  },
576
- onMousemove: ke,
577
- onMouseleave: Ae,
578
- onClick: je,
579
- onTouchstart: w(Me, ["prevent"]),
580
- onTouchmove: w(Ne, ["prevent"]),
581
- onTouchend: Pe
577
+ onMousemove: je,
578
+ onMouseleave: Me,
579
+ onClick: Ne,
580
+ onTouchstart: w(Pe, ["prevent"]),
581
+ onTouchmove: w(Fe, ["prevent"]),
582
+ onTouchend: Q
582
583
  }, null, 40, q)) : r("", !0)
583
584
  ], 8, ce)),
584
- Z.value && Y.value !== null && Q.value ? (m(), i("div", {
585
+ we.value && Y.value !== null && Z.value ? (m(), i("div", {
585
586
  key: 1,
586
587
  ref_key: "tooltipRef",
587
- ref: Se,
588
+ ref: Ce,
588
589
  class: "chart-tooltip-content",
589
590
  style: {
590
591
  position: "absolute",
591
592
  transform: "translateY(-50%)"
592
593
  }
593
- }, [_(t.$slots, "tooltip", d(l(Q.value)), () => [a("div", ye, [Q.value.xLabel ? (m(), i("div", be, v(Q.value.xLabel), 1)) : r("", !0), (m(!0), i(e, null, g(Q.value.values, (e) => (m(), i("div", {
594
+ }, [_(t.$slots, "tooltip", d(l(Z.value)), () => [a("div", ye, [Z.value.xLabel ? (m(), i("div", be, v(Z.value.xLabel), 1)) : r("", !0), (m(!0), i(e, null, g(Z.value.values, (e) => (m(), i("div", {
594
595
  key: e.seriesIndex,
595
596
  class: "line-chart-tooltip-row"
596
597
  }, [a("span", {
597
598
  class: "line-chart-tooltip-swatch",
598
599
  style: f({ background: e.color })
599
- }, null, 4), o(" " + v(isFinite(e.value) ? L(e.value) : "—"), 1)]))), 128))])], !0)], 512)) : r("", !0)
600
+ }, null, 4), o(" " + v(isFinite(e.value) ? L(e.value) : "—"), 1)]))), 128))])], !0)], 512)) : r("", !0),
601
+ $.value ? (m(), i("a", {
602
+ key: 2,
603
+ class: "line-chart-download-link",
604
+ href: Ie.value,
605
+ download: `${B()}.csv`
606
+ }, v($.value), 9, xe)) : r("", !0)
600
607
  ], 512));
601
608
  }
602
- }), [["__scopeId", "data-v-4ea55781"]]), Y = {
609
+ }), [["__scopeId", "data-v-61fdeef2"]]), Y = {
603
610
  "01013": "010259",
604
611
  "01015": "010177",
605
612
  "01029": "010177",
@@ -4710,25 +4717,25 @@ var ce = ["width", "height"], le = ["x"], U = [
4710
4717
  560775: "Teton, WY - Lincoln, WY",
4711
4718
  560792: "Uinta, WY",
4712
4719
  560804: "Weston, WY"
4713
- }, Se = ["width", "height"], Z = [
4720
+ }, Ce = ["width", "height"], we = [
4714
4721
  "data-feat-id",
4715
4722
  "d",
4716
4723
  "fill",
4717
4724
  "stroke",
4718
4725
  "stroke-width"
4719
- ], Ce = { key: 0 }, we = ["d", "stroke"], Q = ["transform"], Te = {
4726
+ ], Te = { key: 0 }, Ee = ["d", "stroke"], Z = ["transform"], De = {
4720
4727
  key: 0,
4721
4728
  y: 5,
4722
4729
  "font-size": "13",
4723
4730
  "font-weight": "600",
4724
4731
  fill: "currentColor"
4725
- }, Ee = ["x", "fill"], De = ["x"], Oe = {
4732
+ }, Oe = ["x", "fill"], ke = ["x"], Ae = {
4726
4733
  key: 0,
4727
4734
  y: 5,
4728
4735
  "font-size": "13",
4729
4736
  "font-weight": "600",
4730
4737
  fill: "currentColor"
4731
- }, ke = ["offset", "stop-color"], Ae = ["x", "fill"], je = ["x"], Me = ["x"], Ne = /* @__PURE__ */ B(/* @__PURE__ */ c({
4738
+ }, je = ["offset", "stop-color"], Me = ["x", "fill"], Ne = ["x"], Pe = ["x"], Fe = /* @__PURE__ */ B(/* @__PURE__ */ c({
4732
4739
  __name: "ChoroplethMap",
4733
4740
  props: {
4734
4741
  topology: {},
@@ -4767,11 +4774,11 @@ var ce = ["width", "height"], le = ["x"], U = [
4767
4774
  function A() {
4768
4775
  if (D) return;
4769
4776
  let e = b.value;
4770
- e && (e.addEventListener("click", $), e.addEventListener("mouseover", $), e.addEventListener("mousemove", Fe), e.addEventListener("mouseout", Ie));
4777
+ e && (e.addEventListener("click", Q), e.addEventListener("mouseover", Q), e.addEventListener("mousemove", $), e.addEventListener("mouseout", Ie));
4771
4778
  }
4772
4779
  function j() {
4773
4780
  let e = b.value;
4774
- e && (e.removeEventListener("click", $), e.removeEventListener("mouseover", $), e.removeEventListener("mousemove", Fe), e.removeEventListener("mouseout", Ie));
4781
+ e && (e.removeEventListener("click", Q), e.removeEventListener("mouseover", Q), e.removeEventListener("mousemove", $), e.removeEventListener("mouseout", Ie));
4775
4782
  }
4776
4783
  p(() => {
4777
4784
  f.value && (C.value = f.value.clientWidth, O = new ResizeObserver((e) => {
@@ -4779,13 +4786,13 @@ var ce = ["width", "height"], le = ["x"], U = [
4779
4786
  t && (C.value = t.contentRect.width);
4780
4787
  }), O.observe(f.value)), M(), A();
4781
4788
  }), ee(() => {
4782
- O?.disconnect(), N(), j(), J();
4789
+ O?.disconnect(), N(), j(), Se();
4783
4790
  });
4784
4791
  function M() {
4785
4792
  if (!_.value || !b.value || !c.zoom && !c.pan) return;
4786
4793
  let e = re(_.value);
4787
4794
  k = ne().scaleExtent(c.zoom ? [1, 12] : [1, 1]).on("start", () => {
4788
- E = !0, Pe();
4795
+ E = !0, Fe();
4789
4796
  }).on("zoom", (e) => {
4790
4797
  b.value && b.value.setAttribute("transform", e.transform);
4791
4798
  }).on("end", () => {
@@ -4913,34 +4920,34 @@ var ce = ["width", "height"], le = ["x"], U = [
4913
4920
  };
4914
4921
  c.tooltipFormat ? T.innerHTML = c.tooltipFormat(a) : T.textContent = i == null ? r : `${r}: ${i}`, T.style.left = `${t + 16}px`, T.style.top = `${n}px`;
4915
4922
  }
4916
- function J() {
4923
+ function Se() {
4917
4924
  T &&= (T.remove(), null);
4918
4925
  }
4919
- function Ne(e, t) {
4926
+ function J(e, t) {
4920
4927
  w && w !== e && (w.setAttribute("stroke-width", String(U.value)), w.setAttribute("stroke", c.strokeColor)), w = e, e.parentNode?.appendChild(e), e.setAttribute("stroke-width", String(U.value + 1)), e.setAttribute("stroke", "#555");
4921
4928
  }
4922
- function Pe() {
4923
- w && (w.setAttribute("stroke-width", String(U.value)), w.setAttribute("stroke", c.strokeColor), w = null, l("stateHover", null)), J();
4929
+ function Fe() {
4930
+ w && (w.setAttribute("stroke-width", String(U.value)), w.setAttribute("stroke", c.strokeColor), w = null, l("stateHover", null)), Se();
4924
4931
  }
4925
- function $(e) {
4932
+ function Q(e) {
4926
4933
  if (E) return;
4927
4934
  let t = e, n = be(t.target);
4928
4935
  n && (e.type === "click" ? l("stateClick", {
4929
4936
  id: String(n.feat.id),
4930
4937
  name: K(n.feat),
4931
4938
  value: q(n.feat)
4932
- }) : e.type === "mouseover" && (Ne(n.pathEl, n.feat), c.tooltipTrigger && xe(n.feat, t.clientX, t.clientY), l("stateHover", {
4939
+ }) : e.type === "mouseover" && (J(n.pathEl, n.feat), c.tooltipTrigger && xe(n.feat, t.clientX, t.clientY), l("stateHover", {
4933
4940
  id: String(n.feat.id),
4934
4941
  name: K(n.feat),
4935
4942
  value: q(n.feat)
4936
4943
  })));
4937
4944
  }
4938
- function Fe(e) {
4945
+ function $(e) {
4939
4946
  E || !T || (T.style.left = `${e.clientX + 16}px`, T.style.top = `${e.clientY}px`);
4940
4947
  }
4941
4948
  function Ie(e) {
4942
4949
  let t = e.relatedTarget;
4943
- t && b.value?.contains(t) || Pe();
4950
+ t && b.value?.contains(t) || Fe();
4944
4951
  }
4945
4952
  function Le() {
4946
4953
  return typeof c.menu == "string" ? c.menu : "choropleth";
@@ -5030,7 +5037,7 @@ var ce = ["width", "height"], le = ["x"], U = [
5030
5037
  stroke: o.strokeColor,
5031
5038
  "stroke-width": U.value,
5032
5039
  class: "state-path"
5033
- }, [o.tooltipTrigger ? r("", !0) : (m(), i("title", Ce, v(K(e)) + v(q(e) == null ? "" : `: ${q(e)}`), 1))], 8, Z))), 128)), H.value ? (m(), i("path", {
5040
+ }, [o.tooltipTrigger ? r("", !0) : (m(), i("title", Te, v(K(e)) + v(q(e) == null ? "" : `: ${q(e)}`), 1))], 8, we))), 128)), H.value ? (m(), i("path", {
5034
5041
  key: 0,
5035
5042
  d: le.value(H.value) ?? void 0,
5036
5043
  fill: "none",
@@ -5038,25 +5045,25 @@ var ce = ["width", "height"], le = ["x"], U = [
5038
5045
  "stroke-width": 1,
5039
5046
  "stroke-linejoin": "round",
5040
5047
  "pointer-events": "none"
5041
- }, null, 8, we)) : r("", !0)], 512),
5048
+ }, null, 8, Ee)) : r("", !0)], 512),
5042
5049
  Re.value ? (m(), i("g", {
5043
5050
  key: 0,
5044
5051
  class: "choropleth-legend",
5045
5052
  transform: `translate(${Xe.value},${We.value})`
5046
- }, [W.value || G.value ? (m(), i(e, { key: 0 }, [o.legendTitle ? (m(), i("text", Te, v(o.legendTitle), 1)) : r("", !0), (m(!0), i(e, null, g(qe.value, (t, n) => (m(), i(e, { key: t.key }, [a("rect", {
5053
+ }, [W.value || G.value ? (m(), i(e, { key: 0 }, [o.legendTitle ? (m(), i("text", De, v(o.legendTitle), 1)) : r("", !0), (m(!0), i(e, null, g(qe.value, (t, n) => (m(), i(e, { key: t.key }, [a("rect", {
5047
5054
  x: Ye.value[n],
5048
5055
  y: -5,
5049
5056
  width: "12",
5050
5057
  height: "12",
5051
5058
  rx: "3",
5052
5059
  fill: t.color
5053
- }, null, 8, Ee), a("text", {
5060
+ }, null, 8, Oe), a("text", {
5054
5061
  x: Ye.value[n] + 16,
5055
5062
  y: 5,
5056
5063
  "font-size": "13",
5057
5064
  fill: "currentColor"
5058
- }, v(t.label), 9, De)], 64))), 128))], 64)) : (m(), i(e, { key: 1 }, [
5059
- o.legendTitle ? (m(), i("text", Oe, v(o.legendTitle), 1)) : r("", !0),
5065
+ }, v(t.label), 9, ke)], 64))), 128))], 64)) : (m(), i(e, { key: 1 }, [
5066
+ o.legendTitle ? (m(), i("text", Ae, v(o.legendTitle), 1)) : r("", !0),
5060
5067
  a("defs", null, [a("linearGradient", {
5061
5068
  id: d,
5062
5069
  x1: "0",
@@ -5067,7 +5074,7 @@ var ce = ["width", "height"], le = ["x"], U = [
5067
5074
  key: e.offset,
5068
5075
  offset: e.offset,
5069
5076
  "stop-color": e.color
5070
- }, null, 8, ke))), 128))])]),
5077
+ }, null, 8, je))), 128))])]),
5071
5078
  a("rect", {
5072
5079
  x: o.legendTitle ? o.legendTitle.length * 8 + 12 : 0,
5073
5080
  y: -6,
@@ -5075,7 +5082,7 @@ var ce = ["width", "height"], le = ["x"], U = [
5075
5082
  height: 12,
5076
5083
  rx: "2",
5077
5084
  fill: `url(#${d})`
5078
- }, null, 8, Ae),
5085
+ }, null, 8, Me),
5079
5086
  (m(!0), i(e, null, g(Ke.value, (e) => (m(), i("text", {
5080
5087
  key: e.value,
5081
5088
  x: (o.legendTitle ? o.legendTitle.length * 8 + 12 : 0) + e.pct / 100 * 160,
@@ -5084,8 +5091,8 @@ var ce = ["width", "height"], le = ["x"], U = [
5084
5091
  fill: "currentColor",
5085
5092
  opacity: "0.7",
5086
5093
  "text-anchor": "middle"
5087
- }, v(e.value), 9, je))), 128))
5088
- ], 64))], 8, Q)) : r("", !0),
5094
+ }, v(e.value), 9, Ne))), 128))
5095
+ ], 64))], 8, Z)) : r("", !0),
5089
5096
  o.title ? (m(), i("text", {
5090
5097
  key: 1,
5091
5098
  x: L.value / 2,
@@ -5094,10 +5101,10 @@ var ce = ["width", "height"], le = ["x"], U = [
5094
5101
  "font-size": "14",
5095
5102
  "font-weight": "600",
5096
5103
  fill: "currentColor"
5097
- }, v(o.title), 9, Me)) : r("", !0)
5098
- ], 8, Se))], 2));
5104
+ }, v(o.title), 9, Pe)) : r("", !0)
5105
+ ], 8, Ce))], 2));
5099
5106
  }
5100
- }), [["__scopeId", "data-v-ffaf1671"]]), Pe = /* @__PURE__ */ B(/* @__PURE__ */ c({
5107
+ }), [["__scopeId", "data-v-ffaf1671"]]), Q = /* @__PURE__ */ B(/* @__PURE__ */ c({
5101
5108
  __name: "ChartTooltip",
5102
5109
  props: {
5103
5110
  x: {},
@@ -5148,7 +5155,7 @@ var ce = ["width", "height"], le = ["x"], U = [
5148
5155
  _: 3
5149
5156
  }, 8, ["open"])) : r("", !0);
5150
5157
  }
5151
- }), [["__scopeId", "data-v-44377f70"]]), $ = { class: "TableWrapper" }, Fe = { class: "Table" }, Ie = /* @__PURE__ */ B(/* @__PURE__ */ c({
5158
+ }), [["__scopeId", "data-v-44377f70"]]), $ = { class: "TableWrapper" }, Ie = { class: "Table" }, Le = ["href", "download"], Re = /* @__PURE__ */ B(/* @__PURE__ */ c({
5152
5159
  __name: "DataTable",
5153
5160
  props: {
5154
5161
  data: {},
@@ -5157,7 +5164,10 @@ var ce = ["width", "height"], le = ["x"], U = [
5157
5164
  menu: {
5158
5165
  type: [Boolean, String],
5159
5166
  default: !0
5160
- }
5167
+ },
5168
+ csv: {},
5169
+ filename: {},
5170
+ downloadLink: { type: [Boolean, String] }
5161
5171
  },
5162
5172
  setup(o) {
5163
5173
  let s = {
@@ -5206,12 +5216,14 @@ var ce = ["width", "height"], le = ["x"], U = [
5206
5216
  return n == null ? "" : e.enumLabels && typeof n == "number" ? e.enumLabels[n] ?? String(n) : typeof n == "number" ? Number.isInteger(n) ? n.toString() : n.toFixed(4) : typeof n == "boolean" ? n ? "true" : "false" : String(n);
5207
5217
  }
5208
5218
  function b() {
5209
- return typeof c.menu == "string" ? c.menu : "data";
5219
+ return c.filename ? c.filename : typeof c.menu == "string" ? c.menu : "data";
5210
5220
  }
5211
5221
  function x(e) {
5212
5222
  return e.includes(",") || e.includes("\"") || e.includes("\n") ? `"${e.replace(/"/g, "\"\"")}"` : e;
5213
5223
  }
5214
5224
  function S() {
5225
+ if (typeof c.csv == "function") return c.csv();
5226
+ if (typeof c.csv == "string") return c.csv;
5215
5227
  let e = h.value, t = _.value, n = [e.map((e) => x(l(e.name))).join(",")];
5216
5228
  for (let r = 0; r < t; r++) {
5217
5229
  let t = e.map((e) => x(y(e, r)));
@@ -5219,29 +5231,38 @@ var ce = ["width", "height"], le = ["x"], U = [
5219
5231
  }
5220
5232
  return n.join("\n");
5221
5233
  }
5222
- let C = t(() => [{
5234
+ let C = t(() => c.downloadLink ? [] : [{
5223
5235
  label: "Download CSV",
5224
5236
  action: () => H(S(), b())
5225
- }]);
5226
- return (t, s) => (m(), i("div", { class: u(["TableOuter", { "has-menu": o.menu }]) }, [o.menu ? (m(), n(ae, {
5227
- key: 0,
5228
- items: C.value
5229
- }, null, 8, ["items"])) : r("", !0), a("div", $, [a("table", Fe, [
5230
- a("colgroup", null, [(m(!0), i(e, null, g(h.value, (e) => (m(), i("col", {
5231
- key: e.name,
5232
- style: f(d(e.name))
5233
- }, null, 4))), 128))]),
5234
- a("thead", null, [a("tr", null, [(m(!0), i(e, null, g(h.value, (e) => (m(), i("th", {
5235
- key: e.name,
5236
- style: f(p(e.name))
5237
- }, v(l(e.name)), 5))), 128))])]),
5238
- a("tbody", null, [(m(!0), i(e, null, g(_.value, (t) => (m(), i("tr", { key: t }, [(m(!0), i(e, null, g(h.value, (e) => (m(), i("td", {
5239
- key: e.name,
5240
- class: u(o.columnConfig?.[e.name]?.cellClass),
5241
- style: f(p(e.name))
5242
- }, v(y(e, t - 1)), 7))), 128))]))), 128))])
5243
- ])])], 2));
5237
+ }]), w = t(() => c.downloadLink ? typeof c.downloadLink == "string" ? c.downloadLink : "Download data (CSV)" : null), T = t(() => c.downloadLink ? `data:text/csv;charset=utf-8,${encodeURIComponent(S())}` : null), E = t(() => c.menu && C.value.length > 0);
5238
+ return (t, s) => (m(), i("div", { class: u(["TableOuter", { "has-menu": E.value }]) }, [
5239
+ E.value ? (m(), n(ae, {
5240
+ key: 0,
5241
+ items: C.value
5242
+ }, null, 8, ["items"])) : r("", !0),
5243
+ a("div", $, [a("table", Ie, [
5244
+ a("colgroup", null, [(m(!0), i(e, null, g(h.value, (e) => (m(), i("col", {
5245
+ key: e.name,
5246
+ style: f(d(e.name))
5247
+ }, null, 4))), 128))]),
5248
+ a("thead", null, [a("tr", null, [(m(!0), i(e, null, g(h.value, (e) => (m(), i("th", {
5249
+ key: e.name,
5250
+ style: f(p(e.name))
5251
+ }, v(l(e.name)), 5))), 128))])]),
5252
+ a("tbody", null, [(m(!0), i(e, null, g(_.value, (t) => (m(), i("tr", { key: t }, [(m(!0), i(e, null, g(h.value, (e) => (m(), i("td", {
5253
+ key: e.name,
5254
+ class: u(o.columnConfig?.[e.name]?.cellClass),
5255
+ style: f(p(e.name))
5256
+ }, v(y(e, t - 1)), 7))), 128))]))), 128))])
5257
+ ])]),
5258
+ w.value ? (m(), i("a", {
5259
+ key: 1,
5260
+ class: "data-table-download-link",
5261
+ href: T.value,
5262
+ download: `${b()}.csv`
5263
+ }, v(w.value), 9, Le)) : r("", !0)
5264
+ ], 2));
5244
5265
  }
5245
- }), [["__scopeId", "data-v-dbfb7c84"]]);
5266
+ }), [["__scopeId", "data-v-505e2187"]]);
5246
5267
  //#endregion
5247
- export { Pe as ChartTooltip, Ne as ChoroplethMap, Ie as DataTable, J as LineChart };
5268
+ export { Q as ChartTooltip, Fe as ChoroplethMap, Re as DataTable, J as LineChart };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cfasim-ui/charts",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "description": "Chart visualization components for cfasim-ui",
6
6
  "license": "Apache-2.0",
@@ -33,7 +33,7 @@
33
33
  "d3-zoom": "^3.0.0",
34
34
  "reka-ui": "^2.9.2",
35
35
  "topojson-client": "^3.1.0",
36
- "@cfasim-ui/shared": "0.3.0"
36
+ "@cfasim-ui/shared": "0.3.1"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "vue": "^3.5.0"