@smallwebco/tinypivot-react 1.0.51 → 1.0.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -29,10 +39,10 @@ __export(index_exports, {
29
39
  enableDemoMode: () => enableDemoMode,
30
40
  exportPivotToCSV: () => exportPivotToCSV,
31
41
  exportToCSV: () => exportToCSV,
32
- formatCellValue: () => import_tinypivot_core2.formatCellValue,
42
+ formatCellValue: () => import_tinypivot_core3.formatCellValue,
33
43
  formatSelectionForClipboard: () => formatSelectionForClipboard,
34
- getAggregationLabel: () => import_tinypivot_core5.getAggregationLabel,
35
- getColumnUniqueValues: () => import_tinypivot_core2.getColumnUniqueValues,
44
+ getAggregationLabel: () => import_tinypivot_core6.getAggregationLabel,
45
+ getColumnUniqueValues: () => import_tinypivot_core3.getColumnUniqueValues,
36
46
  setLicenseKey: () => setLicenseKey,
37
47
  useColumnResize: () => useColumnResize,
38
48
  useExcelGrid: () => useExcelGrid,
@@ -234,21 +244,519 @@ function CalculatedFieldModal({
234
244
  return (0, import_react_dom.createPortal)(modalContent, document.body);
235
245
  }
236
246
 
247
+ // src/components/ChartBuilder.tsx
248
+ var import_tinypivot_core2 = require("@smallwebco/tinypivot-core");
249
+ var import_react2 = require("react");
250
+ var import_react_apexcharts = __toESM(require("react-apexcharts"), 1);
251
+ var import_jsx_runtime2 = require("react/jsx-runtime");
252
+ function ChartBuilder({
253
+ data,
254
+ theme = "light",
255
+ onConfigChange
256
+ }) {
257
+ const [chartConfig, setChartConfig] = (0, import_react2.useState)((0, import_tinypivot_core2.createDefaultChartConfig)());
258
+ const [draggingField, setDraggingField] = (0, import_react2.useState)(null);
259
+ const [dragOverZone, setDragOverZone] = (0, import_react2.useState)(null);
260
+ const fieldInfos = (0, import_react2.useMemo)(() => (0, import_tinypivot_core2.analyzeFieldsForChart)(data), [data]);
261
+ const dimensions = (0, import_react2.useMemo)(
262
+ () => fieldInfos.filter((f) => f.role === "dimension" || f.role === "temporal"),
263
+ [fieldInfos]
264
+ );
265
+ const measures = (0, import_react2.useMemo)(
266
+ () => fieldInfos.filter((f) => f.role === "measure"),
267
+ [fieldInfos]
268
+ );
269
+ const guidance = (0, import_react2.useMemo)(() => (0, import_tinypivot_core2.getChartGuidance)(chartConfig), [chartConfig]);
270
+ const chartIsValid = (0, import_react2.useMemo)(() => (0, import_tinypivot_core2.isChartConfigValid)(chartConfig), [chartConfig]);
271
+ const selectedChartType = (0, import_react2.useMemo)(
272
+ () => import_tinypivot_core2.CHART_TYPES.find((ct) => ct.type === chartConfig.type),
273
+ [chartConfig.type]
274
+ );
275
+ const handleDragStart = (0, import_react2.useCallback)((field, event) => {
276
+ setDraggingField(field);
277
+ event.dataTransfer?.setData("text/plain", field.field);
278
+ }, []);
279
+ const handleDragEnd = (0, import_react2.useCallback)(() => {
280
+ setDraggingField(null);
281
+ setDragOverZone(null);
282
+ }, []);
283
+ const handleDragOver = (0, import_react2.useCallback)((zone, event) => {
284
+ event.preventDefault();
285
+ setDragOverZone(zone);
286
+ }, []);
287
+ const handleDragLeave = (0, import_react2.useCallback)(() => {
288
+ setDragOverZone(null);
289
+ }, []);
290
+ const handleDrop = (0, import_react2.useCallback)((zone, event) => {
291
+ event.preventDefault();
292
+ setDragOverZone(null);
293
+ if (!draggingField)
294
+ return;
295
+ const field = draggingField;
296
+ const chartField = {
297
+ field: field.field,
298
+ label: field.label,
299
+ role: field.role,
300
+ aggregation: field.role === "measure" ? "sum" : void 0
301
+ };
302
+ let newConfig = { ...chartConfig };
303
+ switch (zone) {
304
+ case "xAxis":
305
+ newConfig = { ...newConfig, xAxis: chartField };
306
+ break;
307
+ case "yAxis":
308
+ newConfig = { ...newConfig, yAxis: chartField };
309
+ break;
310
+ case "series":
311
+ newConfig = { ...newConfig, seriesField: chartField };
312
+ break;
313
+ case "size":
314
+ newConfig = { ...newConfig, sizeField: chartField };
315
+ break;
316
+ case "color":
317
+ newConfig = { ...newConfig, colorField: chartField };
318
+ break;
319
+ }
320
+ setChartConfig(newConfig);
321
+ onConfigChange?.(newConfig);
322
+ }, [chartConfig, draggingField, onConfigChange]);
323
+ const removeField = (0, import_react2.useCallback)((zone) => {
324
+ let newConfig = { ...chartConfig };
325
+ switch (zone) {
326
+ case "xAxis":
327
+ newConfig = { ...newConfig, xAxis: void 0 };
328
+ break;
329
+ case "yAxis":
330
+ newConfig = { ...newConfig, yAxis: void 0 };
331
+ break;
332
+ case "series":
333
+ newConfig = { ...newConfig, seriesField: void 0 };
334
+ break;
335
+ case "size":
336
+ newConfig = { ...newConfig, sizeField: void 0 };
337
+ break;
338
+ case "color":
339
+ newConfig = { ...newConfig, colorField: void 0 };
340
+ break;
341
+ }
342
+ setChartConfig(newConfig);
343
+ onConfigChange?.(newConfig);
344
+ }, [chartConfig, onConfigChange]);
345
+ const selectChartType = (0, import_react2.useCallback)((type) => {
346
+ const newConfig = { ...chartConfig, type };
347
+ setChartConfig(newConfig);
348
+ onConfigChange?.(newConfig);
349
+ }, [chartConfig, onConfigChange]);
350
+ const updateAggregation = (0, import_react2.useCallback)((zone, aggregation) => {
351
+ const field = zone === "yAxis" ? chartConfig.yAxis : chartConfig.sizeField;
352
+ if (!field)
353
+ return;
354
+ const updated = { ...field, aggregation };
355
+ let newConfig = { ...chartConfig };
356
+ if (zone === "yAxis") {
357
+ newConfig = { ...newConfig, yAxis: updated };
358
+ } else if (zone === "size") {
359
+ newConfig = { ...newConfig, sizeField: updated };
360
+ }
361
+ setChartConfig(newConfig);
362
+ onConfigChange?.(newConfig);
363
+ }, [chartConfig, onConfigChange]);
364
+ const getApexChartType = (0, import_react2.useCallback)((type) => {
365
+ const mapping = {
366
+ bar: "bar",
367
+ line: "line",
368
+ area: "area",
369
+ pie: "pie",
370
+ donut: "donut",
371
+ scatter: "scatter",
372
+ bubble: "bubble",
373
+ heatmap: "heatmap",
374
+ treemap: "bar",
375
+ // Treemap rendered as bar (compatibility)
376
+ radar: "radar"
377
+ };
378
+ return mapping[type] || "bar";
379
+ }, []);
380
+ const formatValue = (0, import_react2.useCallback)((val, format, decimals) => {
381
+ const dec = decimals ?? 0;
382
+ if (format === "percent") {
383
+ return `${val.toFixed(dec)}%`;
384
+ }
385
+ if (format === "currency") {
386
+ return `$${val.toLocaleString(void 0, { minimumFractionDigits: dec, maximumFractionDigits: dec })}`;
387
+ }
388
+ if (Math.abs(val) >= 1e3) {
389
+ return val.toLocaleString(void 0, { maximumFractionDigits: dec });
390
+ }
391
+ return val.toFixed(dec);
392
+ }, []);
393
+ const chartOptions = (0, import_react2.useMemo)(() => {
394
+ const isDark = theme === "dark";
395
+ const config = chartConfig;
396
+ const options = config.options || {};
397
+ const baseOptions = {
398
+ chart: {
399
+ type: getApexChartType(config.type),
400
+ background: "transparent",
401
+ foreColor: isDark ? "#e2e8f0" : "#334155",
402
+ toolbar: {
403
+ show: true,
404
+ tools: {
405
+ download: true,
406
+ selection: false,
407
+ zoom: options.enableZoom ?? false,
408
+ zoomin: options.enableZoom ?? false,
409
+ zoomout: options.enableZoom ?? false,
410
+ pan: false,
411
+ reset: options.enableZoom ?? false
412
+ },
413
+ export: {
414
+ csv: { filename: "chart-data" },
415
+ svg: { filename: "chart" },
416
+ png: { filename: "chart" }
417
+ }
418
+ },
419
+ animations: {
420
+ enabled: options.animated ?? true,
421
+ speed: 400,
422
+ dynamicAnimation: { enabled: true, speed: 300 }
423
+ },
424
+ fontFamily: "system-ui, -apple-system, sans-serif"
425
+ },
426
+ colors: options.colors || import_tinypivot_core2.CHART_COLORS,
427
+ theme: {
428
+ mode: isDark ? "dark" : "light"
429
+ },
430
+ grid: {
431
+ show: options.showGrid ?? true,
432
+ borderColor: isDark ? "#334155" : "#e2e8f0"
433
+ },
434
+ legend: {
435
+ show: options.showLegend ?? true,
436
+ position: options.legendPosition || "top"
437
+ },
438
+ dataLabels: {
439
+ enabled: options.showDataLabels ?? false
440
+ },
441
+ tooltip: {
442
+ theme: isDark ? "dark" : "light"
443
+ },
444
+ stroke: {
445
+ curve: "smooth",
446
+ width: config.type === "line" ? 3 : config.type === "area" ? 2 : 0
447
+ },
448
+ fill: {
449
+ opacity: config.type === "area" ? 0.4 : 1
450
+ }
451
+ };
452
+ if (config.xAxis) {
453
+ baseOptions.xaxis = {
454
+ ...baseOptions.xaxis,
455
+ title: { text: options.xAxisTitle || config.xAxis.label },
456
+ labels: {
457
+ style: { colors: isDark ? "#94a3b8" : "#64748b" }
458
+ }
459
+ };
460
+ }
461
+ if (config.yAxis && !["pie", "donut", "radar", "treemap"].includes(config.type)) {
462
+ baseOptions.yaxis = {
463
+ title: { text: options.yAxisTitle || config.yAxis.label },
464
+ labels: {
465
+ style: { colors: isDark ? "#94a3b8" : "#64748b" },
466
+ formatter: (val) => formatValue(val, options.valueFormat, options.decimals)
467
+ }
468
+ };
469
+ }
470
+ if (options.title) {
471
+ baseOptions.title = {
472
+ text: options.title,
473
+ style: {
474
+ fontSize: "16px",
475
+ fontWeight: "600",
476
+ color: isDark ? "#e2e8f0" : "#334155"
477
+ }
478
+ };
479
+ }
480
+ if (options.stacked && ["bar", "area"].includes(config.type)) {
481
+ baseOptions.chart.stacked = true;
482
+ }
483
+ if (config.type === "pie" || config.type === "donut") {
484
+ baseOptions.plotOptions = {
485
+ pie: {
486
+ donut: {
487
+ size: config.type === "donut" ? "55%" : "0%",
488
+ labels: {
489
+ show: config.type === "donut",
490
+ total: {
491
+ show: true,
492
+ label: "Total",
493
+ formatter: (w) => {
494
+ const total = w.globals.seriesTotals.reduce((a, b) => a + b, 0);
495
+ return formatValue(total, options.valueFormat, options.decimals);
496
+ }
497
+ }
498
+ }
499
+ }
500
+ }
501
+ };
502
+ }
503
+ if (config.type === "radar") {
504
+ baseOptions.plotOptions = {
505
+ radar: {
506
+ polygons: {
507
+ strokeColors: isDark ? "#334155" : "#e2e8f0",
508
+ fill: { colors: isDark ? ["#1e293b", "#0f172a"] : ["#f8fafc", "#f1f5f9"] }
509
+ }
510
+ }
511
+ };
512
+ }
513
+ return baseOptions;
514
+ }, [chartConfig, theme, getApexChartType, formatValue]);
515
+ const chartSeries = (0, import_react2.useMemo)(() => {
516
+ const config = chartConfig;
517
+ if (!chartIsValid)
518
+ return [];
519
+ if (config.type === "pie" || config.type === "donut") {
520
+ const chartData2 = (0, import_tinypivot_core2.processChartDataForPie)(data, config);
521
+ return chartData2.series[0]?.data || [];
522
+ }
523
+ if (config.type === "scatter" || config.type === "bubble") {
524
+ const points = (0, import_tinypivot_core2.processChartDataForScatter)(data, config);
525
+ return [{
526
+ name: config.yAxis?.label || "Data",
527
+ data: points
528
+ }];
529
+ }
530
+ const chartData = (0, import_tinypivot_core2.processChartData)(data, config);
531
+ return chartData.series;
532
+ }, [data, chartConfig, chartIsValid]);
533
+ const chartLabels = (0, import_react2.useMemo)(() => {
534
+ const config = chartConfig;
535
+ if (!chartIsValid)
536
+ return [];
537
+ if (config.type === "pie" || config.type === "donut") {
538
+ const chartData2 = (0, import_tinypivot_core2.processChartDataForPie)(data, config);
539
+ return chartData2.categories;
540
+ }
541
+ const chartData = (0, import_tinypivot_core2.processChartData)(data, config);
542
+ return chartData.categories;
543
+ }, [data, chartConfig, chartIsValid]);
544
+ const chartOptionsWithCategories = (0, import_react2.useMemo)(() => {
545
+ const options = { ...chartOptions };
546
+ const config = chartConfig;
547
+ if (!["pie", "donut", "scatter", "bubble"].includes(config.type)) {
548
+ options.xaxis = {
549
+ ...options.xaxis,
550
+ categories: chartLabels
551
+ };
552
+ }
553
+ if (config.type === "pie" || config.type === "donut") {
554
+ options.labels = chartLabels;
555
+ }
556
+ return options;
557
+ }, [chartOptions, chartConfig, chartLabels]);
558
+ const getChartIcon = (0, import_react2.useCallback)((type) => {
559
+ const icons = {
560
+ bar: "M3 3v18h18V3H3zm4 14H5v-6h2v6zm4 0H9V7h2v10zm4 0h-2V9h2v8zm4 0h-2v-4h2v4z",
561
+ line: "M3.5 18.5l6-6 4 4 8-8M14.5 8.5h6v6",
562
+ area: "M3 17l6-6 4 4 8-8v10H3z",
563
+ pie: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8v8l5.66 5.66C14.28 19.04 13.18 20 12 20z",
564
+ donut: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 14c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z",
565
+ scatter: "M7 14c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6-5c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm4 7c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z",
566
+ bubble: "M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm-6 3c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 2c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z",
567
+ heatmap: "M3 3h4v4H3V3zm6 0h4v4H9V3zm6 0h4v4h-4V3zM3 9h4v4H3V9zm6 0h4v4H9V9zm6 0h4v4h-4V9zM3 15h4v4H3v-4zm6 0h4v4H9v-4zm6 0h4v4h-4v-4z",
568
+ treemap: "M3 3h8v10H3V3zm10 0h8v6h-8V3zM3 15h8v6H3v-6zm10-4h8v10h-8V11z",
569
+ radar: "M12 2L4 6v6c0 5.55 3.84 10.74 8 12 4.16-1.26 8-6.45 8-12V6l-8-4zm0 3.18l6 3v5.09c0 4.08-2.76 7.91-6 9.14V5.18z"
570
+ };
571
+ return icons[type] || icons.bar;
572
+ }, []);
573
+ (0, import_react2.useEffect)(() => {
574
+ onConfigChange?.(chartConfig);
575
+ }, []);
576
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-builder", children: [
577
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-chart-type-bar", children: import_tinypivot_core2.CHART_TYPES.map((ct) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
578
+ "button",
579
+ {
580
+ className: `vpg-chart-type-btn ${chartConfig.type === ct.type ? "active" : ""}`,
581
+ title: ct.description,
582
+ onClick: () => selectChartType(ct.type),
583
+ children: [
584
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: getChartIcon(ct.type) }) }),
585
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-chart-type-label", children: ct.label.replace(" Chart", "") })
586
+ ]
587
+ },
588
+ ct.type
589
+ )) }),
590
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-builder-content", children: [
591
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-fields-panel", children: [
592
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-fields-section", children: [
593
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h4", { className: "vpg-chart-fields-title", children: [
594
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-sm", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M4 6h16M4 12h10M4 18h6" }) }),
595
+ "Dimensions"
596
+ ] }),
597
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-fields-list", children: [
598
+ dimensions.map((field) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
599
+ "div",
600
+ {
601
+ className: "vpg-chart-field-chip vpg-field-dimension",
602
+ draggable: true,
603
+ onDragStart: (e) => handleDragStart(field, e),
604
+ onDragEnd: handleDragEnd,
605
+ children: [
606
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-field-name", children: field.label }),
607
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-field-type", children: field.role === "temporal" ? "date" : "text" })
608
+ ]
609
+ },
610
+ field.field
611
+ )),
612
+ dimensions.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-chart-fields-empty", children: "No dimension fields detected" })
613
+ ] })
614
+ ] }),
615
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-fields-section", children: [
616
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("h4", { className: "vpg-chart-fields-title", children: [
617
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-sm", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M16 8v8M12 11v5M8 14v2M4 4v16h16" }) }),
618
+ "Measures"
619
+ ] }),
620
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-fields-list", children: [
621
+ measures.map((field) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
622
+ "div",
623
+ {
624
+ className: "vpg-chart-field-chip vpg-field-measure",
625
+ draggable: true,
626
+ onDragStart: (e) => handleDragStart(field, e),
627
+ onDragEnd: handleDragEnd,
628
+ children: [
629
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-field-name", children: field.label }),
630
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-field-type", children: "#" })
631
+ ]
632
+ },
633
+ field.field
634
+ )),
635
+ measures.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-chart-fields-empty", children: "No numeric fields detected" })
636
+ ] })
637
+ ] })
638
+ ] }),
639
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-config-panel", children: [
640
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-drop-zone-wrapper", children: [
641
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-chart-zone-label", children: "X-Axis / Category" }),
642
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
643
+ "div",
644
+ {
645
+ className: `vpg-chart-drop-zone ${dragOverZone === "xAxis" ? "drag-over" : ""} ${chartConfig.xAxis ? "has-field" : ""}`,
646
+ onDragOver: (e) => handleDragOver("xAxis", e),
647
+ onDragLeave: handleDragLeave,
648
+ onDrop: (e) => handleDrop("xAxis", e),
649
+ children: chartConfig.xAxis ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
650
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-field-name", children: chartConfig.xAxis.label }),
651
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("xAxis"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
652
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-placeholder", children: "Drop dimension here" })
653
+ }
654
+ )
655
+ ] }),
656
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-drop-zone-wrapper", children: [
657
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-chart-zone-label", children: "Y-Axis / Value" }),
658
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
659
+ "div",
660
+ {
661
+ className: `vpg-chart-drop-zone ${dragOverZone === "yAxis" ? "drag-over" : ""} ${chartConfig.yAxis ? "has-field" : ""}`,
662
+ onDragOver: (e) => handleDragOver("yAxis", e),
663
+ onDragLeave: handleDragLeave,
664
+ onDrop: (e) => handleDrop("yAxis", e),
665
+ children: chartConfig.yAxis ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
666
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-field-name", children: chartConfig.yAxis.label }),
667
+ chartConfig.yAxis.role === "measure" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
668
+ "select",
669
+ {
670
+ className: "vpg-zone-aggregation",
671
+ value: chartConfig.yAxis.aggregation || "sum",
672
+ onChange: (e) => updateAggregation("yAxis", e.target.value),
673
+ children: import_tinypivot_core2.CHART_AGGREGATIONS.map((agg) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: agg.value, children: agg.symbol }, agg.value))
674
+ }
675
+ ),
676
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("yAxis"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
677
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-placeholder", children: "Drop measure here" })
678
+ }
679
+ )
680
+ ] }),
681
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-drop-zone-wrapper", children: [
682
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-chart-zone-label", children: "Color / Series (optional)" }),
683
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
684
+ "div",
685
+ {
686
+ className: `vpg-chart-drop-zone vpg-zone-optional ${dragOverZone === "series" ? "drag-over" : ""} ${chartConfig.seriesField ? "has-field" : ""}`,
687
+ onDragOver: (e) => handleDragOver("series", e),
688
+ onDragLeave: handleDragLeave,
689
+ onDrop: (e) => handleDrop("series", e),
690
+ children: chartConfig.seriesField ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
691
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-field-name", children: chartConfig.seriesField.label }),
692
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("series"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
693
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-placeholder", children: "Group by dimension" })
694
+ }
695
+ )
696
+ ] }),
697
+ (chartConfig.type === "scatter" || chartConfig.type === "bubble") && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-drop-zone-wrapper", children: [
698
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-chart-zone-label", children: "Size (bubble)" }),
699
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
700
+ "div",
701
+ {
702
+ className: `vpg-chart-drop-zone vpg-zone-optional ${dragOverZone === "size" ? "drag-over" : ""} ${chartConfig.sizeField ? "has-field" : ""}`,
703
+ onDragOver: (e) => handleDragOver("size", e),
704
+ onDragLeave: handleDragLeave,
705
+ onDrop: (e) => handleDrop("size", e),
706
+ children: chartConfig.sizeField ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
707
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-field-name", children: chartConfig.sizeField.label }),
708
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "vpg-zone-remove-btn", onClick: () => removeField("size"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 18L18 6M6 6l12 12" }) }) })
709
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-zone-placeholder", children: "Drop measure for size" })
710
+ }
711
+ )
712
+ ] }),
713
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-guidance", children: [
714
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { className: "vpg-icon-sm", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
715
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
716
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 16v-4M12 8h.01" })
717
+ ] }),
718
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: guidance })
719
+ ] })
720
+ ] }),
721
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-chart-preview-panel", children: chartIsValid ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-chart-container", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
722
+ import_react_apexcharts.default,
723
+ {
724
+ type: getApexChartType(chartConfig.type),
725
+ options: chartOptionsWithCategories,
726
+ series: chartSeries,
727
+ height: "100%"
728
+ },
729
+ `${chartConfig.type}-${JSON.stringify(chartConfig.xAxis)}-${JSON.stringify(chartConfig.yAxis)}`
730
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-empty-state", children: [
731
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-lg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: getChartIcon(chartConfig.type) }) }),
732
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: "Build your chart" }),
733
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: "Drag fields from the left panel to configure your visualization" }),
734
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-chart-hint", children: [
735
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: selectedChartType?.label }),
736
+ ":",
737
+ " ",
738
+ selectedChartType?.description
739
+ ] })
740
+ ] }) })
741
+ ] })
742
+ ] });
743
+ }
744
+
237
745
  // src/components/ColumnFilter.tsx
238
- var import_react3 = require("react");
746
+ var import_react4 = require("react");
239
747
 
240
748
  // src/components/NumericRangeFilter.tsx
241
- var import_react2 = require("react");
242
- var import_jsx_runtime2 = require("react/jsx-runtime");
749
+ var import_react3 = require("react");
750
+ var import_jsx_runtime3 = require("react/jsx-runtime");
243
751
  function NumericRangeFilter({
244
752
  dataMin,
245
753
  dataMax,
246
754
  currentRange,
247
755
  onChange
248
756
  }) {
249
- const [localMin, setLocalMin] = (0, import_react2.useState)(currentRange?.min ?? null);
250
- const [localMax, setLocalMax] = (0, import_react2.useState)(currentRange?.max ?? null);
251
- const step = (0, import_react2.useMemo)(() => {
757
+ const [localMin, setLocalMin] = (0, import_react3.useState)(currentRange?.min ?? null);
758
+ const [localMax, setLocalMax] = (0, import_react3.useState)(currentRange?.max ?? null);
759
+ const step = (0, import_react3.useMemo)(() => {
252
760
  const range = dataMax - dataMin;
253
761
  if (range === 0)
254
762
  return 1;
@@ -262,7 +770,7 @@ function NumericRangeFilter({
262
770
  return 10;
263
771
  return 10 ** (Math.floor(Math.log10(range)) - 2);
264
772
  }, [dataMin, dataMax]);
265
- const formatValue = (0, import_react2.useCallback)((val) => {
773
+ const formatValue = (0, import_react3.useCallback)((val) => {
266
774
  if (val === null)
267
775
  return "";
268
776
  if (Number.isInteger(val))
@@ -270,17 +778,17 @@ function NumericRangeFilter({
270
778
  return val.toLocaleString(void 0, { maximumFractionDigits: 2 });
271
779
  }, []);
272
780
  const isFilterActive = localMin !== null || localMax !== null;
273
- const minPercent = (0, import_react2.useMemo)(() => {
781
+ const minPercent = (0, import_react3.useMemo)(() => {
274
782
  if (localMin === null || dataMax === dataMin)
275
783
  return 0;
276
784
  return (localMin - dataMin) / (dataMax - dataMin) * 100;
277
785
  }, [localMin, dataMin, dataMax]);
278
- const maxPercent = (0, import_react2.useMemo)(() => {
786
+ const maxPercent = (0, import_react3.useMemo)(() => {
279
787
  if (localMax === null || dataMax === dataMin)
280
788
  return 100;
281
789
  return (localMax - dataMin) / (dataMax - dataMin) * 100;
282
790
  }, [localMax, dataMin, dataMax]);
283
- const handleMinSlider = (0, import_react2.useCallback)((event) => {
791
+ const handleMinSlider = (0, import_react3.useCallback)((event) => {
284
792
  const value = Number.parseFloat(event.target.value);
285
793
  setLocalMin(() => {
286
794
  if (localMax !== null && value > localMax) {
@@ -289,7 +797,7 @@ function NumericRangeFilter({
289
797
  return value;
290
798
  });
291
799
  }, [localMax]);
292
- const handleMaxSlider = (0, import_react2.useCallback)((event) => {
800
+ const handleMaxSlider = (0, import_react3.useCallback)((event) => {
293
801
  const value = Number.parseFloat(event.target.value);
294
802
  setLocalMax(() => {
295
803
  if (localMin !== null && value < localMin) {
@@ -298,14 +806,14 @@ function NumericRangeFilter({
298
806
  return value;
299
807
  });
300
808
  }, [localMin]);
301
- const handleSliderChange = (0, import_react2.useCallback)(() => {
809
+ const handleSliderChange = (0, import_react3.useCallback)(() => {
302
810
  if (localMin === null && localMax === null) {
303
811
  onChange(null);
304
812
  } else {
305
813
  onChange({ min: localMin, max: localMax });
306
814
  }
307
815
  }, [localMin, localMax, onChange]);
308
- const handleMinInput = (0, import_react2.useCallback)((event) => {
816
+ const handleMinInput = (0, import_react3.useCallback)((event) => {
309
817
  const value = event.target.value === "" ? null : Number.parseFloat(event.target.value);
310
818
  if (value !== null && !Number.isNaN(value)) {
311
819
  setLocalMin(Math.max(dataMin, Math.min(value, localMax ?? dataMax)));
@@ -313,7 +821,7 @@ function NumericRangeFilter({
313
821
  setLocalMin(null);
314
822
  }
315
823
  }, [dataMin, dataMax, localMax]);
316
- const handleMaxInput = (0, import_react2.useCallback)((event) => {
824
+ const handleMaxInput = (0, import_react3.useCallback)((event) => {
317
825
  const value = event.target.value === "" ? null : Number.parseFloat(event.target.value);
318
826
  if (value !== null && !Number.isNaN(value)) {
319
827
  setLocalMax(Math.min(dataMax, Math.max(value, localMin ?? dataMin)));
@@ -321,39 +829,39 @@ function NumericRangeFilter({
321
829
  setLocalMax(null);
322
830
  }
323
831
  }, [dataMin, dataMax, localMin]);
324
- const handleInputBlur = (0, import_react2.useCallback)(() => {
832
+ const handleInputBlur = (0, import_react3.useCallback)(() => {
325
833
  if (localMin === null && localMax === null) {
326
834
  onChange(null);
327
835
  } else {
328
836
  onChange({ min: localMin, max: localMax });
329
837
  }
330
838
  }, [localMin, localMax, onChange]);
331
- const clearFilter = (0, import_react2.useCallback)(() => {
839
+ const clearFilter = (0, import_react3.useCallback)(() => {
332
840
  setLocalMin(null);
333
841
  setLocalMax(null);
334
842
  onChange(null);
335
843
  }, [onChange]);
336
- const setFullRange = (0, import_react2.useCallback)(() => {
844
+ const setFullRange = (0, import_react3.useCallback)(() => {
337
845
  setLocalMin(dataMin);
338
846
  setLocalMax(dataMax);
339
847
  onChange({ min: dataMin, max: dataMax });
340
848
  }, [dataMin, dataMax, onChange]);
341
- (0, import_react2.useEffect)(() => {
849
+ (0, import_react3.useEffect)(() => {
342
850
  setLocalMin(currentRange?.min ?? null);
343
851
  setLocalMax(currentRange?.max ?? null);
344
852
  }, [currentRange]);
345
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-range-filter", children: [
346
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-range-info", children: [
347
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-range-label", children: "Data range:" }),
348
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "vpg-range-bounds", children: [
853
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-range-filter", children: [
854
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-range-info", children: [
855
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "vpg-range-label", children: "Data range:" }),
856
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "vpg-range-bounds", children: [
349
857
  formatValue(dataMin),
350
858
  " ",
351
859
  "\u2013",
352
860
  formatValue(dataMax)
353
861
  ] })
354
862
  ] }),
355
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-slider-container", children: [
356
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "vpg-slider-track", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
863
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-slider-container", children: [
864
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "vpg-slider-track", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
357
865
  "div",
358
866
  {
359
867
  className: "vpg-slider-fill",
@@ -363,7 +871,7 @@ function NumericRangeFilter({
363
871
  }
364
872
  }
365
873
  ) }),
366
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
874
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
367
875
  "input",
368
876
  {
369
877
  type: "range",
@@ -377,7 +885,7 @@ function NumericRangeFilter({
377
885
  onTouchEnd: handleSliderChange
378
886
  }
379
887
  ),
380
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
888
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
381
889
  "input",
382
890
  {
383
891
  type: "range",
@@ -392,10 +900,10 @@ function NumericRangeFilter({
392
900
  }
393
901
  )
394
902
  ] }),
395
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-range-inputs", children: [
396
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-input-group", children: [
397
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-input-label", children: "Min" }),
398
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
903
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-range-inputs", children: [
904
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-input-group", children: [
905
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: "vpg-input-label", children: "Min" }),
906
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
399
907
  "input",
400
908
  {
401
909
  type: "number",
@@ -408,10 +916,10 @@ function NumericRangeFilter({
408
916
  }
409
917
  )
410
918
  ] }),
411
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "vpg-input-separator", children: "to" }),
412
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-input-group", children: [
413
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "vpg-input-label", children: "Max" }),
414
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
919
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "vpg-input-separator", children: "to" }),
920
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-input-group", children: [
921
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: "vpg-input-label", children: "Max" }),
922
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
415
923
  "input",
416
924
  {
417
925
  type: "number",
@@ -425,15 +933,15 @@ function NumericRangeFilter({
425
933
  )
426
934
  ] })
427
935
  ] }),
428
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-range-actions", children: [
429
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
936
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-range-actions", children: [
937
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
430
938
  "button",
431
939
  {
432
940
  className: "vpg-range-btn",
433
941
  disabled: !isFilterActive,
434
942
  onClick: clearFilter,
435
943
  children: [
436
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
944
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
437
945
  "path",
438
946
  {
439
947
  strokeLinecap: "round",
@@ -446,8 +954,8 @@ function NumericRangeFilter({
446
954
  ]
447
955
  }
448
956
  ),
449
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { className: "vpg-range-btn", onClick: setFullRange, children: [
450
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
957
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { className: "vpg-range-btn", onClick: setFullRange, children: [
958
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
451
959
  "path",
452
960
  {
453
961
  strokeLinecap: "round",
@@ -459,8 +967,8 @@ function NumericRangeFilter({
459
967
  "Full Range"
460
968
  ] })
461
969
  ] }),
462
- isFilterActive && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "vpg-filter-summary", children: [
463
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
970
+ isFilterActive && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-filter-summary", children: [
971
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
464
972
  "path",
465
973
  {
466
974
  strokeLinecap: "round",
@@ -469,15 +977,15 @@ function NumericRangeFilter({
469
977
  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"
470
978
  }
471
979
  ) }),
472
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
980
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
473
981
  "Showing values",
474
982
  " ",
475
- localMin !== null && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("strong", { children: [
983
+ localMin !== null && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("strong", { children: [
476
984
  "\u2265",
477
985
  formatValue(localMin)
478
986
  ] }),
479
987
  localMin !== null && localMax !== null && " and ",
480
- localMax !== null && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("strong", { children: [
988
+ localMax !== null && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("strong", { children: [
481
989
  "\u2264",
482
990
  formatValue(localMax)
483
991
  ] })
@@ -487,7 +995,7 @@ function NumericRangeFilter({
487
995
  }
488
996
 
489
997
  // src/components/ColumnFilter.tsx
490
- var import_jsx_runtime3 = require("react/jsx-runtime");
998
+ var import_jsx_runtime4 = require("react/jsx-runtime");
491
999
  function ColumnFilter({
492
1000
  columnName,
493
1001
  stats,
@@ -499,33 +1007,33 @@ function ColumnFilter({
499
1007
  onClose,
500
1008
  onRangeFilter
501
1009
  }) {
502
- const [searchQuery, setSearchQuery] = (0, import_react3.useState)("");
503
- const [localSelected, setLocalSelected] = (0, import_react3.useState)(new Set(selectedValues));
504
- const dropdownRef = (0, import_react3.useRef)(null);
505
- const searchInputRef = (0, import_react3.useRef)(null);
1010
+ const [searchQuery, setSearchQuery] = (0, import_react4.useState)("");
1011
+ const [localSelected, setLocalSelected] = (0, import_react4.useState)(new Set(selectedValues));
1012
+ const dropdownRef = (0, import_react4.useRef)(null);
1013
+ const searchInputRef = (0, import_react4.useRef)(null);
506
1014
  const isNumericColumn = stats.type === "number" && stats.numericMin !== void 0 && stats.numericMax !== void 0;
507
- const [filterMode, setFilterMode] = (0, import_react3.useState)(numericRange ? "range" : "values");
508
- const [localRange, setLocalRange] = (0, import_react3.useState)(numericRange ?? null);
1015
+ const [filterMode, setFilterMode] = (0, import_react4.useState)(numericRange ? "range" : "values");
1016
+ const [localRange, setLocalRange] = (0, import_react4.useState)(numericRange ?? null);
509
1017
  const hasBlankValues = stats.nullCount > 0;
510
- const filteredValues = (0, import_react3.useMemo)(() => {
1018
+ const filteredValues = (0, import_react4.useMemo)(() => {
511
1019
  const values = stats.uniqueValues;
512
1020
  if (!searchQuery)
513
1021
  return values;
514
1022
  const query = searchQuery.toLowerCase();
515
1023
  return values.filter((v) => v.toLowerCase().includes(query));
516
1024
  }, [stats.uniqueValues, searchQuery]);
517
- const allValues = (0, import_react3.useMemo)(() => {
1025
+ const allValues = (0, import_react4.useMemo)(() => {
518
1026
  const values = [...filteredValues];
519
1027
  if (hasBlankValues && (!searchQuery || "(blank)".includes(searchQuery.toLowerCase()))) {
520
1028
  values.unshift("(blank)");
521
1029
  }
522
1030
  return values;
523
1031
  }, [filteredValues, hasBlankValues, searchQuery]);
524
- const _isAllSelected = (0, import_react3.useMemo)(
1032
+ const _isAllSelected = (0, import_react4.useMemo)(
525
1033
  () => allValues.every((v) => localSelected.has(v)),
526
1034
  [allValues, localSelected]
527
1035
  );
528
- const toggleValue = (0, import_react3.useCallback)((value) => {
1036
+ const toggleValue = (0, import_react4.useCallback)((value) => {
529
1037
  setLocalSelected((prev) => {
530
1038
  const next = new Set(prev);
531
1039
  if (next.has(value)) {
@@ -536,7 +1044,7 @@ function ColumnFilter({
536
1044
  return next;
537
1045
  });
538
1046
  }, []);
539
- const selectAll = (0, import_react3.useCallback)(() => {
1047
+ const selectAll = (0, import_react4.useCallback)(() => {
540
1048
  setLocalSelected((prev) => {
541
1049
  const next = new Set(prev);
542
1050
  for (const value of allValues) {
@@ -545,10 +1053,10 @@ function ColumnFilter({
545
1053
  return next;
546
1054
  });
547
1055
  }, [allValues]);
548
- const clearAll = (0, import_react3.useCallback)(() => {
1056
+ const clearAll = (0, import_react4.useCallback)(() => {
549
1057
  setLocalSelected(/* @__PURE__ */ new Set());
550
1058
  }, []);
551
- const applyFilter = (0, import_react3.useCallback)(() => {
1059
+ const applyFilter = (0, import_react4.useCallback)(() => {
552
1060
  if (localSelected.size === 0) {
553
1061
  onFilter([]);
554
1062
  } else {
@@ -556,30 +1064,30 @@ function ColumnFilter({
556
1064
  }
557
1065
  onClose();
558
1066
  }, [localSelected, onFilter, onClose]);
559
- const sortAscending = (0, import_react3.useCallback)(() => {
1067
+ const sortAscending = (0, import_react4.useCallback)(() => {
560
1068
  onSort(sortDirection === "asc" ? null : "asc");
561
1069
  }, [sortDirection, onSort]);
562
- const sortDescending = (0, import_react3.useCallback)(() => {
1070
+ const sortDescending = (0, import_react4.useCallback)(() => {
563
1071
  onSort(sortDirection === "desc" ? null : "desc");
564
1072
  }, [sortDirection, onSort]);
565
- const clearFilter = (0, import_react3.useCallback)(() => {
1073
+ const clearFilter = (0, import_react4.useCallback)(() => {
566
1074
  setLocalSelected(/* @__PURE__ */ new Set());
567
1075
  onFilter([]);
568
1076
  onClose();
569
1077
  }, [onFilter, onClose]);
570
- const handleRangeChange = (0, import_react3.useCallback)((range) => {
1078
+ const handleRangeChange = (0, import_react4.useCallback)((range) => {
571
1079
  setLocalRange(range);
572
1080
  }, []);
573
- const applyRangeFilter = (0, import_react3.useCallback)(() => {
1081
+ const applyRangeFilter = (0, import_react4.useCallback)(() => {
574
1082
  onRangeFilter?.(localRange);
575
1083
  onClose();
576
1084
  }, [localRange, onRangeFilter, onClose]);
577
- const clearRangeFilter = (0, import_react3.useCallback)(() => {
1085
+ const clearRangeFilter = (0, import_react4.useCallback)(() => {
578
1086
  setLocalRange(null);
579
1087
  onRangeFilter?.(null);
580
1088
  onClose();
581
1089
  }, [onRangeFilter, onClose]);
582
- (0, import_react3.useEffect)(() => {
1090
+ (0, import_react4.useEffect)(() => {
583
1091
  const handleClickOutside = (event) => {
584
1092
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
585
1093
  onClose();
@@ -588,7 +1096,7 @@ function ColumnFilter({
588
1096
  document.addEventListener("mousedown", handleClickOutside);
589
1097
  return () => document.removeEventListener("mousedown", handleClickOutside);
590
1098
  }, [onClose]);
591
- (0, import_react3.useEffect)(() => {
1099
+ (0, import_react4.useEffect)(() => {
592
1100
  const handleKeydown = (event) => {
593
1101
  if (event.key === "Escape") {
594
1102
  onClose();
@@ -599,36 +1107,36 @@ function ColumnFilter({
599
1107
  document.addEventListener("keydown", handleKeydown);
600
1108
  return () => document.removeEventListener("keydown", handleKeydown);
601
1109
  }, [onClose, applyFilter]);
602
- (0, import_react3.useEffect)(() => {
1110
+ (0, import_react4.useEffect)(() => {
603
1111
  searchInputRef.current?.focus();
604
1112
  }, []);
605
- (0, import_react3.useEffect)(() => {
1113
+ (0, import_react4.useEffect)(() => {
606
1114
  setLocalSelected(new Set(selectedValues));
607
1115
  }, [selectedValues]);
608
- (0, import_react3.useEffect)(() => {
1116
+ (0, import_react4.useEffect)(() => {
609
1117
  setLocalRange(numericRange ?? null);
610
1118
  if (numericRange) {
611
1119
  setFilterMode("range");
612
1120
  }
613
1121
  }, [numericRange]);
614
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { ref: dropdownRef, className: "vpg-filter-dropdown", children: [
615
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-filter-header", children: [
616
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "vpg-filter-title", children: columnName }),
617
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "vpg-filter-count", children: [
1122
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { ref: dropdownRef, className: "vpg-filter-dropdown", children: [
1123
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-filter-header", children: [
1124
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-filter-title", children: columnName }),
1125
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "vpg-filter-count", children: [
618
1126
  stats.uniqueValues.length.toLocaleString(),
619
1127
  " ",
620
1128
  "unique"
621
1129
  ] })
622
1130
  ] }),
623
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-sort-controls", children: [
624
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1131
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-sort-controls", children: [
1132
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
625
1133
  "button",
626
1134
  {
627
1135
  className: `vpg-sort-btn ${sortDirection === "asc" ? "active" : ""}`,
628
1136
  title: isNumericColumn ? "Sort Low to High" : "Sort A to Z",
629
1137
  onClick: sortAscending,
630
1138
  children: [
631
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1139
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
632
1140
  "path",
633
1141
  {
634
1142
  strokeLinecap: "round",
@@ -637,18 +1145,18 @@ function ColumnFilter({
637
1145
  d: "M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12"
638
1146
  }
639
1147
  ) }),
640
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: isNumericColumn ? "1\u21929" : "A\u2192Z" })
1148
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: isNumericColumn ? "1\u21929" : "A\u2192Z" })
641
1149
  ]
642
1150
  }
643
1151
  ),
644
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1152
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
645
1153
  "button",
646
1154
  {
647
1155
  className: `vpg-sort-btn ${sortDirection === "desc" ? "active" : ""}`,
648
1156
  title: isNumericColumn ? "Sort High to Low" : "Sort Z to A",
649
1157
  onClick: sortDescending,
650
1158
  children: [
651
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1159
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
652
1160
  "path",
653
1161
  {
654
1162
  strokeLinecap: "round",
@@ -657,20 +1165,20 @@ function ColumnFilter({
657
1165
  d: "M3 4h13M3 8h9m-9 4h9m5-4v12m0 0l-4-4m4 4l4-4"
658
1166
  }
659
1167
  ) }),
660
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: isNumericColumn ? "9\u21921" : "Z\u2192A" })
1168
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: isNumericColumn ? "9\u21921" : "Z\u2192A" })
661
1169
  ]
662
1170
  }
663
1171
  )
664
1172
  ] }),
665
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "vpg-divider" }),
666
- isNumericColumn && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-filter-tabs", children: [
667
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1173
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-divider" }),
1174
+ isNumericColumn && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-filter-tabs", children: [
1175
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
668
1176
  "button",
669
1177
  {
670
1178
  className: `vpg-tab-btn ${filterMode === "values" ? "active" : ""}`,
671
1179
  onClick: () => setFilterMode("values"),
672
1180
  children: [
673
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1181
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
674
1182
  "path",
675
1183
  {
676
1184
  strokeLinecap: "round",
@@ -683,13 +1191,13 @@ function ColumnFilter({
683
1191
  ]
684
1192
  }
685
1193
  ),
686
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1194
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
687
1195
  "button",
688
1196
  {
689
1197
  className: `vpg-tab-btn ${filterMode === "range" ? "active" : ""}`,
690
1198
  onClick: () => setFilterMode("range"),
691
1199
  children: [
692
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1200
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
693
1201
  "path",
694
1202
  {
695
1203
  strokeLinecap: "round",
@@ -703,9 +1211,9 @@ function ColumnFilter({
703
1211
  }
704
1212
  )
705
1213
  ] }),
706
- (!isNumericColumn || filterMode === "values") && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
707
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-search-container", children: [
708
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1214
+ (!isNumericColumn || filterMode === "values") && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1215
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-search-container", children: [
1216
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
709
1217
  "path",
710
1218
  {
711
1219
  strokeLinecap: "round",
@@ -714,7 +1222,7 @@ function ColumnFilter({
714
1222
  d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
715
1223
  }
716
1224
  ) }),
717
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1225
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
718
1226
  "input",
719
1227
  {
720
1228
  ref: searchInputRef,
@@ -725,11 +1233,11 @@ function ColumnFilter({
725
1233
  className: "vpg-search-input"
726
1234
  }
727
1235
  ),
728
- searchQuery && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "vpg-clear-search", onClick: () => setSearchQuery(""), children: "\xD7" })
1236
+ searchQuery && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: "vpg-clear-search", onClick: () => setSearchQuery(""), children: "\xD7" })
729
1237
  ] }),
730
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-bulk-actions", children: [
731
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { className: "vpg-bulk-btn", onClick: selectAll, children: [
732
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1238
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-bulk-actions", children: [
1239
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { className: "vpg-bulk-btn", onClick: selectAll, children: [
1240
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
733
1241
  "path",
734
1242
  {
735
1243
  strokeLinecap: "round",
@@ -740,8 +1248,8 @@ function ColumnFilter({
740
1248
  ) }),
741
1249
  "Select All"
742
1250
  ] }),
743
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { className: "vpg-bulk-btn", onClick: clearAll, children: [
744
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1251
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { className: "vpg-bulk-btn", onClick: clearAll, children: [
1252
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
745
1253
  "path",
746
1254
  {
747
1255
  strokeLinecap: "round",
@@ -753,13 +1261,13 @@ function ColumnFilter({
753
1261
  "Clear All"
754
1262
  ] })
755
1263
  ] }),
756
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-values-list", children: [
757
- allValues.map((value) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1264
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-values-list", children: [
1265
+ allValues.map((value) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
758
1266
  "label",
759
1267
  {
760
1268
  className: `vpg-value-item ${localSelected.has(value) ? "selected" : ""}`,
761
1269
  children: [
762
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1270
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
763
1271
  "input",
764
1272
  {
765
1273
  type: "checkbox",
@@ -768,20 +1276,20 @@ function ColumnFilter({
768
1276
  className: "vpg-value-checkbox"
769
1277
  }
770
1278
  ),
771
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: `vpg-value-text ${value === "(blank)" ? "vpg-blank" : ""}`, children: value })
1279
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: `vpg-value-text ${value === "(blank)" ? "vpg-blank" : ""}`, children: value })
772
1280
  ]
773
1281
  },
774
1282
  value
775
1283
  )),
776
- allValues.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "vpg-no-results", children: "No matching values" })
1284
+ allValues.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-no-results", children: "No matching values" })
777
1285
  ] }),
778
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-filter-footer", children: [
779
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "vpg-btn-clear", onClick: clearFilter, children: "Clear Filter" }),
780
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "vpg-btn-apply", onClick: applyFilter, children: "Apply" })
1286
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-filter-footer", children: [
1287
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: "vpg-btn-clear", onClick: clearFilter, children: "Clear Filter" }),
1288
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: "vpg-btn-apply", onClick: applyFilter, children: "Apply" })
781
1289
  ] })
782
1290
  ] }),
783
- isNumericColumn && filterMode === "range" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
784
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1291
+ isNumericColumn && filterMode === "range" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1292
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
785
1293
  NumericRangeFilter,
786
1294
  {
787
1295
  dataMin: stats.numericMin,
@@ -790,26 +1298,26 @@ function ColumnFilter({
790
1298
  onChange: handleRangeChange
791
1299
  }
792
1300
  ),
793
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "vpg-filter-footer", children: [
794
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "vpg-btn-clear", onClick: clearRangeFilter, children: "Clear Filter" }),
795
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "vpg-btn-apply", onClick: applyRangeFilter, children: "Apply" })
1301
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-filter-footer", children: [
1302
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: "vpg-btn-clear", onClick: clearRangeFilter, children: "Clear Filter" }),
1303
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: "vpg-btn-apply", onClick: applyRangeFilter, children: "Apply" })
796
1304
  ] })
797
1305
  ] })
798
1306
  ] });
799
1307
  }
800
1308
 
801
1309
  // src/components/DataGrid.tsx
802
- var import_react10 = require("react");
1310
+ var import_react11 = require("react");
803
1311
  var import_react_dom2 = require("react-dom");
804
1312
 
805
1313
  // src/hooks/useExcelGrid.ts
806
- var import_tinypivot_core2 = require("@smallwebco/tinypivot-core");
1314
+ var import_tinypivot_core3 = require("@smallwebco/tinypivot-core");
807
1315
  var import_react_table = require("@tanstack/react-table");
808
- var import_react4 = require("react");
1316
+ var import_react5 = require("react");
809
1317
  var multiSelectFilter = (row, columnId, filterValue) => {
810
1318
  if (!filterValue)
811
1319
  return true;
812
- if ((0, import_tinypivot_core2.isNumericRange)(filterValue)) {
1320
+ if ((0, import_tinypivot_core3.isNumericRange)(filterValue)) {
813
1321
  const cellValue = row.getValue(columnId);
814
1322
  if (cellValue === null || cellValue === void 0 || cellValue === "") {
815
1323
  return false;
@@ -833,25 +1341,25 @@ var multiSelectFilter = (row, columnId, filterValue) => {
833
1341
  };
834
1342
  function useExcelGrid(options) {
835
1343
  const { data, enableSorting = true, enableFiltering = true } = options;
836
- const [sorting, setSorting] = (0, import_react4.useState)([]);
837
- const [columnFilters, setColumnFilters] = (0, import_react4.useState)([]);
838
- const [columnVisibility, setColumnVisibility] = (0, import_react4.useState)({});
839
- const [globalFilter, setGlobalFilter] = (0, import_react4.useState)("");
840
- const [columnStatsCache, setColumnStatsCache] = (0, import_react4.useState)({});
841
- const dataSignature = (0, import_react4.useMemo)(
1344
+ const [sorting, setSorting] = (0, import_react5.useState)([]);
1345
+ const [columnFilters, setColumnFilters] = (0, import_react5.useState)([]);
1346
+ const [columnVisibility, setColumnVisibility] = (0, import_react5.useState)({});
1347
+ const [globalFilter, setGlobalFilter] = (0, import_react5.useState)("");
1348
+ const [columnStatsCache, setColumnStatsCache] = (0, import_react5.useState)({});
1349
+ const dataSignature = (0, import_react5.useMemo)(
842
1350
  () => `${Date.now()}-${Math.random().toString(36).slice(2)}`,
843
1351
  [data]
844
1352
  );
845
- const columnKeys = (0, import_react4.useMemo)(() => {
1353
+ const columnKeys = (0, import_react5.useMemo)(() => {
846
1354
  if (data.length === 0)
847
1355
  return [];
848
1356
  return Object.keys(data[0]);
849
1357
  }, [data]);
850
- const getColumnStats = (0, import_react4.useCallback)(
1358
+ const getColumnStats = (0, import_react5.useCallback)(
851
1359
  (columnKey) => {
852
1360
  const cacheKey = `${columnKey}-${dataSignature}`;
853
1361
  if (!columnStatsCache[cacheKey]) {
854
- const stats = (0, import_tinypivot_core2.getColumnUniqueValues)(data, columnKey);
1362
+ const stats = (0, import_tinypivot_core3.getColumnUniqueValues)(data, columnKey);
855
1363
  setColumnStatsCache((prev) => ({ ...prev, [cacheKey]: stats }));
856
1364
  return stats;
857
1365
  }
@@ -859,20 +1367,20 @@ function useExcelGrid(options) {
859
1367
  },
860
1368
  [data, columnStatsCache, dataSignature]
861
1369
  );
862
- const clearStatsCache = (0, import_react4.useCallback)(() => {
1370
+ const clearStatsCache = (0, import_react5.useCallback)(() => {
863
1371
  setColumnStatsCache({});
864
1372
  }, []);
865
- (0, import_react4.useEffect)(() => {
1373
+ (0, import_react5.useEffect)(() => {
866
1374
  clearStatsCache();
867
1375
  }, [dataSignature, clearStatsCache]);
868
- const columnDefs = (0, import_react4.useMemo)(() => {
1376
+ const columnDefs = (0, import_react5.useMemo)(() => {
869
1377
  return columnKeys.map((key) => {
870
1378
  const stats = getColumnStats(key);
871
1379
  return {
872
1380
  id: key,
873
1381
  accessorKey: key,
874
1382
  header: key,
875
- cell: (info) => (0, import_tinypivot_core2.formatCellValue)(info.getValue(), stats.type),
1383
+ cell: (info) => (0, import_tinypivot_core3.formatCellValue)(info.getValue(), stats.type),
876
1384
  filterFn: multiSelectFilter,
877
1385
  meta: {
878
1386
  type: stats.type,
@@ -905,10 +1413,10 @@ function useExcelGrid(options) {
905
1413
  });
906
1414
  const filteredRowCount = table.getFilteredRowModel().rows.length;
907
1415
  const totalRowCount = data.length;
908
- const activeFilters = (0, import_react4.useMemo)(() => {
1416
+ const activeFilters = (0, import_react5.useMemo)(() => {
909
1417
  return columnFilters.map((f) => {
910
1418
  const filterValue = f.value;
911
- if (filterValue && (0, import_tinypivot_core2.isNumericRange)(filterValue)) {
1419
+ if (filterValue && (0, import_tinypivot_core3.isNumericRange)(filterValue)) {
912
1420
  return {
913
1421
  column: f.id,
914
1422
  type: "range",
@@ -924,7 +1432,7 @@ function useExcelGrid(options) {
924
1432
  };
925
1433
  });
926
1434
  }, [columnFilters]);
927
- const hasActiveFilter = (0, import_react4.useCallback)(
1435
+ const hasActiveFilter = (0, import_react5.useCallback)(
928
1436
  (columnId) => {
929
1437
  const column = table.getColumn(columnId);
930
1438
  if (!column)
@@ -932,14 +1440,14 @@ function useExcelGrid(options) {
932
1440
  const filterValue = column.getFilterValue();
933
1441
  if (!filterValue)
934
1442
  return false;
935
- if ((0, import_tinypivot_core2.isNumericRange)(filterValue)) {
1443
+ if ((0, import_tinypivot_core3.isNumericRange)(filterValue)) {
936
1444
  return filterValue.min !== null || filterValue.max !== null;
937
1445
  }
938
1446
  return Array.isArray(filterValue) && filterValue.length > 0;
939
1447
  },
940
1448
  [table]
941
1449
  );
942
- const setColumnFilter = (0, import_react4.useCallback)(
1450
+ const setColumnFilter = (0, import_react5.useCallback)(
943
1451
  (columnId, values) => {
944
1452
  const column = table.getColumn(columnId);
945
1453
  if (column) {
@@ -948,7 +1456,7 @@ function useExcelGrid(options) {
948
1456
  },
949
1457
  [table]
950
1458
  );
951
- const setNumericRangeFilter = (0, import_react4.useCallback)(
1459
+ const setNumericRangeFilter = (0, import_react5.useCallback)(
952
1460
  (columnId, range) => {
953
1461
  const column = table.getColumn(columnId);
954
1462
  if (column) {
@@ -961,25 +1469,25 @@ function useExcelGrid(options) {
961
1469
  },
962
1470
  [table]
963
1471
  );
964
- const getNumericRangeFilter = (0, import_react4.useCallback)(
1472
+ const getNumericRangeFilter = (0, import_react5.useCallback)(
965
1473
  (columnId) => {
966
1474
  const column = table.getColumn(columnId);
967
1475
  if (!column)
968
1476
  return null;
969
1477
  const filterValue = column.getFilterValue();
970
- if (filterValue && (0, import_tinypivot_core2.isNumericRange)(filterValue)) {
1478
+ if (filterValue && (0, import_tinypivot_core3.isNumericRange)(filterValue)) {
971
1479
  return filterValue;
972
1480
  }
973
1481
  return null;
974
1482
  },
975
1483
  [table]
976
1484
  );
977
- const clearAllFilters = (0, import_react4.useCallback)(() => {
1485
+ const clearAllFilters = (0, import_react5.useCallback)(() => {
978
1486
  table.resetColumnFilters();
979
1487
  setGlobalFilter("");
980
1488
  setColumnFilters([]);
981
1489
  }, [table]);
982
- const getColumnFilterValues = (0, import_react4.useCallback)(
1490
+ const getColumnFilterValues = (0, import_react5.useCallback)(
983
1491
  (columnId) => {
984
1492
  const column = table.getColumn(columnId);
985
1493
  if (!column)
@@ -989,7 +1497,7 @@ function useExcelGrid(options) {
989
1497
  },
990
1498
  [table]
991
1499
  );
992
- const toggleSort = (0, import_react4.useCallback)((columnId) => {
1500
+ const toggleSort = (0, import_react5.useCallback)((columnId) => {
993
1501
  setSorting((prev) => {
994
1502
  const current = prev.find((s) => s.id === columnId);
995
1503
  if (!current) {
@@ -1001,7 +1509,7 @@ function useExcelGrid(options) {
1001
1509
  }
1002
1510
  });
1003
1511
  }, []);
1004
- const getSortDirection = (0, import_react4.useCallback)(
1512
+ const getSortDirection = (0, import_react5.useCallback)(
1005
1513
  (columnId) => {
1006
1514
  const sort = sorting.find((s) => s.id === columnId);
1007
1515
  if (!sort)
@@ -1042,60 +1550,60 @@ function useExcelGrid(options) {
1042
1550
  }
1043
1551
 
1044
1552
  // src/hooks/useGridFeatures.ts
1045
- var import_tinypivot_core3 = require("@smallwebco/tinypivot-core");
1046
- var import_react5 = require("react");
1553
+ var import_tinypivot_core4 = require("@smallwebco/tinypivot-core");
1554
+ var import_react6 = require("react");
1047
1555
  function exportToCSV(data, columns, options) {
1048
- (0, import_tinypivot_core3.exportToCSV)(data, columns, options);
1556
+ (0, import_tinypivot_core4.exportToCSV)(data, columns, options);
1049
1557
  }
1050
1558
  function exportPivotToCSV(pivotData, rowFields, columnFields, valueFields, options) {
1051
- (0, import_tinypivot_core3.exportPivotToCSV)(pivotData, rowFields, columnFields, valueFields, options);
1559
+ (0, import_tinypivot_core4.exportPivotToCSV)(pivotData, rowFields, columnFields, valueFields, options);
1052
1560
  }
1053
1561
  function copyToClipboard(text, onSuccess, onError) {
1054
- (0, import_tinypivot_core3.copyToClipboard)(text, onSuccess, onError);
1562
+ (0, import_tinypivot_core4.copyToClipboard)(text, onSuccess, onError);
1055
1563
  }
1056
1564
  function formatSelectionForClipboard(rows, columns, selectionBounds) {
1057
- return (0, import_tinypivot_core3.formatSelectionForClipboard)(rows, columns, selectionBounds);
1565
+ return (0, import_tinypivot_core4.formatSelectionForClipboard)(rows, columns, selectionBounds);
1058
1566
  }
1059
1567
  function usePagination(data, options = {}) {
1060
- const [pageSize, setPageSize] = (0, import_react5.useState)(options.pageSize ?? 50);
1061
- const [currentPage, setCurrentPage] = (0, import_react5.useState)(options.currentPage ?? 1);
1062
- const totalPages = (0, import_react5.useMemo)(
1568
+ const [pageSize, setPageSize] = (0, import_react6.useState)(options.pageSize ?? 50);
1569
+ const [currentPage, setCurrentPage] = (0, import_react6.useState)(options.currentPage ?? 1);
1570
+ const totalPages = (0, import_react6.useMemo)(
1063
1571
  () => Math.max(1, Math.ceil(data.length / pageSize)),
1064
1572
  [data.length, pageSize]
1065
1573
  );
1066
- const paginatedData = (0, import_react5.useMemo)(() => {
1574
+ const paginatedData = (0, import_react6.useMemo)(() => {
1067
1575
  const start = (currentPage - 1) * pageSize;
1068
1576
  const end = start + pageSize;
1069
1577
  return data.slice(start, end);
1070
1578
  }, [data, currentPage, pageSize]);
1071
- const startIndex = (0, import_react5.useMemo)(() => (currentPage - 1) * pageSize + 1, [currentPage, pageSize]);
1072
- const endIndex = (0, import_react5.useMemo)(
1579
+ const startIndex = (0, import_react6.useMemo)(() => (currentPage - 1) * pageSize + 1, [currentPage, pageSize]);
1580
+ const endIndex = (0, import_react6.useMemo)(
1073
1581
  () => Math.min(currentPage * pageSize, data.length),
1074
1582
  [currentPage, pageSize, data.length]
1075
1583
  );
1076
- const goToPage = (0, import_react5.useCallback)(
1584
+ const goToPage = (0, import_react6.useCallback)(
1077
1585
  (page) => {
1078
1586
  setCurrentPage(Math.max(1, Math.min(page, totalPages)));
1079
1587
  },
1080
1588
  [totalPages]
1081
1589
  );
1082
- const nextPage = (0, import_react5.useCallback)(() => {
1590
+ const nextPage = (0, import_react6.useCallback)(() => {
1083
1591
  if (currentPage < totalPages) {
1084
1592
  setCurrentPage((prev) => prev + 1);
1085
1593
  }
1086
1594
  }, [currentPage, totalPages]);
1087
- const prevPage = (0, import_react5.useCallback)(() => {
1595
+ const prevPage = (0, import_react6.useCallback)(() => {
1088
1596
  if (currentPage > 1) {
1089
1597
  setCurrentPage((prev) => prev - 1);
1090
1598
  }
1091
1599
  }, [currentPage]);
1092
- const firstPage = (0, import_react5.useCallback)(() => {
1600
+ const firstPage = (0, import_react6.useCallback)(() => {
1093
1601
  setCurrentPage(1);
1094
1602
  }, []);
1095
- const lastPage = (0, import_react5.useCallback)(() => {
1603
+ const lastPage = (0, import_react6.useCallback)(() => {
1096
1604
  setCurrentPage(totalPages);
1097
1605
  }, [totalPages]);
1098
- const updatePageSize = (0, import_react5.useCallback)((size) => {
1606
+ const updatePageSize = (0, import_react6.useCallback)((size) => {
1099
1607
  setPageSize(size);
1100
1608
  setCurrentPage(1);
1101
1609
  }, []);
@@ -1115,9 +1623,9 @@ function usePagination(data, options = {}) {
1115
1623
  };
1116
1624
  }
1117
1625
  function useGlobalSearch(data, columns) {
1118
- const [searchTerm, setSearchTerm] = (0, import_react5.useState)("");
1119
- const [caseSensitive, setCaseSensitive] = (0, import_react5.useState)(false);
1120
- const filteredData = (0, import_react5.useMemo)(() => {
1626
+ const [searchTerm, setSearchTerm] = (0, import_react6.useState)("");
1627
+ const [caseSensitive, setCaseSensitive] = (0, import_react6.useState)(false);
1628
+ const filteredData = (0, import_react6.useMemo)(() => {
1121
1629
  if (!searchTerm.trim()) {
1122
1630
  return data;
1123
1631
  }
@@ -1135,7 +1643,7 @@ function useGlobalSearch(data, columns) {
1135
1643
  return false;
1136
1644
  });
1137
1645
  }, [data, columns, searchTerm, caseSensitive]);
1138
- const clearSearch = (0, import_react5.useCallback)(() => {
1646
+ const clearSearch = (0, import_react6.useCallback)(() => {
1139
1647
  setSearchTerm("");
1140
1648
  }, []);
1141
1649
  return {
@@ -1148,17 +1656,17 @@ function useGlobalSearch(data, columns) {
1148
1656
  };
1149
1657
  }
1150
1658
  function useRowSelection(data) {
1151
- const [selectedRowIndices, setSelectedRowIndices] = (0, import_react5.useState)(/* @__PURE__ */ new Set());
1152
- const selectedRows = (0, import_react5.useMemo)(() => {
1659
+ const [selectedRowIndices, setSelectedRowIndices] = (0, import_react6.useState)(/* @__PURE__ */ new Set());
1660
+ const selectedRows = (0, import_react6.useMemo)(() => {
1153
1661
  return Array.from(selectedRowIndices).sort((a, b) => a - b).map((idx) => data[idx]).filter(Boolean);
1154
1662
  }, [data, selectedRowIndices]);
1155
- const allSelected = (0, import_react5.useMemo)(() => {
1663
+ const allSelected = (0, import_react6.useMemo)(() => {
1156
1664
  return data.length > 0 && selectedRowIndices.size === data.length;
1157
1665
  }, [data.length, selectedRowIndices.size]);
1158
- const someSelected = (0, import_react5.useMemo)(() => {
1666
+ const someSelected = (0, import_react6.useMemo)(() => {
1159
1667
  return selectedRowIndices.size > 0 && selectedRowIndices.size < data.length;
1160
1668
  }, [data.length, selectedRowIndices.size]);
1161
- const toggleRow = (0, import_react5.useCallback)((index) => {
1669
+ const toggleRow = (0, import_react6.useCallback)((index) => {
1162
1670
  setSelectedRowIndices((prev) => {
1163
1671
  const next = new Set(prev);
1164
1672
  if (next.has(index)) {
@@ -1169,36 +1677,36 @@ function useRowSelection(data) {
1169
1677
  return next;
1170
1678
  });
1171
1679
  }, []);
1172
- const selectRow = (0, import_react5.useCallback)((index) => {
1680
+ const selectRow = (0, import_react6.useCallback)((index) => {
1173
1681
  setSelectedRowIndices((prev) => /* @__PURE__ */ new Set([...prev, index]));
1174
1682
  }, []);
1175
- const deselectRow = (0, import_react5.useCallback)((index) => {
1683
+ const deselectRow = (0, import_react6.useCallback)((index) => {
1176
1684
  setSelectedRowIndices((prev) => {
1177
1685
  const next = new Set(prev);
1178
1686
  next.delete(index);
1179
1687
  return next;
1180
1688
  });
1181
1689
  }, []);
1182
- const selectAll = (0, import_react5.useCallback)(() => {
1690
+ const selectAll = (0, import_react6.useCallback)(() => {
1183
1691
  setSelectedRowIndices(new Set(data.map((_, idx) => idx)));
1184
1692
  }, [data]);
1185
- const deselectAll = (0, import_react5.useCallback)(() => {
1693
+ const deselectAll = (0, import_react6.useCallback)(() => {
1186
1694
  setSelectedRowIndices(/* @__PURE__ */ new Set());
1187
1695
  }, []);
1188
- const toggleAll = (0, import_react5.useCallback)(() => {
1696
+ const toggleAll = (0, import_react6.useCallback)(() => {
1189
1697
  if (allSelected) {
1190
1698
  deselectAll();
1191
1699
  } else {
1192
1700
  selectAll();
1193
1701
  }
1194
1702
  }, [allSelected, selectAll, deselectAll]);
1195
- const isSelected = (0, import_react5.useCallback)(
1703
+ const isSelected = (0, import_react6.useCallback)(
1196
1704
  (index) => {
1197
1705
  return selectedRowIndices.has(index);
1198
1706
  },
1199
1707
  [selectedRowIndices]
1200
1708
  );
1201
- const selectRange = (0, import_react5.useCallback)((startIndex, endIndex) => {
1709
+ const selectRange = (0, import_react6.useCallback)((startIndex, endIndex) => {
1202
1710
  const min = Math.min(startIndex, endIndex);
1203
1711
  const max = Math.max(startIndex, endIndex);
1204
1712
  setSelectedRowIndices((prev) => {
@@ -1225,10 +1733,10 @@ function useRowSelection(data) {
1225
1733
  };
1226
1734
  }
1227
1735
  function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
1228
- const [columnWidths, setColumnWidths] = (0, import_react5.useState)({ ...initialWidths });
1229
- const [isResizing, setIsResizing] = (0, import_react5.useState)(false);
1230
- const [resizingColumn, setResizingColumn] = (0, import_react5.useState)(null);
1231
- const startResize = (0, import_react5.useCallback)(
1736
+ const [columnWidths, setColumnWidths] = (0, import_react6.useState)({ ...initialWidths });
1737
+ const [isResizing, setIsResizing] = (0, import_react6.useState)(false);
1738
+ const [resizingColumn, setResizingColumn] = (0, import_react6.useState)(null);
1739
+ const startResize = (0, import_react6.useCallback)(
1232
1740
  (columnId, event) => {
1233
1741
  setIsResizing(true);
1234
1742
  setResizingColumn(columnId);
@@ -1253,7 +1761,7 @@ function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
1253
1761
  },
1254
1762
  [columnWidths, minWidth, maxWidth]
1255
1763
  );
1256
- const resetColumnWidth = (0, import_react5.useCallback)(
1764
+ const resetColumnWidth = (0, import_react6.useCallback)(
1257
1765
  (columnId) => {
1258
1766
  if (initialWidths[columnId]) {
1259
1767
  setColumnWidths((prev) => ({
@@ -1264,7 +1772,7 @@ function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
1264
1772
  },
1265
1773
  [initialWidths]
1266
1774
  );
1267
- const resetAllWidths = (0, import_react5.useCallback)(() => {
1775
+ const resetAllWidths = (0, import_react6.useCallback)(() => {
1268
1776
  setColumnWidths({ ...initialWidths });
1269
1777
  }, [initialWidths]);
1270
1778
  return {
@@ -1279,16 +1787,16 @@ function useColumnResize(initialWidths, minWidth = 60, maxWidth = 600) {
1279
1787
  }
1280
1788
 
1281
1789
  // src/hooks/useLicense.ts
1282
- var import_tinypivot_core4 = require("@smallwebco/tinypivot-core");
1283
- var import_react6 = require("react");
1284
- var globalLicenseInfo = (0, import_tinypivot_core4.getFreeLicenseInfo)();
1790
+ var import_tinypivot_core5 = require("@smallwebco/tinypivot-core");
1791
+ var import_react7 = require("react");
1792
+ var globalLicenseInfo = (0, import_tinypivot_core5.getFreeLicenseInfo)();
1285
1793
  var globalDemoMode = false;
1286
1794
  var listeners = /* @__PURE__ */ new Set();
1287
1795
  function notifyListeners() {
1288
1796
  listeners.forEach((listener) => listener());
1289
1797
  }
1290
1798
  async function setLicenseKey(key) {
1291
- globalLicenseInfo = await (0, import_tinypivot_core4.validateLicenseKey)(key);
1799
+ globalLicenseInfo = await (0, import_tinypivot_core5.validateLicenseKey)(key);
1292
1800
  if (!globalLicenseInfo.isValid) {
1293
1801
  console.warn("[TinyPivot] Invalid or expired license key. Running in free mode.");
1294
1802
  } else if (globalLicenseInfo.type !== "free") {
@@ -1297,7 +1805,7 @@ async function setLicenseKey(key) {
1297
1805
  notifyListeners();
1298
1806
  }
1299
1807
  async function enableDemoMode(secret) {
1300
- const demoLicense = await (0, import_tinypivot_core4.getDemoLicenseInfo)(secret);
1808
+ const demoLicense = await (0, import_tinypivot_core5.getDemoLicenseInfo)(secret);
1301
1809
  if (!demoLicense) {
1302
1810
  console.warn("[TinyPivot] Demo mode activation failed - invalid secret");
1303
1811
  return false;
@@ -1309,40 +1817,44 @@ async function enableDemoMode(secret) {
1309
1817
  return true;
1310
1818
  }
1311
1819
  function configureLicenseSecret(secret) {
1312
- (0, import_tinypivot_core4.configureLicenseSecret)(secret);
1820
+ (0, import_tinypivot_core5.configureLicenseSecret)(secret);
1313
1821
  }
1314
1822
  function useLicense() {
1315
- const [, forceUpdate] = (0, import_react6.useState)({});
1316
- (0, import_react6.useState)(() => {
1823
+ const [, forceUpdate] = (0, import_react7.useState)({});
1824
+ (0, import_react7.useState)(() => {
1317
1825
  const update = () => forceUpdate({});
1318
1826
  listeners.add(update);
1319
1827
  return () => listeners.delete(update);
1320
1828
  });
1321
1829
  const isDemo = globalDemoMode;
1322
1830
  const licenseInfo = globalLicenseInfo;
1323
- const isPro = (0, import_react6.useMemo)(
1324
- () => globalDemoMode || (0, import_tinypivot_core4.isPro)(licenseInfo),
1831
+ const isPro = (0, import_react7.useMemo)(
1832
+ () => globalDemoMode || (0, import_tinypivot_core5.isPro)(licenseInfo),
1325
1833
  [licenseInfo]
1326
1834
  );
1327
- const canUsePivot = (0, import_react6.useMemo)(
1328
- () => globalDemoMode || (0, import_tinypivot_core4.canUsePivot)(licenseInfo),
1835
+ const canUsePivot = (0, import_react7.useMemo)(
1836
+ () => globalDemoMode || (0, import_tinypivot_core5.canUsePivot)(licenseInfo),
1329
1837
  [licenseInfo]
1330
1838
  );
1331
- const canUseAdvancedAggregations = (0, import_react6.useMemo)(
1839
+ const canUseAdvancedAggregations = (0, import_react7.useMemo)(
1332
1840
  () => globalDemoMode || licenseInfo.features.advancedAggregations,
1333
1841
  [licenseInfo]
1334
1842
  );
1335
- const canUsePercentageMode = (0, import_react6.useMemo)(
1843
+ const canUsePercentageMode = (0, import_react7.useMemo)(
1336
1844
  () => globalDemoMode || licenseInfo.features.percentageMode,
1337
1845
  [licenseInfo]
1338
1846
  );
1339
- const showWatermark = (0, import_react6.useMemo)(
1340
- () => (0, import_tinypivot_core4.shouldShowWatermark)(licenseInfo, globalDemoMode),
1847
+ const canUseCharts = (0, import_react7.useMemo)(
1848
+ () => globalDemoMode || (0, import_tinypivot_core5.canUseCharts)(licenseInfo),
1341
1849
  [licenseInfo]
1342
1850
  );
1343
- const requirePro = (0, import_react6.useCallback)((feature) => {
1851
+ const showWatermark = (0, import_react7.useMemo)(
1852
+ () => (0, import_tinypivot_core5.shouldShowWatermark)(licenseInfo, globalDemoMode),
1853
+ [licenseInfo]
1854
+ );
1855
+ const requirePro = (0, import_react7.useCallback)((feature) => {
1344
1856
  if (!isPro) {
1345
- (0, import_tinypivot_core4.logProRequired)(feature);
1857
+ (0, import_tinypivot_core5.logProRequired)(feature);
1346
1858
  return false;
1347
1859
  }
1348
1860
  return true;
@@ -1354,31 +1866,32 @@ function useLicense() {
1354
1866
  canUsePivot,
1355
1867
  canUseAdvancedAggregations,
1356
1868
  canUsePercentageMode,
1869
+ canUseCharts,
1357
1870
  showWatermark,
1358
1871
  requirePro
1359
1872
  };
1360
1873
  }
1361
1874
 
1362
1875
  // src/hooks/usePivotTable.ts
1363
- var import_tinypivot_core5 = require("@smallwebco/tinypivot-core");
1364
- var import_react7 = require("react");
1876
+ var import_tinypivot_core6 = require("@smallwebco/tinypivot-core");
1877
+ var import_react8 = require("react");
1365
1878
  function usePivotTable(data) {
1366
1879
  const { canUsePivot, requirePro } = useLicense();
1367
- const [rowFields, setRowFieldsState] = (0, import_react7.useState)([]);
1368
- const [columnFields, setColumnFieldsState] = (0, import_react7.useState)([]);
1369
- const [valueFields, setValueFields] = (0, import_react7.useState)([]);
1370
- const [showRowTotals, setShowRowTotals] = (0, import_react7.useState)(true);
1371
- const [showColumnTotals, setShowColumnTotals] = (0, import_react7.useState)(true);
1372
- const [calculatedFields, setCalculatedFields] = (0, import_react7.useState)(() => (0, import_tinypivot_core5.loadCalculatedFields)());
1373
- const [currentStorageKey, setCurrentStorageKey] = (0, import_react7.useState)(null);
1374
- const availableFields = (0, import_react7.useMemo)(() => {
1375
- return (0, import_tinypivot_core5.computeAvailableFields)(data);
1880
+ const [rowFields, setRowFieldsState] = (0, import_react8.useState)([]);
1881
+ const [columnFields, setColumnFieldsState] = (0, import_react8.useState)([]);
1882
+ const [valueFields, setValueFields] = (0, import_react8.useState)([]);
1883
+ const [showRowTotals, setShowRowTotals] = (0, import_react8.useState)(true);
1884
+ const [showColumnTotals, setShowColumnTotals] = (0, import_react8.useState)(true);
1885
+ const [calculatedFields, setCalculatedFields] = (0, import_react8.useState)(() => (0, import_tinypivot_core6.loadCalculatedFields)());
1886
+ const [currentStorageKey, setCurrentStorageKey] = (0, import_react8.useState)(null);
1887
+ const availableFields = (0, import_react8.useMemo)(() => {
1888
+ return (0, import_tinypivot_core6.computeAvailableFields)(data);
1376
1889
  }, [data]);
1377
- const unassignedFields = (0, import_react7.useMemo)(() => {
1378
- return (0, import_tinypivot_core5.getUnassignedFields)(availableFields, rowFields, columnFields, valueFields);
1890
+ const unassignedFields = (0, import_react8.useMemo)(() => {
1891
+ return (0, import_tinypivot_core6.getUnassignedFields)(availableFields, rowFields, columnFields, valueFields);
1379
1892
  }, [availableFields, rowFields, columnFields, valueFields]);
1380
- const isConfigured = (0, import_react7.useMemo)(() => {
1381
- return (0, import_tinypivot_core5.isPivotConfigured)({
1893
+ const isConfigured = (0, import_react8.useMemo)(() => {
1894
+ return (0, import_tinypivot_core6.isPivotConfigured)({
1382
1895
  rowFields,
1383
1896
  columnFields,
1384
1897
  valueFields,
@@ -1386,12 +1899,12 @@ function usePivotTable(data) {
1386
1899
  showColumnTotals
1387
1900
  });
1388
1901
  }, [rowFields, columnFields, valueFields, showRowTotals, showColumnTotals]);
1389
- const pivotResult = (0, import_react7.useMemo)(() => {
1902
+ const pivotResult = (0, import_react8.useMemo)(() => {
1390
1903
  if (!isConfigured)
1391
1904
  return null;
1392
1905
  if (!canUsePivot)
1393
1906
  return null;
1394
- return (0, import_tinypivot_core5.computePivotResult)(data, {
1907
+ return (0, import_tinypivot_core6.computePivotResult)(data, {
1395
1908
  rowFields,
1396
1909
  columnFields,
1397
1910
  valueFields,
@@ -1400,15 +1913,15 @@ function usePivotTable(data) {
1400
1913
  calculatedFields
1401
1914
  });
1402
1915
  }, [data, isConfigured, canUsePivot, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals, calculatedFields]);
1403
- (0, import_react7.useEffect)(() => {
1916
+ (0, import_react8.useEffect)(() => {
1404
1917
  if (data.length === 0)
1405
1918
  return;
1406
1919
  const newKeys = Object.keys(data[0]);
1407
- const storageKey = (0, import_tinypivot_core5.generateStorageKey)(newKeys);
1920
+ const storageKey = (0, import_tinypivot_core6.generateStorageKey)(newKeys);
1408
1921
  if (storageKey !== currentStorageKey) {
1409
1922
  setCurrentStorageKey(storageKey);
1410
- const savedConfig = (0, import_tinypivot_core5.loadPivotConfig)(storageKey);
1411
- if (savedConfig && (0, import_tinypivot_core5.isConfigValidForFields)(savedConfig, newKeys)) {
1923
+ const savedConfig = (0, import_tinypivot_core6.loadPivotConfig)(storageKey);
1924
+ if (savedConfig && (0, import_tinypivot_core6.isConfigValidForFields)(savedConfig, newKeys)) {
1412
1925
  setRowFieldsState(savedConfig.rowFields);
1413
1926
  setColumnFieldsState(savedConfig.columnFields);
1414
1927
  setValueFields(savedConfig.valueFields);
@@ -1425,7 +1938,7 @@ function usePivotTable(data) {
1425
1938
  showRowTotals,
1426
1939
  showColumnTotals
1427
1940
  };
1428
- if (!(0, import_tinypivot_core5.isConfigValidForFields)(currentConfig, newKeys)) {
1941
+ if (!(0, import_tinypivot_core6.isConfigValidForFields)(currentConfig, newKeys)) {
1429
1942
  setRowFieldsState([]);
1430
1943
  setColumnFieldsState([]);
1431
1944
  setValueFields([]);
@@ -1433,7 +1946,7 @@ function usePivotTable(data) {
1433
1946
  }
1434
1947
  }
1435
1948
  }, [data]);
1436
- (0, import_react7.useEffect)(() => {
1949
+ (0, import_react8.useEffect)(() => {
1437
1950
  if (!currentStorageKey)
1438
1951
  return;
1439
1952
  const config = {
@@ -1444,9 +1957,9 @@ function usePivotTable(data) {
1444
1957
  showColumnTotals,
1445
1958
  calculatedFields
1446
1959
  };
1447
- (0, import_tinypivot_core5.savePivotConfig)(currentStorageKey, config);
1960
+ (0, import_tinypivot_core6.savePivotConfig)(currentStorageKey, config);
1448
1961
  }, [currentStorageKey, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals, calculatedFields]);
1449
- const addRowField = (0, import_react7.useCallback)(
1962
+ const addRowField = (0, import_react8.useCallback)(
1450
1963
  (field) => {
1451
1964
  if (!rowFields.includes(field)) {
1452
1965
  setRowFieldsState((prev) => [...prev, field]);
@@ -1454,13 +1967,13 @@ function usePivotTable(data) {
1454
1967
  },
1455
1968
  [rowFields]
1456
1969
  );
1457
- const removeRowField = (0, import_react7.useCallback)((field) => {
1970
+ const removeRowField = (0, import_react8.useCallback)((field) => {
1458
1971
  setRowFieldsState((prev) => prev.filter((f) => f !== field));
1459
1972
  }, []);
1460
- const setRowFields = (0, import_react7.useCallback)((fields) => {
1973
+ const setRowFields = (0, import_react8.useCallback)((fields) => {
1461
1974
  setRowFieldsState(fields);
1462
1975
  }, []);
1463
- const addColumnField = (0, import_react7.useCallback)(
1976
+ const addColumnField = (0, import_react8.useCallback)(
1464
1977
  (field) => {
1465
1978
  if (!columnFields.includes(field)) {
1466
1979
  setColumnFieldsState((prev) => [...prev, field]);
@@ -1468,13 +1981,13 @@ function usePivotTable(data) {
1468
1981
  },
1469
1982
  [columnFields]
1470
1983
  );
1471
- const removeColumnField = (0, import_react7.useCallback)((field) => {
1984
+ const removeColumnField = (0, import_react8.useCallback)((field) => {
1472
1985
  setColumnFieldsState((prev) => prev.filter((f) => f !== field));
1473
1986
  }, []);
1474
- const setColumnFields = (0, import_react7.useCallback)((fields) => {
1987
+ const setColumnFields = (0, import_react8.useCallback)((fields) => {
1475
1988
  setColumnFieldsState(fields);
1476
1989
  }, []);
1477
- const addValueField = (0, import_react7.useCallback)(
1990
+ const addValueField = (0, import_react8.useCallback)(
1478
1991
  (field, aggregation = "sum") => {
1479
1992
  if (aggregation !== "sum" && !requirePro(`${aggregation} aggregation`)) {
1480
1993
  return;
@@ -1488,7 +2001,7 @@ function usePivotTable(data) {
1488
2001
  },
1489
2002
  [requirePro]
1490
2003
  );
1491
- const removeValueField = (0, import_react7.useCallback)((field, aggregation) => {
2004
+ const removeValueField = (0, import_react8.useCallback)((field, aggregation) => {
1492
2005
  setValueFields((prev) => {
1493
2006
  if (aggregation) {
1494
2007
  return prev.filter((v) => !(v.field === field && v.aggregation === aggregation));
@@ -1496,7 +2009,7 @@ function usePivotTable(data) {
1496
2009
  return prev.filter((v) => v.field !== field);
1497
2010
  });
1498
2011
  }, []);
1499
- const updateValueFieldAggregation = (0, import_react7.useCallback)(
2012
+ const updateValueFieldAggregation = (0, import_react8.useCallback)(
1500
2013
  (field, oldAgg, newAgg) => {
1501
2014
  setValueFields(
1502
2015
  (prev) => prev.map((v) => {
@@ -1509,12 +2022,12 @@ function usePivotTable(data) {
1509
2022
  },
1510
2023
  []
1511
2024
  );
1512
- const clearConfig = (0, import_react7.useCallback)(() => {
2025
+ const clearConfig = (0, import_react8.useCallback)(() => {
1513
2026
  setRowFieldsState([]);
1514
2027
  setColumnFieldsState([]);
1515
2028
  setValueFields([]);
1516
2029
  }, []);
1517
- const autoSuggestConfig = (0, import_react7.useCallback)(() => {
2030
+ const autoSuggestConfig = (0, import_react8.useCallback)(() => {
1518
2031
  if (!requirePro("Pivot Table - Auto Suggest"))
1519
2032
  return;
1520
2033
  if (availableFields.length === 0)
@@ -1526,7 +2039,7 @@ function usePivotTable(data) {
1526
2039
  setValueFields([{ field: numericFields[0].field, aggregation: "sum" }]);
1527
2040
  }
1528
2041
  }, [availableFields, requirePro]);
1529
- const addCalculatedField = (0, import_react7.useCallback)((field) => {
2042
+ const addCalculatedField = (0, import_react8.useCallback)((field) => {
1530
2043
  setCalculatedFields((prev) => {
1531
2044
  const existing = prev.findIndex((f) => f.id === field.id);
1532
2045
  let updated;
@@ -1535,14 +2048,14 @@ function usePivotTable(data) {
1535
2048
  } else {
1536
2049
  updated = [...prev, field];
1537
2050
  }
1538
- (0, import_tinypivot_core5.saveCalculatedFields)(updated);
2051
+ (0, import_tinypivot_core6.saveCalculatedFields)(updated);
1539
2052
  return updated;
1540
2053
  });
1541
2054
  }, []);
1542
- const removeCalculatedField = (0, import_react7.useCallback)((id) => {
2055
+ const removeCalculatedField = (0, import_react8.useCallback)((id) => {
1543
2056
  setCalculatedFields((prev) => {
1544
2057
  const updated = prev.filter((f) => f.id !== id);
1545
- (0, import_tinypivot_core5.saveCalculatedFields)(updated);
2058
+ (0, import_tinypivot_core6.saveCalculatedFields)(updated);
1546
2059
  return updated;
1547
2060
  });
1548
2061
  setValueFields((prev) => prev.filter((v) => v.field !== `calc:${id}`));
@@ -1580,9 +2093,9 @@ function usePivotTable(data) {
1580
2093
  }
1581
2094
 
1582
2095
  // src/components/PivotConfig.tsx
1583
- var import_tinypivot_core6 = require("@smallwebco/tinypivot-core");
1584
- var import_react8 = require("react");
1585
- var import_jsx_runtime4 = require("react/jsx-runtime");
2096
+ var import_tinypivot_core7 = require("@smallwebco/tinypivot-core");
2097
+ var import_react9 = require("react");
2098
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1586
2099
  function aggregationRequiresPro(agg) {
1587
2100
  return agg !== "sum";
1588
2101
  }
@@ -1623,15 +2136,15 @@ function PivotConfig({
1623
2136
  onRemoveCalculatedField,
1624
2137
  onUpdateCalculatedField
1625
2138
  }) {
1626
- const [fieldSearch, setFieldSearch] = (0, import_react8.useState)("");
1627
- const [showCalcModal, setShowCalcModal] = (0, import_react8.useState)(false);
1628
- const [editingCalcField, setEditingCalcField] = (0, import_react8.useState)(null);
2139
+ const [fieldSearch, setFieldSearch] = (0, import_react9.useState)("");
2140
+ const [showCalcModal, setShowCalcModal] = (0, import_react9.useState)(false);
2141
+ const [editingCalcField, setEditingCalcField] = (0, import_react9.useState)(null);
1629
2142
  const { canUseAdvancedAggregations } = useLicense();
1630
- const isAggregationAvailable = (0, import_react8.useCallback)((agg) => {
2143
+ const isAggregationAvailable = (0, import_react9.useCallback)((agg) => {
1631
2144
  return !aggregationRequiresPro(agg) || canUseAdvancedAggregations;
1632
2145
  }, [canUseAdvancedAggregations]);
1633
- const numericFieldNames = (0, import_react8.useMemo)(() => availableFields.filter((f) => f.isNumeric).map((f) => f.field), [availableFields]);
1634
- const calculatedFieldsAsStats = (0, import_react8.useMemo)(() => {
2146
+ const numericFieldNames = (0, import_react9.useMemo)(() => availableFields.filter((f) => f.isNumeric).map((f) => f.field), [availableFields]);
2147
+ const calculatedFieldsAsStats = (0, import_react9.useMemo)(() => {
1635
2148
  if (!calculatedFields)
1636
2149
  return [];
1637
2150
  return calculatedFields.map((calc) => ({
@@ -1645,11 +2158,11 @@ function PivotConfig({
1645
2158
  calcFormula: calc.formula
1646
2159
  }));
1647
2160
  }, [calculatedFields]);
1648
- const allAvailableFields = (0, import_react8.useMemo)(() => [
2161
+ const allAvailableFields = (0, import_react9.useMemo)(() => [
1649
2162
  ...availableFields.map((f) => ({ ...f, isCalculated: false })),
1650
2163
  ...calculatedFieldsAsStats
1651
2164
  ], [availableFields, calculatedFieldsAsStats]);
1652
- const assignedFields = (0, import_react8.useMemo)(() => {
2165
+ const assignedFields = (0, import_react9.useMemo)(() => {
1653
2166
  const rowSet = new Set(rowFields);
1654
2167
  const colSet = new Set(columnFields);
1655
2168
  const valueMap = new Map(valueFields.map((v) => [v.field, v]));
@@ -1659,7 +2172,7 @@ function PivotConfig({
1659
2172
  valueConfig: valueMap.get(f.field)
1660
2173
  }));
1661
2174
  }, [allAvailableFields, rowFields, columnFields, valueFields]);
1662
- const unassignedFields = (0, import_react8.useMemo)(() => {
2175
+ const unassignedFields = (0, import_react9.useMemo)(() => {
1663
2176
  const rowSet = new Set(rowFields);
1664
2177
  const colSet = new Set(columnFields);
1665
2178
  const valSet = new Set(valueFields.map((v) => v.field));
@@ -1667,7 +2180,7 @@ function PivotConfig({
1667
2180
  (f) => !rowSet.has(f.field) && !colSet.has(f.field) && !valSet.has(f.field)
1668
2181
  );
1669
2182
  }, [allAvailableFields, rowFields, columnFields, valueFields]);
1670
- const filteredUnassignedFields = (0, import_react8.useMemo)(() => {
2183
+ const filteredUnassignedFields = (0, import_react9.useMemo)(() => {
1671
2184
  if (!fieldSearch.trim())
1672
2185
  return unassignedFields;
1673
2186
  const search = fieldSearch.toLowerCase().trim();
@@ -1678,13 +2191,13 @@ function PivotConfig({
1678
2191
  });
1679
2192
  }, [unassignedFields, fieldSearch]);
1680
2193
  const assignedCount = assignedFields.length;
1681
- const getFieldDisplayName = (0, import_react8.useCallback)((field) => {
2194
+ const getFieldDisplayName = (0, import_react9.useCallback)((field) => {
1682
2195
  if (field.isCalculated && field.calcName) {
1683
2196
  return field.calcName;
1684
2197
  }
1685
2198
  return field.field;
1686
2199
  }, []);
1687
- const handleDragStart = (0, import_react8.useCallback)(
2200
+ const handleDragStart = (0, import_react9.useCallback)(
1688
2201
  (field, event) => {
1689
2202
  event.dataTransfer?.setData("text/plain", field);
1690
2203
  event.dataTransfer.effectAllowed = "move";
@@ -1692,7 +2205,7 @@ function PivotConfig({
1692
2205
  },
1693
2206
  [onDragStart]
1694
2207
  );
1695
- const handleAggregationChange = (0, import_react8.useCallback)(
2208
+ const handleAggregationChange = (0, import_react9.useCallback)(
1696
2209
  (field, currentAgg, newAgg) => {
1697
2210
  if (!isAggregationAvailable(newAgg)) {
1698
2211
  console.warn(`[TinyPivot] "${newAgg}" aggregation requires a Pro license. Visit https://tiny-pivot.com/#pricing to upgrade.`);
@@ -1702,7 +2215,7 @@ function PivotConfig({
1702
2215
  },
1703
2216
  [onUpdateAggregation, isAggregationAvailable]
1704
2217
  );
1705
- const toggleRowColumn = (0, import_react8.useCallback)(
2218
+ const toggleRowColumn = (0, import_react9.useCallback)(
1706
2219
  (field, currentAssignment) => {
1707
2220
  if (currentAssignment === "row") {
1708
2221
  onRemoveRowField(field);
@@ -1714,7 +2227,7 @@ function PivotConfig({
1714
2227
  },
1715
2228
  [onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddRowField]
1716
2229
  );
1717
- const removeField = (0, import_react8.useCallback)(
2230
+ const removeField = (0, import_react9.useCallback)(
1718
2231
  (field, assignedTo, valueConfig) => {
1719
2232
  if (assignedTo === "row") {
1720
2233
  onRemoveRowField(field);
@@ -1726,15 +2239,15 @@ function PivotConfig({
1726
2239
  },
1727
2240
  [onRemoveRowField, onRemoveColumnField, onRemoveValueField]
1728
2241
  );
1729
- const handleTotalsToggle = (0, import_react8.useCallback)((checked) => {
2242
+ const handleTotalsToggle = (0, import_react9.useCallback)((checked) => {
1730
2243
  onShowRowTotalsChange(checked);
1731
2244
  onShowColumnTotalsChange(checked);
1732
2245
  }, [onShowRowTotalsChange, onShowColumnTotalsChange]);
1733
- const openCalcModal = (0, import_react8.useCallback)((field) => {
2246
+ const openCalcModal = (0, import_react9.useCallback)((field) => {
1734
2247
  setEditingCalcField(field || null);
1735
2248
  setShowCalcModal(true);
1736
2249
  }, []);
1737
- const handleSaveCalcField = (0, import_react8.useCallback)((field) => {
2250
+ const handleSaveCalcField = (0, import_react9.useCallback)((field) => {
1738
2251
  if (editingCalcField && onUpdateCalculatedField) {
1739
2252
  onUpdateCalculatedField(field);
1740
2253
  } else if (onAddCalculatedField) {
@@ -1743,14 +2256,14 @@ function PivotConfig({
1743
2256
  setShowCalcModal(false);
1744
2257
  setEditingCalcField(null);
1745
2258
  }, [editingCalcField, onAddCalculatedField, onUpdateCalculatedField]);
1746
- const handleCloseCalcModal = (0, import_react8.useCallback)(() => {
2259
+ const handleCloseCalcModal = (0, import_react9.useCallback)(() => {
1747
2260
  setShowCalcModal(false);
1748
2261
  setEditingCalcField(null);
1749
2262
  }, []);
1750
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-pivot-config", children: [
1751
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-config-header", children: [
1752
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("h3", { className: "vpg-config-title", children: [
1753
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2263
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-pivot-config", children: [
2264
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-config-header", children: [
2265
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("h3", { className: "vpg-config-title", children: [
2266
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1754
2267
  "path",
1755
2268
  {
1756
2269
  strokeLinecap: "round",
@@ -1761,13 +2274,13 @@ function PivotConfig({
1761
2274
  ) }),
1762
2275
  "Fields"
1763
2276
  ] }),
1764
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-header-actions", children: assignedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2277
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-header-actions", children: assignedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1765
2278
  "button",
1766
2279
  {
1767
2280
  className: "vpg-action-btn vpg-clear-btn",
1768
2281
  title: "Clear all",
1769
2282
  onClick: onClearConfig,
1770
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2283
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1771
2284
  "path",
1772
2285
  {
1773
2286
  strokeLinecap: "round",
@@ -1779,9 +2292,9 @@ function PivotConfig({
1779
2292
  }
1780
2293
  ) })
1781
2294
  ] }),
1782
- assignedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-assigned-section", children: [
1783
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-section-label", children: "Active" }),
1784
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-assigned-list", children: assignedFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2295
+ assignedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-assigned-section", children: [
2296
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-section-label", children: "Active" }),
2297
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-assigned-list", children: assignedFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1785
2298
  "div",
1786
2299
  {
1787
2300
  className: `vpg-assigned-item vpg-type-${field.assignedTo}${field.isCalculated ? " vpg-type-calc" : ""}`,
@@ -1790,12 +2303,12 @@ function PivotConfig({
1790
2303
  onDragStart: (e) => handleDragStart(field.field, e),
1791
2304
  onDragEnd,
1792
2305
  children: [
1793
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-item-main", children: [
1794
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: `vpg-item-badge ${field.assignedTo}${field.isCalculated ? " calc" : ""}`, children: field.isCalculated ? "\u0192" : field.assignedTo === "row" ? "R" : field.assignedTo === "column" ? "C" : (0, import_tinypivot_core6.getAggregationSymbol)(field.valueConfig?.aggregation || "sum") }),
1795
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-item-name", children: getFieldDisplayName(field) })
2306
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-item-main", children: [
2307
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: `vpg-item-badge ${field.assignedTo}${field.isCalculated ? " calc" : ""}`, children: field.isCalculated ? "\u0192" : field.assignedTo === "row" ? "R" : field.assignedTo === "column" ? "C" : (0, import_tinypivot_core7.getAggregationSymbol)(field.valueConfig?.aggregation || "sum") }),
2308
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-item-name", children: getFieldDisplayName(field) })
1796
2309
  ] }),
1797
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-item-actions", children: [
1798
- (field.assignedTo === "row" || field.assignedTo === "column") && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2310
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-item-actions", children: [
2311
+ (field.assignedTo === "row" || field.assignedTo === "column") && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1799
2312
  "button",
1800
2313
  {
1801
2314
  className: "vpg-toggle-btn",
@@ -1804,14 +2317,14 @@ function PivotConfig({
1804
2317
  e.stopPropagation();
1805
2318
  toggleRowColumn(field.field, field.assignedTo);
1806
2319
  },
1807
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2320
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1808
2321
  "svg",
1809
2322
  {
1810
2323
  className: "vpg-icon-xs",
1811
2324
  fill: "none",
1812
2325
  stroke: "currentColor",
1813
2326
  viewBox: "0 0 24 24",
1814
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2327
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1815
2328
  "path",
1816
2329
  {
1817
2330
  strokeLinecap: "round",
@@ -1824,7 +2337,7 @@ function PivotConfig({
1824
2337
  )
1825
2338
  }
1826
2339
  ),
1827
- field.assignedTo === "value" && field.valueConfig && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2340
+ field.assignedTo === "value" && field.valueConfig && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1828
2341
  "select",
1829
2342
  {
1830
2343
  className: "vpg-agg-select",
@@ -1838,7 +2351,7 @@ function PivotConfig({
1838
2351
  );
1839
2352
  },
1840
2353
  onClick: (e) => e.stopPropagation(),
1841
- children: import_tinypivot_core6.AGGREGATION_OPTIONS.map((agg) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2354
+ children: import_tinypivot_core7.AGGREGATION_OPTIONS.map((agg) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1842
2355
  "option",
1843
2356
  {
1844
2357
  value: agg.value,
@@ -1854,7 +2367,7 @@ function PivotConfig({
1854
2367
  ))
1855
2368
  }
1856
2369
  ),
1857
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2370
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1858
2371
  "button",
1859
2372
  {
1860
2373
  className: "vpg-remove-btn",
@@ -1872,14 +2385,14 @@ function PivotConfig({
1872
2385
  field.field
1873
2386
  )) })
1874
2387
  ] }),
1875
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-unassigned-section", children: [
1876
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-section-header", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-section-label", children: [
2388
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-unassigned-section", children: [
2389
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-section-header", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-section-label", children: [
1877
2390
  "Available",
1878
2391
  " ",
1879
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-count", children: unassignedFields.length })
2392
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-count", children: unassignedFields.length })
1880
2393
  ] }) }),
1881
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-field-search", children: [
1882
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2394
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-field-search", children: [
2395
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-search-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1883
2396
  "path",
1884
2397
  {
1885
2398
  strokeLinecap: "round",
@@ -1888,7 +2401,7 @@ function PivotConfig({
1888
2401
  d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
1889
2402
  }
1890
2403
  ) }),
1891
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2404
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1892
2405
  "input",
1893
2406
  {
1894
2407
  type: "text",
@@ -1898,7 +2411,7 @@ function PivotConfig({
1898
2411
  className: "vpg-search-input"
1899
2412
  }
1900
2413
  ),
1901
- fieldSearch && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: "vpg-clear-search", onClick: () => setFieldSearch(""), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2414
+ fieldSearch && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { className: "vpg-clear-search", onClick: () => setFieldSearch(""), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon-xs", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1902
2415
  "path",
1903
2416
  {
1904
2417
  strokeLinecap: "round",
@@ -1908,8 +2421,8 @@ function PivotConfig({
1908
2421
  }
1909
2422
  ) }) })
1910
2423
  ] }),
1911
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-field-list", children: [
1912
- filteredUnassignedFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2424
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-field-list", children: [
2425
+ filteredUnassignedFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1913
2426
  "div",
1914
2427
  {
1915
2428
  className: `vpg-field-item${field.isNumeric && !field.isCalculated ? " vpg-is-numeric" : ""}${field.isCalculated ? " vpg-is-calculated" : ""}`,
@@ -1918,10 +2431,10 @@ function PivotConfig({
1918
2431
  onDragStart: (e) => handleDragStart(field.field, e),
1919
2432
  onDragEnd,
1920
2433
  children: [
1921
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: `vpg-field-type-icon${field.isCalculated ? " vpg-calc-type" : ""}`, title: field.type, children: getFieldIcon(field.type, field.isCalculated) }),
1922
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-field-name", children: getFieldDisplayName(field) }),
1923
- field.isCalculated ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1924
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2434
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: `vpg-field-type-icon${field.isCalculated ? " vpg-calc-type" : ""}`, title: field.type, children: getFieldIcon(field.type, field.isCalculated) }),
2435
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-field-name", children: getFieldDisplayName(field) }),
2436
+ field.isCalculated ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2437
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1925
2438
  "button",
1926
2439
  {
1927
2440
  className: "vpg-field-edit",
@@ -1935,7 +2448,7 @@ function PivotConfig({
1935
2448
  children: "\u270E"
1936
2449
  }
1937
2450
  ),
1938
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2451
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1939
2452
  "button",
1940
2453
  {
1941
2454
  className: "vpg-field-delete",
@@ -1949,22 +2462,22 @@ function PivotConfig({
1949
2462
  children: "\xD7"
1950
2463
  }
1951
2464
  )
1952
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-unique-count", children: field.uniqueCount })
2465
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-unique-count", children: field.uniqueCount })
1953
2466
  ]
1954
2467
  },
1955
2468
  field.field
1956
2469
  )),
1957
- filteredUnassignedFields.length === 0 && fieldSearch && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-empty-hint", children: [
2470
+ filteredUnassignedFields.length === 0 && fieldSearch && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-empty-hint", children: [
1958
2471
  'No fields match "',
1959
2472
  fieldSearch,
1960
2473
  '"'
1961
2474
  ] }),
1962
- unassignedFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-empty-hint", children: "All fields assigned" })
2475
+ unassignedFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-empty-hint", children: "All fields assigned" })
1963
2476
  ] })
1964
2477
  ] }),
1965
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "vpg-options-section", children: [
1966
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "vpg-option-toggle", children: [
1967
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2478
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-options-section", children: [
2479
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "vpg-option-toggle", children: [
2480
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1968
2481
  "input",
1969
2482
  {
1970
2483
  type: "checkbox",
@@ -1972,14 +2485,14 @@ function PivotConfig({
1972
2485
  onChange: (e) => handleTotalsToggle(e.target.checked)
1973
2486
  }
1974
2487
  ),
1975
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Totals" })
2488
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Totals" })
1976
2489
  ] }),
1977
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { className: "vpg-calc-btn", onClick: () => openCalcModal(), title: "Add calculated field (e.g. Profit Margin %)", children: [
1978
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "vpg-calc-icon", children: "\u0192" }),
1979
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "+ Calc" })
2490
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { className: "vpg-calc-btn", onClick: () => openCalcModal(), title: "Add calculated field (e.g. Profit Margin %)", children: [
2491
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-calc-icon", children: "\u0192" }),
2492
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "+ Calc" })
1980
2493
  ] })
1981
2494
  ] }),
1982
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2495
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1983
2496
  CalculatedFieldModal,
1984
2497
  {
1985
2498
  show: showCalcModal,
@@ -1993,9 +2506,9 @@ function PivotConfig({
1993
2506
  }
1994
2507
 
1995
2508
  // src/components/PivotSkeleton.tsx
1996
- var import_tinypivot_core7 = require("@smallwebco/tinypivot-core");
1997
- var import_react9 = require("react");
1998
- var import_jsx_runtime5 = require("react/jsx-runtime");
2509
+ var import_tinypivot_core8 = require("@smallwebco/tinypivot-core");
2510
+ var import_react10 = require("react");
2511
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1999
2512
  function PivotSkeleton({
2000
2513
  rowFields,
2001
2514
  columnFields,
@@ -2018,7 +2531,7 @@ function PivotSkeleton({
2018
2531
  onReorderColumnFields
2019
2532
  }) {
2020
2533
  const { showWatermark, canUsePivot, isDemo } = useLicense();
2021
- const getValueFieldDisplayName = (0, import_react9.useCallback)((field) => {
2534
+ const getValueFieldDisplayName = (0, import_react10.useCallback)((field) => {
2022
2535
  if (field.startsWith("calc:")) {
2023
2536
  const calcId = field.replace("calc:", "");
2024
2537
  const calcField = calculatedFields?.find((c) => c.id === calcId);
@@ -2026,15 +2539,15 @@ function PivotSkeleton({
2026
2539
  }
2027
2540
  return field;
2028
2541
  }, [calculatedFields]);
2029
- const isCalculatedField = (0, import_react9.useCallback)((field) => {
2542
+ const isCalculatedField = (0, import_react10.useCallback)((field) => {
2030
2543
  return field.startsWith("calc:");
2031
2544
  }, []);
2032
- const [dragOverArea, setDragOverArea] = (0, import_react9.useState)(null);
2033
- const [reorderDragSource, setReorderDragSource] = (0, import_react9.useState)(null);
2034
- const [reorderDropTarget, setReorderDropTarget] = (0, import_react9.useState)(null);
2035
- const [sortDirection, setSortDirection] = (0, import_react9.useState)("asc");
2036
- const [sortTarget, setSortTarget] = (0, import_react9.useState)("row");
2037
- const toggleSort = (0, import_react9.useCallback)((target = "row") => {
2545
+ const [dragOverArea, setDragOverArea] = (0, import_react10.useState)(null);
2546
+ const [reorderDragSource, setReorderDragSource] = (0, import_react10.useState)(null);
2547
+ const [reorderDropTarget, setReorderDropTarget] = (0, import_react10.useState)(null);
2548
+ const [sortDirection, setSortDirection] = (0, import_react10.useState)("asc");
2549
+ const [sortTarget, setSortTarget] = (0, import_react10.useState)("row");
2550
+ const toggleSort = (0, import_react10.useCallback)((target = "row") => {
2038
2551
  if (sortTarget === target) {
2039
2552
  setSortDirection((prev) => prev === "asc" ? "desc" : "asc");
2040
2553
  } else {
@@ -2042,13 +2555,13 @@ function PivotSkeleton({
2042
2555
  setSortDirection("asc");
2043
2556
  }
2044
2557
  }, [sortTarget]);
2045
- const [selectedCell, setSelectedCell] = (0, import_react9.useState)(null);
2046
- const [selectionStart, setSelectionStart] = (0, import_react9.useState)(null);
2047
- const [selectionEnd, setSelectionEnd] = (0, import_react9.useState)(null);
2048
- const [isSelecting, setIsSelecting] = (0, import_react9.useState)(false);
2049
- const [showCopyToast, setShowCopyToast] = (0, import_react9.useState)(false);
2050
- const [copyToastMessage, setCopyToastMessage] = (0, import_react9.useState)("");
2051
- const selectionBounds = (0, import_react9.useMemo)(() => {
2558
+ const [selectedCell, setSelectedCell] = (0, import_react10.useState)(null);
2559
+ const [selectionStart, setSelectionStart] = (0, import_react10.useState)(null);
2560
+ const [selectionEnd, setSelectionEnd] = (0, import_react10.useState)(null);
2561
+ const [isSelecting, setIsSelecting] = (0, import_react10.useState)(false);
2562
+ const [showCopyToast, setShowCopyToast] = (0, import_react10.useState)(false);
2563
+ const [copyToastMessage, setCopyToastMessage] = (0, import_react10.useState)("");
2564
+ const selectionBounds = (0, import_react10.useMemo)(() => {
2052
2565
  if (!selectionStart || !selectionEnd)
2053
2566
  return null;
2054
2567
  return {
@@ -2058,7 +2571,7 @@ function PivotSkeleton({
2058
2571
  maxCol: Math.max(selectionStart.col, selectionEnd.col)
2059
2572
  };
2060
2573
  }, [selectionStart, selectionEnd]);
2061
- const handleCellMouseDown = (0, import_react9.useCallback)(
2574
+ const handleCellMouseDown = (0, import_react10.useCallback)(
2062
2575
  (rowIndex, colIndex, event) => {
2063
2576
  event.preventDefault();
2064
2577
  if (event.shiftKey && selectedCell) {
@@ -2072,7 +2585,7 @@ function PivotSkeleton({
2072
2585
  },
2073
2586
  [selectedCell]
2074
2587
  );
2075
- const handleCellMouseEnter = (0, import_react9.useCallback)(
2588
+ const handleCellMouseEnter = (0, import_react10.useCallback)(
2076
2589
  (rowIndex, colIndex) => {
2077
2590
  if (isSelecting) {
2078
2591
  setSelectionEnd({ row: rowIndex, col: colIndex });
@@ -2080,7 +2593,7 @@ function PivotSkeleton({
2080
2593
  },
2081
2594
  [isSelecting]
2082
2595
  );
2083
- const isCellSelected = (0, import_react9.useCallback)(
2596
+ const isCellSelected = (0, import_react10.useCallback)(
2084
2597
  (rowIndex, colIndex) => {
2085
2598
  if (!selectionBounds) {
2086
2599
  return selectedCell?.row === rowIndex && selectedCell?.col === colIndex;
@@ -2090,12 +2603,12 @@ function PivotSkeleton({
2090
2603
  },
2091
2604
  [selectionBounds, selectedCell]
2092
2605
  );
2093
- (0, import_react9.useEffect)(() => {
2606
+ (0, import_react10.useEffect)(() => {
2094
2607
  const handleMouseUp = () => setIsSelecting(false);
2095
2608
  document.addEventListener("mouseup", handleMouseUp);
2096
2609
  return () => document.removeEventListener("mouseup", handleMouseUp);
2097
2610
  }, []);
2098
- const sortedRowIndices = (0, import_react9.useMemo)(() => {
2611
+ const sortedRowIndices = (0, import_react10.useMemo)(() => {
2099
2612
  if (!pivotResult)
2100
2613
  return [];
2101
2614
  const indices = pivotResult.rowHeaders.map((_, i) => i);
@@ -2123,7 +2636,7 @@ function PivotSkeleton({
2123
2636
  });
2124
2637
  return indices;
2125
2638
  }, [pivotResult, sortTarget, sortDirection]);
2126
- const copySelectionToClipboard = (0, import_react9.useCallback)(() => {
2639
+ const copySelectionToClipboard = (0, import_react10.useCallback)(() => {
2127
2640
  if (!selectionBounds || !pivotResult)
2128
2641
  return;
2129
2642
  const { minRow, maxRow, minCol, maxCol } = selectionBounds;
@@ -2149,7 +2662,7 @@ function PivotSkeleton({
2149
2662
  console.error("Copy failed:", err);
2150
2663
  });
2151
2664
  }, [selectionBounds, pivotResult, sortedRowIndices]);
2152
- (0, import_react9.useEffect)(() => {
2665
+ (0, import_react10.useEffect)(() => {
2153
2666
  const handleKeydown = (event) => {
2154
2667
  if (!selectionBounds)
2155
2668
  return;
@@ -2167,7 +2680,7 @@ function PivotSkeleton({
2167
2680
  document.addEventListener("keydown", handleKeydown);
2168
2681
  return () => document.removeEventListener("keydown", handleKeydown);
2169
2682
  }, [selectionBounds, copySelectionToClipboard]);
2170
- const selectionStats = (0, import_react9.useMemo)(() => {
2683
+ const selectionStats = (0, import_react10.useMemo)(() => {
2171
2684
  if (!selectionBounds || !pivotResult)
2172
2685
  return null;
2173
2686
  const { minRow, maxRow, minCol, maxCol } = selectionBounds;
@@ -2196,18 +2709,18 @@ function PivotSkeleton({
2196
2709
  avg
2197
2710
  };
2198
2711
  }, [selectionBounds, pivotResult, sortedRowIndices]);
2199
- const formatStatValue = (0, import_react9.useCallback)((val) => {
2712
+ const formatStatValue = (0, import_react10.useCallback)((val) => {
2200
2713
  if (Math.abs(val) >= 1e6)
2201
2714
  return `${(val / 1e6).toFixed(2)}M`;
2202
2715
  if (Math.abs(val) >= 1e3)
2203
2716
  return `${(val / 1e3).toFixed(2)}K`;
2204
2717
  return val.toFixed(2);
2205
2718
  }, []);
2206
- const columnHeaderCells = (0, import_react9.useMemo)(() => {
2719
+ const columnHeaderCells = (0, import_react10.useMemo)(() => {
2207
2720
  if (!pivotResult || pivotResult.headers.length === 0) {
2208
2721
  return [
2209
2722
  valueFields.map((vf) => ({
2210
- label: `${getValueFieldDisplayName(vf.field)} (${(0, import_tinypivot_core7.getAggregationLabel)(vf.aggregation)})`,
2723
+ label: `${getValueFieldDisplayName(vf.field)} (${(0, import_tinypivot_core8.getAggregationLabel)(vf.aggregation)})`,
2211
2724
  colspan: 1
2212
2725
  }))
2213
2726
  ];
@@ -2231,13 +2744,13 @@ function PivotSkeleton({
2231
2744
  return result;
2232
2745
  }, [pivotResult, valueFields]);
2233
2746
  const hasActiveFilters = activeFilters && activeFilters.length > 0;
2234
- const filterSummary = (0, import_react9.useMemo)(() => {
2747
+ const filterSummary = (0, import_react10.useMemo)(() => {
2235
2748
  if (!activeFilters || activeFilters.length === 0)
2236
2749
  return "";
2237
2750
  return activeFilters.map((f) => f.column).join(", ");
2238
2751
  }, [activeFilters]);
2239
- const [showFilterTooltip, setShowFilterTooltip] = (0, import_react9.useState)(false);
2240
- const filterTooltipDetails = (0, import_react9.useMemo)(() => {
2752
+ const [showFilterTooltip, setShowFilterTooltip] = (0, import_react10.useState)(false);
2753
+ const filterTooltipDetails = (0, import_react10.useMemo)(() => {
2241
2754
  if (!activeFilters || activeFilters.length === 0)
2242
2755
  return [];
2243
2756
  return activeFilters.map((f) => {
@@ -2262,7 +2775,7 @@ function PivotSkeleton({
2262
2775
  };
2263
2776
  });
2264
2777
  }, [activeFilters]);
2265
- const handleDragOver = (0, import_react9.useCallback)(
2778
+ const handleDragOver = (0, import_react10.useCallback)(
2266
2779
  (area, event) => {
2267
2780
  event.preventDefault();
2268
2781
  event.dataTransfer.dropEffect = "move";
@@ -2270,10 +2783,10 @@ function PivotSkeleton({
2270
2783
  },
2271
2784
  []
2272
2785
  );
2273
- const handleDragLeave = (0, import_react9.useCallback)(() => {
2786
+ const handleDragLeave = (0, import_react10.useCallback)(() => {
2274
2787
  setDragOverArea(null);
2275
2788
  }, []);
2276
- const handleDrop = (0, import_react9.useCallback)(
2789
+ const handleDrop = (0, import_react10.useCallback)(
2277
2790
  (area, event) => {
2278
2791
  event.preventDefault();
2279
2792
  const field = event.dataTransfer?.getData("text/plain");
@@ -2303,7 +2816,7 @@ function PivotSkeleton({
2303
2816
  },
2304
2817
  [rowFields, columnFields, valueFields, onAddRowField, onRemoveRowField, onAddColumnField, onRemoveColumnField, onAddValueField, onRemoveValueField]
2305
2818
  );
2306
- const handleChipDragStart = (0, import_react9.useCallback)(
2819
+ const handleChipDragStart = (0, import_react10.useCallback)(
2307
2820
  (zone, index, event) => {
2308
2821
  setReorderDragSource({ zone, index });
2309
2822
  event.dataTransfer.effectAllowed = "move";
@@ -2314,11 +2827,11 @@ function PivotSkeleton({
2314
2827
  },
2315
2828
  []
2316
2829
  );
2317
- const handleChipDragEnd = (0, import_react9.useCallback)(() => {
2830
+ const handleChipDragEnd = (0, import_react10.useCallback)(() => {
2318
2831
  setReorderDragSource(null);
2319
2832
  setReorderDropTarget(null);
2320
2833
  }, []);
2321
- const handleChipDragOver = (0, import_react9.useCallback)(
2834
+ const handleChipDragOver = (0, import_react10.useCallback)(
2322
2835
  (zone, index, event) => {
2323
2836
  event.preventDefault();
2324
2837
  if (reorderDragSource && reorderDragSource.zone === zone) {
@@ -2328,10 +2841,10 @@ function PivotSkeleton({
2328
2841
  },
2329
2842
  [reorderDragSource]
2330
2843
  );
2331
- const handleChipDragLeave = (0, import_react9.useCallback)(() => {
2844
+ const handleChipDragLeave = (0, import_react10.useCallback)(() => {
2332
2845
  setReorderDropTarget(null);
2333
2846
  }, []);
2334
- const handleChipDrop = (0, import_react9.useCallback)(
2847
+ const handleChipDrop = (0, import_react10.useCallback)(
2335
2848
  (zone, targetIndex, event) => {
2336
2849
  event.preventDefault();
2337
2850
  event.stopPropagation();
@@ -2357,13 +2870,13 @@ function PivotSkeleton({
2357
2870
  },
2358
2871
  [reorderDragSource, rowFields, columnFields, onReorderRowFields, onReorderColumnFields]
2359
2872
  );
2360
- const isChipDragSource = (0, import_react9.useCallback)(
2873
+ const isChipDragSource = (0, import_react10.useCallback)(
2361
2874
  (zone, index) => {
2362
2875
  return reorderDragSource?.zone === zone && reorderDragSource?.index === index;
2363
2876
  },
2364
2877
  [reorderDragSource]
2365
2878
  );
2366
- const isChipDropTarget = (0, import_react9.useCallback)(
2879
+ const isChipDropTarget = (0, import_react10.useCallback)(
2367
2880
  (zone, index) => {
2368
2881
  return reorderDropTarget?.zone === zone && reorderDropTarget?.index === index;
2369
2882
  },
@@ -2371,25 +2884,25 @@ function PivotSkeleton({
2371
2884
  );
2372
2885
  const currentFontSize = fontSize;
2373
2886
  const rowHeaderWidth = 180;
2374
- const rowHeaderColWidth = (0, import_react9.useMemo)(() => {
2887
+ const rowHeaderColWidth = (0, import_react10.useMemo)(() => {
2375
2888
  const numCols = Math.max(rowFields.length, 1);
2376
2889
  return Math.max(rowHeaderWidth / numCols, 80);
2377
2890
  }, [rowFields.length]);
2378
- const getRowHeaderLeftOffset = (0, import_react9.useCallback)((fieldIdx) => {
2891
+ const getRowHeaderLeftOffset = (0, import_react10.useCallback)((fieldIdx) => {
2379
2892
  return fieldIdx * rowHeaderColWidth;
2380
2893
  }, [rowHeaderColWidth]);
2381
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2894
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2382
2895
  "div",
2383
2896
  {
2384
2897
  className: `vpg-pivot-skeleton vpg-font-${currentFontSize} ${draggingField ? "vpg-is-dragging" : ""}`,
2385
2898
  children: [
2386
- showCopyToast && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-toast", children: [
2387
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
2899
+ showCopyToast && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-toast", children: [
2900
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
2388
2901
  copyToastMessage
2389
2902
  ] }),
2390
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-skeleton-header", children: [
2391
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-skeleton-title", children: [
2392
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2903
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-skeleton-header", children: [
2904
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-skeleton-title", children: [
2905
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2393
2906
  "path",
2394
2907
  {
2395
2908
  strokeLinecap: "round",
@@ -2398,24 +2911,24 @@ function PivotSkeleton({
2398
2911
  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"
2399
2912
  }
2400
2913
  ) }),
2401
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Pivot Table" })
2914
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Pivot Table" })
2402
2915
  ] }),
2403
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-header-right", children: [
2404
- hasActiveFilters && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2916
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-header-right", children: [
2917
+ hasActiveFilters && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2405
2918
  "div",
2406
2919
  {
2407
2920
  className: "vpg-filter-indicator",
2408
2921
  onMouseEnter: () => setShowFilterTooltip(true),
2409
2922
  onMouseLeave: () => setShowFilterTooltip(false),
2410
2923
  children: [
2411
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2924
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2412
2925
  "svg",
2413
2926
  {
2414
2927
  className: "vpg-filter-icon",
2415
2928
  fill: "none",
2416
2929
  stroke: "currentColor",
2417
2930
  viewBox: "0 0 24 24",
2418
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2931
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2419
2932
  "path",
2420
2933
  {
2421
2934
  strokeLinecap: "round",
@@ -2426,11 +2939,11 @@ function PivotSkeleton({
2426
2939
  )
2427
2940
  }
2428
2941
  ),
2429
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-filter-text", children: [
2942
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-filter-text", children: [
2430
2943
  "Filtered:",
2431
2944
  " ",
2432
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: filterSummary }),
2433
- filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-filter-count", children: [
2945
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: filterSummary }),
2946
+ filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-filter-count", children: [
2434
2947
  "(",
2435
2948
  filteredRowCount.toLocaleString(),
2436
2949
  " ",
@@ -2441,13 +2954,13 @@ function PivotSkeleton({
2441
2954
  "rows)"
2442
2955
  ] })
2443
2956
  ] }),
2444
- showFilterTooltip && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-filter-tooltip", children: [
2445
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-tooltip-header", children: "Active Filters" }),
2446
- filterTooltipDetails.map((filter) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-tooltip-filter", children: [
2447
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-tooltip-column", children: filter.column }),
2448
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-tooltip-values", children: filter.isRange ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-tooltip-value vpg-range-value", children: filter.displayText }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2449
- filter.values.map((val, idx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-tooltip-value", children: val }, idx)),
2450
- filter.remaining > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-tooltip-more", children: [
2957
+ showFilterTooltip && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-filter-tooltip", children: [
2958
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-tooltip-header", children: "Active Filters" }),
2959
+ filterTooltipDetails.map((filter) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-tooltip-filter", children: [
2960
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-tooltip-column", children: filter.column }),
2961
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-tooltip-values", children: filter.isRange ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-tooltip-value vpg-range-value", children: filter.displayText }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2962
+ filter.values.map((val, idx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-tooltip-value", children: val }, idx)),
2963
+ filter.remaining > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-tooltip-more", children: [
2451
2964
  "+",
2452
2965
  filter.remaining,
2453
2966
  " ",
@@ -2455,7 +2968,7 @@ function PivotSkeleton({
2455
2968
  ] })
2456
2969
  ] }) })
2457
2970
  ] }, filter.column)),
2458
- filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-tooltip-summary", children: [
2971
+ filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-tooltip-summary", children: [
2459
2972
  "Showing",
2460
2973
  " ",
2461
2974
  filteredRowCount.toLocaleString(),
@@ -2470,20 +2983,20 @@ function PivotSkeleton({
2470
2983
  ]
2471
2984
  }
2472
2985
  ),
2473
- isConfigured && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-config-summary", children: [
2474
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-summary-badge vpg-rows", children: [
2986
+ isConfigured && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-config-summary", children: [
2987
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-summary-badge vpg-rows", children: [
2475
2988
  rowFields.length,
2476
2989
  " ",
2477
2990
  "row",
2478
2991
  rowFields.length !== 1 ? "s" : ""
2479
2992
  ] }),
2480
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-summary-badge vpg-cols", children: [
2993
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-summary-badge vpg-cols", children: [
2481
2994
  columnFields.length,
2482
2995
  " ",
2483
2996
  "col",
2484
2997
  columnFields.length !== 1 ? "s" : ""
2485
2998
  ] }),
2486
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-summary-badge vpg-vals", children: [
2999
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-summary-badge vpg-vals", children: [
2487
3000
  valueFields.length,
2488
3001
  " ",
2489
3002
  "val",
@@ -2492,8 +3005,8 @@ function PivotSkeleton({
2492
3005
  ] })
2493
3006
  ] })
2494
3007
  ] }),
2495
- !canUsePivot ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-pro-required", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-pro-content", children: [
2496
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "vpg-pro-icon", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3008
+ !canUsePivot ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-pro-required", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-pro-content", children: [
3009
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-pro-icon", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2497
3010
  "path",
2498
3011
  {
2499
3012
  strokeLinecap: "round",
@@ -2502,12 +3015,12 @@ function PivotSkeleton({
2502
3015
  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"
2503
3016
  }
2504
3017
  ) }),
2505
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { children: "Pro Feature" }),
2506
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { children: "Pivot Table functionality requires a Pro license." }),
2507
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", className: "vpg-pro-link", children: "Get Pro License \u2192" })
2508
- ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2509
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-config-bar", children: [
2510
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3018
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { children: "Pro Feature" }),
3019
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: "Pivot Table functionality requires a Pro license." }),
3020
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", className: "vpg-pro-link", children: "Get Pro License \u2192" })
3021
+ ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3022
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-config-bar", children: [
3023
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2511
3024
  "div",
2512
3025
  {
2513
3026
  className: `vpg-drop-zone vpg-row-zone ${dragOverArea === "row" ? "vpg-drag-over" : ""}`,
@@ -2515,12 +3028,12 @@ function PivotSkeleton({
2515
3028
  onDragLeave: handleDragLeave,
2516
3029
  onDrop: (e) => handleDrop("row", e),
2517
3030
  children: [
2518
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-zone-header", children: [
2519
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-icon vpg-row-icon", children: "\u2193" }),
2520
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-label", children: "Rows" })
3031
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-zone-header", children: [
3032
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-icon vpg-row-icon", children: "\u2193" }),
3033
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-label", children: "Rows" })
2521
3034
  ] }),
2522
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-zone-chips", children: [
2523
- rowFields.map((field, idx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3035
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-zone-chips", children: [
3036
+ rowFields.map((field, idx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2524
3037
  "div",
2525
3038
  {
2526
3039
  className: `vpg-mini-chip vpg-row-chip ${isChipDragSource("row", idx) ? "vpg-chip-dragging" : ""} ${isChipDropTarget("row", idx) ? "vpg-chip-drop-target" : ""}`,
@@ -2531,9 +3044,9 @@ function PivotSkeleton({
2531
3044
  onDragLeave: handleChipDragLeave,
2532
3045
  onDrop: (e) => handleChipDrop("row", idx, e),
2533
3046
  children: [
2534
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
2535
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-mini-name", children: field }),
2536
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3047
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
3048
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-mini-name", children: field }),
3049
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2537
3050
  "button",
2538
3051
  {
2539
3052
  className: "vpg-mini-remove",
@@ -2548,12 +3061,12 @@ function PivotSkeleton({
2548
3061
  },
2549
3062
  field
2550
3063
  )),
2551
- rowFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-hint", children: "Drop here" })
3064
+ rowFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-hint", children: "Drop here" })
2552
3065
  ] })
2553
3066
  ]
2554
3067
  }
2555
3068
  ),
2556
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3069
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2557
3070
  "div",
2558
3071
  {
2559
3072
  className: `vpg-drop-zone vpg-column-zone ${dragOverArea === "column" ? "vpg-drag-over" : ""}`,
@@ -2561,12 +3074,12 @@ function PivotSkeleton({
2561
3074
  onDragLeave: handleDragLeave,
2562
3075
  onDrop: (e) => handleDrop("column", e),
2563
3076
  children: [
2564
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-zone-header", children: [
2565
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-icon vpg-column-icon", children: "\u2192" }),
2566
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-label", children: "Columns" })
3077
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-zone-header", children: [
3078
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-icon vpg-column-icon", children: "\u2192" }),
3079
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-label", children: "Columns" })
2567
3080
  ] }),
2568
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-zone-chips", children: [
2569
- columnFields.map((field, idx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3081
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-zone-chips", children: [
3082
+ columnFields.map((field, idx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2570
3083
  "div",
2571
3084
  {
2572
3085
  className: `vpg-mini-chip vpg-column-chip ${isChipDragSource("column", idx) ? "vpg-chip-dragging" : ""} ${isChipDropTarget("column", idx) ? "vpg-chip-drop-target" : ""}`,
@@ -2577,9 +3090,9 @@ function PivotSkeleton({
2577
3090
  onDragLeave: handleChipDragLeave,
2578
3091
  onDrop: (e) => handleChipDrop("column", idx, e),
2579
3092
  children: [
2580
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
2581
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-mini-name", children: field }),
2582
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3093
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-drag-handle", children: "\u22EE\u22EE" }),
3094
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-mini-name", children: field }),
3095
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2583
3096
  "button",
2584
3097
  {
2585
3098
  className: "vpg-mini-remove",
@@ -2594,12 +3107,12 @@ function PivotSkeleton({
2594
3107
  },
2595
3108
  field
2596
3109
  )),
2597
- columnFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-hint", children: "Drop here" })
3110
+ columnFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-hint", children: "Drop here" })
2598
3111
  ] })
2599
3112
  ]
2600
3113
  }
2601
3114
  ),
2602
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3115
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2603
3116
  "div",
2604
3117
  {
2605
3118
  className: `vpg-drop-zone vpg-value-zone ${dragOverArea === "value" ? "vpg-drag-over" : ""}`,
@@ -2607,19 +3120,19 @@ function PivotSkeleton({
2607
3120
  onDragLeave: handleDragLeave,
2608
3121
  onDrop: (e) => handleDrop("value", e),
2609
3122
  children: [
2610
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-zone-header", children: [
2611
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-icon vpg-value-icon", children: "\u03A3" }),
2612
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-label", children: "Values" })
3123
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-zone-header", children: [
3124
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-icon vpg-value-icon", children: "\u03A3" }),
3125
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-label", children: "Values" })
2613
3126
  ] }),
2614
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-zone-chips", children: [
2615
- valueFields.map((vf) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3127
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-zone-chips", children: [
3128
+ valueFields.map((vf) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2616
3129
  "div",
2617
3130
  {
2618
3131
  className: `vpg-mini-chip vpg-value-chip${isCalculatedField(vf.field) ? " vpg-calc-chip" : ""}`,
2619
3132
  children: [
2620
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-agg-symbol", children: isCalculatedField(vf.field) ? "\u0192" : (0, import_tinypivot_core7.getAggregationSymbol)(vf.aggregation) }),
2621
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-mini-name", children: getValueFieldDisplayName(vf.field) }),
2622
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3133
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-agg-symbol", children: isCalculatedField(vf.field) ? "\u0192" : (0, import_tinypivot_core8.getAggregationSymbol)(vf.aggregation) }),
3134
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-mini-name", children: getValueFieldDisplayName(vf.field) }),
3135
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2623
3136
  "button",
2624
3137
  {
2625
3138
  className: "vpg-mini-remove",
@@ -2631,21 +3144,21 @@ function PivotSkeleton({
2631
3144
  },
2632
3145
  `${vf.field}-${vf.aggregation}`
2633
3146
  )),
2634
- valueFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-zone-hint", children: "Drop numeric" })
3147
+ valueFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-zone-hint", children: "Drop numeric" })
2635
3148
  ] })
2636
3149
  ]
2637
3150
  }
2638
3151
  )
2639
3152
  ] }),
2640
- (!isConfigured || !pivotResult) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-placeholder", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-placeholder-content", children: [
2641
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3153
+ (!isConfigured || !pivotResult) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-placeholder", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-placeholder-content", children: [
3154
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2642
3155
  "svg",
2643
3156
  {
2644
3157
  className: "vpg-placeholder-icon",
2645
3158
  fill: "none",
2646
3159
  viewBox: "0 0 24 24",
2647
3160
  stroke: "currentColor",
2648
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3161
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2649
3162
  "path",
2650
3163
  {
2651
3164
  strokeLinecap: "round",
@@ -2656,58 +3169,58 @@ function PivotSkeleton({
2656
3169
  )
2657
3170
  }
2658
3171
  ),
2659
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-placeholder-text", children: valueFields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
3172
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-placeholder-text", children: valueFields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2660
3173
  "Add a",
2661
3174
  " ",
2662
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: "Values" }),
3175
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "Values" }),
2663
3176
  " ",
2664
3177
  "field to see your pivot table"
2665
- ] }) : rowFields.length === 0 && columnFields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
3178
+ ] }) : rowFields.length === 0 && columnFields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2666
3179
  "Add",
2667
3180
  " ",
2668
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: "Row" }),
3181
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "Row" }),
2669
3182
  " ",
2670
3183
  "or",
2671
3184
  " ",
2672
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: "Column" }),
3185
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "Column" }),
2673
3186
  " ",
2674
3187
  "fields to group your data"
2675
3188
  ] }) : "Your pivot table will appear here" })
2676
3189
  ] }) }),
2677
- isConfigured && pivotResult && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "vpg-table-container", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { className: "vpg-pivot-table", children: [
2678
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { children: columnHeaderCells.map((headerRow, levelIdx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "vpg-column-header-row", children: [
2679
- levelIdx === 0 && (rowFields.length > 0 ? rowFields : ["Rows"]).map((field, fieldIdx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3190
+ isConfigured && pivotResult && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-table-container", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("table", { className: "vpg-pivot-table", children: [
3191
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("thead", { children: columnHeaderCells.map((headerRow, levelIdx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("tr", { className: "vpg-column-header-row", children: [
3192
+ levelIdx === 0 && (rowFields.length > 0 ? rowFields : ["Rows"]).map((field, fieldIdx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2680
3193
  "th",
2681
3194
  {
2682
3195
  className: "vpg-row-header-label",
2683
3196
  rowSpan: columnHeaderCells.length,
2684
3197
  style: { width: `${rowHeaderColWidth}px`, minWidth: "80px", left: `${getRowHeaderLeftOffset(fieldIdx)}px` },
2685
3198
  onClick: () => toggleSort("row"),
2686
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-header-content", children: [
2687
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: field }),
2688
- (fieldIdx === rowFields.length - 1 || rowFields.length === 0) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: `vpg-sort-indicator ${sortTarget === "row" ? "active" : ""}`, children: sortTarget === "row" ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
3199
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-header-content", children: [
3200
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: field }),
3201
+ (fieldIdx === rowFields.length - 1 || rowFields.length === 0) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: `vpg-sort-indicator ${sortTarget === "row" ? "active" : ""}`, children: sortTarget === "row" ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
2689
3202
  ] })
2690
3203
  },
2691
3204
  `row-header-${fieldIdx}`
2692
3205
  )),
2693
- headerRow.map((cell, idx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3206
+ headerRow.map((cell, idx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2694
3207
  "th",
2695
3208
  {
2696
3209
  className: "vpg-column-header-cell",
2697
3210
  colSpan: cell.colspan,
2698
3211
  onClick: () => levelIdx === columnHeaderCells.length - 1 && toggleSort(idx),
2699
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-header-content", children: [
2700
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: cell.label }),
2701
- levelIdx === columnHeaderCells.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: `vpg-sort-indicator ${sortTarget === idx ? "active" : ""}`, children: sortTarget === idx ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
3212
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-header-content", children: [
3213
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: cell.label }),
3214
+ levelIdx === columnHeaderCells.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: `vpg-sort-indicator ${sortTarget === idx ? "active" : ""}`, children: sortTarget === idx ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u21C5" })
2702
3215
  ] })
2703
3216
  },
2704
3217
  idx
2705
3218
  )),
2706
- pivotResult.rowTotals.length > 0 && levelIdx === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: "vpg-total-header", rowSpan: columnHeaderCells.length, children: "Total" })
3219
+ pivotResult.rowTotals.length > 0 && levelIdx === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("th", { className: "vpg-total-header", rowSpan: columnHeaderCells.length, children: "Total" })
2707
3220
  ] }, `header-${levelIdx}`)) }),
2708
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tbody", { children: [
2709
- sortedRowIndices.map((sortedIdx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "vpg-data-row", children: [
2710
- pivotResult.rowHeaders[sortedIdx].map((val, idx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3221
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("tbody", { children: [
3222
+ sortedRowIndices.map((sortedIdx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("tr", { className: "vpg-data-row", children: [
3223
+ pivotResult.rowHeaders[sortedIdx].map((val, idx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2711
3224
  "th",
2712
3225
  {
2713
3226
  className: "vpg-row-header-cell",
@@ -2718,7 +3231,7 @@ function PivotSkeleton({
2718
3231
  )),
2719
3232
  pivotResult.data[sortedIdx].map((cell, colIdx) => {
2720
3233
  const displayRowIdx = sortedRowIndices.indexOf(sortedIdx);
2721
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3234
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2722
3235
  "td",
2723
3236
  {
2724
3237
  className: `vpg-data-cell ${isCellSelected(displayRowIdx, colIdx) ? "selected" : ""} ${cell.value === null ? "vpg-is-null" : ""}`,
@@ -2729,10 +3242,10 @@ function PivotSkeleton({
2729
3242
  colIdx
2730
3243
  );
2731
3244
  }),
2732
- pivotResult.rowTotals[sortedIdx] && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "vpg-data-cell vpg-total-cell", children: pivotResult.rowTotals[sortedIdx].formattedValue })
3245
+ pivotResult.rowTotals[sortedIdx] && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "vpg-data-cell vpg-total-cell", children: pivotResult.rowTotals[sortedIdx].formattedValue })
2733
3246
  ] }, sortedIdx)),
2734
- pivotResult.columnTotals.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "vpg-totals-row", children: [
2735
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3247
+ pivotResult.columnTotals.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("tr", { className: "vpg-totals-row", children: [
3248
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2736
3249
  "th",
2737
3250
  {
2738
3251
  className: "vpg-row-header-cell vpg-total-label",
@@ -2741,13 +3254,13 @@ function PivotSkeleton({
2741
3254
  children: "Total"
2742
3255
  }
2743
3256
  ),
2744
- pivotResult.columnTotals.map((cell, colIdx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "vpg-data-cell vpg-total-cell", children: cell.formattedValue }, colIdx)),
2745
- pivotResult.rowTotals.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "vpg-data-cell vpg-grand-total-cell", children: pivotResult.grandTotal.formattedValue })
3257
+ pivotResult.columnTotals.map((cell, colIdx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "vpg-data-cell vpg-total-cell", children: cell.formattedValue }, colIdx)),
3258
+ pivotResult.rowTotals.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "vpg-data-cell vpg-grand-total-cell", children: pivotResult.grandTotal.formattedValue })
2746
3259
  ] })
2747
3260
  ] })
2748
3261
  ] }) }),
2749
- isConfigured && pivotResult && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-skeleton-footer", children: [
2750
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-footer-info", children: [
3262
+ isConfigured && pivotResult && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-skeleton-footer", children: [
3263
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-footer-info", children: [
2751
3264
  pivotResult.rowHeaders.length,
2752
3265
  " ",
2753
3266
  "rows \xD7",
@@ -2755,30 +3268,30 @@ function PivotSkeleton({
2755
3268
  " ",
2756
3269
  "columns"
2757
3270
  ] }),
2758
- selectionStats && selectionStats.count > 1 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "vpg-selection-stats", children: [
2759
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-stat", children: [
2760
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-label", children: "Count:" }),
2761
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-value", children: selectionStats.count })
3271
+ selectionStats && selectionStats.count > 1 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-selection-stats", children: [
3272
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-stat", children: [
3273
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-label", children: "Count:" }),
3274
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-value", children: selectionStats.count })
2762
3275
  ] }),
2763
- selectionStats.numericCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2764
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
2765
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-stat", children: [
2766
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-label", children: "Sum:" }),
2767
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
3276
+ selectionStats.numericCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3277
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
3278
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-stat", children: [
3279
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-label", children: "Sum:" }),
3280
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
2768
3281
  ] }),
2769
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
2770
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "vpg-stat", children: [
2771
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-label", children: "Avg:" }),
2772
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
3282
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
3283
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-stat", children: [
3284
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-label", children: "Avg:" }),
3285
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
2773
3286
  ] })
2774
3287
  ] })
2775
3288
  ] })
2776
3289
  ] })
2777
3290
  ] }),
2778
- showWatermark && canUsePivot && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: `vpg-watermark ${isDemo ? "vpg-demo-mode" : ""}`, children: isDemo ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2779
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-demo-badge", children: "DEMO" }),
2780
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Pro features unlocked for evaluation" }),
2781
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3291
+ showWatermark && canUsePivot && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: `vpg-watermark ${isDemo ? "vpg-demo-mode" : ""}`, children: isDemo ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3292
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-demo-badge", children: "DEMO" }),
3293
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Pro features unlocked for evaluation" }),
3294
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2782
3295
  "a",
2783
3296
  {
2784
3297
  href: "https://tiny-pivot.com/#pricing",
@@ -2788,14 +3301,14 @@ function PivotSkeleton({
2788
3301
  children: "Get Pro License \u2192"
2789
3302
  }
2790
3303
  )
2791
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: "Powered by TinyPivot" }) })
3304
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: "Powered by TinyPivot" }) })
2792
3305
  ]
2793
3306
  }
2794
3307
  );
2795
3308
  }
2796
3309
 
2797
3310
  // src/components/DataGrid.tsx
2798
- var import_jsx_runtime6 = require("react/jsx-runtime");
3311
+ var import_jsx_runtime7 = require("react/jsx-runtime");
2799
3312
  var MIN_COL_WIDTH = 120;
2800
3313
  var MAX_COL_WIDTH = 350;
2801
3314
  function DataGrid({
@@ -2820,38 +3333,42 @@ function DataGrid({
2820
3333
  onExport,
2821
3334
  onCopy
2822
3335
  }) {
2823
- const { showWatermark, canUsePivot, isDemo, isPro } = useLicense();
2824
- const currentTheme = (0, import_react10.useMemo)(() => {
3336
+ const { showWatermark, canUsePivot, canUseCharts, isDemo, isPro } = useLicense();
3337
+ const currentTheme = (0, import_react11.useMemo)(() => {
2825
3338
  if (theme === "auto") {
2826
3339
  return window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
2827
3340
  }
2828
3341
  return theme;
2829
3342
  }, [theme]);
2830
- const [currentFontSize, setCurrentFontSize] = (0, import_react10.useState)(initialFontSize);
2831
- const [globalSearchTerm, setGlobalSearchTerm] = (0, import_react10.useState)("");
2832
- const [showSearchInput, setShowSearchInput] = (0, import_react10.useState)(false);
2833
- const [currentPage, setCurrentPage] = (0, import_react10.useState)(1);
2834
- const [columnWidths, setColumnWidths] = (0, import_react10.useState)({});
2835
- const [resizingColumnId, setResizingColumnId] = (0, import_react10.useState)(null);
2836
- const [resizeStartX, setResizeStartX] = (0, import_react10.useState)(0);
2837
- const [resizeStartWidth, setResizeStartWidth] = (0, import_react10.useState)(0);
2838
- const [gridHeight, setGridHeight] = (0, import_react10.useState)(initialHeight);
2839
- const [isResizingVertically, setIsResizingVertically] = (0, import_react10.useState)(false);
2840
- const [verticalResizeStartY, setVerticalResizeStartY] = (0, import_react10.useState)(0);
2841
- const [verticalResizeStartHeight, setVerticalResizeStartHeight] = (0, import_react10.useState)(0);
2842
- const [showCopyToast, setShowCopyToast] = (0, import_react10.useState)(false);
2843
- const [copyToastMessage, setCopyToastMessage] = (0, import_react10.useState)("");
2844
- const [viewMode, setViewMode] = (0, import_react10.useState)("grid");
2845
- const [showPivotConfig, setShowPivotConfig] = (0, import_react10.useState)(true);
2846
- const [draggingField, setDraggingField] = (0, import_react10.useState)(null);
2847
- const [activeFilterColumn, setActiveFilterColumn] = (0, import_react10.useState)(null);
2848
- const [filterDropdownPosition, setFilterDropdownPosition] = (0, import_react10.useState)({ top: 0, left: 0, maxHeight: 400 });
2849
- const [selectedCell, setSelectedCell] = (0, import_react10.useState)(null);
2850
- const [selectionStart, setSelectionStart] = (0, import_react10.useState)(null);
2851
- const [selectionEnd, setSelectionEnd] = (0, import_react10.useState)(null);
2852
- const [isSelecting, setIsSelecting] = (0, import_react10.useState)(false);
2853
- const tableContainerRef = (0, import_react10.useRef)(null);
2854
- const tableBodyRef = (0, import_react10.useRef)(null);
3343
+ const [currentFontSize, setCurrentFontSize] = (0, import_react11.useState)(initialFontSize);
3344
+ const [globalSearchTerm, setGlobalSearchTerm] = (0, import_react11.useState)("");
3345
+ const [showSearchInput, setShowSearchInput] = (0, import_react11.useState)(false);
3346
+ const [currentPage, setCurrentPage] = (0, import_react11.useState)(1);
3347
+ const [columnWidths, setColumnWidths] = (0, import_react11.useState)({});
3348
+ const [resizingColumnId, setResizingColumnId] = (0, import_react11.useState)(null);
3349
+ const [resizeStartX, setResizeStartX] = (0, import_react11.useState)(0);
3350
+ const [resizeStartWidth, setResizeStartWidth] = (0, import_react11.useState)(0);
3351
+ const [gridHeight, setGridHeight] = (0, import_react11.useState)(initialHeight);
3352
+ const [isResizingVertically, setIsResizingVertically] = (0, import_react11.useState)(false);
3353
+ const [verticalResizeStartY, setVerticalResizeStartY] = (0, import_react11.useState)(0);
3354
+ const [verticalResizeStartHeight, setVerticalResizeStartHeight] = (0, import_react11.useState)(0);
3355
+ const [showCopyToast, setShowCopyToast] = (0, import_react11.useState)(false);
3356
+ const [copyToastMessage, setCopyToastMessage] = (0, import_react11.useState)("");
3357
+ const [viewMode, setViewMode] = (0, import_react11.useState)("grid");
3358
+ const [_chartConfig, setChartConfig] = (0, import_react11.useState)(null);
3359
+ const handleChartConfigChange = (0, import_react11.useCallback)((config) => {
3360
+ setChartConfig(config);
3361
+ }, []);
3362
+ const [showPivotConfig, setShowPivotConfig] = (0, import_react11.useState)(true);
3363
+ const [draggingField, setDraggingField] = (0, import_react11.useState)(null);
3364
+ const [activeFilterColumn, setActiveFilterColumn] = (0, import_react11.useState)(null);
3365
+ const [filterDropdownPosition, setFilterDropdownPosition] = (0, import_react11.useState)({ top: 0, left: 0, maxHeight: 400 });
3366
+ const [selectedCell, setSelectedCell] = (0, import_react11.useState)(null);
3367
+ const [selectionStart, setSelectionStart] = (0, import_react11.useState)(null);
3368
+ const [selectionEnd, setSelectionEnd] = (0, import_react11.useState)(null);
3369
+ const [isSelecting, setIsSelecting] = (0, import_react11.useState)(false);
3370
+ const tableContainerRef = (0, import_react11.useRef)(null);
3371
+ const tableBodyRef = (0, import_react11.useRef)(null);
2855
3372
  const fontSizeOptions = [
2856
3373
  { value: "xs", label: "S" },
2857
3374
  { value: "sm", label: "M" },
@@ -2875,7 +3392,7 @@ function DataGrid({
2875
3392
  setNumericRangeFilter,
2876
3393
  getNumericRangeFilter
2877
3394
  } = useExcelGrid({ data, enableSorting: true, enableFiltering: true });
2878
- const filteredDataForPivot = (0, import_react10.useMemo)(() => {
3395
+ const filteredDataForPivot = (0, import_react11.useMemo)(() => {
2879
3396
  const filteredRows = table.getFilteredRowModel().rows;
2880
3397
  return filteredRows.map((row) => row.original);
2881
3398
  }, [table, columnFilters]);
@@ -2905,7 +3422,7 @@ function DataGrid({
2905
3422
  addCalculatedField,
2906
3423
  removeCalculatedField
2907
3424
  } = usePivotTable(filteredDataForPivot);
2908
- const activeFilterInfo = (0, import_react10.useMemo)(() => {
3425
+ const activeFilterInfo = (0, import_react11.useMemo)(() => {
2909
3426
  if (activeFilters.length === 0)
2910
3427
  return null;
2911
3428
  return activeFilters.map((f) => {
@@ -2930,8 +3447,8 @@ function DataGrid({
2930
3447
  };
2931
3448
  });
2932
3449
  }, [activeFilters]);
2933
- const rows = (0, import_react10.useMemo)(() => table.getFilteredRowModel().rows, [table, columnFilters]);
2934
- const searchFilteredData = (0, import_react10.useMemo)(() => {
3450
+ const rows = (0, import_react11.useMemo)(() => table.getFilteredRowModel().rows, [table, columnFilters]);
3451
+ const searchFilteredData = (0, import_react11.useMemo)(() => {
2935
3452
  if (!globalSearchTerm.trim() || !enableSearch) {
2936
3453
  return rows;
2937
3454
  }
@@ -2949,22 +3466,22 @@ function DataGrid({
2949
3466
  });
2950
3467
  }, [rows, globalSearchTerm, enableSearch, columnKeys]);
2951
3468
  const totalSearchedRows = searchFilteredData.length;
2952
- const totalPages = (0, import_react10.useMemo)(() => {
3469
+ const totalPages = (0, import_react11.useMemo)(() => {
2953
3470
  if (!enablePagination)
2954
3471
  return 1;
2955
3472
  return Math.max(1, Math.ceil(totalSearchedRows / pageSize));
2956
3473
  }, [enablePagination, totalSearchedRows, pageSize]);
2957
- const paginatedRows = (0, import_react10.useMemo)(() => {
3474
+ const paginatedRows = (0, import_react11.useMemo)(() => {
2958
3475
  if (!enablePagination)
2959
3476
  return searchFilteredData;
2960
3477
  const start = (currentPage - 1) * pageSize;
2961
3478
  const end = start + pageSize;
2962
3479
  return searchFilteredData.slice(start, end);
2963
3480
  }, [enablePagination, searchFilteredData, currentPage, pageSize]);
2964
- (0, import_react10.useEffect)(() => {
3481
+ (0, import_react11.useEffect)(() => {
2965
3482
  setCurrentPage(1);
2966
3483
  }, [columnFilters, globalSearchTerm]);
2967
- const selectionBounds = (0, import_react10.useMemo)(() => {
3484
+ const selectionBounds = (0, import_react11.useMemo)(() => {
2968
3485
  if (!selectionStart || !selectionEnd)
2969
3486
  return null;
2970
3487
  return {
@@ -2974,7 +3491,7 @@ function DataGrid({
2974
3491
  maxCol: Math.max(selectionStart.col, selectionEnd.col)
2975
3492
  };
2976
3493
  }, [selectionStart, selectionEnd]);
2977
- const selectionStats = (0, import_react10.useMemo)(() => {
3494
+ const selectionStats = (0, import_react11.useMemo)(() => {
2978
3495
  if (!selectionBounds)
2979
3496
  return null;
2980
3497
  const { minRow, maxRow, minCol, maxCol } = selectionBounds;
@@ -3004,7 +3521,7 @@ function DataGrid({
3004
3521
  const avg = sum / values.length;
3005
3522
  return { count, sum, avg, numericCount: values.length };
3006
3523
  }, [selectionBounds, rows, columnKeys]);
3007
- (0, import_react10.useEffect)(() => {
3524
+ (0, import_react11.useEffect)(() => {
3008
3525
  if (typeof document === "undefined")
3009
3526
  return;
3010
3527
  if (data.length === 0)
@@ -3028,7 +3545,7 @@ function DataGrid({
3028
3545
  }
3029
3546
  setColumnWidths(widths);
3030
3547
  }, [data, columnKeys]);
3031
- const startColumnResize = (0, import_react10.useCallback)(
3548
+ const startColumnResize = (0, import_react11.useCallback)(
3032
3549
  (columnId, event) => {
3033
3550
  if (!enableColumnResize)
3034
3551
  return;
@@ -3040,7 +3557,7 @@ function DataGrid({
3040
3557
  },
3041
3558
  [enableColumnResize, columnWidths]
3042
3559
  );
3043
- (0, import_react10.useEffect)(() => {
3560
+ (0, import_react11.useEffect)(() => {
3044
3561
  if (!resizingColumnId)
3045
3562
  return;
3046
3563
  const handleResizeMove = (event) => {
@@ -3061,7 +3578,7 @@ function DataGrid({
3061
3578
  document.removeEventListener("mouseup", handleResizeEnd);
3062
3579
  };
3063
3580
  }, [resizingColumnId, resizeStartX, resizeStartWidth]);
3064
- const startVerticalResize = (0, import_react10.useCallback)(
3581
+ const startVerticalResize = (0, import_react11.useCallback)(
3065
3582
  (event) => {
3066
3583
  if (!enableVerticalResize)
3067
3584
  return;
@@ -3072,7 +3589,7 @@ function DataGrid({
3072
3589
  },
3073
3590
  [enableVerticalResize, gridHeight]
3074
3591
  );
3075
- (0, import_react10.useEffect)(() => {
3592
+ (0, import_react11.useEffect)(() => {
3076
3593
  if (!isResizingVertically)
3077
3594
  return;
3078
3595
  const handleVerticalResizeMove = (event) => {
@@ -3090,7 +3607,7 @@ function DataGrid({
3090
3607
  document.removeEventListener("mouseup", handleVerticalResizeEnd);
3091
3608
  };
3092
3609
  }, [isResizingVertically, verticalResizeStartY, verticalResizeStartHeight, minHeight, maxHeight]);
3093
- const handleExport = (0, import_react10.useCallback)(() => {
3610
+ const handleExport = (0, import_react11.useCallback)(() => {
3094
3611
  if (viewMode === "pivot") {
3095
3612
  if (!pivotResult)
3096
3613
  return;
@@ -3136,7 +3653,7 @@ function DataGrid({
3136
3653
  columnKeys,
3137
3654
  onExport
3138
3655
  ]);
3139
- const copySelectionToClipboard = (0, import_react10.useCallback)(() => {
3656
+ const copySelectionToClipboard = (0, import_react11.useCallback)(() => {
3140
3657
  if (!selectionBounds || !enableClipboard)
3141
3658
  return;
3142
3659
  const text = formatSelectionForClipboard(
@@ -3161,7 +3678,7 @@ function DataGrid({
3161
3678
  }
3162
3679
  );
3163
3680
  }, [selectionBounds, enableClipboard, rows, columnKeys, onCopy]);
3164
- const handleMouseDown = (0, import_react10.useCallback)(
3681
+ const handleMouseDown = (0, import_react11.useCallback)(
3165
3682
  (rowIndex, colIndex, event) => {
3166
3683
  event.preventDefault();
3167
3684
  if (event.shiftKey && selectedCell) {
@@ -3185,7 +3702,7 @@ function DataGrid({
3185
3702
  },
3186
3703
  [selectedCell, rows, columnKeys, onCellClick]
3187
3704
  );
3188
- const handleMouseEnter = (0, import_react10.useCallback)(
3705
+ const handleMouseEnter = (0, import_react11.useCallback)(
3189
3706
  (rowIndex, colIndex) => {
3190
3707
  if (isSelecting) {
3191
3708
  setSelectionEnd({ row: rowIndex, col: colIndex });
@@ -3193,12 +3710,12 @@ function DataGrid({
3193
3710
  },
3194
3711
  [isSelecting]
3195
3712
  );
3196
- (0, import_react10.useEffect)(() => {
3713
+ (0, import_react11.useEffect)(() => {
3197
3714
  const handleMouseUp = () => setIsSelecting(false);
3198
3715
  document.addEventListener("mouseup", handleMouseUp);
3199
3716
  return () => document.removeEventListener("mouseup", handleMouseUp);
3200
3717
  }, []);
3201
- (0, import_react10.useEffect)(() => {
3718
+ (0, import_react11.useEffect)(() => {
3202
3719
  const handleKeydown = (event) => {
3203
3720
  if ((event.ctrlKey || event.metaKey) && event.key === "c" && selectionBounds) {
3204
3721
  event.preventDefault();
@@ -3216,7 +3733,7 @@ function DataGrid({
3216
3733
  document.addEventListener("keydown", handleKeydown);
3217
3734
  return () => document.removeEventListener("keydown", handleKeydown);
3218
3735
  }, [selectionBounds, copySelectionToClipboard]);
3219
- const openFilterDropdown = (0, import_react10.useCallback)(
3736
+ const openFilterDropdown = (0, import_react11.useCallback)(
3220
3737
  (columnId, event) => {
3221
3738
  event.stopPropagation();
3222
3739
  const target = event.currentTarget;
@@ -3245,22 +3762,22 @@ function DataGrid({
3245
3762
  },
3246
3763
  []
3247
3764
  );
3248
- const closeFilterDropdown = (0, import_react10.useCallback)(() => {
3765
+ const closeFilterDropdown = (0, import_react11.useCallback)(() => {
3249
3766
  setActiveFilterColumn(null);
3250
3767
  }, []);
3251
- const handleFilter = (0, import_react10.useCallback)(
3768
+ const handleFilter = (0, import_react11.useCallback)(
3252
3769
  (columnId, values) => {
3253
3770
  setColumnFilter(columnId, values);
3254
3771
  },
3255
3772
  [setColumnFilter]
3256
3773
  );
3257
- const handleRangeFilter = (0, import_react10.useCallback)(
3774
+ const handleRangeFilter = (0, import_react11.useCallback)(
3258
3775
  (columnId, range) => {
3259
3776
  setNumericRangeFilter(columnId, range);
3260
3777
  },
3261
3778
  [setNumericRangeFilter]
3262
3779
  );
3263
- const handleSort = (0, import_react10.useCallback)(
3780
+ const handleSort = (0, import_react11.useCallback)(
3264
3781
  (columnId, direction) => {
3265
3782
  if (direction === null) {
3266
3783
  const current = getSortDirection(columnId);
@@ -3284,7 +3801,7 @@ function DataGrid({
3284
3801
  },
3285
3802
  [getSortDirection, toggleSort]
3286
3803
  );
3287
- const isCellSelected = (0, import_react10.useCallback)(
3804
+ const isCellSelected = (0, import_react11.useCallback)(
3288
3805
  (rowIndex, colIndex) => {
3289
3806
  if (!selectionBounds) {
3290
3807
  return selectedCell?.row === rowIndex && selectedCell?.col === colIndex;
@@ -3326,30 +3843,30 @@ function DataGrid({
3326
3843
  }
3327
3844
  return String(value);
3328
3845
  };
3329
- const totalTableWidth = (0, import_react10.useMemo)(() => {
3846
+ const totalTableWidth = (0, import_react11.useMemo)(() => {
3330
3847
  return columnKeys.reduce((sum, key) => sum + (columnWidths[key] || MIN_COL_WIDTH), 0);
3331
3848
  }, [columnKeys, columnWidths]);
3332
3849
  const activeFilterCount = columnFilters.length;
3333
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3850
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3334
3851
  "div",
3335
3852
  {
3336
3853
  className: `vpg-data-grid vpg-font-${currentFontSize} vpg-theme-${currentTheme} ${stripedRows ? "vpg-striped" : ""} ${resizingColumnId ? "vpg-resizing" : ""} ${isResizingVertically ? "vpg-resizing-vertical" : ""}`,
3337
3854
  style: { height: `${gridHeight}px` },
3338
3855
  children: [
3339
- showCopyToast && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-toast", children: [
3340
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
3856
+ showCopyToast && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-toast", children: [
3857
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
3341
3858
  copyToastMessage
3342
3859
  ] }),
3343
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-toolbar", children: [
3344
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-toolbar-left", children: [
3345
- showPivot && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-view-toggle", children: [
3346
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3860
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-toolbar", children: [
3861
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-toolbar-left", children: [
3862
+ showPivot && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-view-toggle", children: [
3863
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3347
3864
  "button",
3348
3865
  {
3349
3866
  className: `vpg-view-btn ${viewMode === "grid" ? "active" : ""}`,
3350
3867
  onClick: () => setViewMode("grid"),
3351
3868
  children: [
3352
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3869
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3353
3870
  "path",
3354
3871
  {
3355
3872
  strokeLinecap: "round",
@@ -3362,13 +3879,13 @@ function DataGrid({
3362
3879
  ]
3363
3880
  }
3364
3881
  ),
3365
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3882
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3366
3883
  "button",
3367
3884
  {
3368
3885
  className: `vpg-view-btn vpg-pivot-btn ${viewMode === "pivot" ? "active" : ""}`,
3369
3886
  onClick: () => setViewMode("pivot"),
3370
3887
  children: [
3371
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3888
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3372
3889
  "path",
3373
3890
  {
3374
3891
  strokeLinecap: "round",
@@ -3380,16 +3897,37 @@ function DataGrid({
3380
3897
  "Pivot"
3381
3898
  ]
3382
3899
  }
3900
+ ),
3901
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3902
+ "button",
3903
+ {
3904
+ className: `vpg-view-btn vpg-chart-btn ${viewMode === "chart" ? "active" : ""} ${!canUseCharts ? "vpg-pro-feature" : ""}`,
3905
+ title: canUseCharts ? "Chart Builder" : "Chart Builder (Pro feature)",
3906
+ onClick: () => canUseCharts && setViewMode("chart"),
3907
+ children: [
3908
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3909
+ "path",
3910
+ {
3911
+ strokeLinecap: "round",
3912
+ strokeLinejoin: "round",
3913
+ strokeWidth: 2,
3914
+ 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"
3915
+ }
3916
+ ) }),
3917
+ "Chart",
3918
+ !canUseCharts && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-pro-badge", children: "Pro" })
3919
+ ]
3920
+ }
3383
3921
  )
3384
3922
  ] }),
3385
- viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3386
- enableSearch && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-search-container", children: !showSearchInput ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3923
+ viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
3924
+ enableSearch && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-search-container", children: !showSearchInput ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3387
3925
  "button",
3388
3926
  {
3389
3927
  className: "vpg-icon-btn",
3390
3928
  title: "Search (Ctrl+F)",
3391
3929
  onClick: () => setShowSearchInput(true),
3392
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3930
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3393
3931
  "path",
3394
3932
  {
3395
3933
  strokeLinecap: "round",
@@ -3399,15 +3937,15 @@ function DataGrid({
3399
3937
  }
3400
3938
  ) })
3401
3939
  }
3402
- ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-search-box", children: [
3403
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3940
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-search-box", children: [
3941
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3404
3942
  "svg",
3405
3943
  {
3406
3944
  className: "vpg-search-icon",
3407
3945
  fill: "none",
3408
3946
  stroke: "currentColor",
3409
3947
  viewBox: "0 0 24 24",
3410
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3948
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3411
3949
  "path",
3412
3950
  {
3413
3951
  strokeLinecap: "round",
@@ -3418,7 +3956,7 @@ function DataGrid({
3418
3956
  )
3419
3957
  }
3420
3958
  ),
3421
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3959
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3422
3960
  "input",
3423
3961
  {
3424
3962
  type: "text",
@@ -3435,14 +3973,14 @@ function DataGrid({
3435
3973
  autoFocus: true
3436
3974
  }
3437
3975
  ),
3438
- globalSearchTerm && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: "vpg-search-clear", onClick: () => setGlobalSearchTerm(""), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3976
+ globalSearchTerm && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "vpg-search-clear", onClick: () => setGlobalSearchTerm(""), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3439
3977
  "svg",
3440
3978
  {
3441
3979
  className: "vpg-icon-xs",
3442
3980
  fill: "none",
3443
3981
  stroke: "currentColor",
3444
3982
  viewBox: "0 0 24 24",
3445
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3983
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3446
3984
  "path",
3447
3985
  {
3448
3986
  strokeLinecap: "round",
@@ -3454,9 +3992,9 @@ function DataGrid({
3454
3992
  }
3455
3993
  ) })
3456
3994
  ] }) }),
3457
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-font-size-control", children: [
3458
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-label", children: "Size:" }),
3459
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-font-size-toggle", children: fontSizeOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3995
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-font-size-control", children: [
3996
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-label", children: "Size:" }),
3997
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-font-size-toggle", children: fontSizeOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3460
3998
  "button",
3461
3999
  {
3462
4000
  className: `vpg-font-size-btn ${currentFontSize === opt.value ? "active" : ""}`,
@@ -3466,8 +4004,8 @@ function DataGrid({
3466
4004
  opt.value
3467
4005
  )) })
3468
4006
  ] }),
3469
- activeFilterCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-filter-info", children: [
3470
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4007
+ activeFilterCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-filter-info", children: [
4008
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3471
4009
  "path",
3472
4010
  {
3473
4011
  fillRule: "evenodd",
@@ -3475,28 +4013,28 @@ function DataGrid({
3475
4013
  clipRule: "evenodd"
3476
4014
  }
3477
4015
  ) }),
3478
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
4016
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
3479
4017
  activeFilterCount,
3480
4018
  " ",
3481
4019
  "filter",
3482
4020
  activeFilterCount > 1 ? "s" : ""
3483
4021
  ] })
3484
4022
  ] }),
3485
- globalSearchTerm && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-search-info", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
4023
+ globalSearchTerm && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-search-info", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
3486
4024
  totalSearchedRows,
3487
4025
  " ",
3488
4026
  "match",
3489
4027
  totalSearchedRows !== 1 ? "es" : ""
3490
4028
  ] }) })
3491
4029
  ] }),
3492
- viewMode === "pivot" && canUsePivot && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3493
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4030
+ viewMode === "pivot" && canUsePivot && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4031
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3494
4032
  "button",
3495
4033
  {
3496
4034
  className: `vpg-config-toggle ${showPivotConfig ? "active" : ""}`,
3497
4035
  onClick: () => setShowPivotConfig(!showPivotConfig),
3498
4036
  children: [
3499
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4037
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3500
4038
  "path",
3501
4039
  {
3502
4040
  strokeLinecap: "round",
@@ -3511,8 +4049,8 @@ function DataGrid({
3511
4049
  ]
3512
4050
  }
3513
4051
  ),
3514
- pivotIsConfigured && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-pivot-status", children: [
3515
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4052
+ pivotIsConfigured && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-pivot-status", children: [
4053
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3516
4054
  "path",
3517
4055
  {
3518
4056
  fillRule: "evenodd",
@@ -3520,13 +4058,13 @@ function DataGrid({
3520
4058
  clipRule: "evenodd"
3521
4059
  }
3522
4060
  ) }),
3523
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Pivot configured" })
4061
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Pivot configured" })
3524
4062
  ] })
3525
4063
  ] })
3526
4064
  ] }),
3527
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-toolbar-right", children: [
3528
- viewMode === "grid" && activeFilterCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("button", { className: "vpg-clear-filters", onClick: clearAllFilters, children: [
3529
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4065
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-toolbar-right", children: [
4066
+ viewMode === "grid" && activeFilterCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("button", { className: "vpg-clear-filters", onClick: clearAllFilters, children: [
4067
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3530
4068
  "path",
3531
4069
  {
3532
4070
  strokeLinecap: "round",
@@ -3537,13 +4075,13 @@ function DataGrid({
3537
4075
  ) }),
3538
4076
  "Clear Filters"
3539
4077
  ] }),
3540
- enableClipboard && selectionBounds && viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4078
+ enableClipboard && selectionBounds && viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3541
4079
  "button",
3542
4080
  {
3543
4081
  className: "vpg-icon-btn",
3544
4082
  title: "Copy selection (Ctrl+C)",
3545
4083
  onClick: copySelectionToClipboard,
3546
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4084
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3547
4085
  "path",
3548
4086
  {
3549
4087
  strokeLinecap: "round",
@@ -3554,14 +4092,14 @@ function DataGrid({
3554
4092
  ) })
3555
4093
  }
3556
4094
  ),
3557
- enableExport && viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4095
+ enableExport && viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3558
4096
  "button",
3559
4097
  {
3560
4098
  className: "vpg-export-btn",
3561
4099
  title: "Export to CSV",
3562
4100
  onClick: handleExport,
3563
4101
  children: [
3564
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4102
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3565
4103
  "path",
3566
4104
  {
3567
4105
  strokeLinecap: "round",
@@ -3574,7 +4112,7 @@ function DataGrid({
3574
4112
  ]
3575
4113
  }
3576
4114
  ),
3577
- enableExport && viewMode === "pivot" && pivotIsConfigured && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4115
+ enableExport && viewMode === "pivot" && pivotIsConfigured && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3578
4116
  "button",
3579
4117
  {
3580
4118
  className: `vpg-export-btn ${!isPro ? "vpg-export-btn-disabled" : ""}`,
@@ -3582,7 +4120,7 @@ function DataGrid({
3582
4120
  title: isPro ? "Export Pivot to CSV" : "Export Pivot to CSV (Pro feature)",
3583
4121
  onClick: () => isPro && handleExport(),
3584
4122
  children: [
3585
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4123
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3586
4124
  "path",
3587
4125
  {
3588
4126
  strokeLinecap: "round",
@@ -3598,13 +4136,13 @@ function DataGrid({
3598
4136
  )
3599
4137
  ] })
3600
4138
  ] }),
3601
- viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { ref: tableContainerRef, className: "vpg-grid-container", tabIndex: 0, children: [
3602
- loading && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-loading", children: [
3603
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-spinner" }),
3604
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Loading data..." })
4139
+ viewMode === "grid" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { ref: tableContainerRef, className: "vpg-grid-container", tabIndex: 0, children: [
4140
+ loading && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-loading", children: [
4141
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-spinner" }),
4142
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Loading data..." })
3605
4143
  ] }),
3606
- !loading && data.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-empty", children: [
3607
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4144
+ !loading && data.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-empty", children: [
4145
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3608
4146
  "path",
3609
4147
  {
3610
4148
  strokeLinecap: "round",
@@ -3613,10 +4151,10 @@ function DataGrid({
3613
4151
  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"
3614
4152
  }
3615
4153
  ) }) }),
3616
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "No data available" })
4154
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "No data available" })
3617
4155
  ] }),
3618
- !loading && data.length > 0 && filteredRowCount === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-empty", children: [
3619
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-empty-icon vpg-warning", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4156
+ !loading && data.length > 0 && filteredRowCount === 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-empty", children: [
4157
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-empty-icon vpg-warning", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon-lg", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3620
4158
  "path",
3621
4159
  {
3622
4160
  strokeLinecap: "round",
@@ -3625,11 +4163,11 @@ function DataGrid({
3625
4163
  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"
3626
4164
  }
3627
4165
  ) }) }),
3628
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "No matching records" }),
3629
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: "vpg-clear-link", onClick: clearAllFilters, children: "Clear all filters" })
4166
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "No matching records" }),
4167
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "vpg-clear-link", onClick: clearAllFilters, children: "Clear all filters" })
3630
4168
  ] }),
3631
- !loading && filteredRowCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-table-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("table", { className: "vpg-table", style: { minWidth: `${totalTableWidth}px` }, children: [
3632
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: columnKeys.map((colId) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4169
+ !loading && filteredRowCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-table-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("table", { className: "vpg-table", style: { minWidth: `${totalTableWidth}px` }, children: [
4170
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("tr", { children: columnKeys.map((colId) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3633
4171
  "th",
3634
4172
  {
3635
4173
  className: `vpg-header-cell ${hasActiveFilter(colId) ? "vpg-has-filter" : ""} ${getSortDirection(colId) !== null ? "vpg-is-sorted" : ""} ${activeFilterColumn === colId ? "vpg-is-active" : ""}`,
@@ -3644,16 +4182,16 @@ function DataGrid({
3644
4182
  }
3645
4183
  },
3646
4184
  children: [
3647
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-header-content", children: [
3648
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-header-text", children: colId }),
3649
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-header-icons", children: [
3650
- getSortDirection(colId) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-sort-indicator", children: getSortDirection(colId) === "asc" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4185
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-header-content", children: [
4186
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-header-text", children: colId }),
4187
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-header-icons", children: [
4188
+ getSortDirection(colId) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-sort-indicator", children: getSortDirection(colId) === "asc" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3651
4189
  "svg",
3652
4190
  {
3653
4191
  className: "vpg-icon-sm",
3654
4192
  fill: "currentColor",
3655
4193
  viewBox: "0 0 20 20",
3656
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4194
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3657
4195
  "path",
3658
4196
  {
3659
4197
  fillRule: "evenodd",
@@ -3662,13 +4200,13 @@ function DataGrid({
3662
4200
  }
3663
4201
  )
3664
4202
  }
3665
- ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4203
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3666
4204
  "svg",
3667
4205
  {
3668
4206
  className: "vpg-icon-sm",
3669
4207
  fill: "currentColor",
3670
4208
  viewBox: "0 0 20 20",
3671
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4209
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3672
4210
  "path",
3673
4211
  {
3674
4212
  fillRule: "evenodd",
@@ -3678,13 +4216,13 @@ function DataGrid({
3678
4216
  )
3679
4217
  }
3680
4218
  ) }),
3681
- hasActiveFilter(colId) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-filter-indicator", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4219
+ hasActiveFilter(colId) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-filter-indicator", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3682
4220
  "svg",
3683
4221
  {
3684
4222
  className: "vpg-icon-xs",
3685
4223
  fill: "currentColor",
3686
4224
  viewBox: "0 0 20 20",
3687
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4225
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3688
4226
  "path",
3689
4227
  {
3690
4228
  fillRule: "evenodd",
@@ -3694,14 +4232,14 @@ function DataGrid({
3694
4232
  )
3695
4233
  }
3696
4234
  ) }),
3697
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-dropdown-arrow", title: "Filter & Sort", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4235
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-dropdown-arrow", title: "Filter & Sort", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3698
4236
  "svg",
3699
4237
  {
3700
4238
  className: "vpg-icon-sm",
3701
4239
  fill: "none",
3702
4240
  stroke: "currentColor",
3703
4241
  viewBox: "0 0 24 24",
3704
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4242
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3705
4243
  "path",
3706
4244
  {
3707
4245
  strokeLinecap: "round",
@@ -3714,7 +4252,7 @@ function DataGrid({
3714
4252
  ) })
3715
4253
  ] })
3716
4254
  ] }),
3717
- enableColumnResize && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4255
+ enableColumnResize && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3718
4256
  "div",
3719
4257
  {
3720
4258
  className: "vpg-resize-handle",
@@ -3725,7 +4263,7 @@ function DataGrid({
3725
4263
  },
3726
4264
  colId
3727
4265
  )) }) }),
3728
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tbody", { ref: tableBodyRef, children: paginatedRows.map((row, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { className: "vpg-row", children: columnKeys.map((colId, colIndex) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4266
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("tbody", { ref: tableBodyRef, children: paginatedRows.map((row, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("tr", { className: "vpg-row", children: columnKeys.map((colId, colIndex) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3729
4267
  "td",
3730
4268
  {
3731
4269
  className: `vpg-cell ${isCellSelected(rowIndex, colIndex) ? "vpg-selected" : ""} ${getColumnStats(colId).type === "number" ? "vpg-is-number" : ""}`,
@@ -3743,8 +4281,8 @@ function DataGrid({
3743
4281
  )) }, row.id)) })
3744
4282
  ] }) })
3745
4283
  ] }),
3746
- viewMode === "pivot" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-pivot-container", children: [
3747
- showPivotConfig && canUsePivot && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-pivot-config-panel", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4284
+ viewMode === "pivot" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-pivot-container", children: [
4285
+ showPivotConfig && canUsePivot && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-pivot-config-panel", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3748
4286
  PivotConfig,
3749
4287
  {
3750
4288
  availableFields: pivotAvailableFields,
@@ -3772,7 +4310,7 @@ function DataGrid({
3772
4310
  onUpdateCalculatedField: addCalculatedField
3773
4311
  }
3774
4312
  ) }),
3775
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: `vpg-pivot-main ${!showPivotConfig ? "vpg-full-width" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4313
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `vpg-pivot-main ${!showPivotConfig ? "vpg-full-width" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3776
4314
  PivotSkeleton,
3777
4315
  {
3778
4316
  rowFields: pivotRowFields,
@@ -3798,47 +4336,78 @@ function DataGrid({
3798
4336
  }
3799
4337
  ) })
3800
4338
  ] }),
3801
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-footer", children: [
3802
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-footer-left", children: viewMode === "grid" ? enablePagination ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3803
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
4339
+ viewMode === "chart" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-chart-view", children: [
4340
+ activeFilterInfo && activeFilterInfo.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-chart-filter-bar", children: [
4341
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("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" }) }),
4342
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
4343
+ "Chart showing",
4344
+ filteredRowCount.toLocaleString(),
4345
+ " ",
4346
+ "of",
4347
+ totalRowCount.toLocaleString(),
4348
+ " ",
4349
+ "records"
4350
+ ] }),
4351
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "vpg-chart-clear-filters", onClick: clearAllFilters, children: "Clear filters" })
4352
+ ] }),
4353
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4354
+ ChartBuilder,
4355
+ {
4356
+ data: filteredDataForPivot,
4357
+ theme: currentTheme,
4358
+ onConfigChange: handleChartConfigChange
4359
+ }
4360
+ )
4361
+ ] }),
4362
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-footer", children: [
4363
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-footer-left", children: viewMode === "grid" ? enablePagination ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4364
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
3804
4365
  ((currentPage - 1) * pageSize + 1).toLocaleString(),
3805
4366
  "-",
3806
4367
  Math.min(currentPage * pageSize, totalSearchedRows).toLocaleString()
3807
4368
  ] }),
3808
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-separator", children: "of" }),
3809
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: totalSearchedRows.toLocaleString() }),
3810
- totalSearchedRows !== totalRowCount && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-filtered-note", children: [
4369
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-separator", children: "of" }),
4370
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: totalSearchedRows.toLocaleString() }),
4371
+ totalSearchedRows !== totalRowCount && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "vpg-filtered-note", children: [
3811
4372
  "(",
3812
4373
  totalRowCount.toLocaleString(),
3813
4374
  " ",
3814
4375
  "total)"
3815
4376
  ] })
3816
- ] }) : filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
4377
+ ] }) : filteredRowCount === totalRowCount && totalSearchedRows === totalRowCount ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
3817
4378
  totalRowCount.toLocaleString(),
3818
4379
  " ",
3819
4380
  "records"
3820
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3821
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-filtered-count", children: totalSearchedRows.toLocaleString() }),
3822
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-separator", children: "of" }),
3823
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: totalRowCount.toLocaleString() }),
3824
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-separator", children: "records" })
3825
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3826
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-pivot-label", children: "Pivot Table" }),
3827
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-separator", children: "\u2022" }),
3828
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
4381
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4382
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-filtered-count", children: totalSearchedRows.toLocaleString() }),
4383
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-separator", children: "of" }),
4384
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: totalRowCount.toLocaleString() }),
4385
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-separator", children: "records" })
4386
+ ] }) : viewMode === "pivot" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4387
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-pivot-label", children: "Pivot Table" }),
4388
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-separator", children: "\u2022" }),
4389
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
3829
4390
  totalRowCount.toLocaleString(),
3830
4391
  " ",
3831
4392
  "source records"
3832
4393
  ] })
4394
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4395
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-chart-label", children: "Chart Builder" }),
4396
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-separator", children: "\u2022" }),
4397
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
4398
+ totalRowCount.toLocaleString(),
4399
+ " ",
4400
+ "records"
4401
+ ] })
3833
4402
  ] }) }),
3834
- enablePagination && viewMode === "grid" && totalPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-pagination", children: [
3835
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4403
+ enablePagination && viewMode === "grid" && totalPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-pagination", children: [
4404
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3836
4405
  "button",
3837
4406
  {
3838
4407
  className: "vpg-page-btn",
3839
4408
  disabled: currentPage === 1,
3840
4409
  onClick: () => setCurrentPage(1),
3841
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4410
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3842
4411
  "path",
3843
4412
  {
3844
4413
  strokeLinecap: "round",
@@ -3849,13 +4418,13 @@ function DataGrid({
3849
4418
  ) })
3850
4419
  }
3851
4420
  ),
3852
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4421
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3853
4422
  "button",
3854
4423
  {
3855
4424
  className: "vpg-page-btn",
3856
4425
  disabled: currentPage === 1,
3857
4426
  onClick: () => setCurrentPage((p) => Math.max(1, p - 1)),
3858
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4427
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3859
4428
  "path",
3860
4429
  {
3861
4430
  strokeLinecap: "round",
@@ -3866,7 +4435,7 @@ function DataGrid({
3866
4435
  ) })
3867
4436
  }
3868
4437
  ),
3869
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-page-info", children: [
4438
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "vpg-page-info", children: [
3870
4439
  "Page",
3871
4440
  " ",
3872
4441
  currentPage,
@@ -3875,13 +4444,13 @@ function DataGrid({
3875
4444
  " ",
3876
4445
  totalPages
3877
4446
  ] }),
3878
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4447
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3879
4448
  "button",
3880
4449
  {
3881
4450
  className: "vpg-page-btn",
3882
4451
  disabled: currentPage === totalPages,
3883
4452
  onClick: () => setCurrentPage((p) => Math.min(totalPages, p + 1)),
3884
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4453
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3885
4454
  "path",
3886
4455
  {
3887
4456
  strokeLinecap: "round",
@@ -3892,13 +4461,13 @@ function DataGrid({
3892
4461
  ) })
3893
4462
  }
3894
4463
  ),
3895
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4464
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3896
4465
  "button",
3897
4466
  {
3898
4467
  className: "vpg-page-btn",
3899
4468
  disabled: currentPage === totalPages,
3900
4469
  onClick: () => setCurrentPage(totalPages),
3901
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4470
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon-sm", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3902
4471
  "path",
3903
4472
  {
3904
4473
  strokeLinecap: "round",
@@ -3910,45 +4479,45 @@ function DataGrid({
3910
4479
  }
3911
4480
  )
3912
4481
  ] }),
3913
- viewMode === "grid" && selectionStats && selectionStats.count > 1 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-selection-stats", children: [
3914
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-stat", children: [
3915
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-label", children: "Count:" }),
3916
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-value", children: selectionStats.count })
4482
+ viewMode === "grid" && selectionStats && selectionStats.count > 1 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-selection-stats", children: [
4483
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "vpg-stat", children: [
4484
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-stat-label", children: "Count:" }),
4485
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-stat-value", children: selectionStats.count })
3917
4486
  ] }),
3918
- selectionStats.numericCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3919
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
3920
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-stat", children: [
3921
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-label", children: "Sum:" }),
3922
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
4487
+ selectionStats.numericCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
4488
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
4489
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "vpg-stat", children: [
4490
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-stat-label", children: "Sum:" }),
4491
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.sum) })
3923
4492
  ] }),
3924
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
3925
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-stat", children: [
3926
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-label", children: "Avg:" }),
3927
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
4493
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-stat-divider", children: "|" }),
4494
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "vpg-stat", children: [
4495
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-stat-label", children: "Avg:" }),
4496
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-stat-value", children: formatStatValue(selectionStats.avg) })
3928
4497
  ] })
3929
4498
  ] })
3930
4499
  ] }),
3931
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-footer-right", children: isDemo ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-demo-banner", children: [
3932
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-demo-badge", children: "DEMO" }),
3933
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Pro features enabled" }),
3934
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", children: "Get License \u2192" })
3935
- ] }) : showWatermark ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "vpg-watermark-inline", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: [
3936
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("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: [
3937
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "3", y: "3", width: "7", height: "7" }),
3938
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "14", y: "3", width: "7", height: "7" }),
3939
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "14", y: "14", width: "7", height: "7" }),
3940
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "3", y: "14", width: "7", height: "7" })
4500
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-footer-right", children: isDemo ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-demo-banner", children: [
4501
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-demo-badge", children: "DEMO" }),
4502
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Pro features enabled" }),
4503
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("a", { href: "https://tiny-pivot.com/#pricing", target: "_blank", rel: "noopener noreferrer", children: "Get License \u2192" })
4504
+ ] }) : showWatermark ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "vpg-watermark-inline", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("a", { href: "https://tiny-pivot.com", target: "_blank", rel: "noopener noreferrer", children: [
4505
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("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: [
4506
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("rect", { x: "3", y: "3", width: "7", height: "7" }),
4507
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("rect", { x: "14", y: "3", width: "7", height: "7" }),
4508
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("rect", { x: "14", y: "14", width: "7", height: "7" }),
4509
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("rect", { x: "3", y: "14", width: "7", height: "7" })
3941
4510
  ] }),
3942
4511
  "Powered by TinyPivot"
3943
4512
  ] }) }) : null })
3944
4513
  ] }),
3945
- enableVerticalResize && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "vpg-vertical-resize-handle", onMouseDown: startVerticalResize, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "vpg-resize-grip", children: [
3946
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", {}),
3947
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", {}),
3948
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", {})
4514
+ enableVerticalResize && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "vpg-vertical-resize-handle", onMouseDown: startVerticalResize, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-resize-grip", children: [
4515
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", {}),
4516
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", {}),
4517
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", {})
3949
4518
  ] }) }),
3950
4519
  activeFilterColumn && typeof document !== "undefined" && (0, import_react_dom2.createPortal)(
3951
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4520
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3952
4521
  "div",
3953
4522
  {
3954
4523
  className: "vpg-filter-portal",
@@ -3959,7 +4528,7 @@ function DataGrid({
3959
4528
  maxHeight: `${filterDropdownPosition.maxHeight}px`,
3960
4529
  zIndex: 9999
3961
4530
  },
3962
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4531
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3963
4532
  ColumnFilter,
3964
4533
  {
3965
4534
  columnId: activeFilterColumn,