@smallwebco/tinypivot-react 1.0.51 → 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
@@ -188,21 +188,702 @@ function CalculatedFieldModal({
188
188
  return createPortal(modalContent, document.body);
189
189
  }
190
190
 
191
+ // src/components/ChartBuilder.tsx
192
+ import {
193
+ analyzeFieldsForChart,
194
+ CHART_AGGREGATIONS,
195
+ CHART_COLORS,
196
+ CHART_TYPES,
197
+ createDefaultChartConfig,
198
+ getChartGuidance,
199
+ isChartConfigValid,
200
+ processChartData,
201
+ processChartDataForHeatmap,
202
+ processChartDataForPie,
203
+ processChartDataForScatter
204
+ } from "@smallwebco/tinypivot-core";
205
+ import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useState as useState2 } from "react";
206
+ import Chart from "react-apexcharts";
207
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
208
+ function ChartBuilder({
209
+ data,
210
+ theme = "light",
211
+ onConfigChange
212
+ }) {
213
+ const [chartConfig, setChartConfig] = useState2(createDefaultChartConfig());
214
+ const [draggingField, setDraggingField] = useState2(null);
215
+ const [dragOverZone, setDragOverZone] = useState2(null);
216
+ const fieldInfos = useMemo2(() => analyzeFieldsForChart(data), [data]);
217
+ const dimensions = useMemo2(
218
+ () => fieldInfos.filter((f) => f.role === "dimension" || f.role === "temporal"),
219
+ [fieldInfos]
220
+ );
221
+ const measures = useMemo2(
222
+ () => fieldInfos.filter((f) => f.role === "measure"),
223
+ [fieldInfos]
224
+ );
225
+ const guidance = useMemo2(() => getChartGuidance(chartConfig), [chartConfig]);
226
+ const chartIsValid = useMemo2(() => isChartConfigValid(chartConfig), [chartConfig]);
227
+ const selectedChartType = useMemo2(
228
+ () => CHART_TYPES.find((ct) => ct.type === chartConfig.type),
229
+ [chartConfig.type]
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]);
301
+ const handleDragStart = useCallback2((field, event) => {
302
+ setDraggingField(field);
303
+ event.dataTransfer?.setData("text/plain", field.field);
304
+ }, []);
305
+ const handleDragEnd = useCallback2(() => {
306
+ setDraggingField(null);
307
+ setDragOverZone(null);
308
+ }, []);
309
+ const handleDragOver = useCallback2((zone, event) => {
310
+ event.preventDefault();
311
+ setDragOverZone(zone);
312
+ }, []);
313
+ const handleDragLeave = useCallback2(() => {
314
+ setDragOverZone(null);
315
+ }, []);
316
+ const handleDrop = useCallback2((zone, event) => {
317
+ event.preventDefault();
318
+ setDragOverZone(null);
319
+ if (!draggingField)
320
+ return;
321
+ const field = draggingField;
322
+ const chartField = {
323
+ field: field.field,
324
+ label: field.label,
325
+ role: field.role,
326
+ aggregation: field.role === "measure" ? "sum" : void 0
327
+ };
328
+ let newConfig = { ...chartConfig };
329
+ switch (zone) {
330
+ case "xAxis":
331
+ newConfig = { ...newConfig, xAxis: chartField };
332
+ break;
333
+ case "yAxis":
334
+ newConfig = { ...newConfig, yAxis: chartField };
335
+ break;
336
+ case "series":
337
+ newConfig = { ...newConfig, seriesField: chartField };
338
+ break;
339
+ case "size":
340
+ newConfig = { ...newConfig, sizeField: chartField };
341
+ break;
342
+ case "color":
343
+ newConfig = { ...newConfig, colorField: chartField };
344
+ break;
345
+ }
346
+ setChartConfig(newConfig);
347
+ onConfigChange?.(newConfig);
348
+ }, [chartConfig, draggingField, onConfigChange]);
349
+ const removeField = useCallback2((zone) => {
350
+ let newConfig = { ...chartConfig };
351
+ switch (zone) {
352
+ case "xAxis":
353
+ newConfig = { ...newConfig, xAxis: void 0 };
354
+ break;
355
+ case "yAxis":
356
+ newConfig = { ...newConfig, yAxis: void 0 };
357
+ break;
358
+ case "series":
359
+ newConfig = { ...newConfig, seriesField: void 0 };
360
+ break;
361
+ case "size":
362
+ newConfig = { ...newConfig, sizeField: void 0 };
363
+ break;
364
+ case "color":
365
+ newConfig = { ...newConfig, colorField: void 0 };
366
+ break;
367
+ }
368
+ setChartConfig(newConfig);
369
+ onConfigChange?.(newConfig);
370
+ }, [chartConfig, onConfigChange]);
371
+ const selectChartType = useCallback2((type) => {
372
+ const newConfig = { ...chartConfig, type };
373
+ setChartConfig(newConfig);
374
+ onConfigChange?.(newConfig);
375
+ }, [chartConfig, onConfigChange]);
376
+ const updateAggregation = useCallback2((zone, aggregation) => {
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
+ }
394
+ if (!field)
395
+ return;
396
+ const updated = { ...field, aggregation };
397
+ let newConfig = { ...chartConfig };
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;
411
+ }
412
+ setChartConfig(newConfig);
413
+ onConfigChange?.(newConfig);
414
+ }, [chartConfig, onConfigChange]);
415
+ const getApexChartType = useCallback2((type) => {
416
+ const mapping = {
417
+ bar: "bar",
418
+ line: "line",
419
+ area: "area",
420
+ pie: "pie",
421
+ donut: "donut",
422
+ radar: "radar",
423
+ scatter: "scatter",
424
+ bubble: "bubble",
425
+ heatmap: "heatmap"
426
+ };
427
+ return mapping[type] || "bar";
428
+ }, []);
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 "";
436
+ const dec = decimals ?? 0;
437
+ if (format === "percent") {
438
+ return `${val.toFixed(dec)}%`;
439
+ }
440
+ if (format === "currency") {
441
+ return `$${val.toLocaleString(void 0, { minimumFractionDigits: dec, maximumFractionDigits: dec })}`;
442
+ }
443
+ if (Math.abs(val) >= 1e3) {
444
+ return val.toLocaleString(void 0, { maximumFractionDigits: dec });
445
+ }
446
+ return val.toFixed(dec);
447
+ }, []);
448
+ const chartOptions = useMemo2(() => {
449
+ const isDark = theme === "dark";
450
+ const config = chartConfig;
451
+ const options = config.options || {};
452
+ const baseOptions = {
453
+ chart: {
454
+ type: getApexChartType(config.type),
455
+ background: "transparent",
456
+ foreColor: isDark ? "#e2e8f0" : "#334155",
457
+ toolbar: {
458
+ show: true,
459
+ tools: {
460
+ download: true,
461
+ selection: false,
462
+ zoom: options.enableZoom ?? false,
463
+ zoomin: options.enableZoom ?? false,
464
+ zoomout: options.enableZoom ?? false,
465
+ pan: false,
466
+ reset: options.enableZoom ?? false
467
+ },
468
+ export: {
469
+ csv: { filename: "chart-data" },
470
+ svg: { filename: "chart" },
471
+ png: { filename: "chart" }
472
+ }
473
+ },
474
+ animations: {
475
+ enabled: options.animated ?? true,
476
+ speed: 400,
477
+ dynamicAnimation: { enabled: true, speed: 300 }
478
+ },
479
+ fontFamily: "system-ui, -apple-system, sans-serif"
480
+ },
481
+ colors: options.colors || CHART_COLORS,
482
+ theme: {
483
+ mode: isDark ? "dark" : "light"
484
+ },
485
+ grid: {
486
+ show: options.showGrid ?? true,
487
+ borderColor: isDark ? "#334155" : "#e2e8f0"
488
+ },
489
+ legend: {
490
+ show: options.showLegend ?? true,
491
+ position: options.legendPosition || "top"
492
+ },
493
+ dataLabels: {
494
+ enabled: options.showDataLabels ?? false
495
+ },
496
+ tooltip: {
497
+ theme: isDark ? "dark" : "light",
498
+ style: {
499
+ fontSize: "12px"
500
+ }
501
+ },
502
+ stroke: {
503
+ curve: "smooth",
504
+ width: config.type === "line" ? 3 : config.type === "area" ? 2 : 0
505
+ },
506
+ fill: {
507
+ opacity: config.type === "area" ? 0.4 : 1
508
+ }
509
+ };
510
+ if (config.xAxis) {
511
+ baseOptions.xaxis = {
512
+ ...baseOptions.xaxis,
513
+ title: { text: options.xAxisTitle || config.xAxis.label },
514
+ labels: {
515
+ style: { colors: isDark ? "#94a3b8" : "#64748b" }
516
+ }
517
+ };
518
+ }
519
+ if (config.yAxis && !["pie", "donut", "radar"].includes(config.type)) {
520
+ baseOptions.yaxis = {
521
+ title: { text: options.yAxisTitle || config.yAxis.label },
522
+ labels: {
523
+ style: { colors: isDark ? "#94a3b8" : "#64748b" },
524
+ formatter: (val) => formatValue(val, options.valueFormat, options.decimals)
525
+ }
526
+ };
527
+ }
528
+ if (options.title) {
529
+ baseOptions.title = {
530
+ text: options.title,
531
+ style: {
532
+ fontSize: "16px",
533
+ fontWeight: "600",
534
+ color: isDark ? "#e2e8f0" : "#334155"
535
+ }
536
+ };
537
+ }
538
+ if (options.stacked && ["bar", "area"].includes(config.type)) {
539
+ baseOptions.chart.stacked = true;
540
+ }
541
+ if (config.type === "pie" || config.type === "donut") {
542
+ baseOptions.plotOptions = {
543
+ pie: {
544
+ donut: {
545
+ size: config.type === "donut" ? "55%" : "0%",
546
+ labels: {
547
+ show: config.type === "donut",
548
+ total: {
549
+ show: true,
550
+ label: "Total",
551
+ formatter: (w) => {
552
+ const total = w.globals.seriesTotals.reduce((a, b) => a + b, 0);
553
+ return formatValue(total, options.valueFormat, options.decimals);
554
+ }
555
+ }
556
+ }
557
+ }
558
+ }
559
+ };
560
+ }
561
+ if (config.type === "radar") {
562
+ baseOptions.plotOptions = {
563
+ radar: {
564
+ polygons: {
565
+ strokeColors: isDark ? "#334155" : "#e2e8f0",
566
+ fill: { colors: isDark ? ["#1e293b", "#0f172a"] : ["#f8fafc", "#f1f5f9"] }
567
+ }
568
+ }
569
+ };
570
+ }
571
+ return baseOptions;
572
+ }, [chartConfig, theme, getApexChartType, formatValue]);
573
+ const chartSeries = useMemo2(() => {
574
+ const config = chartConfig;
575
+ if (!chartIsValid)
576
+ return [];
577
+ if (config.type === "pie" || config.type === "donut") {
578
+ const chartData2 = processChartDataForPie(data, config);
579
+ return chartData2.series[0]?.data || [];
580
+ }
581
+ if (config.type === "scatter" || config.type === "bubble") {
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;
588
+ }
589
+ const chartData = processChartData(data, config);
590
+ return chartData.series;
591
+ }, [data, chartConfig, chartIsValid]);
592
+ const chartLabels = useMemo2(() => {
593
+ const config = chartConfig;
594
+ if (!chartIsValid)
595
+ return [];
596
+ if (config.type === "pie" || config.type === "donut") {
597
+ const chartData2 = processChartDataForPie(data, config);
598
+ return chartData2.categories;
599
+ }
600
+ const chartData = processChartData(data, config);
601
+ return chartData.categories;
602
+ }, [data, chartConfig, chartIsValid]);
603
+ const chartOptionsWithCategories = useMemo2(() => {
604
+ const options = { ...chartOptions };
605
+ const config = chartConfig;
606
+ if (!["pie", "donut", "scatter", "bubble", "heatmap"].includes(config.type)) {
607
+ options.xaxis = {
608
+ ...options.xaxis,
609
+ categories: chartLabels
610
+ };
611
+ }
612
+ if (config.type === "pie" || config.type === "donut") {
613
+ options.labels = chartLabels;
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
+ }
655
+ return options;
656
+ }, [chartOptions, chartConfig, chartLabels]);
657
+ const getChartIcon = useCallback2((type) => {
658
+ const icons = {
659
+ bar: "M3 3v18h18V3H3zm4 14H5v-6h2v6zm4 0H9V7h2v10zm4 0h-2V9h2v8zm4 0h-2v-4h2v4z",
660
+ line: "M3.5 18.5l6-6 4 4 8-8M14.5 8.5h6v6",
661
+ area: "M3 17l6-6 4 4 8-8v10H3z",
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",
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",
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",
666
+ heatmap: "M3 3h4v4H3V3zm6 0h4v4H9V3zm6 0h4v4h-4V3zM3 9h4v4H3V9zm6 0h4v4H9V9zm6 0h4v4h-4V9zM3 15h4v4H3v-4zm6 0h4v4H9v-4zm6 0h4v4h-4v-4z",
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"
668
+ };
669
+ return icons[type] || icons.bar;
670
+ }, []);
671
+ useEffect2(() => {
672
+ onConfigChange?.(chartConfig);
673
+ }, []);
674
+ return /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-builder", children: [
675
+ /* @__PURE__ */ jsx2("div", { className: "vpg-chart-type-bar", children: CHART_TYPES.map((ct) => /* @__PURE__ */ jsxs2(
676
+ "button",
677
+ {
678
+ className: `vpg-chart-type-btn ${chartConfig.type === ct.type ? "active" : ""}`,
679
+ title: ct.description,
680
+ onClick: () => selectChartType(ct.type),
681
+ children: [
682
+ /* @__PURE__ */ jsx2("svg", { className: "vpg-icon", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx2("path", { d: getChartIcon(ct.type) }) }),
683
+ /* @__PURE__ */ jsx2("span", { className: "vpg-chart-type-label", children: ct.label.replace(" Chart", "") })
684
+ ]
685
+ },
686
+ ct.type
687
+ )) }),
688
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-builder-content", children: [
689
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-fields-panel", children: [
690
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-fields-section", children: [
691
+ /* @__PURE__ */ jsxs2("h4", { className: "vpg-chart-fields-title", children: [
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" }) }),
693
+ "Dimensions",
694
+ /* @__PURE__ */ jsx2("span", { className: "vpg-chart-fields-hint", children: "(text/date)" })
695
+ ] }),
696
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-fields-list", children: [
697
+ dimensions.map((field) => /* @__PURE__ */ jsxs2(
698
+ "div",
699
+ {
700
+ className: "vpg-chart-field-chip vpg-field-dimension",
701
+ draggable: true,
702
+ onDragStart: (e) => handleDragStart(field, e),
703
+ onDragEnd: handleDragEnd,
704
+ children: [
705
+ /* @__PURE__ */ jsx2("span", { className: "vpg-field-name", children: field.label }),
706
+ /* @__PURE__ */ jsx2("span", { className: "vpg-field-type", children: field.role === "temporal" ? "date" : "text" })
707
+ ]
708
+ },
709
+ field.field
710
+ )),
711
+ dimensions.length === 0 && /* @__PURE__ */ jsx2("div", { className: "vpg-chart-fields-empty", children: "No dimension fields detected" })
712
+ ] })
713
+ ] }),
714
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-fields-section", children: [
715
+ /* @__PURE__ */ jsxs2("h4", { className: "vpg-chart-fields-title", children: [
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" }) }),
717
+ "Measures",
718
+ /* @__PURE__ */ jsx2("span", { className: "vpg-chart-fields-hint", children: "(numbers)" })
719
+ ] }),
720
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-fields-list", children: [
721
+ measures.map((field) => /* @__PURE__ */ jsxs2(
722
+ "div",
723
+ {
724
+ className: "vpg-chart-field-chip vpg-field-measure",
725
+ draggable: true,
726
+ onDragStart: (e) => handleDragStart(field, e),
727
+ onDragEnd: handleDragEnd,
728
+ children: [
729
+ /* @__PURE__ */ jsx2("span", { className: "vpg-field-name", children: field.label }),
730
+ /* @__PURE__ */ jsx2("span", { className: "vpg-field-type", children: "#" })
731
+ ]
732
+ },
733
+ field.field
734
+ )),
735
+ measures.length === 0 && /* @__PURE__ */ jsx2("div", { className: "vpg-chart-fields-empty", children: "No numeric fields detected" })
736
+ ] })
737
+ ] })
738
+ ] }),
739
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-config-panel", children: [
740
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-drop-zone-wrapper", children: [
741
+ /* @__PURE__ */ jsx2("label", { className: "vpg-chart-zone-label", children: zoneLabels.xAxis }),
742
+ /* @__PURE__ */ jsx2(
743
+ "div",
744
+ {
745
+ className: `vpg-chart-drop-zone ${dragOverZone === "xAxis" ? "drag-over" : ""} ${chartConfig.xAxis ? "has-field" : ""}`,
746
+ onDragOver: (e) => handleDragOver("xAxis", e),
747
+ onDragLeave: handleDragLeave,
748
+ onDrop: (e) => handleDrop("xAxis", e),
749
+ children: chartConfig.xAxis ? /* @__PURE__ */ jsxs2(Fragment, { children: [
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
+ ),
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" }) }) })
761
+ ] }) : /* @__PURE__ */ jsx2("span", { className: "vpg-zone-placeholder", children: zoneLabels.xAxisPlaceholder })
762
+ }
763
+ )
764
+ ] }),
765
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-drop-zone-wrapper", children: [
766
+ /* @__PURE__ */ jsx2("label", { className: "vpg-chart-zone-label", children: zoneLabels.yAxis }),
767
+ /* @__PURE__ */ jsx2(
768
+ "div",
769
+ {
770
+ className: `vpg-chart-drop-zone ${dragOverZone === "yAxis" ? "drag-over" : ""} ${chartConfig.yAxis ? "has-field" : ""}`,
771
+ onDragOver: (e) => handleDragOver("yAxis", e),
772
+ onDragLeave: handleDragLeave,
773
+ onDrop: (e) => handleDrop("yAxis", e),
774
+ children: chartConfig.yAxis ? /* @__PURE__ */ jsxs2(Fragment, { children: [
775
+ /* @__PURE__ */ jsx2("span", { className: "vpg-zone-field-name", children: chartConfig.yAxis.label }),
776
+ chartConfig.yAxis.role === "measure" && !isHeatmapType && /* @__PURE__ */ jsx2(
777
+ "select",
778
+ {
779
+ className: "vpg-zone-aggregation",
780
+ value: chartConfig.yAxis.aggregation || "sum",
781
+ onChange: (e) => updateAggregation("yAxis", e.target.value),
782
+ children: CHART_AGGREGATIONS.map((agg) => /* @__PURE__ */ jsx2("option", { value: agg.value, children: agg.symbol }, agg.value))
783
+ }
784
+ ),
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" }) }) })
786
+ ] }) : /* @__PURE__ */ jsx2("span", { className: "vpg-zone-placeholder", children: zoneLabels.yAxisPlaceholder })
787
+ }
788
+ )
789
+ ] }),
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 }),
792
+ /* @__PURE__ */ jsx2(
793
+ "div",
794
+ {
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),
797
+ onDragLeave: handleDragLeave,
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 })
812
+ }
813
+ )
814
+ ] }),
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)" }),
817
+ /* @__PURE__ */ jsx2(
818
+ "div",
819
+ {
820
+ className: `vpg-chart-drop-zone vpg-zone-optional ${dragOverZone === "size" ? "drag-over" : ""} ${chartConfig.sizeField ? "has-field" : ""}`,
821
+ onDragOver: (e) => handleDragOver("size", e),
822
+ onDragLeave: handleDragLeave,
823
+ onDrop: (e) => handleDrop("size", e),
824
+ children: chartConfig.sizeField ? /* @__PURE__ */ jsxs2(Fragment, { children: [
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
+ ),
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" }) }) })
836
+ ] }) : /* @__PURE__ */ jsx2("span", { className: "vpg-zone-placeholder", children: "Drop a number for bubble size" })
837
+ }
838
+ )
839
+ ] }),
840
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-guidance", children: [
841
+ /* @__PURE__ */ jsxs2("svg", { className: "vpg-icon-sm", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
842
+ /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "10" }),
843
+ /* @__PURE__ */ jsx2("path", { d: "M12 16v-4M12 8h.01" })
844
+ ] }),
845
+ /* @__PURE__ */ jsx2("span", { children: guidance })
846
+ ] })
847
+ ] }),
848
+ /* @__PURE__ */ jsx2("div", { className: "vpg-chart-preview-panel", children: chartIsValid ? /* @__PURE__ */ jsx2("div", { className: "vpg-chart-container", children: /* @__PURE__ */ jsx2(
849
+ Chart,
850
+ {
851
+ type: getApexChartType(chartConfig.type),
852
+ options: chartOptionsWithCategories,
853
+ series: chartSeries,
854
+ height: "100%"
855
+ },
856
+ `${chartConfig.type}-${JSON.stringify(chartConfig.xAxis)}-${JSON.stringify(chartConfig.yAxis)}`
857
+ ) }) : /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-empty-state", children: [
858
+ /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-lg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx2("path", { d: getChartIcon(chartConfig.type) }) }),
859
+ /* @__PURE__ */ jsx2("h3", { children: "Build your chart" }),
860
+ /* @__PURE__ */ jsx2("p", { children: "Drag fields from the left panel to configure your visualization" }),
861
+ /* @__PURE__ */ jsxs2("div", { className: "vpg-chart-hint", children: [
862
+ /* @__PURE__ */ jsx2("strong", { children: selectedChartType?.label }),
863
+ ":",
864
+ " ",
865
+ selectedChartType?.description
866
+ ] })
867
+ ] }) })
868
+ ] })
869
+ ] });
870
+ }
871
+
191
872
  // src/components/ColumnFilter.tsx
192
- import { useCallback as useCallback3, useEffect as useEffect3, useMemo as useMemo3, useRef, useState as useState3 } from "react";
873
+ import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo4, useRef, useState as useState4 } from "react";
193
874
 
194
875
  // src/components/NumericRangeFilter.tsx
195
- import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useState as useState2 } from "react";
196
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
876
+ import { useCallback as useCallback3, useEffect as useEffect3, useMemo as useMemo3, useState as useState3 } from "react";
877
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
197
878
  function NumericRangeFilter({
198
879
  dataMin,
199
880
  dataMax,
200
881
  currentRange,
201
882
  onChange
202
883
  }) {
203
- const [localMin, setLocalMin] = useState2(currentRange?.min ?? null);
204
- const [localMax, setLocalMax] = useState2(currentRange?.max ?? null);
205
- const step = useMemo2(() => {
884
+ const [localMin, setLocalMin] = useState3(currentRange?.min ?? null);
885
+ const [localMax, setLocalMax] = useState3(currentRange?.max ?? null);
886
+ const step = useMemo3(() => {
206
887
  const range = dataMax - dataMin;
207
888
  if (range === 0)
208
889
  return 1;
@@ -216,7 +897,7 @@ function NumericRangeFilter({
216
897
  return 10;
217
898
  return 10 ** (Math.floor(Math.log10(range)) - 2);
218
899
  }, [dataMin, dataMax]);
219
- const formatValue = useCallback2((val) => {
900
+ const formatValue = useCallback3((val) => {
220
901
  if (val === null)
221
902
  return "";
222
903
  if (Number.isInteger(val))
@@ -224,17 +905,17 @@ function NumericRangeFilter({
224
905
  return val.toLocaleString(void 0, { maximumFractionDigits: 2 });
225
906
  }, []);
226
907
  const isFilterActive = localMin !== null || localMax !== null;
227
- const minPercent = useMemo2(() => {
908
+ const minPercent = useMemo3(() => {
228
909
  if (localMin === null || dataMax === dataMin)
229
910
  return 0;
230
911
  return (localMin - dataMin) / (dataMax - dataMin) * 100;
231
912
  }, [localMin, dataMin, dataMax]);
232
- const maxPercent = useMemo2(() => {
913
+ const maxPercent = useMemo3(() => {
233
914
  if (localMax === null || dataMax === dataMin)
234
915
  return 100;
235
916
  return (localMax - dataMin) / (dataMax - dataMin) * 100;
236
917
  }, [localMax, dataMin, dataMax]);
237
- const handleMinSlider = useCallback2((event) => {
918
+ const handleMinSlider = useCallback3((event) => {
238
919
  const value = Number.parseFloat(event.target.value);
239
920
  setLocalMin(() => {
240
921
  if (localMax !== null && value > localMax) {
@@ -243,7 +924,7 @@ function NumericRangeFilter({
243
924
  return value;
244
925
  });
245
926
  }, [localMax]);
246
- const handleMaxSlider = useCallback2((event) => {
927
+ const handleMaxSlider = useCallback3((event) => {
247
928
  const value = Number.parseFloat(event.target.value);
248
929
  setLocalMax(() => {
249
930
  if (localMin !== null && value < localMin) {
@@ -252,14 +933,14 @@ function NumericRangeFilter({
252
933
  return value;
253
934
  });
254
935
  }, [localMin]);
255
- const handleSliderChange = useCallback2(() => {
936
+ const handleSliderChange = useCallback3(() => {
256
937
  if (localMin === null && localMax === null) {
257
938
  onChange(null);
258
939
  } else {
259
940
  onChange({ min: localMin, max: localMax });
260
941
  }
261
942
  }, [localMin, localMax, onChange]);
262
- const handleMinInput = useCallback2((event) => {
943
+ const handleMinInput = useCallback3((event) => {
263
944
  const value = event.target.value === "" ? null : Number.parseFloat(event.target.value);
264
945
  if (value !== null && !Number.isNaN(value)) {
265
946
  setLocalMin(Math.max(dataMin, Math.min(value, localMax ?? dataMax)));
@@ -267,7 +948,7 @@ function NumericRangeFilter({
267
948
  setLocalMin(null);
268
949
  }
269
950
  }, [dataMin, dataMax, localMax]);
270
- const handleMaxInput = useCallback2((event) => {
951
+ const handleMaxInput = useCallback3((event) => {
271
952
  const value = event.target.value === "" ? null : Number.parseFloat(event.target.value);
272
953
  if (value !== null && !Number.isNaN(value)) {
273
954
  setLocalMax(Math.min(dataMax, Math.max(value, localMin ?? dataMin)));
@@ -275,39 +956,39 @@ function NumericRangeFilter({
275
956
  setLocalMax(null);
276
957
  }
277
958
  }, [dataMin, dataMax, localMin]);
278
- const handleInputBlur = useCallback2(() => {
959
+ const handleInputBlur = useCallback3(() => {
279
960
  if (localMin === null && localMax === null) {
280
961
  onChange(null);
281
962
  } else {
282
963
  onChange({ min: localMin, max: localMax });
283
964
  }
284
965
  }, [localMin, localMax, onChange]);
285
- const clearFilter = useCallback2(() => {
966
+ const clearFilter = useCallback3(() => {
286
967
  setLocalMin(null);
287
968
  setLocalMax(null);
288
969
  onChange(null);
289
970
  }, [onChange]);
290
- const setFullRange = useCallback2(() => {
971
+ const setFullRange = useCallback3(() => {
291
972
  setLocalMin(dataMin);
292
973
  setLocalMax(dataMax);
293
974
  onChange({ min: dataMin, max: dataMax });
294
975
  }, [dataMin, dataMax, onChange]);
295
- useEffect2(() => {
976
+ useEffect3(() => {
296
977
  setLocalMin(currentRange?.min ?? null);
297
978
  setLocalMax(currentRange?.max ?? null);
298
979
  }, [currentRange]);
299
- return /* @__PURE__ */ jsxs2("div", { className: "vpg-range-filter", children: [
300
- /* @__PURE__ */ jsxs2("div", { className: "vpg-range-info", children: [
301
- /* @__PURE__ */ jsx2("span", { className: "vpg-range-label", children: "Data range:" }),
302
- /* @__PURE__ */ jsxs2("span", { className: "vpg-range-bounds", children: [
980
+ return /* @__PURE__ */ jsxs3("div", { className: "vpg-range-filter", children: [
981
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-range-info", children: [
982
+ /* @__PURE__ */ jsx3("span", { className: "vpg-range-label", children: "Data range:" }),
983
+ /* @__PURE__ */ jsxs3("span", { className: "vpg-range-bounds", children: [
303
984
  formatValue(dataMin),
304
985
  " ",
305
986
  "\u2013",
306
987
  formatValue(dataMax)
307
988
  ] })
308
989
  ] }),
309
- /* @__PURE__ */ jsxs2("div", { className: "vpg-slider-container", children: [
310
- /* @__PURE__ */ jsx2("div", { className: "vpg-slider-track", children: /* @__PURE__ */ jsx2(
990
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-slider-container", children: [
991
+ /* @__PURE__ */ jsx3("div", { className: "vpg-slider-track", children: /* @__PURE__ */ jsx3(
311
992
  "div",
312
993
  {
313
994
  className: "vpg-slider-fill",
@@ -317,7 +998,7 @@ function NumericRangeFilter({
317
998
  }
318
999
  }
319
1000
  ) }),
320
- /* @__PURE__ */ jsx2(
1001
+ /* @__PURE__ */ jsx3(
321
1002
  "input",
322
1003
  {
323
1004
  type: "range",
@@ -331,7 +1012,7 @@ function NumericRangeFilter({
331
1012
  onTouchEnd: handleSliderChange
332
1013
  }
333
1014
  ),
334
- /* @__PURE__ */ jsx2(
1015
+ /* @__PURE__ */ jsx3(
335
1016
  "input",
336
1017
  {
337
1018
  type: "range",
@@ -346,10 +1027,10 @@ function NumericRangeFilter({
346
1027
  }
347
1028
  )
348
1029
  ] }),
349
- /* @__PURE__ */ jsxs2("div", { className: "vpg-range-inputs", children: [
350
- /* @__PURE__ */ jsxs2("div", { className: "vpg-input-group", children: [
351
- /* @__PURE__ */ jsx2("label", { className: "vpg-input-label", children: "Min" }),
352
- /* @__PURE__ */ jsx2(
1030
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-range-inputs", children: [
1031
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-input-group", children: [
1032
+ /* @__PURE__ */ jsx3("label", { className: "vpg-input-label", children: "Min" }),
1033
+ /* @__PURE__ */ jsx3(
353
1034
  "input",
354
1035
  {
355
1036
  type: "number",
@@ -362,10 +1043,10 @@ function NumericRangeFilter({
362
1043
  }
363
1044
  )
364
1045
  ] }),
365
- /* @__PURE__ */ jsx2("span", { className: "vpg-input-separator", children: "to" }),
366
- /* @__PURE__ */ jsxs2("div", { className: "vpg-input-group", children: [
367
- /* @__PURE__ */ jsx2("label", { className: "vpg-input-label", children: "Max" }),
368
- /* @__PURE__ */ jsx2(
1046
+ /* @__PURE__ */ jsx3("span", { className: "vpg-input-separator", children: "to" }),
1047
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-input-group", children: [
1048
+ /* @__PURE__ */ jsx3("label", { className: "vpg-input-label", children: "Max" }),
1049
+ /* @__PURE__ */ jsx3(
369
1050
  "input",
370
1051
  {
371
1052
  type: "number",
@@ -379,15 +1060,15 @@ function NumericRangeFilter({
379
1060
  )
380
1061
  ] })
381
1062
  ] }),
382
- /* @__PURE__ */ jsxs2("div", { className: "vpg-range-actions", children: [
383
- /* @__PURE__ */ jsxs2(
1063
+ /* @__PURE__ */ jsxs3("div", { className: "vpg-range-actions", children: [
1064
+ /* @__PURE__ */ jsxs3(
384
1065
  "button",
385
1066
  {
386
1067
  className: "vpg-range-btn",
387
1068
  disabled: !isFilterActive,
388
1069
  onClick: clearFilter,
389
1070
  children: [
390
- /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2(
1071
+ /* @__PURE__ */ jsx3("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
391
1072
  "path",
392
1073
  {
393
1074
  strokeLinecap: "round",
@@ -400,8 +1081,8 @@ function NumericRangeFilter({
400
1081
  ]
401
1082
  }
402
1083
  ),
403
- /* @__PURE__ */ jsxs2("button", { className: "vpg-range-btn", onClick: setFullRange, children: [
404
- /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2(
1084
+ /* @__PURE__ */ jsxs3("button", { className: "vpg-range-btn", onClick: setFullRange, children: [
1085
+ /* @__PURE__ */ jsx3("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
405
1086
  "path",
406
1087
  {
407
1088
  strokeLinecap: "round",
@@ -413,8 +1094,8 @@ function NumericRangeFilter({
413
1094
  "Full Range"
414
1095
  ] })
415
1096
  ] }),
416
- isFilterActive && /* @__PURE__ */ jsxs2("div", { className: "vpg-filter-summary", children: [
417
- /* @__PURE__ */ jsx2("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2(
1097
+ isFilterActive && /* @__PURE__ */ jsxs3("div", { className: "vpg-filter-summary", children: [
1098
+ /* @__PURE__ */ jsx3("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
418
1099
  "path",
419
1100
  {
420
1101
  strokeLinecap: "round",
@@ -423,15 +1104,15 @@ function NumericRangeFilter({
423
1104
  d: "M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"
424
1105
  }
425
1106
  ) }),
426
- /* @__PURE__ */ jsxs2("span", { children: [
1107
+ /* @__PURE__ */ jsxs3("span", { children: [
427
1108
  "Showing values",
428
1109
  " ",
429
- localMin !== null && /* @__PURE__ */ jsxs2("strong", { children: [
1110
+ localMin !== null && /* @__PURE__ */ jsxs3("strong", { children: [
430
1111
  "\u2265",
431
1112
  formatValue(localMin)
432
1113
  ] }),
433
1114
  localMin !== null && localMax !== null && " and ",
434
- localMax !== null && /* @__PURE__ */ jsxs2("strong", { children: [
1115
+ localMax !== null && /* @__PURE__ */ jsxs3("strong", { children: [
435
1116
  "\u2264",
436
1117
  formatValue(localMax)
437
1118
  ] })
@@ -441,7 +1122,7 @@ function NumericRangeFilter({
441
1122
  }
442
1123
 
443
1124
  // src/components/ColumnFilter.tsx
444
- import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1125
+ import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
445
1126
  function ColumnFilter({
446
1127
  columnName,
447
1128
  stats,
@@ -453,33 +1134,33 @@ function ColumnFilter({
453
1134
  onClose,
454
1135
  onRangeFilter
455
1136
  }) {
456
- const [searchQuery, setSearchQuery] = useState3("");
457
- const [localSelected, setLocalSelected] = useState3(new Set(selectedValues));
1137
+ const [searchQuery, setSearchQuery] = useState4("");
1138
+ const [localSelected, setLocalSelected] = useState4(new Set(selectedValues));
458
1139
  const dropdownRef = useRef(null);
459
1140
  const searchInputRef = useRef(null);
460
1141
  const isNumericColumn = stats.type === "number" && stats.numericMin !== void 0 && stats.numericMax !== void 0;
461
- const [filterMode, setFilterMode] = useState3(numericRange ? "range" : "values");
462
- const [localRange, setLocalRange] = useState3(numericRange ?? null);
1142
+ const [filterMode, setFilterMode] = useState4(numericRange ? "range" : "values");
1143
+ const [localRange, setLocalRange] = useState4(numericRange ?? null);
463
1144
  const hasBlankValues = stats.nullCount > 0;
464
- const filteredValues = useMemo3(() => {
1145
+ const filteredValues = useMemo4(() => {
465
1146
  const values = stats.uniqueValues;
466
1147
  if (!searchQuery)
467
1148
  return values;
468
1149
  const query = searchQuery.toLowerCase();
469
1150
  return values.filter((v) => v.toLowerCase().includes(query));
470
1151
  }, [stats.uniqueValues, searchQuery]);
471
- const allValues = useMemo3(() => {
1152
+ const allValues = useMemo4(() => {
472
1153
  const values = [...filteredValues];
473
1154
  if (hasBlankValues && (!searchQuery || "(blank)".includes(searchQuery.toLowerCase()))) {
474
1155
  values.unshift("(blank)");
475
1156
  }
476
1157
  return values;
477
1158
  }, [filteredValues, hasBlankValues, searchQuery]);
478
- const _isAllSelected = useMemo3(
1159
+ const _isAllSelected = useMemo4(
479
1160
  () => allValues.every((v) => localSelected.has(v)),
480
1161
  [allValues, localSelected]
481
1162
  );
482
- const toggleValue = useCallback3((value) => {
1163
+ const toggleValue = useCallback4((value) => {
483
1164
  setLocalSelected((prev) => {
484
1165
  const next = new Set(prev);
485
1166
  if (next.has(value)) {
@@ -490,7 +1171,7 @@ function ColumnFilter({
490
1171
  return next;
491
1172
  });
492
1173
  }, []);
493
- const selectAll = useCallback3(() => {
1174
+ const selectAll = useCallback4(() => {
494
1175
  setLocalSelected((prev) => {
495
1176
  const next = new Set(prev);
496
1177
  for (const value of allValues) {
@@ -499,10 +1180,10 @@ function ColumnFilter({
499
1180
  return next;
500
1181
  });
501
1182
  }, [allValues]);
502
- const clearAll = useCallback3(() => {
1183
+ const clearAll = useCallback4(() => {
503
1184
  setLocalSelected(/* @__PURE__ */ new Set());
504
1185
  }, []);
505
- const applyFilter = useCallback3(() => {
1186
+ const applyFilter = useCallback4(() => {
506
1187
  if (localSelected.size === 0) {
507
1188
  onFilter([]);
508
1189
  } else {
@@ -510,30 +1191,30 @@ function ColumnFilter({
510
1191
  }
511
1192
  onClose();
512
1193
  }, [localSelected, onFilter, onClose]);
513
- const sortAscending = useCallback3(() => {
1194
+ const sortAscending = useCallback4(() => {
514
1195
  onSort(sortDirection === "asc" ? null : "asc");
515
1196
  }, [sortDirection, onSort]);
516
- const sortDescending = useCallback3(() => {
1197
+ const sortDescending = useCallback4(() => {
517
1198
  onSort(sortDirection === "desc" ? null : "desc");
518
1199
  }, [sortDirection, onSort]);
519
- const clearFilter = useCallback3(() => {
1200
+ const clearFilter = useCallback4(() => {
520
1201
  setLocalSelected(/* @__PURE__ */ new Set());
521
1202
  onFilter([]);
522
1203
  onClose();
523
1204
  }, [onFilter, onClose]);
524
- const handleRangeChange = useCallback3((range) => {
1205
+ const handleRangeChange = useCallback4((range) => {
525
1206
  setLocalRange(range);
526
1207
  }, []);
527
- const applyRangeFilter = useCallback3(() => {
1208
+ const applyRangeFilter = useCallback4(() => {
528
1209
  onRangeFilter?.(localRange);
529
1210
  onClose();
530
1211
  }, [localRange, onRangeFilter, onClose]);
531
- const clearRangeFilter = useCallback3(() => {
1212
+ const clearRangeFilter = useCallback4(() => {
532
1213
  setLocalRange(null);
533
1214
  onRangeFilter?.(null);
534
1215
  onClose();
535
1216
  }, [onRangeFilter, onClose]);
536
- useEffect3(() => {
1217
+ useEffect4(() => {
537
1218
  const handleClickOutside = (event) => {
538
1219
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
539
1220
  onClose();
@@ -542,7 +1223,7 @@ function ColumnFilter({
542
1223
  document.addEventListener("mousedown", handleClickOutside);
543
1224
  return () => document.removeEventListener("mousedown", handleClickOutside);
544
1225
  }, [onClose]);
545
- useEffect3(() => {
1226
+ useEffect4(() => {
546
1227
  const handleKeydown = (event) => {
547
1228
  if (event.key === "Escape") {
548
1229
  onClose();
@@ -553,36 +1234,36 @@ function ColumnFilter({
553
1234
  document.addEventListener("keydown", handleKeydown);
554
1235
  return () => document.removeEventListener("keydown", handleKeydown);
555
1236
  }, [onClose, applyFilter]);
556
- useEffect3(() => {
1237
+ useEffect4(() => {
557
1238
  searchInputRef.current?.focus();
558
1239
  }, []);
559
- useEffect3(() => {
1240
+ useEffect4(() => {
560
1241
  setLocalSelected(new Set(selectedValues));
561
1242
  }, [selectedValues]);
562
- useEffect3(() => {
1243
+ useEffect4(() => {
563
1244
  setLocalRange(numericRange ?? null);
564
1245
  if (numericRange) {
565
1246
  setFilterMode("range");
566
1247
  }
567
1248
  }, [numericRange]);
568
- return /* @__PURE__ */ jsxs3("div", { ref: dropdownRef, className: "vpg-filter-dropdown", children: [
569
- /* @__PURE__ */ jsxs3("div", { className: "vpg-filter-header", children: [
570
- /* @__PURE__ */ jsx3("span", { className: "vpg-filter-title", children: columnName }),
571
- /* @__PURE__ */ jsxs3("span", { className: "vpg-filter-count", children: [
1249
+ return /* @__PURE__ */ jsxs4("div", { ref: dropdownRef, className: "vpg-filter-dropdown", children: [
1250
+ /* @__PURE__ */ jsxs4("div", { className: "vpg-filter-header", children: [
1251
+ /* @__PURE__ */ jsx4("span", { className: "vpg-filter-title", children: columnName }),
1252
+ /* @__PURE__ */ jsxs4("span", { className: "vpg-filter-count", children: [
572
1253
  stats.uniqueValues.length.toLocaleString(),
573
1254
  " ",
574
1255
  "unique"
575
1256
  ] })
576
1257
  ] }),
577
- /* @__PURE__ */ jsxs3("div", { className: "vpg-sort-controls", children: [
578
- /* @__PURE__ */ jsxs3(
1258
+ /* @__PURE__ */ jsxs4("div", { className: "vpg-sort-controls", children: [
1259
+ /* @__PURE__ */ jsxs4(
579
1260
  "button",
580
1261
  {
581
1262
  className: `vpg-sort-btn ${sortDirection === "asc" ? "active" : ""}`,
582
1263
  title: isNumericColumn ? "Sort Low to High" : "Sort A to Z",
583
1264
  onClick: sortAscending,
584
1265
  children: [
585
- /* @__PURE__ */ jsx3("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
1266
+ /* @__PURE__ */ jsx4("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
586
1267
  "path",
587
1268
  {
588
1269
  strokeLinecap: "round",
@@ -591,18 +1272,18 @@ function ColumnFilter({
591
1272
  d: "M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12"
592
1273
  }
593
1274
  ) }),
594
- /* @__PURE__ */ jsx3("span", { children: isNumericColumn ? "1\u21929" : "A\u2192Z" })
1275
+ /* @__PURE__ */ jsx4("span", { children: isNumericColumn ? "1\u21929" : "A\u2192Z" })
595
1276
  ]
596
1277
  }
597
1278
  ),
598
- /* @__PURE__ */ jsxs3(
1279
+ /* @__PURE__ */ jsxs4(
599
1280
  "button",
600
1281
  {
601
1282
  className: `vpg-sort-btn ${sortDirection === "desc" ? "active" : ""}`,
602
1283
  title: isNumericColumn ? "Sort High to Low" : "Sort Z to A",
603
1284
  onClick: sortDescending,
604
1285
  children: [
605
- /* @__PURE__ */ jsx3("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
1286
+ /* @__PURE__ */ jsx4("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
606
1287
  "path",
607
1288
  {
608
1289
  strokeLinecap: "round",
@@ -611,20 +1292,20 @@ function ColumnFilter({
611
1292
  d: "M3 4h13M3 8h9m-9 4h9m5-4v12m0 0l-4-4m4 4l4-4"
612
1293
  }
613
1294
  ) }),
614
- /* @__PURE__ */ jsx3("span", { children: isNumericColumn ? "9\u21921" : "Z\u2192A" })
1295
+ /* @__PURE__ */ jsx4("span", { children: isNumericColumn ? "9\u21921" : "Z\u2192A" })
615
1296
  ]
616
1297
  }
617
1298
  )
618
1299
  ] }),
619
- /* @__PURE__ */ jsx3("div", { className: "vpg-divider" }),
620
- isNumericColumn && /* @__PURE__ */ jsxs3("div", { className: "vpg-filter-tabs", children: [
621
- /* @__PURE__ */ jsxs3(
1300
+ /* @__PURE__ */ jsx4("div", { className: "vpg-divider" }),
1301
+ isNumericColumn && /* @__PURE__ */ jsxs4("div", { className: "vpg-filter-tabs", children: [
1302
+ /* @__PURE__ */ jsxs4(
622
1303
  "button",
623
1304
  {
624
1305
  className: `vpg-tab-btn ${filterMode === "values" ? "active" : ""}`,
625
1306
  onClick: () => setFilterMode("values"),
626
1307
  children: [
627
- /* @__PURE__ */ jsx3("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
1308
+ /* @__PURE__ */ jsx4("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
628
1309
  "path",
629
1310
  {
630
1311
  strokeLinecap: "round",
@@ -637,13 +1318,13 @@ function ColumnFilter({
637
1318
  ]
638
1319
  }
639
1320
  ),
640
- /* @__PURE__ */ jsxs3(
1321
+ /* @__PURE__ */ jsxs4(
641
1322
  "button",
642
1323
  {
643
1324
  className: `vpg-tab-btn ${filterMode === "range" ? "active" : ""}`,
644
1325
  onClick: () => setFilterMode("range"),
645
1326
  children: [
646
- /* @__PURE__ */ jsx3("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
1327
+ /* @__PURE__ */ jsx4("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
647
1328
  "path",
648
1329
  {
649
1330
  strokeLinecap: "round",
@@ -657,9 +1338,9 @@ function ColumnFilter({
657
1338
  }
658
1339
  )
659
1340
  ] }),
660
- (!isNumericColumn || filterMode === "values") && /* @__PURE__ */ jsxs3(Fragment, { children: [
661
- /* @__PURE__ */ jsxs3("div", { className: "vpg-search-container", children: [
662
- /* @__PURE__ */ jsx3("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
1341
+ (!isNumericColumn || filterMode === "values") && /* @__PURE__ */ jsxs4(Fragment2, { children: [
1342
+ /* @__PURE__ */ jsxs4("div", { className: "vpg-search-container", children: [
1343
+ /* @__PURE__ */ jsx4("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
663
1344
  "path",
664
1345
  {
665
1346
  strokeLinecap: "round",
@@ -668,7 +1349,7 @@ function ColumnFilter({
668
1349
  d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
669
1350
  }
670
1351
  ) }),
671
- /* @__PURE__ */ jsx3(
1352
+ /* @__PURE__ */ jsx4(
672
1353
  "input",
673
1354
  {
674
1355
  ref: searchInputRef,
@@ -679,11 +1360,11 @@ function ColumnFilter({
679
1360
  className: "vpg-search-input"
680
1361
  }
681
1362
  ),
682
- searchQuery && /* @__PURE__ */ jsx3("button", { className: "vpg-clear-search", onClick: () => setSearchQuery(""), children: "\xD7" })
1363
+ searchQuery && /* @__PURE__ */ jsx4("button", { className: "vpg-clear-search", onClick: () => setSearchQuery(""), children: "\xD7" })
683
1364
  ] }),
684
- /* @__PURE__ */ jsxs3("div", { className: "vpg-bulk-actions", children: [
685
- /* @__PURE__ */ jsxs3("button", { className: "vpg-bulk-btn", onClick: selectAll, children: [
686
- /* @__PURE__ */ jsx3("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
1365
+ /* @__PURE__ */ jsxs4("div", { className: "vpg-bulk-actions", children: [
1366
+ /* @__PURE__ */ jsxs4("button", { className: "vpg-bulk-btn", onClick: selectAll, children: [
1367
+ /* @__PURE__ */ jsx4("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
687
1368
  "path",
688
1369
  {
689
1370
  strokeLinecap: "round",
@@ -694,8 +1375,8 @@ function ColumnFilter({
694
1375
  ) }),
695
1376
  "Select All"
696
1377
  ] }),
697
- /* @__PURE__ */ jsxs3("button", { className: "vpg-bulk-btn", onClick: clearAll, children: [
698
- /* @__PURE__ */ jsx3("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx3(
1378
+ /* @__PURE__ */ jsxs4("button", { className: "vpg-bulk-btn", onClick: clearAll, children: [
1379
+ /* @__PURE__ */ jsx4("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
699
1380
  "path",
700
1381
  {
701
1382
  strokeLinecap: "round",
@@ -707,13 +1388,13 @@ function ColumnFilter({
707
1388
  "Clear All"
708
1389
  ] })
709
1390
  ] }),
710
- /* @__PURE__ */ jsxs3("div", { className: "vpg-values-list", children: [
711
- allValues.map((value) => /* @__PURE__ */ jsxs3(
1391
+ /* @__PURE__ */ jsxs4("div", { className: "vpg-values-list", children: [
1392
+ allValues.map((value) => /* @__PURE__ */ jsxs4(
712
1393
  "label",
713
1394
  {
714
1395
  className: `vpg-value-item ${localSelected.has(value) ? "selected" : ""}`,
715
1396
  children: [
716
- /* @__PURE__ */ jsx3(
1397
+ /* @__PURE__ */ jsx4(
717
1398
  "input",
718
1399
  {
719
1400
  type: "checkbox",
@@ -722,20 +1403,20 @@ function ColumnFilter({
722
1403
  className: "vpg-value-checkbox"
723
1404
  }
724
1405
  ),
725
- /* @__PURE__ */ jsx3("span", { className: `vpg-value-text ${value === "(blank)" ? "vpg-blank" : ""}`, children: value })
1406
+ /* @__PURE__ */ jsx4("span", { className: `vpg-value-text ${value === "(blank)" ? "vpg-blank" : ""}`, children: value })
726
1407
  ]
727
1408
  },
728
1409
  value
729
1410
  )),
730
- allValues.length === 0 && /* @__PURE__ */ jsx3("div", { className: "vpg-no-results", children: "No matching values" })
1411
+ allValues.length === 0 && /* @__PURE__ */ jsx4("div", { className: "vpg-no-results", children: "No matching values" })
731
1412
  ] }),
732
- /* @__PURE__ */ jsxs3("div", { className: "vpg-filter-footer", children: [
733
- /* @__PURE__ */ jsx3("button", { className: "vpg-btn-clear", onClick: clearFilter, children: "Clear Filter" }),
734
- /* @__PURE__ */ jsx3("button", { className: "vpg-btn-apply", onClick: applyFilter, children: "Apply" })
1413
+ /* @__PURE__ */ jsxs4("div", { className: "vpg-filter-footer", children: [
1414
+ /* @__PURE__ */ jsx4("button", { className: "vpg-btn-clear", onClick: clearFilter, children: "Clear Filter" }),
1415
+ /* @__PURE__ */ jsx4("button", { className: "vpg-btn-apply", onClick: applyFilter, children: "Apply" })
735
1416
  ] })
736
1417
  ] }),
737
- isNumericColumn && filterMode === "range" && /* @__PURE__ */ jsxs3(Fragment, { children: [
738
- /* @__PURE__ */ jsx3(
1418
+ isNumericColumn && filterMode === "range" && /* @__PURE__ */ jsxs4(Fragment2, { children: [
1419
+ /* @__PURE__ */ jsx4(
739
1420
  NumericRangeFilter,
740
1421
  {
741
1422
  dataMin: stats.numericMin,
@@ -744,16 +1425,16 @@ function ColumnFilter({
744
1425
  onChange: handleRangeChange
745
1426
  }
746
1427
  ),
747
- /* @__PURE__ */ jsxs3("div", { className: "vpg-filter-footer", children: [
748
- /* @__PURE__ */ jsx3("button", { className: "vpg-btn-clear", onClick: clearRangeFilter, children: "Clear Filter" }),
749
- /* @__PURE__ */ jsx3("button", { className: "vpg-btn-apply", onClick: applyRangeFilter, children: "Apply" })
1428
+ /* @__PURE__ */ jsxs4("div", { className: "vpg-filter-footer", children: [
1429
+ /* @__PURE__ */ jsx4("button", { className: "vpg-btn-clear", onClick: clearRangeFilter, children: "Clear Filter" }),
1430
+ /* @__PURE__ */ jsx4("button", { className: "vpg-btn-apply", onClick: applyRangeFilter, children: "Apply" })
750
1431
  ] })
751
1432
  ] })
752
1433
  ] });
753
1434
  }
754
1435
 
755
1436
  // src/components/DataGrid.tsx
756
- import { useCallback as useCallback10, useEffect as useEffect7, useMemo as useMemo10, useRef as useRef2, useState as useState10 } from "react";
1437
+ import { useCallback as useCallback11, useEffect as useEffect8, useMemo as useMemo11, useRef as useRef2, useState as useState11 } from "react";
757
1438
  import { createPortal as createPortal2 } from "react-dom";
758
1439
 
759
1440
  // src/hooks/useExcelGrid.ts
@@ -764,7 +1445,7 @@ import {
764
1445
  getSortedRowModel,
765
1446
  useReactTable
766
1447
  } from "@tanstack/react-table";
767
- import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo4, useState as useState4 } from "react";
1448
+ import { useCallback as useCallback5, useEffect as useEffect5, useMemo as useMemo5, useState as useState5 } from "react";
768
1449
  var multiSelectFilter = (row, columnId, filterValue) => {
769
1450
  if (!filterValue)
770
1451
  return true;
@@ -792,21 +1473,21 @@ var multiSelectFilter = (row, columnId, filterValue) => {
792
1473
  };
793
1474
  function useExcelGrid(options) {
794
1475
  const { data, enableSorting = true, enableFiltering = true } = options;
795
- const [sorting, setSorting] = useState4([]);
796
- const [columnFilters, setColumnFilters] = useState4([]);
797
- const [columnVisibility, setColumnVisibility] = useState4({});
798
- const [globalFilter, setGlobalFilter] = useState4("");
799
- const [columnStatsCache, setColumnStatsCache] = useState4({});
800
- const dataSignature = useMemo4(
1476
+ const [sorting, setSorting] = useState5([]);
1477
+ const [columnFilters, setColumnFilters] = useState5([]);
1478
+ const [columnVisibility, setColumnVisibility] = useState5({});
1479
+ const [globalFilter, setGlobalFilter] = useState5("");
1480
+ const [columnStatsCache, setColumnStatsCache] = useState5({});
1481
+ const dataSignature = useMemo5(
801
1482
  () => `${Date.now()}-${Math.random().toString(36).slice(2)}`,
802
1483
  [data]
803
1484
  );
804
- const columnKeys = useMemo4(() => {
1485
+ const columnKeys = useMemo5(() => {
805
1486
  if (data.length === 0)
806
1487
  return [];
807
1488
  return Object.keys(data[0]);
808
1489
  }, [data]);
809
- const getColumnStats = useCallback4(
1490
+ const getColumnStats = useCallback5(
810
1491
  (columnKey) => {
811
1492
  const cacheKey = `${columnKey}-${dataSignature}`;
812
1493
  if (!columnStatsCache[cacheKey]) {
@@ -818,13 +1499,13 @@ function useExcelGrid(options) {
818
1499
  },
819
1500
  [data, columnStatsCache, dataSignature]
820
1501
  );
821
- const clearStatsCache = useCallback4(() => {
1502
+ const clearStatsCache = useCallback5(() => {
822
1503
  setColumnStatsCache({});
823
1504
  }, []);
824
- useEffect4(() => {
1505
+ useEffect5(() => {
825
1506
  clearStatsCache();
826
1507
  }, [dataSignature, clearStatsCache]);
827
- const columnDefs = useMemo4(() => {
1508
+ const columnDefs = useMemo5(() => {
828
1509
  return columnKeys.map((key) => {
829
1510
  const stats = getColumnStats(key);
830
1511
  return {
@@ -864,7 +1545,7 @@ function useExcelGrid(options) {
864
1545
  });
865
1546
  const filteredRowCount = table.getFilteredRowModel().rows.length;
866
1547
  const totalRowCount = data.length;
867
- const activeFilters = useMemo4(() => {
1548
+ const activeFilters = useMemo5(() => {
868
1549
  return columnFilters.map((f) => {
869
1550
  const filterValue = f.value;
870
1551
  if (filterValue && isNumericRange(filterValue)) {
@@ -883,7 +1564,7 @@ function useExcelGrid(options) {
883
1564
  };
884
1565
  });
885
1566
  }, [columnFilters]);
886
- const hasActiveFilter = useCallback4(
1567
+ const hasActiveFilter = useCallback5(
887
1568
  (columnId) => {
888
1569
  const column = table.getColumn(columnId);
889
1570
  if (!column)
@@ -898,7 +1579,7 @@ function useExcelGrid(options) {
898
1579
  },
899
1580
  [table]
900
1581
  );
901
- const setColumnFilter = useCallback4(
1582
+ const setColumnFilter = useCallback5(
902
1583
  (columnId, values) => {
903
1584
  const column = table.getColumn(columnId);
904
1585
  if (column) {
@@ -907,7 +1588,7 @@ function useExcelGrid(options) {
907
1588
  },
908
1589
  [table]
909
1590
  );
910
- const setNumericRangeFilter = useCallback4(
1591
+ const setNumericRangeFilter = useCallback5(
911
1592
  (columnId, range) => {
912
1593
  const column = table.getColumn(columnId);
913
1594
  if (column) {
@@ -920,7 +1601,7 @@ function useExcelGrid(options) {
920
1601
  },
921
1602
  [table]
922
1603
  );
923
- const getNumericRangeFilter = useCallback4(
1604
+ const getNumericRangeFilter = useCallback5(
924
1605
  (columnId) => {
925
1606
  const column = table.getColumn(columnId);
926
1607
  if (!column)
@@ -933,12 +1614,12 @@ function useExcelGrid(options) {
933
1614
  },
934
1615
  [table]
935
1616
  );
936
- const clearAllFilters = useCallback4(() => {
1617
+ const clearAllFilters = useCallback5(() => {
937
1618
  table.resetColumnFilters();
938
1619
  setGlobalFilter("");
939
1620
  setColumnFilters([]);
940
1621
  }, [table]);
941
- const getColumnFilterValues = useCallback4(
1622
+ const getColumnFilterValues = useCallback5(
942
1623
  (columnId) => {
943
1624
  const column = table.getColumn(columnId);
944
1625
  if (!column)
@@ -948,7 +1629,7 @@ function useExcelGrid(options) {
948
1629
  },
949
1630
  [table]
950
1631
  );
951
- const toggleSort = useCallback4((columnId) => {
1632
+ const toggleSort = useCallback5((columnId) => {
952
1633
  setSorting((prev) => {
953
1634
  const current = prev.find((s) => s.id === columnId);
954
1635
  if (!current) {
@@ -960,7 +1641,7 @@ function useExcelGrid(options) {
960
1641
  }
961
1642
  });
962
1643
  }, []);
963
- const getSortDirection = useCallback4(
1644
+ const getSortDirection = useCallback5(
964
1645
  (columnId) => {
965
1646
  const sort = sorting.find((s) => s.id === columnId);
966
1647
  if (!sort)
@@ -1007,7 +1688,7 @@ import {
1007
1688
  exportToCSV as coreExportToCSV,
1008
1689
  formatSelectionForClipboard as coreFormatSelection
1009
1690
  } from "@smallwebco/tinypivot-core";
1010
- import { useCallback as useCallback5, useMemo as useMemo5, useState as useState5 } from "react";
1691
+ import { useCallback as useCallback6, useMemo as useMemo6, useState as useState6 } from "react";
1011
1692
  function exportToCSV(data, columns, options) {
1012
1693
  coreExportToCSV(data, columns, options);
1013
1694
  }
@@ -1021,45 +1702,45 @@ function formatSelectionForClipboard(rows, columns, selectionBounds) {
1021
1702
  return coreFormatSelection(rows, columns, selectionBounds);
1022
1703
  }
1023
1704
  function usePagination(data, options = {}) {
1024
- const [pageSize, setPageSize] = useState5(options.pageSize ?? 50);
1025
- const [currentPage, setCurrentPage] = useState5(options.currentPage ?? 1);
1026
- const totalPages = useMemo5(
1705
+ const [pageSize, setPageSize] = useState6(options.pageSize ?? 50);
1706
+ const [currentPage, setCurrentPage] = useState6(options.currentPage ?? 1);
1707
+ const totalPages = useMemo6(
1027
1708
  () => Math.max(1, Math.ceil(data.length / pageSize)),
1028
1709
  [data.length, pageSize]
1029
1710
  );
1030
- const paginatedData = useMemo5(() => {
1711
+ const paginatedData = useMemo6(() => {
1031
1712
  const start = (currentPage - 1) * pageSize;
1032
1713
  const end = start + pageSize;
1033
1714
  return data.slice(start, end);
1034
1715
  }, [data, currentPage, pageSize]);
1035
- const startIndex = useMemo5(() => (currentPage - 1) * pageSize + 1, [currentPage, pageSize]);
1036
- const endIndex = useMemo5(
1716
+ const startIndex = useMemo6(() => (currentPage - 1) * pageSize + 1, [currentPage, pageSize]);
1717
+ const endIndex = useMemo6(
1037
1718
  () => Math.min(currentPage * pageSize, data.length),
1038
1719
  [currentPage, pageSize, data.length]
1039
1720
  );
1040
- const goToPage = useCallback5(
1721
+ const goToPage = useCallback6(
1041
1722
  (page) => {
1042
1723
  setCurrentPage(Math.max(1, Math.min(page, totalPages)));
1043
1724
  },
1044
1725
  [totalPages]
1045
1726
  );
1046
- const nextPage = useCallback5(() => {
1727
+ const nextPage = useCallback6(() => {
1047
1728
  if (currentPage < totalPages) {
1048
1729
  setCurrentPage((prev) => prev + 1);
1049
1730
  }
1050
1731
  }, [currentPage, totalPages]);
1051
- const prevPage = useCallback5(() => {
1732
+ const prevPage = useCallback6(() => {
1052
1733
  if (currentPage > 1) {
1053
1734
  setCurrentPage((prev) => prev - 1);
1054
1735
  }
1055
1736
  }, [currentPage]);
1056
- const firstPage = useCallback5(() => {
1737
+ const firstPage = useCallback6(() => {
1057
1738
  setCurrentPage(1);
1058
1739
  }, []);
1059
- const lastPage = useCallback5(() => {
1740
+ const lastPage = useCallback6(() => {
1060
1741
  setCurrentPage(totalPages);
1061
1742
  }, [totalPages]);
1062
- const updatePageSize = useCallback5((size) => {
1743
+ const updatePageSize = useCallback6((size) => {
1063
1744
  setPageSize(size);
1064
1745
  setCurrentPage(1);
1065
1746
  }, []);
@@ -1079,9 +1760,9 @@ function usePagination(data, options = {}) {
1079
1760
  };
1080
1761
  }
1081
1762
  function useGlobalSearch(data, columns) {
1082
- const [searchTerm, setSearchTerm] = useState5("");
1083
- const [caseSensitive, setCaseSensitive] = useState5(false);
1084
- const filteredData = useMemo5(() => {
1763
+ const [searchTerm, setSearchTerm] = useState6("");
1764
+ const [caseSensitive, setCaseSensitive] = useState6(false);
1765
+ const filteredData = useMemo6(() => {
1085
1766
  if (!searchTerm.trim()) {
1086
1767
  return data;
1087
1768
  }
@@ -1099,7 +1780,7 @@ function useGlobalSearch(data, columns) {
1099
1780
  return false;
1100
1781
  });
1101
1782
  }, [data, columns, searchTerm, caseSensitive]);
1102
- const clearSearch = useCallback5(() => {
1783
+ const clearSearch = useCallback6(() => {
1103
1784
  setSearchTerm("");
1104
1785
  }, []);
1105
1786
  return {
@@ -1112,17 +1793,17 @@ function useGlobalSearch(data, columns) {
1112
1793
  };
1113
1794
  }
1114
1795
  function useRowSelection(data) {
1115
- const [selectedRowIndices, setSelectedRowIndices] = useState5(/* @__PURE__ */ new Set());
1116
- const selectedRows = useMemo5(() => {
1796
+ const [selectedRowIndices, setSelectedRowIndices] = useState6(/* @__PURE__ */ new Set());
1797
+ const selectedRows = useMemo6(() => {
1117
1798
  return Array.from(selectedRowIndices).sort((a, b) => a - b).map((idx) => data[idx]).filter(Boolean);
1118
1799
  }, [data, selectedRowIndices]);
1119
- const allSelected = useMemo5(() => {
1800
+ const allSelected = useMemo6(() => {
1120
1801
  return data.length > 0 && selectedRowIndices.size === data.length;
1121
1802
  }, [data.length, selectedRowIndices.size]);
1122
- const someSelected = useMemo5(() => {
1803
+ const someSelected = useMemo6(() => {
1123
1804
  return selectedRowIndices.size > 0 && selectedRowIndices.size < data.length;
1124
1805
  }, [data.length, selectedRowIndices.size]);
1125
- const toggleRow = useCallback5((index) => {
1806
+ const toggleRow = useCallback6((index) => {
1126
1807
  setSelectedRowIndices((prev) => {
1127
1808
  const next = new Set(prev);
1128
1809
  if (next.has(index)) {
@@ -1133,36 +1814,36 @@ function useRowSelection(data) {
1133
1814
  return next;
1134
1815
  });
1135
1816
  }, []);
1136
- const selectRow = useCallback5((index) => {
1817
+ const selectRow = useCallback6((index) => {
1137
1818
  setSelectedRowIndices((prev) => /* @__PURE__ */ new Set([...prev, index]));
1138
1819
  }, []);
1139
- const deselectRow = useCallback5((index) => {
1820
+ const deselectRow = useCallback6((index) => {
1140
1821
  setSelectedRowIndices((prev) => {
1141
1822
  const next = new Set(prev);
1142
1823
  next.delete(index);
1143
1824
  return next;
1144
1825
  });
1145
1826
  }, []);
1146
- const selectAll = useCallback5(() => {
1827
+ const selectAll = useCallback6(() => {
1147
1828
  setSelectedRowIndices(new Set(data.map((_, idx) => idx)));
1148
1829
  }, [data]);
1149
- const deselectAll = useCallback5(() => {
1830
+ const deselectAll = useCallback6(() => {
1150
1831
  setSelectedRowIndices(/* @__PURE__ */ new Set());
1151
1832
  }, []);
1152
- const toggleAll = useCallback5(() => {
1833
+ const toggleAll = useCallback6(() => {
1153
1834
  if (allSelected) {
1154
1835
  deselectAll();
1155
1836
  } else {
1156
1837
  selectAll();
1157
1838
  }
1158
1839
  }, [allSelected, selectAll, deselectAll]);
1159
- const isSelected = useCallback5(
1840
+ const isSelected = useCallback6(
1160
1841
  (index) => {
1161
1842
  return selectedRowIndices.has(index);
1162
1843
  },
1163
1844
  [selectedRowIndices]
1164
1845
  );
1165
- const selectRange = useCallback5((startIndex, endIndex) => {
1846
+ const selectRange = useCallback6((startIndex, endIndex) => {
1166
1847
  const min = Math.min(startIndex, endIndex);
1167
1848
  const max = Math.max(startIndex, endIndex);
1168
1849
  setSelectedRowIndices((prev) => {
@@ -1189,10 +1870,10 @@ function useRowSelection(data) {
1189
1870
  };
1190
1871
  }
1191
1872
  function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
1192
- const [columnWidths, setColumnWidths] = useState5({ ...initialWidths });
1193
- const [isResizing, setIsResizing] = useState5(false);
1194
- const [resizingColumn, setResizingColumn] = useState5(null);
1195
- const startResize = useCallback5(
1873
+ const [columnWidths, setColumnWidths] = useState6({ ...initialWidths });
1874
+ const [isResizing, setIsResizing] = useState6(false);
1875
+ const [resizingColumn, setResizingColumn] = useState6(null);
1876
+ const startResize = useCallback6(
1196
1877
  (columnId, event) => {
1197
1878
  setIsResizing(true);
1198
1879
  setResizingColumn(columnId);
@@ -1217,7 +1898,7 @@ function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
1217
1898
  },
1218
1899
  [columnWidths, minWidth, maxWidth]
1219
1900
  );
1220
- const resetColumnWidth = useCallback5(
1901
+ const resetColumnWidth = useCallback6(
1221
1902
  (columnId) => {
1222
1903
  if (initialWidths[columnId]) {
1223
1904
  setColumnWidths((prev) => ({
@@ -1228,7 +1909,7 @@ function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
1228
1909
  },
1229
1910
  [initialWidths]
1230
1911
  );
1231
- const resetAllWidths = useCallback5(() => {
1912
+ const resetAllWidths = useCallback6(() => {
1232
1913
  setColumnWidths({ ...initialWidths });
1233
1914
  }, [initialWidths]);
1234
1915
  return {
@@ -1244,6 +1925,7 @@ function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
1244
1925
 
1245
1926
  // src/hooks/useLicense.ts
1246
1927
  import {
1928
+ canUseCharts as coreCanUseCharts,
1247
1929
  canUsePivot as coreCanUsePivot,
1248
1930
  configureLicenseSecret as coreConfigureLicenseSecret,
1249
1931
  isPro as coreIsPro,
@@ -1253,7 +1935,7 @@ import {
1253
1935
  logProRequired,
1254
1936
  validateLicenseKey
1255
1937
  } from "@smallwebco/tinypivot-core";
1256
- import { useCallback as useCallback6, useMemo as useMemo6, useState as useState6 } from "react";
1938
+ import { useCallback as useCallback7, useMemo as useMemo7, useState as useState7 } from "react";
1257
1939
  var globalLicenseInfo = getFreeLicenseInfo();
1258
1940
  var globalDemoMode = false;
1259
1941
  var listeners = /* @__PURE__ */ new Set();
@@ -1285,35 +1967,39 @@ function configureLicenseSecret(secret) {
1285
1967
  coreConfigureLicenseSecret(secret);
1286
1968
  }
1287
1969
  function useLicense() {
1288
- const [, forceUpdate] = useState6({});
1289
- useState6(() => {
1970
+ const [, forceUpdate] = useState7({});
1971
+ useState7(() => {
1290
1972
  const update = () => forceUpdate({});
1291
1973
  listeners.add(update);
1292
1974
  return () => listeners.delete(update);
1293
1975
  });
1294
1976
  const isDemo = globalDemoMode;
1295
1977
  const licenseInfo = globalLicenseInfo;
1296
- const isPro = useMemo6(
1978
+ const isPro = useMemo7(
1297
1979
  () => globalDemoMode || coreIsPro(licenseInfo),
1298
1980
  [licenseInfo]
1299
1981
  );
1300
- const canUsePivot = useMemo6(
1982
+ const canUsePivot = useMemo7(
1301
1983
  () => globalDemoMode || coreCanUsePivot(licenseInfo),
1302
1984
  [licenseInfo]
1303
1985
  );
1304
- const canUseAdvancedAggregations = useMemo6(
1986
+ const canUseAdvancedAggregations = useMemo7(
1305
1987
  () => globalDemoMode || licenseInfo.features.advancedAggregations,
1306
1988
  [licenseInfo]
1307
1989
  );
1308
- const canUsePercentageMode = useMemo6(
1990
+ const canUsePercentageMode = useMemo7(
1309
1991
  () => globalDemoMode || licenseInfo.features.percentageMode,
1310
1992
  [licenseInfo]
1311
1993
  );
1312
- const showWatermark = useMemo6(
1994
+ const canUseCharts = useMemo7(
1995
+ () => globalDemoMode || coreCanUseCharts(licenseInfo),
1996
+ [licenseInfo]
1997
+ );
1998
+ const showWatermark = useMemo7(
1313
1999
  () => coreShouldShowWatermark(licenseInfo, globalDemoMode),
1314
2000
  [licenseInfo]
1315
2001
  );
1316
- const requirePro = useCallback6((feature) => {
2002
+ const requirePro = useCallback7((feature) => {
1317
2003
  if (!isPro) {
1318
2004
  logProRequired(feature);
1319
2005
  return false;
@@ -1327,6 +2013,7 @@ function useLicense() {
1327
2013
  canUsePivot,
1328
2014
  canUseAdvancedAggregations,
1329
2015
  canUsePercentageMode,
2016
+ canUseCharts,
1330
2017
  showWatermark,
1331
2018
  requirePro
1332
2019
  };
@@ -1346,23 +2033,23 @@ import {
1346
2033
  saveCalculatedFields,
1347
2034
  savePivotConfig
1348
2035
  } from "@smallwebco/tinypivot-core";
1349
- import { useCallback as useCallback7, useEffect as useEffect5, useMemo as useMemo7, useState as useState7 } from "react";
2036
+ import { useCallback as useCallback8, useEffect as useEffect6, useMemo as useMemo8, useState as useState8 } from "react";
1350
2037
  function usePivotTable(data) {
1351
2038
  const { canUsePivot, requirePro } = useLicense();
1352
- const [rowFields, setRowFieldsState] = useState7([]);
1353
- const [columnFields, setColumnFieldsState] = useState7([]);
1354
- const [valueFields, setValueFields] = useState7([]);
1355
- const [showRowTotals, setShowRowTotals] = useState7(true);
1356
- const [showColumnTotals, setShowColumnTotals] = useState7(true);
1357
- const [calculatedFields, setCalculatedFields] = useState7(() => loadCalculatedFields());
1358
- const [currentStorageKey, setCurrentStorageKey] = useState7(null);
1359
- const availableFields = useMemo7(() => {
2039
+ const [rowFields, setRowFieldsState] = useState8([]);
2040
+ const [columnFields, setColumnFieldsState] = useState8([]);
2041
+ const [valueFields, setValueFields] = useState8([]);
2042
+ const [showRowTotals, setShowRowTotals] = useState8(true);
2043
+ const [showColumnTotals, setShowColumnTotals] = useState8(true);
2044
+ const [calculatedFields, setCalculatedFields] = useState8(() => loadCalculatedFields());
2045
+ const [currentStorageKey, setCurrentStorageKey] = useState8(null);
2046
+ const availableFields = useMemo8(() => {
1360
2047
  return computeAvailableFields(data);
1361
2048
  }, [data]);
1362
- const unassignedFields = useMemo7(() => {
2049
+ const unassignedFields = useMemo8(() => {
1363
2050
  return getUnassignedFields(availableFields, rowFields, columnFields, valueFields);
1364
2051
  }, [availableFields, rowFields, columnFields, valueFields]);
1365
- const isConfigured = useMemo7(() => {
2052
+ const isConfigured = useMemo8(() => {
1366
2053
  return isPivotConfigured({
1367
2054
  rowFields,
1368
2055
  columnFields,
@@ -1371,7 +2058,7 @@ function usePivotTable(data) {
1371
2058
  showColumnTotals
1372
2059
  });
1373
2060
  }, [rowFields, columnFields, valueFields, showRowTotals, showColumnTotals]);
1374
- const pivotResult = useMemo7(() => {
2061
+ const pivotResult = useMemo8(() => {
1375
2062
  if (!isConfigured)
1376
2063
  return null;
1377
2064
  if (!canUsePivot)
@@ -1385,7 +2072,7 @@ function usePivotTable(data) {
1385
2072
  calculatedFields
1386
2073
  });
1387
2074
  }, [data, isConfigured, canUsePivot, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals, calculatedFields]);
1388
- useEffect5(() => {
2075
+ useEffect6(() => {
1389
2076
  if (data.length === 0)
1390
2077
  return;
1391
2078
  const newKeys = Object.keys(data[0]);
@@ -1418,7 +2105,7 @@ function usePivotTable(data) {
1418
2105
  }
1419
2106
  }
1420
2107
  }, [data]);
1421
- useEffect5(() => {
2108
+ useEffect6(() => {
1422
2109
  if (!currentStorageKey)
1423
2110
  return;
1424
2111
  const config = {
@@ -1431,7 +2118,7 @@ function usePivotTable(data) {
1431
2118
  };
1432
2119
  savePivotConfig(currentStorageKey, config);
1433
2120
  }, [currentStorageKey, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals, calculatedFields]);
1434
- const addRowField = useCallback7(
2121
+ const addRowField = useCallback8(
1435
2122
  (field) => {
1436
2123
  if (!rowFields.includes(field)) {
1437
2124
  setRowFieldsState((prev) => [...prev, field]);
@@ -1439,13 +2126,13 @@ function usePivotTable(data) {
1439
2126
  },
1440
2127
  [rowFields]
1441
2128
  );
1442
- const removeRowField = useCallback7((field) => {
2129
+ const removeRowField = useCallback8((field) => {
1443
2130
  setRowFieldsState((prev) => prev.filter((f) => f !== field));
1444
2131
  }, []);
1445
- const setRowFields = useCallback7((fields) => {
2132
+ const setRowFields = useCallback8((fields) => {
1446
2133
  setRowFieldsState(fields);
1447
2134
  }, []);
1448
- const addColumnField = useCallback7(
2135
+ const addColumnField = useCallback8(
1449
2136
  (field) => {
1450
2137
  if (!columnFields.includes(field)) {
1451
2138
  setColumnFieldsState((prev) => [...prev, field]);
@@ -1453,13 +2140,13 @@ function usePivotTable(data) {
1453
2140
  },
1454
2141
  [columnFields]
1455
2142
  );
1456
- const removeColumnField = useCallback7((field) => {
2143
+ const removeColumnField = useCallback8((field) => {
1457
2144
  setColumnFieldsState((prev) => prev.filter((f) => f !== field));
1458
2145
  }, []);
1459
- const setColumnFields = useCallback7((fields) => {
2146
+ const setColumnFields = useCallback8((fields) => {
1460
2147
  setColumnFieldsState(fields);
1461
2148
  }, []);
1462
- const addValueField = useCallback7(
2149
+ const addValueField = useCallback8(
1463
2150
  (field, aggregation = "sum") => {
1464
2151
  if (aggregation !== "sum" && !requirePro(`${aggregation} aggregation`)) {
1465
2152
  return;
@@ -1473,7 +2160,7 @@ function usePivotTable(data) {
1473
2160
  },
1474
2161
  [requirePro]
1475
2162
  );
1476
- const removeValueField = useCallback7((field, aggregation) => {
2163
+ const removeValueField = useCallback8((field, aggregation) => {
1477
2164
  setValueFields((prev) => {
1478
2165
  if (aggregation) {
1479
2166
  return prev.filter((v) => !(v.field === field && v.aggregation === aggregation));
@@ -1481,7 +2168,7 @@ function usePivotTable(data) {
1481
2168
  return prev.filter((v) => v.field !== field);
1482
2169
  });
1483
2170
  }, []);
1484
- const updateValueFieldAggregation = useCallback7(
2171
+ const updateValueFieldAggregation = useCallback8(
1485
2172
  (field, oldAgg, newAgg) => {
1486
2173
  setValueFields(
1487
2174
  (prev) => prev.map((v) => {
@@ -1494,12 +2181,12 @@ function usePivotTable(data) {
1494
2181
  },
1495
2182
  []
1496
2183
  );
1497
- const clearConfig = useCallback7(() => {
2184
+ const clearConfig = useCallback8(() => {
1498
2185
  setRowFieldsState([]);
1499
2186
  setColumnFieldsState([]);
1500
2187
  setValueFields([]);
1501
2188
  }, []);
1502
- const autoSuggestConfig = useCallback7(() => {
2189
+ const autoSuggestConfig = useCallback8(() => {
1503
2190
  if (!requirePro("Pivot Table - Auto Suggest"))
1504
2191
  return;
1505
2192
  if (availableFields.length === 0)
@@ -1511,7 +2198,7 @@ function usePivotTable(data) {
1511
2198
  setValueFields([{ field: numericFields[0].field, aggregation: "sum" }]);
1512
2199
  }
1513
2200
  }, [availableFields, requirePro]);
1514
- const addCalculatedField = useCallback7((field) => {
2201
+ const addCalculatedField = useCallback8((field) => {
1515
2202
  setCalculatedFields((prev) => {
1516
2203
  const existing = prev.findIndex((f) => f.id === field.id);
1517
2204
  let updated;
@@ -1524,7 +2211,7 @@ function usePivotTable(data) {
1524
2211
  return updated;
1525
2212
  });
1526
2213
  }, []);
1527
- const removeCalculatedField = useCallback7((id) => {
2214
+ const removeCalculatedField = useCallback8((id) => {
1528
2215
  setCalculatedFields((prev) => {
1529
2216
  const updated = prev.filter((f) => f.id !== id);
1530
2217
  saveCalculatedFields(updated);
@@ -1566,8 +2253,8 @@ function usePivotTable(data) {
1566
2253
 
1567
2254
  // src/components/PivotConfig.tsx
1568
2255
  import { AGGREGATION_OPTIONS, getAggregationSymbol } from "@smallwebco/tinypivot-core";
1569
- import { useCallback as useCallback8, useMemo as useMemo8, useState as useState8 } from "react";
1570
- import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
2256
+ import { useCallback as useCallback9, useMemo as useMemo9, useState as useState9 } from "react";
2257
+ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1571
2258
  function aggregationRequiresPro(agg) {
1572
2259
  return agg !== "sum";
1573
2260
  }
@@ -1608,15 +2295,15 @@ function PivotConfig({
1608
2295
  onRemoveCalculatedField,
1609
2296
  onUpdateCalculatedField
1610
2297
  }) {
1611
- const [fieldSearch, setFieldSearch] = useState8("");
1612
- const [showCalcModal, setShowCalcModal] = useState8(false);
1613
- const [editingCalcField, setEditingCalcField] = useState8(null);
2298
+ const [fieldSearch, setFieldSearch] = useState9("");
2299
+ const [showCalcModal, setShowCalcModal] = useState9(false);
2300
+ const [editingCalcField, setEditingCalcField] = useState9(null);
1614
2301
  const { canUseAdvancedAggregations } = useLicense();
1615
- const isAggregationAvailable = useCallback8((agg) => {
2302
+ const isAggregationAvailable = useCallback9((agg) => {
1616
2303
  return !aggregationRequiresPro(agg) || canUseAdvancedAggregations;
1617
2304
  }, [canUseAdvancedAggregations]);
1618
- const numericFieldNames = useMemo8(() => availableFields.filter((f) => f.isNumeric).map((f) => f.field), [availableFields]);
1619
- const calculatedFieldsAsStats = useMemo8(() => {
2305
+ const numericFieldNames = useMemo9(() => availableFields.filter((f) => f.isNumeric).map((f) => f.field), [availableFields]);
2306
+ const calculatedFieldsAsStats = useMemo9(() => {
1620
2307
  if (!calculatedFields)
1621
2308
  return [];
1622
2309
  return calculatedFields.map((calc) => ({
@@ -1630,11 +2317,11 @@ function PivotConfig({
1630
2317
  calcFormula: calc.formula
1631
2318
  }));
1632
2319
  }, [calculatedFields]);
1633
- const allAvailableFields = useMemo8(() => [
2320
+ const allAvailableFields = useMemo9(() => [
1634
2321
  ...availableFields.map((f) => ({ ...f, isCalculated: false })),
1635
2322
  ...calculatedFieldsAsStats
1636
2323
  ], [availableFields, calculatedFieldsAsStats]);
1637
- const assignedFields = useMemo8(() => {
2324
+ const assignedFields = useMemo9(() => {
1638
2325
  const rowSet = new Set(rowFields);
1639
2326
  const colSet = new Set(columnFields);
1640
2327
  const valueMap = new Map(valueFields.map((v) => [v.field, v]));
@@ -1644,7 +2331,7 @@ function PivotConfig({
1644
2331
  valueConfig: valueMap.get(f.field)
1645
2332
  }));
1646
2333
  }, [allAvailableFields, rowFields, columnFields, valueFields]);
1647
- const unassignedFields = useMemo8(() => {
2334
+ const unassignedFields = useMemo9(() => {
1648
2335
  const rowSet = new Set(rowFields);
1649
2336
  const colSet = new Set(columnFields);
1650
2337
  const valSet = new Set(valueFields.map((v) => v.field));
@@ -1652,7 +2339,7 @@ function PivotConfig({
1652
2339
  (f) => !rowSet.has(f.field) && !colSet.has(f.field) && !valSet.has(f.field)
1653
2340
  );
1654
2341
  }, [allAvailableFields, rowFields, columnFields, valueFields]);
1655
- const filteredUnassignedFields = useMemo8(() => {
2342
+ const filteredUnassignedFields = useMemo9(() => {
1656
2343
  if (!fieldSearch.trim())
1657
2344
  return unassignedFields;
1658
2345
  const search = fieldSearch.toLowerCase().trim();
@@ -1663,13 +2350,13 @@ function PivotConfig({
1663
2350
  });
1664
2351
  }, [unassignedFields, fieldSearch]);
1665
2352
  const assignedCount = assignedFields.length;
1666
- const getFieldDisplayName = useCallback8((field) => {
2353
+ const getFieldDisplayName = useCallback9((field) => {
1667
2354
  if (field.isCalculated && field.calcName) {
1668
2355
  return field.calcName;
1669
2356
  }
1670
2357
  return field.field;
1671
2358
  }, []);
1672
- const handleDragStart = useCallback8(
2359
+ const handleDragStart = useCallback9(
1673
2360
  (field, event) => {
1674
2361
  event.dataTransfer?.setData("text/plain", field);
1675
2362
  event.dataTransfer.effectAllowed = "move";
@@ -1677,7 +2364,7 @@ function PivotConfig({
1677
2364
  },
1678
2365
  [onDragStart]
1679
2366
  );
1680
- const handleAggregationChange = useCallback8(
2367
+ const handleAggregationChange = useCallback9(
1681
2368
  (field, currentAgg, newAgg) => {
1682
2369
  if (!isAggregationAvailable(newAgg)) {
1683
2370
  console.warn(`[TinyPivot] "${newAgg}" aggregation requires a Pro license. Visit https://tiny-pivot.com/#pricing to upgrade.`);
@@ -1687,7 +2374,7 @@ function PivotConfig({
1687
2374
  },
1688
2375
  [onUpdateAggregation, isAggregationAvailable]
1689
2376
  );
1690
- const toggleRowColumn = useCallback8(
2377
+ const toggleRowColumn = useCallback9(
1691
2378
  (field, currentAssignment) => {
1692
2379
  if (currentAssignment === "row") {
1693
2380
  onRemoveRowField(field);
@@ -1699,7 +2386,7 @@ function PivotConfig({
1699
2386
  },
1700
2387
  [onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddRowField]
1701
2388
  );
1702
- const removeField = useCallback8(
2389
+ const removeField = useCallback9(
1703
2390
  (field, assignedTo, valueConfig) => {
1704
2391
  if (assignedTo === "row") {
1705
2392
  onRemoveRowField(field);
@@ -1711,15 +2398,15 @@ function PivotConfig({
1711
2398
  },
1712
2399
  [onRemoveRowField, onRemoveColumnField, onRemoveValueField]
1713
2400
  );
1714
- const handleTotalsToggle = useCallback8((checked) => {
2401
+ const handleTotalsToggle = useCallback9((checked) => {
1715
2402
  onShowRowTotalsChange(checked);
1716
2403
  onShowColumnTotalsChange(checked);
1717
2404
  }, [onShowRowTotalsChange, onShowColumnTotalsChange]);
1718
- const openCalcModal = useCallback8((field) => {
2405
+ const openCalcModal = useCallback9((field) => {
1719
2406
  setEditingCalcField(field || null);
1720
2407
  setShowCalcModal(true);
1721
2408
  }, []);
1722
- const handleSaveCalcField = useCallback8((field) => {
2409
+ const handleSaveCalcField = useCallback9((field) => {
1723
2410
  if (editingCalcField && onUpdateCalculatedField) {
1724
2411
  onUpdateCalculatedField(field);
1725
2412
  } else if (onAddCalculatedField) {
@@ -1728,14 +2415,14 @@ function PivotConfig({
1728
2415
  setShowCalcModal(false);
1729
2416
  setEditingCalcField(null);
1730
2417
  }, [editingCalcField, onAddCalculatedField, onUpdateCalculatedField]);
1731
- const handleCloseCalcModal = useCallback8(() => {
2418
+ const handleCloseCalcModal = useCallback9(() => {
1732
2419
  setShowCalcModal(false);
1733
2420
  setEditingCalcField(null);
1734
2421
  }, []);
1735
- return /* @__PURE__ */ jsxs4("div", { className: "vpg-pivot-config", children: [
1736
- /* @__PURE__ */ jsxs4("div", { className: "vpg-config-header", children: [
1737
- /* @__PURE__ */ jsxs4("h3", { className: "vpg-config-title", children: [
1738
- /* @__PURE__ */ jsx4("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
2422
+ return /* @__PURE__ */ jsxs5("div", { className: "vpg-pivot-config", children: [
2423
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-config-header", children: [
2424
+ /* @__PURE__ */ jsxs5("h3", { className: "vpg-config-title", children: [
2425
+ /* @__PURE__ */ jsx5("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
1739
2426
  "path",
1740
2427
  {
1741
2428
  strokeLinecap: "round",
@@ -1746,13 +2433,13 @@ function PivotConfig({
1746
2433
  ) }),
1747
2434
  "Fields"
1748
2435
  ] }),
1749
- /* @__PURE__ */ jsx4("div", { className: "vpg-header-actions", children: assignedCount > 0 && /* @__PURE__ */ jsx4(
2436
+ /* @__PURE__ */ jsx5("div", { className: "vpg-header-actions", children: assignedCount > 0 && /* @__PURE__ */ jsx5(
1750
2437
  "button",
1751
2438
  {
1752
2439
  className: "vpg-action-btn vpg-clear-btn",
1753
2440
  title: "Clear all",
1754
2441
  onClick: onClearConfig,
1755
- children: /* @__PURE__ */ jsx4("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
2442
+ children: /* @__PURE__ */ jsx5("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
1756
2443
  "path",
1757
2444
  {
1758
2445
  strokeLinecap: "round",
@@ -1764,9 +2451,9 @@ function PivotConfig({
1764
2451
  }
1765
2452
  ) })
1766
2453
  ] }),
1767
- assignedCount > 0 && /* @__PURE__ */ jsxs4("div", { className: "vpg-assigned-section", children: [
1768
- /* @__PURE__ */ jsx4("div", { className: "vpg-section-label", children: "Active" }),
1769
- /* @__PURE__ */ jsx4("div", { className: "vpg-assigned-list", children: assignedFields.map((field) => /* @__PURE__ */ jsxs4(
2454
+ assignedCount > 0 && /* @__PURE__ */ jsxs5("div", { className: "vpg-assigned-section", children: [
2455
+ /* @__PURE__ */ jsx5("div", { className: "vpg-section-label", children: "Active" }),
2456
+ /* @__PURE__ */ jsx5("div", { className: "vpg-assigned-list", children: assignedFields.map((field) => /* @__PURE__ */ jsxs5(
1770
2457
  "div",
1771
2458
  {
1772
2459
  className: `vpg-assigned-item vpg-type-${field.assignedTo}${field.isCalculated ? " vpg-type-calc" : ""}`,
@@ -1775,12 +2462,12 @@ function PivotConfig({
1775
2462
  onDragStart: (e) => handleDragStart(field.field, e),
1776
2463
  onDragEnd,
1777
2464
  children: [
1778
- /* @__PURE__ */ jsxs4("div", { className: "vpg-item-main", children: [
1779
- /* @__PURE__ */ jsx4("span", { className: `vpg-item-badge ${field.assignedTo}${field.isCalculated ? " calc" : ""}`, children: field.isCalculated ? "\u0192" : field.assignedTo === "row" ? "R" : field.assignedTo === "column" ? "C" : getAggregationSymbol(field.valueConfig?.aggregation || "sum") }),
1780
- /* @__PURE__ */ jsx4("span", { className: "vpg-item-name", children: getFieldDisplayName(field) })
2465
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-item-main", children: [
2466
+ /* @__PURE__ */ jsx5("span", { className: `vpg-item-badge ${field.assignedTo}${field.isCalculated ? " calc" : ""}`, children: field.isCalculated ? "\u0192" : field.assignedTo === "row" ? "R" : field.assignedTo === "column" ? "C" : getAggregationSymbol(field.valueConfig?.aggregation || "sum") }),
2467
+ /* @__PURE__ */ jsx5("span", { className: "vpg-item-name", children: getFieldDisplayName(field) })
1781
2468
  ] }),
1782
- /* @__PURE__ */ jsxs4("div", { className: "vpg-item-actions", children: [
1783
- (field.assignedTo === "row" || field.assignedTo === "column") && /* @__PURE__ */ jsx4(
2469
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-item-actions", children: [
2470
+ (field.assignedTo === "row" || field.assignedTo === "column") && /* @__PURE__ */ jsx5(
1784
2471
  "button",
1785
2472
  {
1786
2473
  className: "vpg-toggle-btn",
@@ -1789,14 +2476,14 @@ function PivotConfig({
1789
2476
  e.stopPropagation();
1790
2477
  toggleRowColumn(field.field, field.assignedTo);
1791
2478
  },
1792
- children: /* @__PURE__ */ jsx4(
2479
+ children: /* @__PURE__ */ jsx5(
1793
2480
  "svg",
1794
2481
  {
1795
2482
  className: "vpg-icon-xs",
1796
2483
  fill: "none",
1797
2484
  stroke: "currentColor",
1798
2485
  viewBox: "0 0 24 24",
1799
- children: /* @__PURE__ */ jsx4(
2486
+ children: /* @__PURE__ */ jsx5(
1800
2487
  "path",
1801
2488
  {
1802
2489
  strokeLinecap: "round",
@@ -1809,7 +2496,7 @@ function PivotConfig({
1809
2496
  )
1810
2497
  }
1811
2498
  ),
1812
- field.assignedTo === "value" && field.valueConfig && /* @__PURE__ */ jsx4(
2499
+ field.assignedTo === "value" && field.valueConfig && /* @__PURE__ */ jsx5(
1813
2500
  "select",
1814
2501
  {
1815
2502
  className: "vpg-agg-select",
@@ -1823,7 +2510,7 @@ function PivotConfig({
1823
2510
  );
1824
2511
  },
1825
2512
  onClick: (e) => e.stopPropagation(),
1826
- children: AGGREGATION_OPTIONS.map((agg) => /* @__PURE__ */ jsxs4(
2513
+ children: AGGREGATION_OPTIONS.map((agg) => /* @__PURE__ */ jsxs5(
1827
2514
  "option",
1828
2515
  {
1829
2516
  value: agg.value,
@@ -1839,7 +2526,7 @@ function PivotConfig({
1839
2526
  ))
1840
2527
  }
1841
2528
  ),
1842
- /* @__PURE__ */ jsx4(
2529
+ /* @__PURE__ */ jsx5(
1843
2530
  "button",
1844
2531
  {
1845
2532
  className: "vpg-remove-btn",
@@ -1857,14 +2544,14 @@ function PivotConfig({
1857
2544
  field.field
1858
2545
  )) })
1859
2546
  ] }),
1860
- /* @__PURE__ */ jsxs4("div", { className: "vpg-unassigned-section", children: [
1861
- /* @__PURE__ */ jsx4("div", { className: "vpg-section-header", children: /* @__PURE__ */ jsxs4("div", { className: "vpg-section-label", children: [
2547
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-unassigned-section", children: [
2548
+ /* @__PURE__ */ jsx5("div", { className: "vpg-section-header", children: /* @__PURE__ */ jsxs5("div", { className: "vpg-section-label", children: [
1862
2549
  "Available",
1863
2550
  " ",
1864
- /* @__PURE__ */ jsx4("span", { className: "vpg-count", children: unassignedFields.length })
2551
+ /* @__PURE__ */ jsx5("span", { className: "vpg-count", children: unassignedFields.length })
1865
2552
  ] }) }),
1866
- /* @__PURE__ */ jsxs4("div", { className: "vpg-field-search", children: [
1867
- /* @__PURE__ */ jsx4("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
2553
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-field-search", children: [
2554
+ /* @__PURE__ */ jsx5("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
1868
2555
  "path",
1869
2556
  {
1870
2557
  strokeLinecap: "round",
@@ -1873,7 +2560,7 @@ function PivotConfig({
1873
2560
  d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
1874
2561
  }
1875
2562
  ) }),
1876
- /* @__PURE__ */ jsx4(
2563
+ /* @__PURE__ */ jsx5(
1877
2564
  "input",
1878
2565
  {
1879
2566
  type: "text",
@@ -1883,7 +2570,7 @@ function PivotConfig({
1883
2570
  className: "vpg-search-input"
1884
2571
  }
1885
2572
  ),
1886
- fieldSearch && /* @__PURE__ */ jsx4("button", { className: "vpg-clear-search", onClick: () => setFieldSearch(""), children: /* @__PURE__ */ jsx4("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4(
2573
+ fieldSearch && /* @__PURE__ */ jsx5("button", { className: "vpg-clear-search", onClick: () => setFieldSearch(""), children: /* @__PURE__ */ jsx5("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
1887
2574
  "path",
1888
2575
  {
1889
2576
  strokeLinecap: "round",
@@ -1893,8 +2580,8 @@ function PivotConfig({
1893
2580
  }
1894
2581
  ) }) })
1895
2582
  ] }),
1896
- /* @__PURE__ */ jsxs4("div", { className: "vpg-field-list", children: [
1897
- filteredUnassignedFields.map((field) => /* @__PURE__ */ jsxs4(
2583
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-field-list", children: [
2584
+ filteredUnassignedFields.map((field) => /* @__PURE__ */ jsxs5(
1898
2585
  "div",
1899
2586
  {
1900
2587
  className: `vpg-field-item${field.isNumeric && !field.isCalculated ? " vpg-is-numeric" : ""}${field.isCalculated ? " vpg-is-calculated" : ""}`,
@@ -1903,10 +2590,10 @@ function PivotConfig({
1903
2590
  onDragStart: (e) => handleDragStart(field.field, e),
1904
2591
  onDragEnd,
1905
2592
  children: [
1906
- /* @__PURE__ */ jsx4("span", { className: `vpg-field-type-icon${field.isCalculated ? " vpg-calc-type" : ""}`, title: field.type, children: getFieldIcon(field.type, field.isCalculated) }),
1907
- /* @__PURE__ */ jsx4("span", { className: "vpg-field-name", children: getFieldDisplayName(field) }),
1908
- field.isCalculated ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
1909
- /* @__PURE__ */ jsx4(
2593
+ /* @__PURE__ */ jsx5("span", { className: `vpg-field-type-icon${field.isCalculated ? " vpg-calc-type" : ""}`, title: field.type, children: getFieldIcon(field.type, field.isCalculated) }),
2594
+ /* @__PURE__ */ jsx5("span", { className: "vpg-field-name", children: getFieldDisplayName(field) }),
2595
+ field.isCalculated ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
2596
+ /* @__PURE__ */ jsx5(
1910
2597
  "button",
1911
2598
  {
1912
2599
  className: "vpg-field-edit",
@@ -1920,7 +2607,7 @@ function PivotConfig({
1920
2607
  children: "\u270E"
1921
2608
  }
1922
2609
  ),
1923
- /* @__PURE__ */ jsx4(
2610
+ /* @__PURE__ */ jsx5(
1924
2611
  "button",
1925
2612
  {
1926
2613
  className: "vpg-field-delete",
@@ -1934,22 +2621,22 @@ function PivotConfig({
1934
2621
  children: "\xD7"
1935
2622
  }
1936
2623
  )
1937
- ] }) : /* @__PURE__ */ jsx4("span", { className: "vpg-unique-count", children: field.uniqueCount })
2624
+ ] }) : /* @__PURE__ */ jsx5("span", { className: "vpg-unique-count", children: field.uniqueCount })
1938
2625
  ]
1939
2626
  },
1940
2627
  field.field
1941
2628
  )),
1942
- filteredUnassignedFields.length === 0 && fieldSearch && /* @__PURE__ */ jsxs4("div", { className: "vpg-empty-hint", children: [
2629
+ filteredUnassignedFields.length === 0 && fieldSearch && /* @__PURE__ */ jsxs5("div", { className: "vpg-empty-hint", children: [
1943
2630
  'No fields match "',
1944
2631
  fieldSearch,
1945
2632
  '"'
1946
2633
  ] }),
1947
- unassignedFields.length === 0 && /* @__PURE__ */ jsx4("div", { className: "vpg-empty-hint", children: "All fields assigned" })
2634
+ unassignedFields.length === 0 && /* @__PURE__ */ jsx5("div", { className: "vpg-empty-hint", children: "All fields assigned" })
1948
2635
  ] })
1949
2636
  ] }),
1950
- /* @__PURE__ */ jsxs4("div", { className: "vpg-options-section", children: [
1951
- /* @__PURE__ */ jsxs4("label", { className: "vpg-option-toggle", children: [
1952
- /* @__PURE__ */ jsx4(
2637
+ /* @__PURE__ */ jsxs5("div", { className: "vpg-options-section", children: [
2638
+ /* @__PURE__ */ jsxs5("label", { className: "vpg-option-toggle", children: [
2639
+ /* @__PURE__ */ jsx5(
1953
2640
  "input",
1954
2641
  {
1955
2642
  type: "checkbox",
@@ -1957,14 +2644,14 @@ function PivotConfig({
1957
2644
  onChange: (e) => handleTotalsToggle(e.target.checked)
1958
2645
  }
1959
2646
  ),
1960
- /* @__PURE__ */ jsx4("span", { children: "Totals" })
2647
+ /* @__PURE__ */ jsx5("span", { children: "Totals" })
1961
2648
  ] }),
1962
- /* @__PURE__ */ jsxs4("button", { className: "vpg-calc-btn", onClick: () => openCalcModal(), title: "Add calculated field (e.g. Profit Margin %)", children: [
1963
- /* @__PURE__ */ jsx4("span", { className: "vpg-calc-icon", children: "\u0192" }),
1964
- /* @__PURE__ */ jsx4("span", { children: "+ Calc" })
2649
+ /* @__PURE__ */ jsxs5("button", { className: "vpg-calc-btn", onClick: () => openCalcModal(), title: "Add calculated field (e.g. Profit Margin %)", children: [
2650
+ /* @__PURE__ */ jsx5("span", { className: "vpg-calc-icon", children: "\u0192" }),
2651
+ /* @__PURE__ */ jsx5("span", { children: "+ Calc" })
1965
2652
  ] })
1966
2653
  ] }),
1967
- /* @__PURE__ */ jsx4(
2654
+ /* @__PURE__ */ jsx5(
1968
2655
  CalculatedFieldModal,
1969
2656
  {
1970
2657
  show: showCalcModal,
@@ -1979,8 +2666,8 @@ function PivotConfig({
1979
2666
 
1980
2667
  // src/components/PivotSkeleton.tsx
1981
2668
  import { getAggregationLabel as getAggregationLabel2, getAggregationSymbol as getAggregationSymbol2 } from "@smallwebco/tinypivot-core";
1982
- import { useCallback as useCallback9, useEffect as useEffect6, useMemo as useMemo9, useState as useState9 } from "react";
1983
- import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
2669
+ import { useCallback as useCallback10, useEffect as useEffect7, useMemo as useMemo10, useState as useState10 } from "react";
2670
+ import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1984
2671
  function PivotSkeleton({
1985
2672
  rowFields,
1986
2673
  columnFields,
@@ -2003,7 +2690,7 @@ function PivotSkeleton({
2003
2690
  onReorderColumnFields
2004
2691
  }) {
2005
2692
  const { showWatermark, canUsePivot, isDemo } = useLicense();
2006
- const getValueFieldDisplayName = useCallback9((field) => {
2693
+ const getValueFieldDisplayName = useCallback10((field) => {
2007
2694
  if (field.startsWith("calc:")) {
2008
2695
  const calcId = field.replace("calc:", "");
2009
2696
  const calcField = calculatedFields?.find((c) => c.id === calcId);
@@ -2011,15 +2698,15 @@ function PivotSkeleton({
2011
2698
  }
2012
2699
  return field;
2013
2700
  }, [calculatedFields]);
2014
- const isCalculatedField = useCallback9((field) => {
2701
+ const isCalculatedField = useCallback10((field) => {
2015
2702
  return field.startsWith("calc:");
2016
2703
  }, []);
2017
- const [dragOverArea, setDragOverArea] = useState9(null);
2018
- const [reorderDragSource, setReorderDragSource] = useState9(null);
2019
- const [reorderDropTarget, setReorderDropTarget] = useState9(null);
2020
- const [sortDirection, setSortDirection] = useState9("asc");
2021
- const [sortTarget, setSortTarget] = useState9("row");
2022
- const toggleSort = useCallback9((target = "row") => {
2704
+ const [dragOverArea, setDragOverArea] = useState10(null);
2705
+ const [reorderDragSource, setReorderDragSource] = useState10(null);
2706
+ const [reorderDropTarget, setReorderDropTarget] = useState10(null);
2707
+ const [sortDirection, setSortDirection] = useState10("asc");
2708
+ const [sortTarget, setSortTarget] = useState10("row");
2709
+ const toggleSort = useCallback10((target = "row") => {
2023
2710
  if (sortTarget === target) {
2024
2711
  setSortDirection((prev) => prev === "asc" ? "desc" : "asc");
2025
2712
  } else {
@@ -2027,13 +2714,13 @@ function PivotSkeleton({
2027
2714
  setSortDirection("asc");
2028
2715
  }
2029
2716
  }, [sortTarget]);
2030
- const [selectedCell, setSelectedCell] = useState9(null);
2031
- const [selectionStart, setSelectionStart] = useState9(null);
2032
- const [selectionEnd, setSelectionEnd] = useState9(null);
2033
- const [isSelecting, setIsSelecting] = useState9(false);
2034
- const [showCopyToast, setShowCopyToast] = useState9(false);
2035
- const [copyToastMessage, setCopyToastMessage] = useState9("");
2036
- const selectionBounds = useMemo9(() => {
2717
+ const [selectedCell, setSelectedCell] = useState10(null);
2718
+ const [selectionStart, setSelectionStart] = useState10(null);
2719
+ const [selectionEnd, setSelectionEnd] = useState10(null);
2720
+ const [isSelecting, setIsSelecting] = useState10(false);
2721
+ const [showCopyToast, setShowCopyToast] = useState10(false);
2722
+ const [copyToastMessage, setCopyToastMessage] = useState10("");
2723
+ const selectionBounds = useMemo10(() => {
2037
2724
  if (!selectionStart || !selectionEnd)
2038
2725
  return null;
2039
2726
  return {
@@ -2043,7 +2730,7 @@ function PivotSkeleton({
2043
2730
  maxCol: Math.max(selectionStart.col, selectionEnd.col)
2044
2731
  };
2045
2732
  }, [selectionStart, selectionEnd]);
2046
- const handleCellMouseDown = useCallback9(
2733
+ const handleCellMouseDown = useCallback10(
2047
2734
  (rowIndex, colIndex, event) => {
2048
2735
  event.preventDefault();
2049
2736
  if (event.shiftKey && selectedCell) {
@@ -2057,7 +2744,7 @@ function PivotSkeleton({
2057
2744
  },
2058
2745
  [selectedCell]
2059
2746
  );
2060
- const handleCellMouseEnter = useCallback9(
2747
+ const handleCellMouseEnter = useCallback10(
2061
2748
  (rowIndex, colIndex) => {
2062
2749
  if (isSelecting) {
2063
2750
  setSelectionEnd({ row: rowIndex, col: colIndex });
@@ -2065,7 +2752,7 @@ function PivotSkeleton({
2065
2752
  },
2066
2753
  [isSelecting]
2067
2754
  );
2068
- const isCellSelected = useCallback9(
2755
+ const isCellSelected = useCallback10(
2069
2756
  (rowIndex, colIndex) => {
2070
2757
  if (!selectionBounds) {
2071
2758
  return selectedCell?.row === rowIndex && selectedCell?.col === colIndex;
@@ -2075,12 +2762,12 @@ function PivotSkeleton({
2075
2762
  },
2076
2763
  [selectionBounds, selectedCell]
2077
2764
  );
2078
- useEffect6(() => {
2765
+ useEffect7(() => {
2079
2766
  const handleMouseUp = () => setIsSelecting(false);
2080
2767
  document.addEventListener("mouseup", handleMouseUp);
2081
2768
  return () => document.removeEventListener("mouseup", handleMouseUp);
2082
2769
  }, []);
2083
- const sortedRowIndices = useMemo9(() => {
2770
+ const sortedRowIndices = useMemo10(() => {
2084
2771
  if (!pivotResult)
2085
2772
  return [];
2086
2773
  const indices = pivotResult.rowHeaders.map((_, i) => i);
@@ -2108,7 +2795,7 @@ function PivotSkeleton({
2108
2795
  });
2109
2796
  return indices;
2110
2797
  }, [pivotResult, sortTarget, sortDirection]);
2111
- const copySelectionToClipboard = useCallback9(() => {
2798
+ const copySelectionToClipboard = useCallback10(() => {
2112
2799
  if (!selectionBounds || !pivotResult)
2113
2800
  return;
2114
2801
  const { minRow, maxRow, minCol, maxCol } = selectionBounds;
@@ -2134,7 +2821,7 @@ function PivotSkeleton({
2134
2821
  console.error("Copy failed:", err);
2135
2822
  });
2136
2823
  }, [selectionBounds, pivotResult, sortedRowIndices]);
2137
- useEffect6(() => {
2824
+ useEffect7(() => {
2138
2825
  const handleKeydown = (event) => {
2139
2826
  if (!selectionBounds)
2140
2827
  return;
@@ -2152,7 +2839,7 @@ function PivotSkeleton({
2152
2839
  document.addEventListener("keydown", handleKeydown);
2153
2840
  return () => document.removeEventListener("keydown", handleKeydown);
2154
2841
  }, [selectionBounds, copySelectionToClipboard]);
2155
- const selectionStats = useMemo9(() => {
2842
+ const selectionStats = useMemo10(() => {
2156
2843
  if (!selectionBounds || !pivotResult)
2157
2844
  return null;
2158
2845
  const { minRow, maxRow, minCol, maxCol } = selectionBounds;
@@ -2181,14 +2868,14 @@ function PivotSkeleton({
2181
2868
  avg
2182
2869
  };
2183
2870
  }, [selectionBounds, pivotResult, sortedRowIndices]);
2184
- const formatStatValue = useCallback9((val) => {
2871
+ const formatStatValue = useCallback10((val) => {
2185
2872
  if (Math.abs(val) >= 1e6)
2186
2873
  return `${(val / 1e6).toFixed(2)}M`;
2187
2874
  if (Math.abs(val) >= 1e3)
2188
2875
  return `${(val / 1e3).toFixed(2)}K`;
2189
2876
  return val.toFixed(2);
2190
2877
  }, []);
2191
- const columnHeaderCells = useMemo9(() => {
2878
+ const columnHeaderCells = useMemo10(() => {
2192
2879
  if (!pivotResult || pivotResult.headers.length === 0) {
2193
2880
  return [
2194
2881
  valueFields.map((vf) => ({
@@ -2216,13 +2903,13 @@ function PivotSkeleton({
2216
2903
  return result;
2217
2904
  }, [pivotResult, valueFields]);
2218
2905
  const hasActiveFilters = activeFilters && activeFilters.length > 0;
2219
- const filterSummary = useMemo9(() => {
2906
+ const filterSummary = useMemo10(() => {
2220
2907
  if (!activeFilters || activeFilters.length === 0)
2221
2908
  return "";
2222
2909
  return activeFilters.map((f) => f.column).join(", ");
2223
2910
  }, [activeFilters]);
2224
- const [showFilterTooltip, setShowFilterTooltip] = useState9(false);
2225
- const filterTooltipDetails = useMemo9(() => {
2911
+ const [showFilterTooltip, setShowFilterTooltip] = useState10(false);
2912
+ const filterTooltipDetails = useMemo10(() => {
2226
2913
  if (!activeFilters || activeFilters.length === 0)
2227
2914
  return [];
2228
2915
  return activeFilters.map((f) => {
@@ -2247,7 +2934,7 @@ function PivotSkeleton({
2247
2934
  };
2248
2935
  });
2249
2936
  }, [activeFilters]);
2250
- const handleDragOver = useCallback9(
2937
+ const handleDragOver = useCallback10(
2251
2938
  (area, event) => {
2252
2939
  event.preventDefault();
2253
2940
  event.dataTransfer.dropEffect = "move";
@@ -2255,10 +2942,10 @@ function PivotSkeleton({
2255
2942
  },
2256
2943
  []
2257
2944
  );
2258
- const handleDragLeave = useCallback9(() => {
2945
+ const handleDragLeave = useCallback10(() => {
2259
2946
  setDragOverArea(null);
2260
2947
  }, []);
2261
- const handleDrop = useCallback9(
2948
+ const handleDrop = useCallback10(
2262
2949
  (area, event) => {
2263
2950
  event.preventDefault();
2264
2951
  const field = event.dataTransfer?.getData("text/plain");
@@ -2288,7 +2975,7 @@ function PivotSkeleton({
2288
2975
  },
2289
2976
  [rowFields, columnFields, valueFields, onAddRowField, onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddValueField, onRemoveValueField]
2290
2977
  );
2291
- const handleChipDragStart = useCallback9(
2978
+ const handleChipDragStart = useCallback10(
2292
2979
  (zone, index, event) => {
2293
2980
  setReorderDragSource({ zone, index });
2294
2981
  event.dataTransfer.effectAllowed = "move";
@@ -2299,11 +2986,11 @@ function PivotSkeleton({
2299
2986
  },
2300
2987
  []
2301
2988
  );
2302
- const handleChipDragEnd = useCallback9(() => {
2989
+ const handleChipDragEnd = useCallback10(() => {
2303
2990
  setReorderDragSource(null);
2304
2991
  setReorderDropTarget(null);
2305
2992
  }, []);
2306
- const handleChipDragOver = useCallback9(
2993
+ const handleChipDragOver = useCallback10(
2307
2994
  (zone, index, event) => {
2308
2995
  event.preventDefault();
2309
2996
  if (reorderDragSource && reorderDragSource.zone === zone) {
@@ -2313,10 +3000,10 @@ function PivotSkeleton({
2313
3000
  },
2314
3001
  [reorderDragSource]
2315
3002
  );
2316
- const handleChipDragLeave = useCallback9(() => {
3003
+ const handleChipDragLeave = useCallback10(() => {
2317
3004
  setReorderDropTarget(null);
2318
3005
  }, []);
2319
- const handleChipDrop = useCallback9(
3006
+ const handleChipDrop = useCallback10(
2320
3007
  (zone, targetIndex, event) => {
2321
3008
  event.preventDefault();
2322
3009
  event.stopPropagation();
@@ -2342,13 +3029,13 @@ function PivotSkeleton({
2342
3029
  },
2343
3030
  [reorderDragSource, rowFields, columnFields, onReorderRowFields, onReorderColumnFields]
2344
3031
  );
2345
- const isChipDragSource = useCallback9(
3032
+ const isChipDragSource = useCallback10(
2346
3033
  (zone, index) => {
2347
3034
  return reorderDragSource?.zone === zone && reorderDragSource?.index === index;
2348
3035
  },
2349
3036
  [reorderDragSource]
2350
3037
  );
2351
- const isChipDropTarget = useCallback9(
3038
+ const isChipDropTarget = useCallback10(
2352
3039
  (zone, index) => {
2353
3040
  return reorderDropTarget?.zone === zone && reorderDropTarget?.index === index;
2354
3041
  },
@@ -2356,25 +3043,25 @@ function PivotSkeleton({
2356
3043
  );
2357
3044
  const currentFontSize = fontSize;
2358
3045
  const rowHeaderWidth = 180;
2359
- const rowHeaderColWidth = useMemo9(() => {
3046
+ const rowHeaderColWidth = useMemo10(() => {
2360
3047
  const numCols = Math.max(rowFields.length, 1);
2361
3048
  return Math.max(rowHeaderWidth / numCols, 80);
2362
3049
  }, [rowFields.length]);
2363
- const getRowHeaderLeftOffset = useCallback9((fieldIdx) => {
3050
+ const getRowHeaderLeftOffset = useCallback10((fieldIdx) => {
2364
3051
  return fieldIdx * rowHeaderColWidth;
2365
3052
  }, [rowHeaderColWidth]);
2366
- return /* @__PURE__ */ jsxs5(
3053
+ return /* @__PURE__ */ jsxs6(
2367
3054
  "div",
2368
3055
  {
2369
3056
  className: `vpg-pivot-skeleton vpg-font-${currentFontSize} ${draggingField ? "vpg-is-dragging" : ""}`,
2370
3057
  children: [
2371
- showCopyToast && /* @__PURE__ */ jsxs5("div", { className: "vpg-toast", children: [
2372
- /* @__PURE__ */ jsx5("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
3058
+ showCopyToast && /* @__PURE__ */ jsxs6("div", { className: "vpg-toast", children: [
3059
+ /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
2373
3060
  copyToastMessage
2374
3061
  ] }),
2375
- /* @__PURE__ */ jsxs5("div", { className: "vpg-skeleton-header", children: [
2376
- /* @__PURE__ */ jsxs5("div", { className: "vpg-skeleton-title", children: [
2377
- /* @__PURE__ */ jsx5("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5(
3062
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-skeleton-header", children: [
3063
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-skeleton-title", children: [
3064
+ /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
2378
3065
  "path",
2379
3066
  {
2380
3067
  strokeLinecap: "round",
@@ -2383,24 +3070,24 @@ function PivotSkeleton({
2383
3070
  d: "M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"
2384
3071
  }
2385
3072
  ) }),
2386
- /* @__PURE__ */ jsx5("span", { children: "Pivot Table" })
3073
+ /* @__PURE__ */ jsx6("span", { children: "Pivot Table" })
2387
3074
  ] }),
2388
- /* @__PURE__ */ jsxs5("div", { className: "vpg-header-right", children: [
2389
- hasActiveFilters && /* @__PURE__ */ jsxs5(
3075
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-header-right", children: [
3076
+ hasActiveFilters && /* @__PURE__ */ jsxs6(
2390
3077
  "div",
2391
3078
  {
2392
3079
  className: "vpg-filter-indicator",
2393
3080
  onMouseEnter: () => setShowFilterTooltip(true),
2394
3081
  onMouseLeave: () => setShowFilterTooltip(false),
2395
3082
  children: [
2396
- /* @__PURE__ */ jsx5(
3083
+ /* @__PURE__ */ jsx6(
2397
3084
  "svg",
2398
3085
  {
2399
3086
  className: "vpg-filter-icon",
2400
3087
  fill: "none",
2401
3088
  stroke: "currentColor",
2402
3089
  viewBox: "0 0 24 24",
2403
- children: /* @__PURE__ */ jsx5(
3090
+ children: /* @__PURE__ */ jsx6(
2404
3091
  "path",
2405
3092
  {
2406
3093
  strokeLinecap: "round",
@@ -2411,11 +3098,11 @@ function PivotSkeleton({
2411
3098
  )
2412
3099
  }
2413
3100
  ),
2414
- /* @__PURE__ */ jsxs5("span", { className: "vpg-filter-text", children: [
3101
+ /* @__PURE__ */ jsxs6("span", { className: "vpg-filter-text", children: [
2415
3102
  "Filtered:",
2416
3103
  " ",
2417
- /* @__PURE__ */ jsx5("strong", { children: filterSummary }),
2418
- filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ jsxs5("span", { className: "vpg-filter-count", children: [
3104
+ /* @__PURE__ */ jsx6("strong", { children: filterSummary }),
3105
+ filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ jsxs6("span", { className: "vpg-filter-count", children: [
2419
3106
  "(",
2420
3107
  filteredRowCount.toLocaleString(),
2421
3108
  " ",
@@ -2426,13 +3113,13 @@ function PivotSkeleton({
2426
3113
  "rows)"
2427
3114
  ] })
2428
3115
  ] }),
2429
- showFilterTooltip && /* @__PURE__ */ jsxs5("div", { className: "vpg-filter-tooltip", children: [
2430
- /* @__PURE__ */ jsx5("div", { className: "vpg-tooltip-header", children: "Active Filters" }),
2431
- filterTooltipDetails.map((filter) => /* @__PURE__ */ jsxs5("div", { className: "vpg-tooltip-filter", children: [
2432
- /* @__PURE__ */ jsx5("div", { className: "vpg-tooltip-column", children: filter.column }),
2433
- /* @__PURE__ */ jsx5("div", { className: "vpg-tooltip-values", children: filter.isRange ? /* @__PURE__ */ jsx5("span", { className: "vpg-tooltip-value vpg-range-value", children: filter.displayText }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
2434
- filter.values.map((val, idx) => /* @__PURE__ */ jsx5("span", { className: "vpg-tooltip-value", children: val }, idx)),
2435
- filter.remaining > 0 && /* @__PURE__ */ jsxs5("span", { className: "vpg-tooltip-more", children: [
3116
+ showFilterTooltip && /* @__PURE__ */ jsxs6("div", { className: "vpg-filter-tooltip", children: [
3117
+ /* @__PURE__ */ jsx6("div", { className: "vpg-tooltip-header", children: "Active Filters" }),
3118
+ filterTooltipDetails.map((filter) => /* @__PURE__ */ jsxs6("div", { className: "vpg-tooltip-filter", children: [
3119
+ /* @__PURE__ */ jsx6("div", { className: "vpg-tooltip-column", children: filter.column }),
3120
+ /* @__PURE__ */ jsx6("div", { className: "vpg-tooltip-values", children: filter.isRange ? /* @__PURE__ */ jsx6("span", { className: "vpg-tooltip-value vpg-range-value", children: filter.displayText }) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
3121
+ filter.values.map((val, idx) => /* @__PURE__ */ jsx6("span", { className: "vpg-tooltip-value", children: val }, idx)),
3122
+ filter.remaining > 0 && /* @__PURE__ */ jsxs6("span", { className: "vpg-tooltip-more", children: [
2436
3123
  "+",
2437
3124
  filter.remaining,
2438
3125
  " ",
@@ -2440,7 +3127,7 @@ function PivotSkeleton({
2440
3127
  ] })
2441
3128
  ] }) })
2442
3129
  ] }, filter.column)),
2443
- filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ jsxs5("div", { className: "vpg-tooltip-summary", children: [
3130
+ filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ jsxs6("div", { className: "vpg-tooltip-summary", children: [
2444
3131
  "Showing",
2445
3132
  " ",
2446
3133
  filteredRowCount.toLocaleString(),
@@ -2455,20 +3142,20 @@ function PivotSkeleton({
2455
3142
  ]
2456
3143
  }
2457
3144
  ),
2458
- isConfigured && /* @__PURE__ */ jsxs5("div", { className: "vpg-config-summary", children: [
2459
- /* @__PURE__ */ jsxs5("span", { className: "vpg-summary-badge vpg-rows", children: [
3145
+ isConfigured && /* @__PURE__ */ jsxs6("div", { className: "vpg-config-summary", children: [
3146
+ /* @__PURE__ */ jsxs6("span", { className: "vpg-summary-badge vpg-rows", children: [
2460
3147
  rowFields.length,
2461
3148
  " ",
2462
3149
  "row",
2463
3150
  rowFields.length !== 1 ? "s" : ""
2464
3151
  ] }),
2465
- /* @__PURE__ */ jsxs5("span", { className: "vpg-summary-badge vpg-cols", children: [
3152
+ /* @__PURE__ */ jsxs6("span", { className: "vpg-summary-badge vpg-cols", children: [
2466
3153
  columnFields.length,
2467
3154
  " ",
2468
3155
  "col",
2469
3156
  columnFields.length !== 1 ? "s" : ""
2470
3157
  ] }),
2471
- /* @__PURE__ */ jsxs5("span", { className: "vpg-summary-badge vpg-vals", children: [
3158
+ /* @__PURE__ */ jsxs6("span", { className: "vpg-summary-badge vpg-vals", children: [
2472
3159
  valueFields.length,
2473
3160
  " ",
2474
3161
  "val",
@@ -2477,8 +3164,8 @@ function PivotSkeleton({
2477
3164
  ] })
2478
3165
  ] })
2479
3166
  ] }),
2480
- !canUsePivot ? /* @__PURE__ */ jsx5("div", { className: "vpg-pro-required", children: /* @__PURE__ */ jsxs5("div", { className: "vpg-pro-content", children: [
2481
- /* @__PURE__ */ jsx5("svg", { className: "vpg-pro-icon", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5(
3167
+ !canUsePivot ? /* @__PURE__ */ jsx6("div", { className: "vpg-pro-required", children: /* @__PURE__ */ jsxs6("div", { className: "vpg-pro-content", children: [
3168
+ /* @__PURE__ */ jsx6("svg", { className: "vpg-pro-icon", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6(
2482
3169
  "path",
2483
3170
  {
2484
3171
  strokeLinecap: "round",
@@ -2487,12 +3174,12 @@ function PivotSkeleton({
2487
3174
  d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
2488
3175
  }
2489
3176
  ) }),
2490
- /* @__PURE__ */ jsx5("h3", { children: "Pro Feature" }),
2491
- /* @__PURE__ */ jsx5("p", { children: "Pivot Table functionality requires a Pro license." }),
2492
- /* @__PURE__ */ jsx5("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", className: "vpg-pro-link", children: "Get Pro License \u2192" })
2493
- ] }) }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
2494
- /* @__PURE__ */ jsxs5("div", { className: "vpg-config-bar", children: [
2495
- /* @__PURE__ */ jsxs5(
3177
+ /* @__PURE__ */ jsx6("h3", { children: "Pro Feature" }),
3178
+ /* @__PURE__ */ jsx6("p", { children: "Pivot Table functionality requires a Pro license." }),
3179
+ /* @__PURE__ */ jsx6("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", className: "vpg-pro-link", children: "Get Pro License \u2192" })
3180
+ ] }) }) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
3181
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-config-bar", children: [
3182
+ /* @__PURE__ */ jsxs6(
2496
3183
  "div",
2497
3184
  {
2498
3185
  className: `vpg-drop-zone vpg-row-zone ${dragOverArea === "row" ? "vpg-drag-over" : ""}`,
@@ -2500,12 +3187,12 @@ function PivotSkeleton({
2500
3187
  onDragLeave: handleDragLeave,
2501
3188
  onDrop: (e) => handleDrop("row", e),
2502
3189
  children: [
2503
- /* @__PURE__ */ jsxs5("div", { className: "vpg-zone-header", children: [
2504
- /* @__PURE__ */ jsx5("span", { className: "vpg-zone-icon vpg-row-icon", children: "\u2193" }),
2505
- /* @__PURE__ */ jsx5("span", { className: "vpg-zone-label", children: "Rows" })
3190
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-zone-header", children: [
3191
+ /* @__PURE__ */ jsx6("span", { className: "vpg-zone-icon vpg-row-icon", children: "\u2193" }),
3192
+ /* @__PURE__ */ jsx6("span", { className: "vpg-zone-label", children: "Rows" })
2506
3193
  ] }),
2507
- /* @__PURE__ */ jsxs5("div", { className: "vpg-zone-chips", children: [
2508
- rowFields.map((field, idx) => /* @__PURE__ */ jsxs5(
3194
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-zone-chips", children: [
3195
+ rowFields.map((field, idx) => /* @__PURE__ */ jsxs6(
2509
3196
  "div",
2510
3197
  {
2511
3198
  className: `vpg-mini-chip vpg-row-chip ${isChipDragSource("row", idx) ? "vpg-chip-dragging" : ""} ${isChipDropTarget("row", idx) ? "vpg-chip-drop-target" : ""}`,
@@ -2516,9 +3203,9 @@ function PivotSkeleton({
2516
3203
  onDragLeave: handleChipDragLeave,
2517
3204
  onDrop: (e) => handleChipDrop("row", idx, e),
2518
3205
  children: [
2519
- /* @__PURE__ */ jsx5("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
2520
- /* @__PURE__ */ jsx5("span", { className: "vpg-mini-name", children: field }),
2521
- /* @__PURE__ */ jsx5(
3206
+ /* @__PURE__ */ jsx6("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
3207
+ /* @__PURE__ */ jsx6("span", { className: "vpg-mini-name", children: field }),
3208
+ /* @__PURE__ */ jsx6(
2522
3209
  "button",
2523
3210
  {
2524
3211
  className: "vpg-mini-remove",
@@ -2533,12 +3220,12 @@ function PivotSkeleton({
2533
3220
  },
2534
3221
  field
2535
3222
  )),
2536
- rowFields.length === 0 && /* @__PURE__ */ jsx5("span", { className: "vpg-zone-hint", children: "Drop here" })
3223
+ rowFields.length === 0 && /* @__PURE__ */ jsx6("span", { className: "vpg-zone-hint", children: "Drop here" })
2537
3224
  ] })
2538
3225
  ]
2539
3226
  }
2540
3227
  ),
2541
- /* @__PURE__ */ jsxs5(
3228
+ /* @__PURE__ */ jsxs6(
2542
3229
  "div",
2543
3230
  {
2544
3231
  className: `vpg-drop-zone vpg-column-zone ${dragOverArea === "column" ? "vpg-drag-over" : ""}`,
@@ -2546,12 +3233,12 @@ function PivotSkeleton({
2546
3233
  onDragLeave: handleDragLeave,
2547
3234
  onDrop: (e) => handleDrop("column", e),
2548
3235
  children: [
2549
- /* @__PURE__ */ jsxs5("div", { className: "vpg-zone-header", children: [
2550
- /* @__PURE__ */ jsx5("span", { className: "vpg-zone-icon vpg-column-icon", children: "\u2192" }),
2551
- /* @__PURE__ */ jsx5("span", { className: "vpg-zone-label", children: "Columns" })
3236
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-zone-header", children: [
3237
+ /* @__PURE__ */ jsx6("span", { className: "vpg-zone-icon vpg-column-icon", children: "\u2192" }),
3238
+ /* @__PURE__ */ jsx6("span", { className: "vpg-zone-label", children: "Columns" })
2552
3239
  ] }),
2553
- /* @__PURE__ */ jsxs5("div", { className: "vpg-zone-chips", children: [
2554
- columnFields.map((field, idx) => /* @__PURE__ */ jsxs5(
3240
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-zone-chips", children: [
3241
+ columnFields.map((field, idx) => /* @__PURE__ */ jsxs6(
2555
3242
  "div",
2556
3243
  {
2557
3244
  className: `vpg-mini-chip vpg-column-chip ${isChipDragSource("column", idx) ? "vpg-chip-dragging" : ""} ${isChipDropTarget("column", idx) ? "vpg-chip-drop-target" : ""}`,
@@ -2562,9 +3249,9 @@ function PivotSkeleton({
2562
3249
  onDragLeave: handleChipDragLeave,
2563
3250
  onDrop: (e) => handleChipDrop("column", idx, e),
2564
3251
  children: [
2565
- /* @__PURE__ */ jsx5("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
2566
- /* @__PURE__ */ jsx5("span", { className: "vpg-mini-name", children: field }),
2567
- /* @__PURE__ */ jsx5(
3252
+ /* @__PURE__ */ jsx6("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
3253
+ /* @__PURE__ */ jsx6("span", { className: "vpg-mini-name", children: field }),
3254
+ /* @__PURE__ */ jsx6(
2568
3255
  "button",
2569
3256
  {
2570
3257
  className: "vpg-mini-remove",
@@ -2579,12 +3266,12 @@ function PivotSkeleton({
2579
3266
  },
2580
3267
  field
2581
3268
  )),
2582
- columnFields.length === 0 && /* @__PURE__ */ jsx5("span", { className: "vpg-zone-hint", children: "Drop here" })
3269
+ columnFields.length === 0 && /* @__PURE__ */ jsx6("span", { className: "vpg-zone-hint", children: "Drop here" })
2583
3270
  ] })
2584
3271
  ]
2585
3272
  }
2586
3273
  ),
2587
- /* @__PURE__ */ jsxs5(
3274
+ /* @__PURE__ */ jsxs6(
2588
3275
  "div",
2589
3276
  {
2590
3277
  className: `vpg-drop-zone vpg-value-zone ${dragOverArea === "value" ? "vpg-drag-over" : ""}`,
@@ -2592,19 +3279,19 @@ function PivotSkeleton({
2592
3279
  onDragLeave: handleDragLeave,
2593
3280
  onDrop: (e) => handleDrop("value", e),
2594
3281
  children: [
2595
- /* @__PURE__ */ jsxs5("div", { className: "vpg-zone-header", children: [
2596
- /* @__PURE__ */ jsx5("span", { className: "vpg-zone-icon vpg-value-icon", children: "\u03A3" }),
2597
- /* @__PURE__ */ jsx5("span", { className: "vpg-zone-label", children: "Values" })
3282
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-zone-header", children: [
3283
+ /* @__PURE__ */ jsx6("span", { className: "vpg-zone-icon vpg-value-icon", children: "\u03A3" }),
3284
+ /* @__PURE__ */ jsx6("span", { className: "vpg-zone-label", children: "Values" })
2598
3285
  ] }),
2599
- /* @__PURE__ */ jsxs5("div", { className: "vpg-zone-chips", children: [
2600
- valueFields.map((vf) => /* @__PURE__ */ jsxs5(
3286
+ /* @__PURE__ */ jsxs6("div", { className: "vpg-zone-chips", children: [
3287
+ valueFields.map((vf) => /* @__PURE__ */ jsxs6(
2601
3288
  "div",
2602
3289
  {
2603
3290
  className: `vpg-mini-chip vpg-value-chip${isCalculatedField(vf.field) ? " vpg-calc-chip" : ""}`,
2604
3291
  children: [
2605
- /* @__PURE__ */ jsx5("span", { className: "vpg-agg-symbol", children: isCalculatedField(vf.field) ? "\u0192" : getAggregationSymbol2(vf.aggregation) }),
2606
- /* @__PURE__ */ jsx5("span", { className: "vpg-mini-name", children: getValueFieldDisplayName(vf.field) }),
2607
- /* @__PURE__ */ jsx5(
3292
+ /* @__PURE__ */ jsx6("span", { className: "vpg-agg-symbol", children: isCalculatedField(vf.field) ? "\u0192" : getAggregationSymbol2(vf.aggregation) }),
3293
+ /* @__PURE__ */ jsx6("span", { className: "vpg-mini-name", children: getValueFieldDisplayName(vf.field) }),
3294
+ /* @__PURE__ */ jsx6(
2608
3295
  "button",
2609
3296
  {
2610
3297
  className: "vpg-mini-remove",
@@ -2616,21 +3303,21 @@ function PivotSkeleton({
2616
3303
  },
2617
3304
  `${vf.field}-${vf.aggregation}`
2618
3305
  )),
2619
- valueFields.length === 0 && /* @__PURE__ */ jsx5("span", { className: "vpg-zone-hint", children: "Drop numeric" })
3306
+ valueFields.length === 0 && /* @__PURE__ */ jsx6("span", { className: "vpg-zone-hint", children: "Drop numeric" })
2620
3307
  ] })
2621
3308
  ]
2622
3309
  }
2623
3310
  )
2624
3311
  ] }),
2625
- (!isConfigured || !pivotResult) && /* @__PURE__ */ jsx5("div", { className: "vpg-placeholder", children: /* @__PURE__ */ jsxs5("div", { className: "vpg-placeholder-content", children: [
2626
- /* @__PURE__ */ jsx5(
3312
+ (!isConfigured || !pivotResult) && /* @__PURE__ */ jsx6("div", { className: "vpg-placeholder", children: /* @__PURE__ */ jsxs6("div", { className: "vpg-placeholder-content", children: [
3313
+ /* @__PURE__ */ jsx6(
2627
3314
  "svg",
2628
3315
  {
2629
3316
  className: "vpg-placeholder-icon",
2630
3317
  fill: "none",
2631
3318
  viewBox: "0 0 24 24",
2632
3319
  stroke: "currentColor",
2633
- children: /* @__PURE__ */ jsx5(
3320
+ children: /* @__PURE__ */ jsx6(
2634
3321
  "path",
2635
3322
  {
2636
3323
  strokeLinecap: "round",
@@ -2641,58 +3328,58 @@ function PivotSkeleton({
2641
3328
  )
2642
3329
  }
2643
3330
  ),
2644
- /* @__PURE__ */ jsx5("span", { className: "vpg-placeholder-text", children: valueFields.length === 0 ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
3331
+ /* @__PURE__ */ jsx6("span", { className: "vpg-placeholder-text", children: valueFields.length === 0 ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
2645
3332
  "Add a",
2646
3333
  " ",
2647
- /* @__PURE__ */ jsx5("strong", { children: "Values" }),
3334
+ /* @__PURE__ */ jsx6("strong", { children: "Values" }),
2648
3335
  " ",
2649
3336
  "field to see your pivot table"
2650
- ] }) : rowFields.length === 0 && columnFields.length === 0 ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
3337
+ ] }) : rowFields.length === 0 && columnFields.length === 0 ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
2651
3338
  "Add",
2652
3339
  " ",
2653
- /* @__PURE__ */ jsx5("strong", { children: "Row" }),
3340
+ /* @__PURE__ */ jsx6("strong", { children: "Row" }),
2654
3341
  " ",
2655
3342
  "or",
2656
3343
  " ",
2657
- /* @__PURE__ */ jsx5("strong", { children: "Column" }),
3344
+ /* @__PURE__ */ jsx6("strong", { children: "Column" }),
2658
3345
  " ",
2659
3346
  "fields to group your data"
2660
3347
  ] }) : "Your pivot table will appear here" })
2661
3348
  ] }) }),
2662
- isConfigured && pivotResult && /* @__PURE__ */ jsx5("div", { className: "vpg-table-container", children: /* @__PURE__ */ jsxs5("table", { className: "vpg-pivot-table", children: [
2663
- /* @__PURE__ */ jsx5("thead", { children: columnHeaderCells.map((headerRow, levelIdx) => /* @__PURE__ */ jsxs5("tr", { className: "vpg-column-header-row", children: [
2664
- levelIdx === 0 && (rowFields.length > 0 ? rowFields : ["Rows"]).map((field, fieldIdx) => /* @__PURE__ */ jsx5(
3349
+ isConfigured && pivotResult && /* @__PURE__ */ jsx6("div", { className: "vpg-table-container", children: /* @__PURE__ */ jsxs6("table", { className: "vpg-pivot-table", children: [
3350
+ /* @__PURE__ */ jsx6("thead", { children: columnHeaderCells.map((headerRow, levelIdx) => /* @__PURE__ */ jsxs6("tr", { className: "vpg-column-header-row", children: [
3351
+ levelIdx === 0 && (rowFields.length > 0 ? rowFields : ["Rows"]).map((field, fieldIdx) => /* @__PURE__ */ jsx6(
2665
3352
  "th",
2666
3353
  {
2667
3354
  className: "vpg-row-header-label",
2668
3355
  rowSpan: columnHeaderCells.length,
2669
3356
  style: { width: `${rowHeaderColWidth}px`, minWidth: "80px", left: `${getRowHeaderLeftOffset(fieldIdx)}px` },
2670
3357
  onClick: () => toggleSort("row"),
2671
- children: /* @__PURE__ */ jsxs5("div", { className: "vpg-header-content", children: [
2672
- /* @__PURE__ */ jsx5("span", { children: field }),
2673
- (fieldIdx === rowFields.length - 1 || rowFields.length === 0) && /* @__PURE__ */ jsx5("span", { className: `vpg-sort-indicator ${sortTarget === "row" ? "active" : ""}`, children: sortTarget === "row" ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
3358
+ children: /* @__PURE__ */ jsxs6("div", { className: "vpg-header-content", children: [
3359
+ /* @__PURE__ */ jsx6("span", { children: field }),
3360
+ (fieldIdx === rowFields.length - 1 || rowFields.length === 0) && /* @__PURE__ */ jsx6("span", { className: `vpg-sort-indicator ${sortTarget === "row" ? "active" : ""}`, children: sortTarget === "row" ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
2674
3361
  ] })
2675
3362
  },
2676
3363
  `row-header-${fieldIdx}`
2677
3364
  )),
2678
- headerRow.map((cell, idx) => /* @__PURE__ */ jsx5(
3365
+ headerRow.map((cell, idx) => /* @__PURE__ */ jsx6(
2679
3366
  "th",
2680
3367
  {
2681
3368
  className: "vpg-column-header-cell",
2682
3369
  colSpan: cell.colspan,
2683
3370
  onClick: () => levelIdx === columnHeaderCells.length - 1 && toggleSort(idx),
2684
- children: /* @__PURE__ */ jsxs5("div", { className: "vpg-header-content", children: [
2685
- /* @__PURE__ */ jsx5("span", { children: cell.label }),
2686
- levelIdx === columnHeaderCells.length - 1 && /* @__PURE__ */ jsx5("span", { className: `vpg-sort-indicator ${sortTarget === idx ? "active" : ""}`, children: sortTarget === idx ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
3371
+ children: /* @__PURE__ */ jsxs6("div", { className: "vpg-header-content", children: [
3372
+ /* @__PURE__ */ jsx6("span", { children: cell.label }),
3373
+ levelIdx === columnHeaderCells.length - 1 && /* @__PURE__ */ jsx6("span", { className: `vpg-sort-indicator ${sortTarget === idx ? "active" : ""}`, children: sortTarget === idx ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
2687
3374
  ] })
2688
3375
  },
2689
3376
  idx
2690
3377
  )),
2691
- pivotResult.rowTotals.length > 0 && levelIdx === 0 && /* @__PURE__ */ jsx5("th", { className: "vpg-total-header", rowSpan: columnHeaderCells.length, children: "Total" })
3378
+ pivotResult.rowTotals.length > 0 && levelIdx === 0 && /* @__PURE__ */ jsx6("th", { className: "vpg-total-header", rowSpan: columnHeaderCells.length, children: "Total" })
2692
3379
  ] }, `header-${levelIdx}`)) }),
2693
- /* @__PURE__ */ jsxs5("tbody", { children: [
2694
- sortedRowIndices.map((sortedIdx) => /* @__PURE__ */ jsxs5("tr", { className: "vpg-data-row", children: [
2695
- pivotResult.rowHeaders[sortedIdx].map((val, idx) => /* @__PURE__ */ jsx5(
3380
+ /* @__PURE__ */ jsxs6("tbody", { children: [
3381
+ sortedRowIndices.map((sortedIdx) => /* @__PURE__ */ jsxs6("tr", { className: "vpg-data-row", children: [
3382
+ pivotResult.rowHeaders[sortedIdx].map((val, idx) => /* @__PURE__ */ jsx6(
2696
3383
  "th",
2697
3384
  {
2698
3385
  className: "vpg-row-header-cell",
@@ -2703,7 +3390,7 @@ function PivotSkeleton({
2703
3390
  )),
2704
3391
  pivotResult.data[sortedIdx].map((cell, colIdx) => {
2705
3392
  const displayRowIdx = sortedRowIndices.indexOf(sortedIdx);
2706
- return /* @__PURE__ */ jsx5(
3393
+ return /* @__PURE__ */ jsx6(
2707
3394
  "td",
2708
3395
  {
2709
3396
  className: `vpg-data-cell ${isCellSelected(displayRowIdx, colIdx) ? "selected" : ""} ${cell.value === null ? "vpg-is-null" : ""}`,
@@ -2714,10 +3401,10 @@ function PivotSkeleton({
2714
3401
  colIdx
2715
3402
  );
2716
3403
  }),
2717
- pivotResult.rowTotals[sortedIdx] && /* @__PURE__ */ jsx5("td", { className: "vpg-data-cell vpg-total-cell", children: pivotResult.rowTotals[sortedIdx].formattedValue })
3404
+ pivotResult.rowTotals[sortedIdx] && /* @__PURE__ */ jsx6("td", { className: "vpg-data-cell vpg-total-cell", children: pivotResult.rowTotals[sortedIdx].formattedValue })
2718
3405
  ] }, sortedIdx)),
2719
- pivotResult.columnTotals.length > 0 && /* @__PURE__ */ jsxs5("tr", { className: "vpg-totals-row", children: [
2720
- /* @__PURE__ */ jsx5(
3406
+ pivotResult.columnTotals.length > 0 && /* @__PURE__ */ jsxs6("tr", { className: "vpg-totals-row", children: [
3407
+ /* @__PURE__ */ jsx6(
2721
3408
  "th",
2722
3409
  {
2723
3410
  className: "vpg-row-header-cell vpg-total-label",
@@ -2726,13 +3413,13 @@ function PivotSkeleton({
2726
3413
  children: "Total"
2727
3414
  }
2728
3415
  ),
2729
- pivotResult.columnTotals.map((cell, colIdx) => /* @__PURE__ */ jsx5("td", { className: "vpg-data-cell vpg-total-cell", children: cell.formattedValue }, colIdx)),
2730
- pivotResult.rowTotals.length > 0 && /* @__PURE__ */ jsx5("td", { className: "vpg-data-cell vpg-grand-total-cell", children: pivotResult.grandTotal.formattedValue })
3416
+ pivotResult.columnTotals.map((cell, colIdx) => /* @__PURE__ */ jsx6("td", { className: "vpg-data-cell vpg-total-cell", children: cell.formattedValue }, colIdx)),
3417
+ pivotResult.rowTotals.length > 0 && /* @__PURE__ */ jsx6("td", { className: "vpg-data-cell vpg-grand-total-cell", children: pivotResult.grandTotal.formattedValue })
2731
3418
  ] })
2732
3419
  ] })
2733
3420
  ] }) }),
2734
- isConfigured && pivotResult && /* @__PURE__ */ jsxs5("div", { className: "vpg-skeleton-footer", children: [
2735
- /* @__PURE__ */ jsxs5("span", { className: "vpg-footer-info", children: [
3421
+ isConfigured && pivotResult && /* @__PURE__ */ jsxs6("div", { className: "vpg-skeleton-footer", children: [
3422
+ /* @__PURE__ */ jsxs6("span", { className: "vpg-footer-info", children: [
2736
3423
  pivotResult.rowHeaders.length,
2737
3424
  " ",
2738
3425
  "rows \xD7",
@@ -2740,30 +3427,30 @@ function PivotSkeleton({
2740
3427
  " ",
2741
3428
  "columns"
2742
3429
  ] }),
2743
- selectionStats && selectionStats.count > 1 && /* @__PURE__ */ jsxs5("div", { className: "vpg-selection-stats", children: [
2744
- /* @__PURE__ */ jsxs5("span", { className: "vpg-stat", children: [
2745
- /* @__PURE__ */ jsx5("span", { className: "vpg-stat-label", children: "Count:" }),
2746
- /* @__PURE__ */ jsx5("span", { className: "vpg-stat-value", children: selectionStats.count })
3430
+ selectionStats && selectionStats.count > 1 && /* @__PURE__ */ jsxs6("div", { className: "vpg-selection-stats", children: [
3431
+ /* @__PURE__ */ jsxs6("span", { className: "vpg-stat", children: [
3432
+ /* @__PURE__ */ jsx6("span", { className: "vpg-stat-label", children: "Count:" }),
3433
+ /* @__PURE__ */ jsx6("span", { className: "vpg-stat-value", children: selectionStats.count })
2747
3434
  ] }),
2748
- selectionStats.numericCount > 0 && /* @__PURE__ */ jsxs5(Fragment3, { children: [
2749
- /* @__PURE__ */ jsx5("span", { className: "vpg-stat-divider", children: "|" }),
2750
- /* @__PURE__ */ jsxs5("span", { className: "vpg-stat", children: [
2751
- /* @__PURE__ */ jsx5("span", { className: "vpg-stat-label", children: "Sum:" }),
2752
- /* @__PURE__ */ jsx5("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
3435
+ selectionStats.numericCount > 0 && /* @__PURE__ */ jsxs6(Fragment4, { children: [
3436
+ /* @__PURE__ */ jsx6("span", { className: "vpg-stat-divider", children: "|" }),
3437
+ /* @__PURE__ */ jsxs6("span", { className: "vpg-stat", children: [
3438
+ /* @__PURE__ */ jsx6("span", { className: "vpg-stat-label", children: "Sum:" }),
3439
+ /* @__PURE__ */ jsx6("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
2753
3440
  ] }),
2754
- /* @__PURE__ */ jsx5("span", { className: "vpg-stat-divider", children: "|" }),
2755
- /* @__PURE__ */ jsxs5("span", { className: "vpg-stat", children: [
2756
- /* @__PURE__ */ jsx5("span", { className: "vpg-stat-label", children: "Avg:" }),
2757
- /* @__PURE__ */ jsx5("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
3441
+ /* @__PURE__ */ jsx6("span", { className: "vpg-stat-divider", children: "|" }),
3442
+ /* @__PURE__ */ jsxs6("span", { className: "vpg-stat", children: [
3443
+ /* @__PURE__ */ jsx6("span", { className: "vpg-stat-label", children: "Avg:" }),
3444
+ /* @__PURE__ */ jsx6("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
2758
3445
  ] })
2759
3446
  ] })
2760
3447
  ] })
2761
3448
  ] })
2762
3449
  ] }),
2763
- showWatermark && canUsePivot && /* @__PURE__ */ jsx5("div", { className: `vpg-watermark ${isDemo ? "vpg-demo-mode" : ""}`, children: isDemo ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
2764
- /* @__PURE__ */ jsx5("span", { className: "vpg-demo-badge", children: "DEMO" }),
2765
- /* @__PURE__ */ jsx5("span", { children: "Pro features unlocked for evaluation" }),
2766
- /* @__PURE__ */ jsx5(
3450
+ showWatermark && canUsePivot && /* @__PURE__ */ jsx6("div", { className: `vpg-watermark ${isDemo ? "vpg-demo-mode" : ""}`, children: isDemo ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
3451
+ /* @__PURE__ */ jsx6("span", { className: "vpg-demo-badge", children: "DEMO" }),
3452
+ /* @__PURE__ */ jsx6("span", { children: "Pro features unlocked for evaluation" }),
3453
+ /* @__PURE__ */ jsx6(
2767
3454
  "a",
2768
3455
  {
2769
3456
  href: "https://tiny-pivot.com/#pricing",
@@ -2773,14 +3460,14 @@ function PivotSkeleton({
2773
3460
  children: "Get Pro License \u2192"
2774
3461
  }
2775
3462
  )
2776
- ] }) : /* @__PURE__ */ jsx5("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: "Powered by TinyPivot" }) })
3463
+ ] }) : /* @__PURE__ */ jsx6("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: "Powered by TinyPivot" }) })
2777
3464
  ]
2778
3465
  }
2779
3466
  );
2780
3467
  }
2781
3468
 
2782
3469
  // src/components/DataGrid.tsx
2783
- import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
3470
+ import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
2784
3471
  var MIN_COL_WIDTH = 120;
2785
3472
  var MAX_COL_WIDTH = 350;
2786
3473
  function DataGrid({
@@ -2805,36 +3492,40 @@ function DataGrid({
2805
3492
  onExport,
2806
3493
  onCopy
2807
3494
  }) {
2808
- const { showWatermark, canUsePivot, isDemo, isPro } = useLicense();
2809
- const currentTheme = useMemo10(() => {
3495
+ const { showWatermark, canUsePivot, canUseCharts, isDemo, isPro } = useLicense();
3496
+ const currentTheme = useMemo11(() => {
2810
3497
  if (theme === "auto") {
2811
3498
  return window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
2812
3499
  }
2813
3500
  return theme;
2814
3501
  }, [theme]);
2815
- const [currentFontSize, setCurrentFontSize] = useState10(initialFontSize);
2816
- const [globalSearchTerm, setGlobalSearchTerm] = useState10("");
2817
- const [showSearchInput, setShowSearchInput] = useState10(false);
2818
- const [currentPage, setCurrentPage] = useState10(1);
2819
- const [columnWidths, setColumnWidths] = useState10({});
2820
- const [resizingColumnId, setResizingColumnId] = useState10(null);
2821
- const [resizeStartX, setResizeStartX] = useState10(0);
2822
- const [resizeStartWidth, setResizeStartWidth] = useState10(0);
2823
- const [gridHeight, setGridHeight] = useState10(initialHeight);
2824
- const [isResizingVertically, setIsResizingVertically] = useState10(false);
2825
- const [verticalResizeStartY, setVerticalResizeStartY] = useState10(0);
2826
- const [verticalResizeStartHeight, setVerticalResizeStartHeight] = useState10(0);
2827
- const [showCopyToast, setShowCopyToast] = useState10(false);
2828
- const [copyToastMessage, setCopyToastMessage] = useState10("");
2829
- const [viewMode, setViewMode] = useState10("grid");
2830
- const [showPivotConfig, setShowPivotConfig] = useState10(true);
2831
- const [draggingField, setDraggingField] = useState10(null);
2832
- const [activeFilterColumn, setActiveFilterColumn] = useState10(null);
2833
- const [filterDropdownPosition, setFilterDropdownPosition] = useState10({ top: 0, left: 0, maxHeight: 400 });
2834
- const [selectedCell, setSelectedCell] = useState10(null);
2835
- const [selectionStart, setSelectionStart] = useState10(null);
2836
- const [selectionEnd, setSelectionEnd] = useState10(null);
2837
- const [isSelecting, setIsSelecting] = useState10(false);
3502
+ const [currentFontSize, setCurrentFontSize] = useState11(initialFontSize);
3503
+ const [globalSearchTerm, setGlobalSearchTerm] = useState11("");
3504
+ const [showSearchInput, setShowSearchInput] = useState11(false);
3505
+ const [currentPage, setCurrentPage] = useState11(1);
3506
+ const [columnWidths, setColumnWidths] = useState11({});
3507
+ const [resizingColumnId, setResizingColumnId] = useState11(null);
3508
+ const [resizeStartX, setResizeStartX] = useState11(0);
3509
+ const [resizeStartWidth, setResizeStartWidth] = useState11(0);
3510
+ const [gridHeight, setGridHeight] = useState11(initialHeight);
3511
+ const [isResizingVertically, setIsResizingVertically] = useState11(false);
3512
+ const [verticalResizeStartY, setVerticalResizeStartY] = useState11(0);
3513
+ const [verticalResizeStartHeight, setVerticalResizeStartHeight] = useState11(0);
3514
+ const [showCopyToast, setShowCopyToast] = useState11(false);
3515
+ const [copyToastMessage, setCopyToastMessage] = useState11("");
3516
+ const [viewMode, setViewMode] = useState11("grid");
3517
+ const [_chartConfig, setChartConfig] = useState11(null);
3518
+ const handleChartConfigChange = useCallback11((config) => {
3519
+ setChartConfig(config);
3520
+ }, []);
3521
+ const [showPivotConfig, setShowPivotConfig] = useState11(true);
3522
+ const [draggingField, setDraggingField] = useState11(null);
3523
+ const [activeFilterColumn, setActiveFilterColumn] = useState11(null);
3524
+ const [filterDropdownPosition, setFilterDropdownPosition] = useState11({ top: 0, left: 0, maxHeight: 400 });
3525
+ const [selectedCell, setSelectedCell] = useState11(null);
3526
+ const [selectionStart, setSelectionStart] = useState11(null);
3527
+ const [selectionEnd, setSelectionEnd] = useState11(null);
3528
+ const [isSelecting, setIsSelecting] = useState11(false);
2838
3529
  const tableContainerRef = useRef2(null);
2839
3530
  const tableBodyRef = useRef2(null);
2840
3531
  const fontSizeOptions = [
@@ -2860,7 +3551,7 @@ function DataGrid({
2860
3551
  setNumericRangeFilter,
2861
3552
  getNumericRangeFilter
2862
3553
  } = useExcelGrid({ data, enableSorting: true, enableFiltering: true });
2863
- const filteredDataForPivot = useMemo10(() => {
3554
+ const filteredDataForPivot = useMemo11(() => {
2864
3555
  const filteredRows = table.getFilteredRowModel().rows;
2865
3556
  return filteredRows.map((row) => row.original);
2866
3557
  }, [table, columnFilters]);
@@ -2890,7 +3581,7 @@ function DataGrid({
2890
3581
  addCalculatedField,
2891
3582
  removeCalculatedField
2892
3583
  } = usePivotTable(filteredDataForPivot);
2893
- const activeFilterInfo = useMemo10(() => {
3584
+ const activeFilterInfo = useMemo11(() => {
2894
3585
  if (activeFilters.length === 0)
2895
3586
  return null;
2896
3587
  return activeFilters.map((f) => {
@@ -2915,8 +3606,8 @@ function DataGrid({
2915
3606
  };
2916
3607
  });
2917
3608
  }, [activeFilters]);
2918
- const rows = useMemo10(() => table.getFilteredRowModel().rows, [table, columnFilters]);
2919
- const searchFilteredData = useMemo10(() => {
3609
+ const rows = useMemo11(() => table.getFilteredRowModel().rows, [table, columnFilters]);
3610
+ const searchFilteredData = useMemo11(() => {
2920
3611
  if (!globalSearchTerm.trim() || !enableSearch) {
2921
3612
  return rows;
2922
3613
  }
@@ -2934,22 +3625,22 @@ function DataGrid({
2934
3625
  });
2935
3626
  }, [rows, globalSearchTerm, enableSearch, columnKeys]);
2936
3627
  const totalSearchedRows = searchFilteredData.length;
2937
- const totalPages = useMemo10(() => {
3628
+ const totalPages = useMemo11(() => {
2938
3629
  if (!enablePagination)
2939
3630
  return 1;
2940
3631
  return Math.max(1, Math.ceil(totalSearchedRows / pageSize));
2941
3632
  }, [enablePagination, totalSearchedRows, pageSize]);
2942
- const paginatedRows = useMemo10(() => {
3633
+ const paginatedRows = useMemo11(() => {
2943
3634
  if (!enablePagination)
2944
3635
  return searchFilteredData;
2945
3636
  const start = (currentPage - 1) * pageSize;
2946
3637
  const end = start + pageSize;
2947
3638
  return searchFilteredData.slice(start, end);
2948
3639
  }, [enablePagination, searchFilteredData, currentPage, pageSize]);
2949
- useEffect7(() => {
3640
+ useEffect8(() => {
2950
3641
  setCurrentPage(1);
2951
3642
  }, [columnFilters, globalSearchTerm]);
2952
- const selectionBounds = useMemo10(() => {
3643
+ const selectionBounds = useMemo11(() => {
2953
3644
  if (!selectionStart || !selectionEnd)
2954
3645
  return null;
2955
3646
  return {
@@ -2959,7 +3650,7 @@ function DataGrid({
2959
3650
  maxCol: Math.max(selectionStart.col, selectionEnd.col)
2960
3651
  };
2961
3652
  }, [selectionStart, selectionEnd]);
2962
- const selectionStats = useMemo10(() => {
3653
+ const selectionStats = useMemo11(() => {
2963
3654
  if (!selectionBounds)
2964
3655
  return null;
2965
3656
  const { minRow, maxRow, minCol, maxCol } = selectionBounds;
@@ -2989,7 +3680,7 @@ function DataGrid({
2989
3680
  const avg = sum / values.length;
2990
3681
  return { count, sum, avg, numericCount: values.length };
2991
3682
  }, [selectionBounds, rows, columnKeys]);
2992
- useEffect7(() => {
3683
+ useEffect8(() => {
2993
3684
  if (typeof document === "undefined")
2994
3685
  return;
2995
3686
  if (data.length === 0)
@@ -3013,7 +3704,7 @@ function DataGrid({
3013
3704
  }
3014
3705
  setColumnWidths(widths);
3015
3706
  }, [data, columnKeys]);
3016
- const startColumnResize = useCallback10(
3707
+ const startColumnResize = useCallback11(
3017
3708
  (columnId, event) => {
3018
3709
  if (!enableColumnResize)
3019
3710
  return;
@@ -3025,7 +3716,7 @@ function DataGrid({
3025
3716
  },
3026
3717
  [enableColumnResize, columnWidths]
3027
3718
  );
3028
- useEffect7(() => {
3719
+ useEffect8(() => {
3029
3720
  if (!resizingColumnId)
3030
3721
  return;
3031
3722
  const handleResizeMove = (event) => {
@@ -3046,7 +3737,7 @@ function DataGrid({
3046
3737
  document.removeEventListener("mouseup", handleResizeEnd);
3047
3738
  };
3048
3739
  }, [resizingColumnId, resizeStartX, resizeStartWidth]);
3049
- const startVerticalResize = useCallback10(
3740
+ const startVerticalResize = useCallback11(
3050
3741
  (event) => {
3051
3742
  if (!enableVerticalResize)
3052
3743
  return;
@@ -3057,7 +3748,7 @@ function DataGrid({
3057
3748
  },
3058
3749
  [enableVerticalResize, gridHeight]
3059
3750
  );
3060
- useEffect7(() => {
3751
+ useEffect8(() => {
3061
3752
  if (!isResizingVertically)
3062
3753
  return;
3063
3754
  const handleVerticalResizeMove = (event) => {
@@ -3075,7 +3766,7 @@ function DataGrid({
3075
3766
  document.removeEventListener("mouseup", handleVerticalResizeEnd);
3076
3767
  };
3077
3768
  }, [isResizingVertically, verticalResizeStartY, verticalResizeStartHeight, minHeight, maxHeight]);
3078
- const handleExport = useCallback10(() => {
3769
+ const handleExport = useCallback11(() => {
3079
3770
  if (viewMode === "pivot") {
3080
3771
  if (!pivotResult)
3081
3772
  return;
@@ -3121,7 +3812,7 @@ function DataGrid({
3121
3812
  columnKeys,
3122
3813
  onExport
3123
3814
  ]);
3124
- const copySelectionToClipboard = useCallback10(() => {
3815
+ const copySelectionToClipboard = useCallback11(() => {
3125
3816
  if (!selectionBounds || !enableClipboard)
3126
3817
  return;
3127
3818
  const text = formatSelectionForClipboard(
@@ -3146,7 +3837,7 @@ function DataGrid({
3146
3837
  }
3147
3838
  );
3148
3839
  }, [selectionBounds, enableClipboard, rows, columnKeys, onCopy]);
3149
- const handleMouseDown = useCallback10(
3840
+ const handleMouseDown = useCallback11(
3150
3841
  (rowIndex, colIndex, event) => {
3151
3842
  event.preventDefault();
3152
3843
  if (event.shiftKey && selectedCell) {
@@ -3170,7 +3861,7 @@ function DataGrid({
3170
3861
  },
3171
3862
  [selectedCell, rows, columnKeys, onCellClick]
3172
3863
  );
3173
- const handleMouseEnter = useCallback10(
3864
+ const handleMouseEnter = useCallback11(
3174
3865
  (rowIndex, colIndex) => {
3175
3866
  if (isSelecting) {
3176
3867
  setSelectionEnd({ row: rowIndex, col: colIndex });
@@ -3178,12 +3869,12 @@ function DataGrid({
3178
3869
  },
3179
3870
  [isSelecting]
3180
3871
  );
3181
- useEffect7(() => {
3872
+ useEffect8(() => {
3182
3873
  const handleMouseUp = () => setIsSelecting(false);
3183
3874
  document.addEventListener("mouseup", handleMouseUp);
3184
3875
  return () => document.removeEventListener("mouseup", handleMouseUp);
3185
3876
  }, []);
3186
- useEffect7(() => {
3877
+ useEffect8(() => {
3187
3878
  const handleKeydown = (event) => {
3188
3879
  if ((event.ctrlKey || event.metaKey) && event.key === "c" && selectionBounds) {
3189
3880
  event.preventDefault();
@@ -3201,7 +3892,7 @@ function DataGrid({
3201
3892
  document.addEventListener("keydown", handleKeydown);
3202
3893
  return () => document.removeEventListener("keydown", handleKeydown);
3203
3894
  }, [selectionBounds, copySelectionToClipboard]);
3204
- const openFilterDropdown = useCallback10(
3895
+ const openFilterDropdown = useCallback11(
3205
3896
  (columnId, event) => {
3206
3897
  event.stopPropagation();
3207
3898
  const target = event.currentTarget;
@@ -3230,22 +3921,22 @@ function DataGrid({
3230
3921
  },
3231
3922
  []
3232
3923
  );
3233
- const closeFilterDropdown = useCallback10(() => {
3924
+ const closeFilterDropdown = useCallback11(() => {
3234
3925
  setActiveFilterColumn(null);
3235
3926
  }, []);
3236
- const handleFilter = useCallback10(
3927
+ const handleFilter = useCallback11(
3237
3928
  (columnId, values) => {
3238
3929
  setColumnFilter(columnId, values);
3239
3930
  },
3240
3931
  [setColumnFilter]
3241
3932
  );
3242
- const handleRangeFilter = useCallback10(
3933
+ const handleRangeFilter = useCallback11(
3243
3934
  (columnId, range) => {
3244
3935
  setNumericRangeFilter(columnId, range);
3245
3936
  },
3246
3937
  [setNumericRangeFilter]
3247
3938
  );
3248
- const handleSort = useCallback10(
3939
+ const handleSort = useCallback11(
3249
3940
  (columnId, direction) => {
3250
3941
  if (direction === null) {
3251
3942
  const current = getSortDirection(columnId);
@@ -3269,7 +3960,7 @@ function DataGrid({
3269
3960
  },
3270
3961
  [getSortDirection, toggleSort]
3271
3962
  );
3272
- const isCellSelected = useCallback10(
3963
+ const isCellSelected = useCallback11(
3273
3964
  (rowIndex, colIndex) => {
3274
3965
  if (!selectionBounds) {
3275
3966
  return selectedCell?.row === rowIndex && selectedCell?.col === colIndex;
@@ -3311,30 +4002,30 @@ function DataGrid({
3311
4002
  }
3312
4003
  return String(value);
3313
4004
  };
3314
- const totalTableWidth = useMemo10(() => {
4005
+ const totalTableWidth = useMemo11(() => {
3315
4006
  return columnKeys.reduce((sum, key) => sum + (columnWidths[key] || MIN_COL_WIDTH), 0);
3316
4007
  }, [columnKeys, columnWidths]);
3317
4008
  const activeFilterCount = columnFilters.length;
3318
- return /* @__PURE__ */ jsxs6(
4009
+ return /* @__PURE__ */ jsxs7(
3319
4010
  "div",
3320
4011
  {
3321
4012
  className: `vpg-data-grid vpg-font-${currentFontSize} vpg-theme-${currentTheme} ${stripedRows ? "vpg-striped" : ""} ${resizingColumnId ? "vpg-resizing" : ""} ${isResizingVertically ? "vpg-resizing-vertical" : ""}`,
3322
4013
  style: { height: `${gridHeight}px` },
3323
4014
  children: [
3324
- showCopyToast && /* @__PURE__ */ jsxs6("div", { className: "vpg-toast", children: [
3325
- /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
4015
+ showCopyToast && /* @__PURE__ */ jsxs7("div", { className: "vpg-toast", children: [
4016
+ /* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
3326
4017
  copyToastMessage
3327
4018
  ] }),
3328
- /* @__PURE__ */ jsxs6("div", { className: "vpg-toolbar", children: [
3329
- /* @__PURE__ */ jsxs6("div", { className: "vpg-toolbar-left", children: [
3330
- showPivot && /* @__PURE__ */ jsxs6("div", { className: "vpg-view-toggle", children: [
3331
- /* @__PURE__ */ jsxs6(
4019
+ /* @__PURE__ */ jsxs7("div", { className: "vpg-toolbar", children: [
4020
+ /* @__PURE__ */ jsxs7("div", { className: "vpg-toolbar-left", children: [
4021
+ showPivot && /* @__PURE__ */ jsxs7("div", { className: "vpg-view-toggle", children: [
4022
+ /* @__PURE__ */ jsxs7(
3332
4023
  "button",
3333
4024
  {
3334
4025
  className: `vpg-view-btn ${viewMode === "grid" ? "active" : ""}`,
3335
4026
  onClick: () => setViewMode("grid"),
3336
4027
  children: [
3337
- /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
4028
+ /* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
3338
4029
  "path",
3339
4030
  {
3340
4031
  strokeLinecap: "round",
@@ -3347,13 +4038,13 @@ function DataGrid({
3347
4038
  ]
3348
4039
  }
3349
4040
  ),
3350
- /* @__PURE__ */ jsxs6(
4041
+ /* @__PURE__ */ jsxs7(
3351
4042
  "button",
3352
4043
  {
3353
4044
  className: `vpg-view-btn vpg-pivot-btn ${viewMode === "pivot" ? "active" : ""}`,
3354
4045
  onClick: () => setViewMode("pivot"),
3355
4046
  children: [
3356
- /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
4047
+ /* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
3357
4048
  "path",
3358
4049
  {
3359
4050
  strokeLinecap: "round",
@@ -3365,16 +4056,37 @@ function DataGrid({
3365
4056
  "Pivot"
3366
4057
  ]
3367
4058
  }
4059
+ ),
4060
+ /* @__PURE__ */ jsxs7(
4061
+ "button",
4062
+ {
4063
+ className: `vpg-view-btn vpg-chart-btn ${viewMode === "chart" ? "active" : ""} ${!canUseCharts ? "vpg-pro-feature" : ""}`,
4064
+ title: canUseCharts ? "Chart Builder" : "Chart Builder (Pro feature)",
4065
+ onClick: () => canUseCharts && setViewMode("chart"),
4066
+ children: [
4067
+ /* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
4068
+ "path",
4069
+ {
4070
+ strokeLinecap: "round",
4071
+ strokeLinejoin: "round",
4072
+ strokeWidth: 2,
4073
+ d: "M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
4074
+ }
4075
+ ) }),
4076
+ "Chart",
4077
+ !canUseCharts && /* @__PURE__ */ jsx7("span", { className: "vpg-pro-badge", children: "Pro" })
4078
+ ]
4079
+ }
3368
4080
  )
3369
4081
  ] }),
3370
- viewMode === "grid" && /* @__PURE__ */ jsxs6(Fragment4, { children: [
3371
- enableSearch && /* @__PURE__ */ jsx6("div", { className: "vpg-search-container", children: !showSearchInput ? /* @__PURE__ */ jsx6(
4082
+ viewMode === "grid" && /* @__PURE__ */ jsxs7(Fragment5, { children: [
4083
+ enableSearch && /* @__PURE__ */ jsx7("div", { className: "vpg-search-container", children: !showSearchInput ? /* @__PURE__ */ jsx7(
3372
4084
  "button",
3373
4085
  {
3374
4086
  className: "vpg-icon-btn",
3375
4087
  title: "Search (Ctrl+F)",
3376
4088
  onClick: () => setShowSearchInput(true),
3377
- children: /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
4089
+ children: /* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
3378
4090
  "path",
3379
4091
  {
3380
4092
  strokeLinecap: "round",
@@ -3384,15 +4096,15 @@ function DataGrid({
3384
4096
  }
3385
4097
  ) })
3386
4098
  }
3387
- ) : /* @__PURE__ */ jsxs6("div", { className: "vpg-search-box", children: [
3388
- /* @__PURE__ */ jsx6(
4099
+ ) : /* @__PURE__ */ jsxs7("div", { className: "vpg-search-box", children: [
4100
+ /* @__PURE__ */ jsx7(
3389
4101
  "svg",
3390
4102
  {
3391
4103
  className: "vpg-search-icon",
3392
4104
  fill: "none",
3393
4105
  stroke: "currentColor",
3394
4106
  viewBox: "0 0 24 24",
3395
- children: /* @__PURE__ */ jsx6(
4107
+ children: /* @__PURE__ */ jsx7(
3396
4108
  "path",
3397
4109
  {
3398
4110
  strokeLinecap: "round",
@@ -3403,7 +4115,7 @@ function DataGrid({
3403
4115
  )
3404
4116
  }
3405
4117
  ),
3406
- /* @__PURE__ */ jsx6(
4118
+ /* @__PURE__ */ jsx7(
3407
4119
  "input",
3408
4120
  {
3409
4121
  type: "text",
@@ -3420,14 +4132,14 @@ function DataGrid({
3420
4132
  autoFocus: true
3421
4133
  }
3422
4134
  ),
3423
- globalSearchTerm && /* @__PURE__ */ jsx6("button", { className: "vpg-search-clear", onClick: () => setGlobalSearchTerm(""), children: /* @__PURE__ */ jsx6(
4135
+ globalSearchTerm && /* @__PURE__ */ jsx7("button", { className: "vpg-search-clear", onClick: () => setGlobalSearchTerm(""), children: /* @__PURE__ */ jsx7(
3424
4136
  "svg",
3425
4137
  {
3426
4138
  className: "vpg-icon-xs",
3427
4139
  fill: "none",
3428
4140
  stroke: "currentColor",
3429
4141
  viewBox: "0 0 24 24",
3430
- children: /* @__PURE__ */ jsx6(
4142
+ children: /* @__PURE__ */ jsx7(
3431
4143
  "path",
3432
4144
  {
3433
4145
  strokeLinecap: "round",
@@ -3439,9 +4151,9 @@ function DataGrid({
3439
4151
  }
3440
4152
  ) })
3441
4153
  ] }) }),
3442
- /* @__PURE__ */ jsxs6("div", { className: "vpg-font-size-control", children: [
3443
- /* @__PURE__ */ jsx6("span", { className: "vpg-label", children: "Size:" }),
3444
- /* @__PURE__ */ jsx6("div", { className: "vpg-font-size-toggle", children: fontSizeOptions.map((opt) => /* @__PURE__ */ jsx6(
4154
+ /* @__PURE__ */ jsxs7("div", { className: "vpg-font-size-control", children: [
4155
+ /* @__PURE__ */ jsx7("span", { className: "vpg-label", children: "Size:" }),
4156
+ /* @__PURE__ */ jsx7("div", { className: "vpg-font-size-toggle", children: fontSizeOptions.map((opt) => /* @__PURE__ */ jsx7(
3445
4157
  "button",
3446
4158
  {
3447
4159
  className: `vpg-font-size-btn ${currentFontSize === opt.value ? "active" : ""}`,
@@ -3451,8 +4163,8 @@ function DataGrid({
3451
4163
  opt.value
3452
4164
  )) })
3453
4165
  ] }),
3454
- activeFilterCount > 0 && /* @__PURE__ */ jsxs6("div", { className: "vpg-filter-info", children: [
3455
- /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx6(
4166
+ activeFilterCount > 0 && /* @__PURE__ */ jsxs7("div", { className: "vpg-filter-info", children: [
4167
+ /* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx7(
3456
4168
  "path",
3457
4169
  {
3458
4170
  fillRule: "evenodd",
@@ -3460,28 +4172,28 @@ function DataGrid({
3460
4172
  clipRule: "evenodd"
3461
4173
  }
3462
4174
  ) }),
3463
- /* @__PURE__ */ jsxs6("span", { children: [
4175
+ /* @__PURE__ */ jsxs7("span", { children: [
3464
4176
  activeFilterCount,
3465
4177
  " ",
3466
4178
  "filter",
3467
4179
  activeFilterCount > 1 ? "s" : ""
3468
4180
  ] })
3469
4181
  ] }),
3470
- globalSearchTerm && /* @__PURE__ */ jsx6("div", { className: "vpg-search-info", children: /* @__PURE__ */ jsxs6("span", { children: [
4182
+ globalSearchTerm && /* @__PURE__ */ jsx7("div", { className: "vpg-search-info", children: /* @__PURE__ */ jsxs7("span", { children: [
3471
4183
  totalSearchedRows,
3472
4184
  " ",
3473
4185
  "match",
3474
4186
  totalSearchedRows !== 1 ? "es" : ""
3475
4187
  ] }) })
3476
4188
  ] }),
3477
- viewMode === "pivot" && canUsePivot && /* @__PURE__ */ jsxs6(Fragment4, { children: [
3478
- /* @__PURE__ */ jsxs6(
4189
+ viewMode === "pivot" && canUsePivot && /* @__PURE__ */ jsxs7(Fragment5, { children: [
4190
+ /* @__PURE__ */ jsxs7(
3479
4191
  "button",
3480
4192
  {
3481
4193
  className: `vpg-config-toggle ${showPivotConfig ? "active" : ""}`,
3482
4194
  onClick: () => setShowPivotConfig(!showPivotConfig),
3483
4195
  children: [
3484
- /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
4196
+ /* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
3485
4197
  "path",
3486
4198
  {
3487
4199
  strokeLinecap: "round",
@@ -3496,8 +4208,8 @@ function DataGrid({
3496
4208
  ]
3497
4209
  }
3498
4210
  ),
3499
- pivotIsConfigured && /* @__PURE__ */ jsxs6("div", { className: "vpg-pivot-status", children: [
3500
- /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx6(
4211
+ pivotIsConfigured && /* @__PURE__ */ jsxs7("div", { className: "vpg-pivot-status", children: [
4212
+ /* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx7(
3501
4213
  "path",
3502
4214
  {
3503
4215
  fillRule: "evenodd",
@@ -3505,13 +4217,13 @@ function DataGrid({
3505
4217
  clipRule: "evenodd"
3506
4218
  }
3507
4219
  ) }),
3508
- /* @__PURE__ */ jsx6("span", { children: "Pivot configured" })
4220
+ /* @__PURE__ */ jsx7("span", { children: "Pivot configured" })
3509
4221
  ] })
3510
4222
  ] })
3511
4223
  ] }),
3512
- /* @__PURE__ */ jsxs6("div", { className: "vpg-toolbar-right", children: [
3513
- viewMode === "grid" && activeFilterCount > 0 && /* @__PURE__ */ jsxs6("button", { className: "vpg-clear-filters", onClick: clearAllFilters, children: [
3514
- /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
4224
+ /* @__PURE__ */ jsxs7("div", { className: "vpg-toolbar-right", children: [
4225
+ viewMode === "grid" && activeFilterCount > 0 && /* @__PURE__ */ jsxs7("button", { className: "vpg-clear-filters", onClick: clearAllFilters, children: [
4226
+ /* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
3515
4227
  "path",
3516
4228
  {
3517
4229
  strokeLinecap: "round",
@@ -3522,13 +4234,13 @@ function DataGrid({
3522
4234
  ) }),
3523
4235
  "Clear Filters"
3524
4236
  ] }),
3525
- enableClipboard && selectionBounds && viewMode === "grid" && /* @__PURE__ */ jsx6(
4237
+ enableClipboard && selectionBounds && viewMode === "grid" && /* @__PURE__ */ jsx7(
3526
4238
  "button",
3527
4239
  {
3528
4240
  className: "vpg-icon-btn",
3529
4241
  title: "Copy selection (Ctrl+C)",
3530
4242
  onClick: copySelectionToClipboard,
3531
- children: /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
4243
+ children: /* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
3532
4244
  "path",
3533
4245
  {
3534
4246
  strokeLinecap: "round",
@@ -3539,14 +4251,14 @@ function DataGrid({
3539
4251
  ) })
3540
4252
  }
3541
4253
  ),
3542
- enableExport && viewMode === "grid" && /* @__PURE__ */ jsxs6(
4254
+ enableExport && viewMode === "grid" && /* @__PURE__ */ jsxs7(
3543
4255
  "button",
3544
4256
  {
3545
4257
  className: "vpg-export-btn",
3546
4258
  title: "Export to CSV",
3547
4259
  onClick: handleExport,
3548
4260
  children: [
3549
- /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
4261
+ /* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
3550
4262
  "path",
3551
4263
  {
3552
4264
  strokeLinecap: "round",
@@ -3559,7 +4271,7 @@ function DataGrid({
3559
4271
  ]
3560
4272
  }
3561
4273
  ),
3562
- enableExport && viewMode === "pivot" && pivotIsConfigured && /* @__PURE__ */ jsxs6(
4274
+ enableExport && viewMode === "pivot" && pivotIsConfigured && /* @__PURE__ */ jsxs7(
3563
4275
  "button",
3564
4276
  {
3565
4277
  className: `vpg-export-btn ${!isPro ? "vpg-export-btn-disabled" : ""}`,
@@ -3567,7 +4279,7 @@ function DataGrid({
3567
4279
  title: isPro ? "Export Pivot to CSV" : "Export Pivot to CSV (Pro feature)",
3568
4280
  onClick: () => isPro && handleExport(),
3569
4281
  children: [
3570
- /* @__PURE__ */ jsx6("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
4282
+ /* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
3571
4283
  "path",
3572
4284
  {
3573
4285
  strokeLinecap: "round",
@@ -3583,13 +4295,13 @@ function DataGrid({
3583
4295
  )
3584
4296
  ] })
3585
4297
  ] }),
3586
- viewMode === "grid" && /* @__PURE__ */ jsxs6("div", { ref: tableContainerRef, className: "vpg-grid-container", tabIndex: 0, children: [
3587
- loading && /* @__PURE__ */ jsxs6("div", { className: "vpg-loading", children: [
3588
- /* @__PURE__ */ jsx6("div", { className: "vpg-spinner" }),
3589
- /* @__PURE__ */ jsx6("span", { children: "Loading data..." })
4298
+ viewMode === "grid" && /* @__PURE__ */ jsxs7("div", { ref: tableContainerRef, className: "vpg-grid-container", tabIndex: 0, children: [
4299
+ loading && /* @__PURE__ */ jsxs7("div", { className: "vpg-loading", children: [
4300
+ /* @__PURE__ */ jsx7("div", { className: "vpg-spinner" }),
4301
+ /* @__PURE__ */ jsx7("span", { children: "Loading data..." })
3590
4302
  ] }),
3591
- !loading && data.length === 0 && /* @__PURE__ */ jsxs6("div", { className: "vpg-empty", children: [
3592
- /* @__PURE__ */ jsx6("div", { className: "vpg-empty-icon", children: /* @__PURE__ */ jsx6("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
4303
+ !loading && data.length === 0 && /* @__PURE__ */ jsxs7("div", { className: "vpg-empty", children: [
4304
+ /* @__PURE__ */ jsx7("div", { className: "vpg-empty-icon", children: /* @__PURE__ */ jsx7("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
3593
4305
  "path",
3594
4306
  {
3595
4307
  strokeLinecap: "round",
@@ -3598,10 +4310,10 @@ function DataGrid({
3598
4310
  d: "M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
3599
4311
  }
3600
4312
  ) }) }),
3601
- /* @__PURE__ */ jsx6("span", { children: "No data available" })
4313
+ /* @__PURE__ */ jsx7("span", { children: "No data available" })
3602
4314
  ] }),
3603
- !loading && data.length > 0 && filteredRowCount === 0 && /* @__PURE__ */ jsxs6("div", { className: "vpg-empty", children: [
3604
- /* @__PURE__ */ jsx6("div", { className: "vpg-empty-icon vpg-warning", children: /* @__PURE__ */ jsx6("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
4315
+ !loading && data.length > 0 && filteredRowCount === 0 && /* @__PURE__ */ jsxs7("div", { className: "vpg-empty", children: [
4316
+ /* @__PURE__ */ jsx7("div", { className: "vpg-empty-icon vpg-warning", children: /* @__PURE__ */ jsx7("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
3605
4317
  "path",
3606
4318
  {
3607
4319
  strokeLinecap: "round",
@@ -3610,11 +4322,11 @@ function DataGrid({
3610
4322
  d: "M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"
3611
4323
  }
3612
4324
  ) }) }),
3613
- /* @__PURE__ */ jsx6("span", { children: "No matching records" }),
3614
- /* @__PURE__ */ jsx6("button", { className: "vpg-clear-link", onClick: clearAllFilters, children: "Clear all filters" })
4325
+ /* @__PURE__ */ jsx7("span", { children: "No matching records" }),
4326
+ /* @__PURE__ */ jsx7("button", { className: "vpg-clear-link", onClick: clearAllFilters, children: "Clear all filters" })
3615
4327
  ] }),
3616
- !loading && filteredRowCount > 0 && /* @__PURE__ */ jsx6("div", { className: "vpg-table-wrapper", children: /* @__PURE__ */ jsxs6("table", { className: "vpg-table", style: { minWidth: `${totalTableWidth}px` }, children: [
3617
- /* @__PURE__ */ jsx6("thead", { children: /* @__PURE__ */ jsx6("tr", { children: columnKeys.map((colId) => /* @__PURE__ */ jsxs6(
4328
+ !loading && filteredRowCount > 0 && /* @__PURE__ */ jsx7("div", { className: "vpg-table-wrapper", children: /* @__PURE__ */ jsxs7("table", { className: "vpg-table", style: { minWidth: `${totalTableWidth}px` }, children: [
4329
+ /* @__PURE__ */ jsx7("thead", { children: /* @__PURE__ */ jsx7("tr", { children: columnKeys.map((colId) => /* @__PURE__ */ jsxs7(
3618
4330
  "th",
3619
4331
  {
3620
4332
  className: `vpg-header-cell ${hasActiveFilter(colId) ? "vpg-has-filter" : ""} ${getSortDirection(colId) !== null ? "vpg-is-sorted" : ""} ${activeFilterColumn === colId ? "vpg-is-active" : ""}`,
@@ -3629,16 +4341,16 @@ function DataGrid({
3629
4341
  }
3630
4342
  },
3631
4343
  children: [
3632
- /* @__PURE__ */ jsxs6("div", { className: "vpg-header-content", children: [
3633
- /* @__PURE__ */ jsx6("span", { className: "vpg-header-text", children: colId }),
3634
- /* @__PURE__ */ jsxs6("div", { className: "vpg-header-icons", children: [
3635
- getSortDirection(colId) && /* @__PURE__ */ jsx6("span", { className: "vpg-sort-indicator", children: getSortDirection(colId) === "asc" ? /* @__PURE__ */ jsx6(
4344
+ /* @__PURE__ */ jsxs7("div", { className: "vpg-header-content", children: [
4345
+ /* @__PURE__ */ jsx7("span", { className: "vpg-header-text", children: colId }),
4346
+ /* @__PURE__ */ jsxs7("div", { className: "vpg-header-icons", children: [
4347
+ getSortDirection(colId) && /* @__PURE__ */ jsx7("span", { className: "vpg-sort-indicator", children: getSortDirection(colId) === "asc" ? /* @__PURE__ */ jsx7(
3636
4348
  "svg",
3637
4349
  {
3638
4350
  className: "vpg-icon-sm",
3639
4351
  fill: "currentColor",
3640
4352
  viewBox: "0 0 20 20",
3641
- children: /* @__PURE__ */ jsx6(
4353
+ children: /* @__PURE__ */ jsx7(
3642
4354
  "path",
3643
4355
  {
3644
4356
  fillRule: "evenodd",
@@ -3647,13 +4359,13 @@ function DataGrid({
3647
4359
  }
3648
4360
  )
3649
4361
  }
3650
- ) : /* @__PURE__ */ jsx6(
4362
+ ) : /* @__PURE__ */ jsx7(
3651
4363
  "svg",
3652
4364
  {
3653
4365
  className: "vpg-icon-sm",
3654
4366
  fill: "currentColor",
3655
4367
  viewBox: "0 0 20 20",
3656
- children: /* @__PURE__ */ jsx6(
4368
+ children: /* @__PURE__ */ jsx7(
3657
4369
  "path",
3658
4370
  {
3659
4371
  fillRule: "evenodd",
@@ -3663,13 +4375,13 @@ function DataGrid({
3663
4375
  )
3664
4376
  }
3665
4377
  ) }),
3666
- hasActiveFilter(colId) && /* @__PURE__ */ jsx6("span", { className: "vpg-filter-indicator", children: /* @__PURE__ */ jsx6(
4378
+ hasActiveFilter(colId) && /* @__PURE__ */ jsx7("span", { className: "vpg-filter-indicator", children: /* @__PURE__ */ jsx7(
3667
4379
  "svg",
3668
4380
  {
3669
4381
  className: "vpg-icon-xs",
3670
4382
  fill: "currentColor",
3671
4383
  viewBox: "0 0 20 20",
3672
- children: /* @__PURE__ */ jsx6(
4384
+ children: /* @__PURE__ */ jsx7(
3673
4385
  "path",
3674
4386
  {
3675
4387
  fillRule: "evenodd",
@@ -3679,14 +4391,14 @@ function DataGrid({
3679
4391
  )
3680
4392
  }
3681
4393
  ) }),
3682
- /* @__PURE__ */ jsx6("span", { className: "vpg-dropdown-arrow", title: "Filter & Sort", children: /* @__PURE__ */ jsx6(
4394
+ /* @__PURE__ */ jsx7("span", { className: "vpg-dropdown-arrow", title: "Filter & Sort", children: /* @__PURE__ */ jsx7(
3683
4395
  "svg",
3684
4396
  {
3685
4397
  className: "vpg-icon-sm",
3686
4398
  fill: "none",
3687
4399
  stroke: "currentColor",
3688
4400
  viewBox: "0 0 24 24",
3689
- children: /* @__PURE__ */ jsx6(
4401
+ children: /* @__PURE__ */ jsx7(
3690
4402
  "path",
3691
4403
  {
3692
4404
  strokeLinecap: "round",
@@ -3699,7 +4411,7 @@ function DataGrid({
3699
4411
  ) })
3700
4412
  ] })
3701
4413
  ] }),
3702
- enableColumnResize && /* @__PURE__ */ jsx6(
4414
+ enableColumnResize && /* @__PURE__ */ jsx7(
3703
4415
  "div",
3704
4416
  {
3705
4417
  className: "vpg-resize-handle",
@@ -3710,7 +4422,7 @@ function DataGrid({
3710
4422
  },
3711
4423
  colId
3712
4424
  )) }) }),
3713
- /* @__PURE__ */ jsx6("tbody", { ref: tableBodyRef, children: paginatedRows.map((row, rowIndex) => /* @__PURE__ */ jsx6("tr", { className: "vpg-row", children: columnKeys.map((colId, colIndex) => /* @__PURE__ */ jsx6(
4425
+ /* @__PURE__ */ jsx7("tbody", { ref: tableBodyRef, children: paginatedRows.map((row, rowIndex) => /* @__PURE__ */ jsx7("tr", { className: "vpg-row", children: columnKeys.map((colId, colIndex) => /* @__PURE__ */ jsx7(
3714
4426
  "td",
3715
4427
  {
3716
4428
  className: `vpg-cell ${isCellSelected(rowIndex, colIndex) ? "vpg-selected" : ""} ${getColumnStats(colId).type === "number" ? "vpg-is-number" : ""}`,
@@ -3728,8 +4440,8 @@ function DataGrid({
3728
4440
  )) }, row.id)) })
3729
4441
  ] }) })
3730
4442
  ] }),
3731
- viewMode === "pivot" && /* @__PURE__ */ jsxs6("div", { className: "vpg-pivot-container", children: [
3732
- showPivotConfig && canUsePivot && /* @__PURE__ */ jsx6("div", { className: "vpg-pivot-config-panel", children: /* @__PURE__ */ jsx6(
4443
+ viewMode === "pivot" && /* @__PURE__ */ jsxs7("div", { className: "vpg-pivot-container", children: [
4444
+ showPivotConfig && canUsePivot && /* @__PURE__ */ jsx7("div", { className: "vpg-pivot-config-panel", children: /* @__PURE__ */ jsx7(
3733
4445
  PivotConfig,
3734
4446
  {
3735
4447
  availableFields: pivotAvailableFields,
@@ -3757,7 +4469,7 @@ function DataGrid({
3757
4469
  onUpdateCalculatedField: addCalculatedField
3758
4470
  }
3759
4471
  ) }),
3760
- /* @__PURE__ */ jsx6("div", { className: `vpg-pivot-main ${!showPivotConfig ? "vpg-full-width" : ""}`, children: /* @__PURE__ */ jsx6(
4472
+ /* @__PURE__ */ jsx7("div", { className: `vpg-pivot-main ${!showPivotConfig ? "vpg-full-width" : ""}`, children: /* @__PURE__ */ jsx7(
3761
4473
  PivotSkeleton,
3762
4474
  {
3763
4475
  rowFields: pivotRowFields,
@@ -3783,47 +4495,78 @@ function DataGrid({
3783
4495
  }
3784
4496
  ) })
3785
4497
  ] }),
3786
- /* @__PURE__ */ jsxs6("div", { className: "vpg-footer", children: [
3787
- /* @__PURE__ */ jsx6("div", { className: "vpg-footer-left", children: viewMode === "grid" ? enablePagination ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
3788
- /* @__PURE__ */ jsxs6("span", { children: [
4498
+ viewMode === "chart" && /* @__PURE__ */ jsxs7("div", { className: "vpg-chart-view", children: [
4499
+ activeFilterInfo && activeFilterInfo.length > 0 && /* @__PURE__ */ jsxs7("div", { className: "vpg-chart-filter-bar", children: [
4500
+ /* @__PURE__ */ jsx7("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx7("path", { fillRule: "evenodd", d: "M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z", clipRule: "evenodd" }) }),
4501
+ /* @__PURE__ */ jsxs7("span", { children: [
4502
+ "Chart showing",
4503
+ filteredRowCount.toLocaleString(),
4504
+ " ",
4505
+ "of",
4506
+ totalRowCount.toLocaleString(),
4507
+ " ",
4508
+ "records"
4509
+ ] }),
4510
+ /* @__PURE__ */ jsx7("button", { className: "vpg-chart-clear-filters", onClick: clearAllFilters, children: "Clear filters" })
4511
+ ] }),
4512
+ /* @__PURE__ */ jsx7(
4513
+ ChartBuilder,
4514
+ {
4515
+ data: filteredDataForPivot,
4516
+ theme: currentTheme,
4517
+ onConfigChange: handleChartConfigChange
4518
+ }
4519
+ )
4520
+ ] }),
4521
+ /* @__PURE__ */ jsxs7("div", { className: "vpg-footer", children: [
4522
+ /* @__PURE__ */ jsx7("div", { className: "vpg-footer-left", children: viewMode === "grid" ? enablePagination ? /* @__PURE__ */ jsxs7(Fragment5, { children: [
4523
+ /* @__PURE__ */ jsxs7("span", { children: [
3789
4524
  ((currentPage - 1) * pageSize + 1).toLocaleString(),
3790
4525
  "-",
3791
4526
  Math.min(currentPage * pageSize, totalSearchedRows).toLocaleString()
3792
4527
  ] }),
3793
- /* @__PURE__ */ jsx6("span", { className: "vpg-separator", children: "of" }),
3794
- /* @__PURE__ */ jsx6("span", { children: totalSearchedRows.toLocaleString() }),
3795
- totalSearchedRows !== totalRowCount && /* @__PURE__ */ jsxs6("span", { className: "vpg-filtered-note", children: [
4528
+ /* @__PURE__ */ jsx7("span", { className: "vpg-separator", children: "of" }),
4529
+ /* @__PURE__ */ jsx7("span", { children: totalSearchedRows.toLocaleString() }),
4530
+ totalSearchedRows !== totalRowCount && /* @__PURE__ */ jsxs7("span", { className: "vpg-filtered-note", children: [
3796
4531
  "(",
3797
4532
  totalRowCount.toLocaleString(),
3798
4533
  " ",
3799
4534
  "total)"
3800
4535
  ] })
3801
- ] }) : filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount ? /* @__PURE__ */ jsxs6("span", { children: [
4536
+ ] }) : filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount ? /* @__PURE__ */ jsxs7("span", { children: [
3802
4537
  totalRowCount.toLocaleString(),
3803
4538
  " ",
3804
4539
  "records"
3805
- ] }) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
3806
- /* @__PURE__ */ jsx6("span", { className: "vpg-filtered-count", children: totalSearchedRows.toLocaleString() }),
3807
- /* @__PURE__ */ jsx6("span", { className: "vpg-separator", children: "of" }),
3808
- /* @__PURE__ */ jsx6("span", { children: totalRowCount.toLocaleString() }),
3809
- /* @__PURE__ */ jsx6("span", { className: "vpg-separator", children: "records" })
3810
- ] }) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
3811
- /* @__PURE__ */ jsx6("span", { className: "vpg-pivot-label", children: "Pivot Table" }),
3812
- /* @__PURE__ */ jsx6("span", { className: "vpg-separator", children: "\u2022" }),
3813
- /* @__PURE__ */ jsxs6("span", { children: [
4540
+ ] }) : /* @__PURE__ */ jsxs7(Fragment5, { children: [
4541
+ /* @__PURE__ */ jsx7("span", { className: "vpg-filtered-count", children: totalSearchedRows.toLocaleString() }),
4542
+ /* @__PURE__ */ jsx7("span", { className: "vpg-separator", children: "of" }),
4543
+ /* @__PURE__ */ jsx7("span", { children: totalRowCount.toLocaleString() }),
4544
+ /* @__PURE__ */ jsx7("span", { className: "vpg-separator", children: "records" })
4545
+ ] }) : viewMode === "pivot" ? /* @__PURE__ */ jsxs7(Fragment5, { children: [
4546
+ /* @__PURE__ */ jsx7("span", { className: "vpg-pivot-label", children: "Pivot Table" }),
4547
+ /* @__PURE__ */ jsx7("span", { className: "vpg-separator", children: "\u2022" }),
4548
+ /* @__PURE__ */ jsxs7("span", { children: [
3814
4549
  totalRowCount.toLocaleString(),
3815
4550
  " ",
3816
4551
  "source records"
3817
4552
  ] })
4553
+ ] }) : /* @__PURE__ */ jsxs7(Fragment5, { children: [
4554
+ /* @__PURE__ */ jsx7("span", { className: "vpg-chart-label", children: "Chart Builder" }),
4555
+ /* @__PURE__ */ jsx7("span", { className: "vpg-separator", children: "\u2022" }),
4556
+ /* @__PURE__ */ jsxs7("span", { children: [
4557
+ totalRowCount.toLocaleString(),
4558
+ " ",
4559
+ "records"
4560
+ ] })
3818
4561
  ] }) }),
3819
- enablePagination && viewMode === "grid" && totalPages > 1 && /* @__PURE__ */ jsxs6("div", { className: "vpg-pagination", children: [
3820
- /* @__PURE__ */ jsx6(
4562
+ enablePagination && viewMode === "grid" && totalPages > 1 && /* @__PURE__ */ jsxs7("div", { className: "vpg-pagination", children: [
4563
+ /* @__PURE__ */ jsx7(
3821
4564
  "button",
3822
4565
  {
3823
4566
  className: "vpg-page-btn",
3824
4567
  disabled: currentPage === 1,
3825
4568
  onClick: () => setCurrentPage(1),
3826
- children: /* @__PURE__ */ jsx6("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
4569
+ children: /* @__PURE__ */ jsx7("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
3827
4570
  "path",
3828
4571
  {
3829
4572
  strokeLinecap: "round",
@@ -3834,13 +4577,13 @@ function DataGrid({
3834
4577
  ) })
3835
4578
  }
3836
4579
  ),
3837
- /* @__PURE__ */ jsx6(
4580
+ /* @__PURE__ */ jsx7(
3838
4581
  "button",
3839
4582
  {
3840
4583
  className: "vpg-page-btn",
3841
4584
  disabled: currentPage === 1,
3842
4585
  onClick: () => setCurrentPage((p) => Math.max(1, p - 1)),
3843
- children: /* @__PURE__ */ jsx6("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
4586
+ children: /* @__PURE__ */ jsx7("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
3844
4587
  "path",
3845
4588
  {
3846
4589
  strokeLinecap: "round",
@@ -3851,7 +4594,7 @@ function DataGrid({
3851
4594
  ) })
3852
4595
  }
3853
4596
  ),
3854
- /* @__PURE__ */ jsxs6("span", { className: "vpg-page-info", children: [
4597
+ /* @__PURE__ */ jsxs7("span", { className: "vpg-page-info", children: [
3855
4598
  "Page",
3856
4599
  " ",
3857
4600
  currentPage,
@@ -3860,13 +4603,13 @@ function DataGrid({
3860
4603
  " ",
3861
4604
  totalPages
3862
4605
  ] }),
3863
- /* @__PURE__ */ jsx6(
4606
+ /* @__PURE__ */ jsx7(
3864
4607
  "button",
3865
4608
  {
3866
4609
  className: "vpg-page-btn",
3867
4610
  disabled: currentPage === totalPages,
3868
4611
  onClick: () => setCurrentPage((p) => Math.min(totalPages, p + 1)),
3869
- children: /* @__PURE__ */ jsx6("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
4612
+ children: /* @__PURE__ */ jsx7("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
3870
4613
  "path",
3871
4614
  {
3872
4615
  strokeLinecap: "round",
@@ -3877,13 +4620,13 @@ function DataGrid({
3877
4620
  ) })
3878
4621
  }
3879
4622
  ),
3880
- /* @__PURE__ */ jsx6(
4623
+ /* @__PURE__ */ jsx7(
3881
4624
  "button",
3882
4625
  {
3883
4626
  className: "vpg-page-btn",
3884
4627
  disabled: currentPage === totalPages,
3885
4628
  onClick: () => setCurrentPage(totalPages),
3886
- children: /* @__PURE__ */ jsx6("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6(
4629
+ children: /* @__PURE__ */ jsx7("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7(
3887
4630
  "path",
3888
4631
  {
3889
4632
  strokeLinecap: "round",
@@ -3895,45 +4638,45 @@ function DataGrid({
3895
4638
  }
3896
4639
  )
3897
4640
  ] }),
3898
- viewMode === "grid" && selectionStats && selectionStats.count > 1 && /* @__PURE__ */ jsxs6("div", { className: "vpg-selection-stats", children: [
3899
- /* @__PURE__ */ jsxs6("span", { className: "vpg-stat", children: [
3900
- /* @__PURE__ */ jsx6("span", { className: "vpg-stat-label", children: "Count:" }),
3901
- /* @__PURE__ */ jsx6("span", { className: "vpg-stat-value", children: selectionStats.count })
4641
+ viewMode === "grid" && selectionStats && selectionStats.count > 1 && /* @__PURE__ */ jsxs7("div", { className: "vpg-selection-stats", children: [
4642
+ /* @__PURE__ */ jsxs7("span", { className: "vpg-stat", children: [
4643
+ /* @__PURE__ */ jsx7("span", { className: "vpg-stat-label", children: "Count:" }),
4644
+ /* @__PURE__ */ jsx7("span", { className: "vpg-stat-value", children: selectionStats.count })
3902
4645
  ] }),
3903
- selectionStats.numericCount > 0 && /* @__PURE__ */ jsxs6(Fragment4, { children: [
3904
- /* @__PURE__ */ jsx6("span", { className: "vpg-stat-divider", children: "|" }),
3905
- /* @__PURE__ */ jsxs6("span", { className: "vpg-stat", children: [
3906
- /* @__PURE__ */ jsx6("span", { className: "vpg-stat-label", children: "Sum:" }),
3907
- /* @__PURE__ */ jsx6("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
4646
+ selectionStats.numericCount > 0 && /* @__PURE__ */ jsxs7(Fragment5, { children: [
4647
+ /* @__PURE__ */ jsx7("span", { className: "vpg-stat-divider", children: "|" }),
4648
+ /* @__PURE__ */ jsxs7("span", { className: "vpg-stat", children: [
4649
+ /* @__PURE__ */ jsx7("span", { className: "vpg-stat-label", children: "Sum:" }),
4650
+ /* @__PURE__ */ jsx7("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
3908
4651
  ] }),
3909
- /* @__PURE__ */ jsx6("span", { className: "vpg-stat-divider", children: "|" }),
3910
- /* @__PURE__ */ jsxs6("span", { className: "vpg-stat", children: [
3911
- /* @__PURE__ */ jsx6("span", { className: "vpg-stat-label", children: "Avg:" }),
3912
- /* @__PURE__ */ jsx6("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
4652
+ /* @__PURE__ */ jsx7("span", { className: "vpg-stat-divider", children: "|" }),
4653
+ /* @__PURE__ */ jsxs7("span", { className: "vpg-stat", children: [
4654
+ /* @__PURE__ */ jsx7("span", { className: "vpg-stat-label", children: "Avg:" }),
4655
+ /* @__PURE__ */ jsx7("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
3913
4656
  ] })
3914
4657
  ] })
3915
4658
  ] }),
3916
- /* @__PURE__ */ jsx6("div", { className: "vpg-footer-right", children: isDemo ? /* @__PURE__ */ jsxs6("div", { className: "vpg-demo-banner", children: [
3917
- /* @__PURE__ */ jsx6("span", { className: "vpg-demo-badge", children: "DEMO" }),
3918
- /* @__PURE__ */ jsx6("span", { children: "Pro features enabled" }),
3919
- /* @__PURE__ */ jsx6("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", children: "Get License \u2192" })
3920
- ] }) : showWatermark ? /* @__PURE__ */ jsx6("span", { className: "vpg-watermark-inline", children: /* @__PURE__ */ jsxs6("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: [
3921
- /* @__PURE__ */ jsxs6("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3922
- /* @__PURE__ */ jsx6("rect", { x: "3", y: "3", width: "7", height: "7" }),
3923
- /* @__PURE__ */ jsx6("rect", { x: "14", y: "3", width: "7", height: "7" }),
3924
- /* @__PURE__ */ jsx6("rect", { x: "14", y: "14", width: "7", height: "7" }),
3925
- /* @__PURE__ */ jsx6("rect", { x: "3", y: "14", width: "7", height: "7" })
4659
+ /* @__PURE__ */ jsx7("div", { className: "vpg-footer-right", children: isDemo ? /* @__PURE__ */ jsxs7("div", { className: "vpg-demo-banner", children: [
4660
+ /* @__PURE__ */ jsx7("span", { className: "vpg-demo-badge", children: "DEMO" }),
4661
+ /* @__PURE__ */ jsx7("span", { children: "Pro features enabled" }),
4662
+ /* @__PURE__ */ jsx7("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", children: "Get License \u2192" })
4663
+ ] }) : showWatermark ? /* @__PURE__ */ jsx7("span", { className: "vpg-watermark-inline", children: /* @__PURE__ */ jsxs7("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: [
4664
+ /* @__PURE__ */ jsxs7("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4665
+ /* @__PURE__ */ jsx7("rect", { x: "3", y: "3", width: "7", height: "7" }),
4666
+ /* @__PURE__ */ jsx7("rect", { x: "14", y: "3", width: "7", height: "7" }),
4667
+ /* @__PURE__ */ jsx7("rect", { x: "14", y: "14", width: "7", height: "7" }),
4668
+ /* @__PURE__ */ jsx7("rect", { x: "3", y: "14", width: "7", height: "7" })
3926
4669
  ] }),
3927
4670
  "Powered by TinyPivot"
3928
4671
  ] }) }) : null })
3929
4672
  ] }),
3930
- enableVerticalResize && /* @__PURE__ */ jsx6("div", { className: "vpg-vertical-resize-handle", onMouseDown: startVerticalResize, children: /* @__PURE__ */ jsxs6("div", { className: "vpg-resize-grip", children: [
3931
- /* @__PURE__ */ jsx6("span", {}),
3932
- /* @__PURE__ */ jsx6("span", {}),
3933
- /* @__PURE__ */ jsx6("span", {})
4673
+ enableVerticalResize && /* @__PURE__ */ jsx7("div", { className: "vpg-vertical-resize-handle", onMouseDown: startVerticalResize, children: /* @__PURE__ */ jsxs7("div", { className: "vpg-resize-grip", children: [
4674
+ /* @__PURE__ */ jsx7("span", {}),
4675
+ /* @__PURE__ */ jsx7("span", {}),
4676
+ /* @__PURE__ */ jsx7("span", {})
3934
4677
  ] }) }),
3935
4678
  activeFilterColumn && typeof document !== "undefined" && createPortal2(
3936
- /* @__PURE__ */ jsx6(
4679
+ /* @__PURE__ */ jsx7(
3937
4680
  "div",
3938
4681
  {
3939
4682
  className: "vpg-filter-portal",
@@ -3944,7 +4687,7 @@ function DataGrid({
3944
4687
  maxHeight: `${filterDropdownPosition.maxHeight}px`,
3945
4688
  zIndex: 9999
3946
4689
  },
3947
- children: /* @__PURE__ */ jsx6(
4690
+ children: /* @__PURE__ */ jsx7(
3948
4691
  ColumnFilter,
3949
4692
  {
3950
4693
  columnId: activeFilterColumn,