@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.js CHANGED
@@ -198,6 +198,7 @@ import {
198
198
  getChartGuidance,
199
199
  isChartConfigValid,
200
200
  processChartData,
201
+ processChartDataForHeatmap,
201
202
  processChartDataForPie,
202
203
  processChartDataForScatter
203
204
  } from "@smallwebco/tinypivot-core";
@@ -227,6 +228,76 @@ function ChartBuilder({
227
228
  () => CHART_TYPES.find((ct) => ct.type === chartConfig.type),
228
229
  [chartConfig.type]
229
230
  );
231
+ const isScatterType = useMemo2(
232
+ () => ["scatter", "bubble"].includes(chartConfig.type),
233
+ [chartConfig.type]
234
+ );
235
+ const isHeatmapType = useMemo2(
236
+ () => chartConfig.type === "heatmap",
237
+ [chartConfig.type]
238
+ );
239
+ const zoneLabels = useMemo2(() => {
240
+ const type = chartConfig.type;
241
+ switch (type) {
242
+ case "scatter":
243
+ case "bubble":
244
+ return {
245
+ xAxis: "X-Axis (measure)",
246
+ xAxisPlaceholder: "Drop a measure",
247
+ yAxis: "Y-Axis (measure)",
248
+ yAxisPlaceholder: "Drop a measure",
249
+ series: "Color by (optional)",
250
+ seriesPlaceholder: "Group points by dimension",
251
+ showSize: type === "bubble",
252
+ showSeries: true
253
+ };
254
+ case "heatmap":
255
+ return {
256
+ xAxis: "X-Axis (dimension)",
257
+ xAxisPlaceholder: "Drop a dimension",
258
+ yAxis: "Y-Axis (dimension)",
259
+ yAxisPlaceholder: "Drop a dimension",
260
+ series: "Value / Intensity",
261
+ seriesPlaceholder: "Drop a measure for color intensity",
262
+ showSize: false,
263
+ showSeries: true
264
+ };
265
+ case "pie":
266
+ case "donut":
267
+ return {
268
+ xAxis: "Slices (dimension)",
269
+ xAxisPlaceholder: "Drop a dimension",
270
+ yAxis: "Values (measure)",
271
+ yAxisPlaceholder: "Drop a measure",
272
+ series: "",
273
+ seriesPlaceholder: "",
274
+ showSize: false,
275
+ showSeries: false
276
+ };
277
+ case "radar":
278
+ return {
279
+ xAxis: "Axes (dimension)",
280
+ xAxisPlaceholder: "Drop a dimension",
281
+ yAxis: "Values (measure)",
282
+ yAxisPlaceholder: "Drop a measure",
283
+ series: "Compare by (optional)",
284
+ seriesPlaceholder: "Group by dimension",
285
+ showSize: false,
286
+ showSeries: true
287
+ };
288
+ default:
289
+ return {
290
+ xAxis: "X-Axis (dimension)",
291
+ xAxisPlaceholder: "Drop a dimension",
292
+ yAxis: "Y-Axis (measure)",
293
+ yAxisPlaceholder: "Drop a measure",
294
+ series: "Color / Series (optional)",
295
+ seriesPlaceholder: "Group by dimension",
296
+ showSize: false,
297
+ showSeries: true
298
+ };
299
+ }
300
+ }, [chartConfig.type]);
230
301
  const handleDragStart = useCallback2((field, event) => {
231
302
  setDraggingField(field);
232
303
  event.dataTransfer?.setData("text/plain", field.field);
@@ -303,15 +374,40 @@ function ChartBuilder({
303
374
  onConfigChange?.(newConfig);
304
375
  }, [chartConfig, onConfigChange]);
305
376
  const updateAggregation = useCallback2((zone, aggregation) => {
306
- const field = zone === "yAxis" ? chartConfig.yAxis : chartConfig.sizeField;
377
+ let field;
378
+ switch (zone) {
379
+ case "xAxis":
380
+ field = chartConfig.xAxis;
381
+ break;
382
+ case "yAxis":
383
+ field = chartConfig.yAxis;
384
+ break;
385
+ case "size":
386
+ field = chartConfig.sizeField;
387
+ break;
388
+ case "color":
389
+ field = chartConfig.colorField;
390
+ break;
391
+ default:
392
+ return;
393
+ }
307
394
  if (!field)
308
395
  return;
309
396
  const updated = { ...field, aggregation };
310
397
  let newConfig = { ...chartConfig };
311
- if (zone === "yAxis") {
312
- newConfig = { ...newConfig, yAxis: updated };
313
- } else if (zone === "size") {
314
- newConfig = { ...newConfig, sizeField: updated };
398
+ switch (zone) {
399
+ case "xAxis":
400
+ newConfig = { ...newConfig, xAxis: updated };
401
+ break;
402
+ case "yAxis":
403
+ newConfig = { ...newConfig, yAxis: updated };
404
+ break;
405
+ case "size":
406
+ newConfig = { ...newConfig, sizeField: updated };
407
+ break;
408
+ case "color":
409
+ newConfig = { ...newConfig, colorField: updated };
410
+ break;
315
411
  }
316
412
  setChartConfig(newConfig);
317
413
  onConfigChange?.(newConfig);
@@ -323,16 +419,20 @@ function ChartBuilder({
323
419
  area: "area",
324
420
  pie: "pie",
325
421
  donut: "donut",
422
+ radar: "radar",
326
423
  scatter: "scatter",
327
424
  bubble: "bubble",
328
- heatmap: "heatmap",
329
- treemap: "bar",
330
- // Treemap rendered as bar (compatibility)
331
- radar: "radar"
425
+ heatmap: "heatmap"
332
426
  };
333
427
  return mapping[type] || "bar";
334
428
  }, []);
335
429
  const formatValue = useCallback2((val, format, decimals) => {
430
+ if (val === null || val === void 0)
431
+ return "";
432
+ if (typeof val !== "number")
433
+ return String(val);
434
+ if (Number.isNaN(val))
435
+ return "";
336
436
  const dec = decimals ?? 0;
337
437
  if (format === "percent") {
338
438
  return `${val.toFixed(dec)}%`;
@@ -394,7 +494,10 @@ function ChartBuilder({
394
494
  enabled: options.showDataLabels ?? false
395
495
  },
396
496
  tooltip: {
397
- theme: isDark ? "dark" : "light"
497
+ theme: isDark ? "dark" : "light",
498
+ style: {
499
+ fontSize: "12px"
500
+ }
398
501
  },
399
502
  stroke: {
400
503
  curve: "smooth",
@@ -413,7 +516,7 @@ function ChartBuilder({
413
516
  }
414
517
  };
415
518
  }
416
- if (config.yAxis && !["pie", "donut", "radar", "treemap"].includes(config.type)) {
519
+ if (config.yAxis && !["pie", "donut", "radar"].includes(config.type)) {
417
520
  baseOptions.yaxis = {
418
521
  title: { text: options.yAxisTitle || config.yAxis.label },
419
522
  labels: {
@@ -476,11 +579,12 @@ function ChartBuilder({
476
579
  return chartData2.series[0]?.data || [];
477
580
  }
478
581
  if (config.type === "scatter" || config.type === "bubble") {
479
- const points = processChartDataForScatter(data, config);
480
- return [{
481
- name: config.yAxis?.label || "Data",
482
- data: points
483
- }];
582
+ const scatterData = processChartDataForScatter(data, config);
583
+ return scatterData.series;
584
+ }
585
+ if (config.type === "heatmap") {
586
+ const heatmapData = processChartDataForHeatmap(data, config);
587
+ return heatmapData.series;
484
588
  }
485
589
  const chartData = processChartData(data, config);
486
590
  return chartData.series;
@@ -499,7 +603,7 @@ function ChartBuilder({
499
603
  const chartOptionsWithCategories = useMemo2(() => {
500
604
  const options = { ...chartOptions };
501
605
  const config = chartConfig;
502
- if (!["pie", "donut", "scatter", "bubble"].includes(config.type)) {
606
+ if (!["pie", "donut", "scatter", "bubble", "heatmap"].includes(config.type)) {
503
607
  options.xaxis = {
504
608
  ...options.xaxis,
505
609
  categories: chartLabels
@@ -508,6 +612,46 @@ function ChartBuilder({
508
612
  if (config.type === "pie" || config.type === "donut") {
509
613
  options.labels = chartLabels;
510
614
  }
615
+ if (config.type === "heatmap") {
616
+ options.chart = {
617
+ ...options.chart,
618
+ type: "heatmap"
619
+ };
620
+ options.xaxis = {
621
+ ...options.xaxis,
622
+ type: "category"
623
+ };
624
+ options.dataLabels = {
625
+ enabled: true,
626
+ style: {
627
+ colors: ["#fff"],
628
+ fontSize: "10px"
629
+ },
630
+ formatter: (val) => {
631
+ if (val === null || val === void 0)
632
+ return "";
633
+ if (typeof val !== "number")
634
+ return String(val);
635
+ if (val >= 1e6)
636
+ return `${(val / 1e6).toFixed(1)}M`;
637
+ if (val >= 1e3)
638
+ return `${(val / 1e3).toFixed(0)}K`;
639
+ return Math.round(val).toLocaleString();
640
+ }
641
+ };
642
+ options.plotOptions = {
643
+ heatmap: {
644
+ shadeIntensity: 0.5,
645
+ radius: 2,
646
+ enableShades: true,
647
+ colorScale: {
648
+ inverse: false
649
+ }
650
+ }
651
+ };
652
+ options.colors = ["#6366f1"];
653
+ options.legend = { show: false };
654
+ }
511
655
  return options;
512
656
  }, [chartOptions, chartConfig, chartLabels]);
513
657
  const getChartIcon = useCallback2((type) => {
@@ -517,10 +661,9 @@ function ChartBuilder({
517
661
  area: "M3 17l6-6 4 4 8-8v10H3z",
518
662
  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",
519
663
  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",
520
- 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",
521
- 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",
664
+ 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",
665
+ 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",
522
666
  heatmap: "M3 3h4v4H3V3zm6 0h4v4H9V3zm6 0h4v4h-4V3zM3 9h4v4H3V9zm6 0h4v4H9V9zm6 0h4v4h-4V9zM3 15h4v4H3v-4zm6 0h4v4H9v-4zm6 0h4v4h-4v-4z",
523
- treemap: "M3 3h8v10H3V3zm10 0h8v6h-8V3zM3 15h8v6H3v-6zm10-4h8v10h-8V11z",
524
667
  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"
525
668
  };
526
669
  return icons[type] || icons.bar;
@@ -547,7 +690,8 @@ function ChartBuilder({
547
690
  /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-fields-section", children: [
548
691
  /* @__PURE__ */ jsxs2("h4", { className: "vpg-chart-fields-title", children: [
549
692
  /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-sm", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx2("path", { d: "M4 6h16M4 12h10M4 18h6" }) }),
550
- "Dimensions"
693
+ "Dimensions",
694
+ /* @__PURE__ */ jsx2("span", { className: "vpg-chart-fields-hint", children: "(text/date)" })
551
695
  ] }),
552
696
  /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-fields-list", children: [
553
697
  dimensions.map((field) => /* @__PURE__ */ jsxs2(
@@ -570,7 +714,8 @@ function ChartBuilder({
570
714
  /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-fields-section", children: [
571
715
  /* @__PURE__ */ jsxs2("h4", { className: "vpg-chart-fields-title", children: [
572
716
  /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-sm", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx2("path", { d: "M16 8v8M12 11v5M8 14v2M4 4v16h16" }) }),
573
- "Measures"
717
+ "Measures",
718
+ /* @__PURE__ */ jsx2("span", { className: "vpg-chart-fields-hint", children: "(numbers)" })
574
719
  ] }),
575
720
  /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-fields-list", children: [
576
721
  measures.map((field) => /* @__PURE__ */ jsxs2(
@@ -593,7 +738,7 @@ function ChartBuilder({
593
738
  ] }),
594
739
  /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-config-panel", children: [
595
740
  /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-drop-zone-wrapper", children: [
596
- /* @__PURE__ */ jsx2("label", { className: "vpg-chart-zone-label", children: "X-Axis / Category" }),
741
+ /* @__PURE__ */ jsx2("label", { className: "vpg-chart-zone-label", children: zoneLabels.xAxis }),
597
742
  /* @__PURE__ */ jsx2(
598
743
  "div",
599
744
  {
@@ -603,13 +748,22 @@ function ChartBuilder({
603
748
  onDrop: (e) => handleDrop("xAxis", e),
604
749
  children: chartConfig.xAxis ? /* @__PURE__ */ jsxs2(Fragment, { children: [
605
750
  /* @__PURE__ */ jsx2("span", { className: "vpg-zone-field-name", children: chartConfig.xAxis.label }),
751
+ isScatterType && chartConfig.xAxis.role === "measure" && /* @__PURE__ */ jsx2(
752
+ "select",
753
+ {
754
+ className: "vpg-zone-aggregation",
755
+ value: chartConfig.xAxis.aggregation || "sum",
756
+ onChange: (e) => updateAggregation("xAxis", e.target.value),
757
+ children: CHART_AGGREGATIONS.map((agg) => /* @__PURE__ */ jsx2("option", { value: agg.value, children: agg.symbol }, agg.value))
758
+ }
759
+ ),
606
760
  /* @__PURE__ */ jsx2("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("xAxis"), children: /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx2("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
607
- ] }) : /* @__PURE__ */ jsx2("span", { className: "vpg-zone-placeholder", children: "Drop dimension here" })
761
+ ] }) : /* @__PURE__ */ jsx2("span", { className: "vpg-zone-placeholder", children: zoneLabels.xAxisPlaceholder })
608
762
  }
609
763
  )
610
764
  ] }),
611
765
  /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-drop-zone-wrapper", children: [
612
- /* @__PURE__ */ jsx2("label", { className: "vpg-chart-zone-label", children: "Y-Axis / Value" }),
766
+ /* @__PURE__ */ jsx2("label", { className: "vpg-chart-zone-label", children: zoneLabels.yAxis }),
613
767
  /* @__PURE__ */ jsx2(
614
768
  "div",
615
769
  {
@@ -619,7 +773,7 @@ function ChartBuilder({
619
773
  onDrop: (e) => handleDrop("yAxis", e),
620
774
  children: chartConfig.yAxis ? /* @__PURE__ */ jsxs2(Fragment, { children: [
621
775
  /* @__PURE__ */ jsx2("span", { className: "vpg-zone-field-name", children: chartConfig.yAxis.label }),
622
- chartConfig.yAxis.role === "measure" && /* @__PURE__ */ jsx2(
776
+ chartConfig.yAxis.role === "measure" && !isHeatmapType && /* @__PURE__ */ jsx2(
623
777
  "select",
624
778
  {
625
779
  className: "vpg-zone-aggregation",
@@ -629,28 +783,37 @@ function ChartBuilder({
629
783
  }
630
784
  ),
631
785
  /* @__PURE__ */ jsx2("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("yAxis"), children: /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx2("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
632
- ] }) : /* @__PURE__ */ jsx2("span", { className: "vpg-zone-placeholder", children: "Drop measure here" })
786
+ ] }) : /* @__PURE__ */ jsx2("span", { className: "vpg-zone-placeholder", children: zoneLabels.yAxisPlaceholder })
633
787
  }
634
788
  )
635
789
  ] }),
636
- /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-drop-zone-wrapper", children: [
637
- /* @__PURE__ */ jsx2("label", { className: "vpg-chart-zone-label", children: "Color / Series (optional)" }),
790
+ zoneLabels.showSeries && /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-drop-zone-wrapper", children: [
791
+ /* @__PURE__ */ jsx2("label", { className: "vpg-chart-zone-label", children: zoneLabels.series }),
638
792
  /* @__PURE__ */ jsx2(
639
793
  "div",
640
794
  {
641
- className: `vpg-chart-drop-zone vpg-zone-optional ${dragOverZone === "series" ? "drag-over" : ""} ${chartConfig.seriesField ? "has-field" : ""}`,
642
- onDragOver: (e) => handleDragOver("series", e),
795
+ className: `vpg-chart-drop-zone vpg-zone-optional ${dragOverZone === "series" ? "drag-over" : ""} ${(isHeatmapType ? chartConfig.colorField : chartConfig.seriesField) ? "has-field" : ""}`,
796
+ onDragOver: (e) => handleDragOver(isHeatmapType ? "color" : "series", e),
643
797
  onDragLeave: handleDragLeave,
644
- onDrop: (e) => handleDrop("series", e),
645
- children: chartConfig.seriesField ? /* @__PURE__ */ jsxs2(Fragment, { children: [
646
- /* @__PURE__ */ jsx2("span", { className: "vpg-zone-field-name", children: chartConfig.seriesField.label }),
647
- /* @__PURE__ */ jsx2("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("series"), children: /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx2("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
648
- ] }) : /* @__PURE__ */ jsx2("span", { className: "vpg-zone-placeholder", children: "Group by dimension" })
798
+ onDrop: (e) => handleDrop(isHeatmapType ? "color" : "series", e),
799
+ children: (isHeatmapType ? chartConfig.colorField : chartConfig.seriesField) ? /* @__PURE__ */ jsxs2(Fragment, { children: [
800
+ /* @__PURE__ */ jsx2("span", { className: "vpg-zone-field-name", children: isHeatmapType ? chartConfig.colorField?.label : chartConfig.seriesField?.label }),
801
+ isHeatmapType && chartConfig.colorField?.role === "measure" && /* @__PURE__ */ jsx2(
802
+ "select",
803
+ {
804
+ className: "vpg-zone-aggregation",
805
+ value: chartConfig.colorField?.aggregation || "sum",
806
+ onChange: (e) => updateAggregation("color", e.target.value),
807
+ children: CHART_AGGREGATIONS.map((agg) => /* @__PURE__ */ jsx2("option", { value: agg.value, children: agg.symbol }, agg.value))
808
+ }
809
+ ),
810
+ /* @__PURE__ */ jsx2("button", { className: "vpg-zone-remove-btn", onClick: () => removeField(isHeatmapType ? "color" : "series"), children: /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx2("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
811
+ ] }) : /* @__PURE__ */ jsx2("span", { className: "vpg-zone-placeholder", children: zoneLabels.seriesPlaceholder })
649
812
  }
650
813
  )
651
814
  ] }),
652
- (chartConfig.type === "scatter" || chartConfig.type === "bubble") && /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-drop-zone-wrapper", children: [
653
- /* @__PURE__ */ jsx2("label", { className: "vpg-chart-zone-label", children: "Size (bubble)" }),
815
+ zoneLabels.showSize && /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-drop-zone-wrapper", children: [
816
+ /* @__PURE__ */ jsx2("label", { className: "vpg-chart-zone-label", children: "Size (number)" }),
654
817
  /* @__PURE__ */ jsx2(
655
818
  "div",
656
819
  {
@@ -660,8 +823,17 @@ function ChartBuilder({
660
823
  onDrop: (e) => handleDrop("size", e),
661
824
  children: chartConfig.sizeField ? /* @__PURE__ */ jsxs2(Fragment, { children: [
662
825
  /* @__PURE__ */ jsx2("span", { className: "vpg-zone-field-name", children: chartConfig.sizeField.label }),
826
+ chartConfig.sizeField.role === "measure" && /* @__PURE__ */ jsx2(
827
+ "select",
828
+ {
829
+ className: "vpg-zone-aggregation",
830
+ value: chartConfig.sizeField.aggregation || "sum",
831
+ onChange: (e) => updateAggregation("size", e.target.value),
832
+ children: CHART_AGGREGATIONS.map((agg) => /* @__PURE__ */ jsx2("option", { value: agg.value, children: agg.symbol }, agg.value))
833
+ }
834
+ ),
663
835
  /* @__PURE__ */ jsx2("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("size"), children: /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx2("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
664
- ] }) : /* @__PURE__ */ jsx2("span", { className: "vpg-zone-placeholder", children: "Drop measure for size" })
836
+ ] }) : /* @__PURE__ */ jsx2("span", { className: "vpg-zone-placeholder", children: "Drop a number for bubble size" })
665
837
  }
666
838
  )
667
839
  ] }),