@smallwebco/tinypivot-react 1.0.52 → 1.0.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -272,6 +272,76 @@ function ChartBuilder({
272
272
  () => import_tinypivot_core2.CHART_TYPES.find((ct) => ct.type === chartConfig.type),
273
273
  [chartConfig.type]
274
274
  );
275
+ const isScatterType = (0, import_react2.useMemo)(
276
+ () => ["scatter", "bubble"].includes(chartConfig.type),
277
+ [chartConfig.type]
278
+ );
279
+ const isHeatmapType = (0, import_react2.useMemo)(
280
+ () => chartConfig.type === "heatmap",
281
+ [chartConfig.type]
282
+ );
283
+ const zoneLabels = (0, import_react2.useMemo)(() => {
284
+ const type = chartConfig.type;
285
+ switch (type) {
286
+ case "scatter":
287
+ case "bubble":
288
+ return {
289
+ xAxis: "X-Axis (measure)",
290
+ xAxisPlaceholder: "Drop a measure",
291
+ yAxis: "Y-Axis (measure)",
292
+ yAxisPlaceholder: "Drop a measure",
293
+ series: "Color by (optional)",
294
+ seriesPlaceholder: "Group points by dimension",
295
+ showSize: type === "bubble",
296
+ showSeries: true
297
+ };
298
+ case "heatmap":
299
+ return {
300
+ xAxis: "X-Axis (dimension)",
301
+ xAxisPlaceholder: "Drop a dimension",
302
+ yAxis: "Y-Axis (dimension)",
303
+ yAxisPlaceholder: "Drop a dimension",
304
+ series: "Value / Intensity",
305
+ seriesPlaceholder: "Drop a measure for color intensity",
306
+ showSize: false,
307
+ showSeries: true
308
+ };
309
+ case "pie":
310
+ case "donut":
311
+ return {
312
+ xAxis: "Slices (dimension)",
313
+ xAxisPlaceholder: "Drop a dimension",
314
+ yAxis: "Values (measure)",
315
+ yAxisPlaceholder: "Drop a measure",
316
+ series: "",
317
+ seriesPlaceholder: "",
318
+ showSize: false,
319
+ showSeries: false
320
+ };
321
+ case "radar":
322
+ return {
323
+ xAxis: "Axes (dimension)",
324
+ xAxisPlaceholder: "Drop a dimension",
325
+ yAxis: "Values (measure)",
326
+ yAxisPlaceholder: "Drop a measure",
327
+ series: "Compare by (optional)",
328
+ seriesPlaceholder: "Group by dimension",
329
+ showSize: false,
330
+ showSeries: true
331
+ };
332
+ default:
333
+ return {
334
+ xAxis: "X-Axis (dimension)",
335
+ xAxisPlaceholder: "Drop a dimension",
336
+ yAxis: "Y-Axis (measure)",
337
+ yAxisPlaceholder: "Drop a measure",
338
+ series: "Color / Series (optional)",
339
+ seriesPlaceholder: "Group by dimension",
340
+ showSize: false,
341
+ showSeries: true
342
+ };
343
+ }
344
+ }, [chartConfig.type]);
275
345
  const handleDragStart = (0, import_react2.useCallback)((field, event) => {
276
346
  setDraggingField(field);
277
347
  event.dataTransfer?.setData("text/plain", field.field);
@@ -348,15 +418,40 @@ function ChartBuilder({
348
418
  onConfigChange?.(newConfig);
349
419
  }, [chartConfig, onConfigChange]);
350
420
  const updateAggregation = (0, import_react2.useCallback)((zone, aggregation) => {
351
- const field = zone === "yAxis" ? chartConfig.yAxis : chartConfig.sizeField;
421
+ let field;
422
+ switch (zone) {
423
+ case "xAxis":
424
+ field = chartConfig.xAxis;
425
+ break;
426
+ case "yAxis":
427
+ field = chartConfig.yAxis;
428
+ break;
429
+ case "size":
430
+ field = chartConfig.sizeField;
431
+ break;
432
+ case "color":
433
+ field = chartConfig.colorField;
434
+ break;
435
+ default:
436
+ return;
437
+ }
352
438
  if (!field)
353
439
  return;
354
440
  const updated = { ...field, aggregation };
355
441
  let newConfig = { ...chartConfig };
356
- if (zone === "yAxis") {
357
- newConfig = { ...newConfig, yAxis: updated };
358
- } else if (zone === "size") {
359
- newConfig = { ...newConfig, sizeField: updated };
442
+ switch (zone) {
443
+ case "xAxis":
444
+ newConfig = { ...newConfig, xAxis: updated };
445
+ break;
446
+ case "yAxis":
447
+ newConfig = { ...newConfig, yAxis: updated };
448
+ break;
449
+ case "size":
450
+ newConfig = { ...newConfig, sizeField: updated };
451
+ break;
452
+ case "color":
453
+ newConfig = { ...newConfig, colorField: updated };
454
+ break;
360
455
  }
361
456
  setChartConfig(newConfig);
362
457
  onConfigChange?.(newConfig);
@@ -368,16 +463,20 @@ function ChartBuilder({
368
463
  area: "area",
369
464
  pie: "pie",
370
465
  donut: "donut",
466
+ radar: "radar",
371
467
  scatter: "scatter",
372
468
  bubble: "bubble",
373
- heatmap: "heatmap",
374
- treemap: "bar",
375
- // Treemap rendered as bar (compatibility)
376
- radar: "radar"
469
+ heatmap: "heatmap"
377
470
  };
378
471
  return mapping[type] || "bar";
379
472
  }, []);
380
473
  const formatValue = (0, import_react2.useCallback)((val, format, decimals) => {
474
+ if (val === null || val === void 0)
475
+ return "";
476
+ if (typeof val !== "number")
477
+ return String(val);
478
+ if (Number.isNaN(val))
479
+ return "";
381
480
  const dec = decimals ?? 0;
382
481
  if (format === "percent") {
383
482
  return `${val.toFixed(dec)}%`;
@@ -439,7 +538,10 @@ function ChartBuilder({
439
538
  enabled: options.showDataLabels ?? false
440
539
  },
441
540
  tooltip: {
442
- theme: isDark ? "dark" : "light"
541
+ theme: isDark ? "dark" : "light",
542
+ style: {
543
+ fontSize: "12px"
544
+ }
443
545
  },
444
546
  stroke: {
445
547
  curve: "smooth",
@@ -458,7 +560,7 @@ function ChartBuilder({
458
560
  }
459
561
  };
460
562
  }
461
- if (config.yAxis && !["pie", "donut", "radar", "treemap"].includes(config.type)) {
563
+ if (config.yAxis && !["pie", "donut", "radar"].includes(config.type)) {
462
564
  baseOptions.yaxis = {
463
565
  title: { text: options.yAxisTitle || config.yAxis.label },
464
566
  labels: {
@@ -521,11 +623,12 @@ function ChartBuilder({
521
623
  return chartData2.series[0]?.data || [];
522
624
  }
523
625
  if (config.type === "scatter" || config.type === "bubble") {
524
- const points = (0, import_tinypivot_core2.processChartDataForScatter)(data, config);
525
- return [{
526
- name: config.yAxis?.label || "Data",
527
- data: points
528
- }];
626
+ const scatterData = (0, import_tinypivot_core2.processChartDataForScatter)(data, config);
627
+ return scatterData.series;
628
+ }
629
+ if (config.type === "heatmap") {
630
+ const heatmapData = (0, import_tinypivot_core2.processChartDataForHeatmap)(data, config);
631
+ return heatmapData.series;
529
632
  }
530
633
  const chartData = (0, import_tinypivot_core2.processChartData)(data, config);
531
634
  return chartData.series;
@@ -544,7 +647,7 @@ function ChartBuilder({
544
647
  const chartOptionsWithCategories = (0, import_react2.useMemo)(() => {
545
648
  const options = { ...chartOptions };
546
649
  const config = chartConfig;
547
- if (!["pie", "donut", "scatter", "bubble"].includes(config.type)) {
650
+ if (!["pie", "donut", "scatter", "bubble", "heatmap"].includes(config.type)) {
548
651
  options.xaxis = {
549
652
  ...options.xaxis,
550
653
  categories: chartLabels
@@ -553,6 +656,46 @@ function ChartBuilder({
553
656
  if (config.type === "pie" || config.type === "donut") {
554
657
  options.labels = chartLabels;
555
658
  }
659
+ if (config.type === "heatmap") {
660
+ options.chart = {
661
+ ...options.chart,
662
+ type: "heatmap"
663
+ };
664
+ options.xaxis = {
665
+ ...options.xaxis,
666
+ type: "category"
667
+ };
668
+ options.dataLabels = {
669
+ enabled: true,
670
+ style: {
671
+ colors: ["#fff"],
672
+ fontSize: "10px"
673
+ },
674
+ formatter: (val) => {
675
+ if (val === null || val === void 0)
676
+ return "";
677
+ if (typeof val !== "number")
678
+ return String(val);
679
+ if (val >= 1e6)
680
+ return `${(val / 1e6).toFixed(1)}M`;
681
+ if (val >= 1e3)
682
+ return `${(val / 1e3).toFixed(0)}K`;
683
+ return Math.round(val).toLocaleString();
684
+ }
685
+ };
686
+ options.plotOptions = {
687
+ heatmap: {
688
+ shadeIntensity: 0.5,
689
+ radius: 2,
690
+ enableShades: true,
691
+ colorScale: {
692
+ inverse: false
693
+ }
694
+ }
695
+ };
696
+ options.colors = ["#6366f1"];
697
+ options.legend = { show: false };
698
+ }
556
699
  return options;
557
700
  }, [chartOptions, chartConfig, chartLabels]);
558
701
  const getChartIcon = (0, import_react2.useCallback)((type) => {
@@ -562,10 +705,9 @@ function ChartBuilder({
562
705
  area: "M3 17l6-6 4 4 8-8v10H3z",
563
706
  pie: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8v8l5.66 5.66C14.28 19.04 13.18 20 12 20z",
564
707
  donut: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 14c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z",
565
- scatter: "M7 14c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6-5c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm4 7c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z",
566
- bubble: "M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm-6 3c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 2c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z",
708
+ scatter: "M7 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm5-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm5 8a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm-3 4a2 2 0 1 0 0-4 2 2 0 0 0 0 4z",
709
+ bubble: "M7 14a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm5-5a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm5 7a4 4 0 1 0 0-8 4 4 0 0 0 0 8z",
567
710
  heatmap: "M3 3h4v4H3V3zm6 0h4v4H9V3zm6 0h4v4h-4V3zM3 9h4v4H3V9zm6 0h4v4H9V9zm6 0h4v4h-4V9zM3 15h4v4H3v-4zm6 0h4v4H9v-4zm6 0h4v4h-4v-4z",
568
- treemap: "M3 3h8v10H3V3zm10 0h8v6h-8V3zM3 15h8v6H3v-6zm10-4h8v10h-8V11z",
569
711
  radar: "M12 2L4 6v6c0 5.55 3.84 10.74 8 12 4.16-1.26 8-6.45 8-12V6l-8-4zm0 3.18l6 3v5.09c0 4.08-2.76 7.91-6 9.14V5.18z"
570
712
  };
571
713
  return icons[type] || icons.bar;
@@ -592,7 +734,8 @@ function ChartBuilder({
592
734
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-fields-section", children: [
593
735
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h4", { className: "vpg-chart-fields-title", children: [
594
736
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-sm", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M4 6h16M4 12h10M4 18h6" }) }),
595
- "Dimensions"
737
+ "Dimensions",
738
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-chart-fields-hint", children: "(text/date)" })
596
739
  ] }),
597
740
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-fields-list", children: [
598
741
  dimensions.map((field) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
@@ -615,7 +758,8 @@ function ChartBuilder({
615
758
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-fields-section", children: [
616
759
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h4", { className: "vpg-chart-fields-title", children: [
617
760
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-sm", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M16 8v8M12 11v5M8 14v2M4 4v16h16" }) }),
618
- "Measures"
761
+ "Measures",
762
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-chart-fields-hint", children: "(numbers)" })
619
763
  ] }),
620
764
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-fields-list", children: [
621
765
  measures.map((field) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
@@ -638,7 +782,7 @@ function ChartBuilder({
638
782
  ] }),
639
783
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-config-panel", children: [
640
784
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-drop-zone-wrapper", children: [
641
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-chart-zone-label", children: "X-Axis / Category" }),
785
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-chart-zone-label", children: zoneLabels.xAxis }),
642
786
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
643
787
  "div",
644
788
  {
@@ -648,13 +792,22 @@ function ChartBuilder({
648
792
  onDrop: (e) => handleDrop("xAxis", e),
649
793
  children: chartConfig.xAxis ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
650
794
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-field-name", children: chartConfig.xAxis.label }),
795
+ isScatterType && chartConfig.xAxis.role === "measure" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
796
+ "select",
797
+ {
798
+ className: "vpg-zone-aggregation",
799
+ value: chartConfig.xAxis.aggregation || "sum",
800
+ onChange: (e) => updateAggregation("xAxis", e.target.value),
801
+ children: import_tinypivot_core2.CHART_AGGREGATIONS.map((agg) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: agg.value, children: agg.symbol }, agg.value))
802
+ }
803
+ ),
651
804
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("xAxis"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
652
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-placeholder", children: "Drop dimension here" })
805
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-placeholder", children: zoneLabels.xAxisPlaceholder })
653
806
  }
654
807
  )
655
808
  ] }),
656
809
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-drop-zone-wrapper", children: [
657
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-chart-zone-label", children: "Y-Axis / Value" }),
810
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-chart-zone-label", children: zoneLabels.yAxis }),
658
811
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
659
812
  "div",
660
813
  {
@@ -664,7 +817,7 @@ function ChartBuilder({
664
817
  onDrop: (e) => handleDrop("yAxis", e),
665
818
  children: chartConfig.yAxis ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
666
819
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-field-name", children: chartConfig.yAxis.label }),
667
- chartConfig.yAxis.role === "measure" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
820
+ chartConfig.yAxis.role === "measure" && !isHeatmapType && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
668
821
  "select",
669
822
  {
670
823
  className: "vpg-zone-aggregation",
@@ -674,28 +827,37 @@ function ChartBuilder({
674
827
  }
675
828
  ),
676
829
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("yAxis"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
677
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-placeholder", children: "Drop measure here" })
830
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-placeholder", children: zoneLabels.yAxisPlaceholder })
678
831
  }
679
832
  )
680
833
  ] }),
681
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-drop-zone-wrapper", children: [
682
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-chart-zone-label", children: "Color / Series (optional)" }),
834
+ zoneLabels.showSeries && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-drop-zone-wrapper", children: [
835
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-chart-zone-label", children: zoneLabels.series }),
683
836
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
684
837
  "div",
685
838
  {
686
- className: `vpg-chart-drop-zone vpg-zone-optional ${dragOverZone === "series" ? "drag-over" : ""} ${chartConfig.seriesField ? "has-field" : ""}`,
687
- onDragOver: (e) => handleDragOver("series", e),
839
+ className: `vpg-chart-drop-zone vpg-zone-optional ${dragOverZone === "series" ? "drag-over" : ""} ${(isHeatmapType ? chartConfig.colorField : chartConfig.seriesField) ? "has-field" : ""}`,
840
+ onDragOver: (e) => handleDragOver(isHeatmapType ? "color" : "series", e),
688
841
  onDragLeave: handleDragLeave,
689
- onDrop: (e) => handleDrop("series", e),
690
- children: chartConfig.seriesField ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
691
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-field-name", children: chartConfig.seriesField.label }),
692
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("series"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
693
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-placeholder", children: "Group by dimension" })
842
+ onDrop: (e) => handleDrop(isHeatmapType ? "color" : "series", e),
843
+ children: (isHeatmapType ? chartConfig.colorField : chartConfig.seriesField) ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
844
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-field-name", children: isHeatmapType ? chartConfig.colorField?.label : chartConfig.seriesField?.label }),
845
+ isHeatmapType && chartConfig.colorField?.role === "measure" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
846
+ "select",
847
+ {
848
+ className: "vpg-zone-aggregation",
849
+ value: chartConfig.colorField?.aggregation || "sum",
850
+ onChange: (e) => updateAggregation("color", e.target.value),
851
+ children: import_tinypivot_core2.CHART_AGGREGATIONS.map((agg) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: agg.value, children: agg.symbol }, agg.value))
852
+ }
853
+ ),
854
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-zone-remove-btn", onClick: () => removeField(isHeatmapType ? "color" : "series"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
855
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-placeholder", children: zoneLabels.seriesPlaceholder })
694
856
  }
695
857
  )
696
858
  ] }),
697
- (chartConfig.type === "scatter" || chartConfig.type === "bubble") && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-drop-zone-wrapper", children: [
698
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-chart-zone-label", children: "Size (bubble)" }),
859
+ zoneLabels.showSize && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-drop-zone-wrapper", children: [
860
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-chart-zone-label", children: "Size (number)" }),
699
861
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
700
862
  "div",
701
863
  {
@@ -705,8 +867,17 @@ function ChartBuilder({
705
867
  onDrop: (e) => handleDrop("size", e),
706
868
  children: chartConfig.sizeField ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
707
869
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-field-name", children: chartConfig.sizeField.label }),
870
+ chartConfig.sizeField.role === "measure" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
871
+ "select",
872
+ {
873
+ className: "vpg-zone-aggregation",
874
+ value: chartConfig.sizeField.aggregation || "sum",
875
+ onChange: (e) => updateAggregation("size", e.target.value),
876
+ children: import_tinypivot_core2.CHART_AGGREGATIONS.map((agg) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: agg.value, children: agg.symbol }, agg.value))
877
+ }
878
+ ),
708
879
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("size"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
709
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-placeholder", children: "Drop measure for size" })
880
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-placeholder", children: "Drop a number for bubble size" })
710
881
  }
711
882
  )
712
883
  ] }),