@smallwebco/tinypivot-react 1.0.50 → 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 +1208 -639
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1167 -596
- package/dist/index.js.map +1 -1
- package/dist/style.css +439 -0
- package/package.json +4 -2
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: () =>
|
|
42
|
+
formatCellValue: () => import_tinypivot_core3.formatCellValue,
|
|
33
43
|
formatSelectionForClipboard: () => formatSelectionForClipboard,
|
|
34
|
-
getAggregationLabel: () =>
|
|
35
|
-
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
|
|
746
|
+
var import_react4 = require("react");
|
|
239
747
|
|
|
240
748
|
// src/components/NumericRangeFilter.tsx
|
|
241
|
-
var
|
|
242
|
-
var
|
|
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,
|
|
250
|
-
const [localMax, setLocalMax] = (0,
|
|
251
|
-
const step = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
849
|
+
(0, import_react3.useEffect)(() => {
|
|
342
850
|
setLocalMin(currentRange?.min ?? null);
|
|
343
851
|
setLocalMax(currentRange?.max ?? null);
|
|
344
852
|
}, [currentRange]);
|
|
345
|
-
return /* @__PURE__ */ (0,
|
|
346
|
-
/* @__PURE__ */ (0,
|
|
347
|
-
/* @__PURE__ */ (0,
|
|
348
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
356
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
396
|
-
/* @__PURE__ */ (0,
|
|
397
|
-
/* @__PURE__ */ (0,
|
|
398
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
412
|
-
/* @__PURE__ */ (0,
|
|
413
|
-
/* @__PURE__ */ (0,
|
|
414
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
429
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
450
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
463
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
980
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
|
|
473
981
|
"Showing values",
|
|
474
982
|
" ",
|
|
475
|
-
localMin !== null && /* @__PURE__ */ (0,
|
|
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,
|
|
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
|
|
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,
|
|
503
|
-
const [localSelected, setLocalSelected] = (0,
|
|
504
|
-
const dropdownRef = (0,
|
|
505
|
-
const searchInputRef = (0,
|
|
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,
|
|
508
|
-
const [localRange, setLocalRange] = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
1056
|
+
const clearAll = (0, import_react4.useCallback)(() => {
|
|
549
1057
|
setLocalSelected(/* @__PURE__ */ new Set());
|
|
550
1058
|
}, []);
|
|
551
|
-
const applyFilter = (0,
|
|
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,
|
|
1067
|
+
const sortAscending = (0, import_react4.useCallback)(() => {
|
|
560
1068
|
onSort(sortDirection === "asc" ? null : "asc");
|
|
561
1069
|
}, [sortDirection, onSort]);
|
|
562
|
-
const sortDescending = (0,
|
|
1070
|
+
const sortDescending = (0, import_react4.useCallback)(() => {
|
|
563
1071
|
onSort(sortDirection === "desc" ? null : "desc");
|
|
564
1072
|
}, [sortDirection, onSort]);
|
|
565
|
-
const clearFilter = (0,
|
|
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,
|
|
1078
|
+
const handleRangeChange = (0, import_react4.useCallback)((range) => {
|
|
571
1079
|
setLocalRange(range);
|
|
572
1080
|
}, []);
|
|
573
|
-
const applyRangeFilter = (0,
|
|
1081
|
+
const applyRangeFilter = (0, import_react4.useCallback)(() => {
|
|
574
1082
|
onRangeFilter?.(localRange);
|
|
575
1083
|
onClose();
|
|
576
1084
|
}, [localRange, onRangeFilter, onClose]);
|
|
577
|
-
const clearRangeFilter = (0,
|
|
1085
|
+
const clearRangeFilter = (0, import_react4.useCallback)(() => {
|
|
578
1086
|
setLocalRange(null);
|
|
579
1087
|
onRangeFilter?.(null);
|
|
580
1088
|
onClose();
|
|
581
1089
|
}, [onRangeFilter, onClose]);
|
|
582
|
-
(0,
|
|
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,
|
|
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,
|
|
1110
|
+
(0, import_react4.useEffect)(() => {
|
|
603
1111
|
searchInputRef.current?.focus();
|
|
604
1112
|
}, []);
|
|
605
|
-
(0,
|
|
1113
|
+
(0, import_react4.useEffect)(() => {
|
|
606
1114
|
setLocalSelected(new Set(selectedValues));
|
|
607
1115
|
}, [selectedValues]);
|
|
608
|
-
(0,
|
|
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,
|
|
615
|
-
/* @__PURE__ */ (0,
|
|
616
|
-
/* @__PURE__ */ (0,
|
|
617
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
624
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
1148
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: isNumericColumn ? "1\u21929" : "A\u2192Z" })
|
|
641
1149
|
]
|
|
642
1150
|
}
|
|
643
1151
|
),
|
|
644
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
666
|
-
isNumericColumn && /* @__PURE__ */ (0,
|
|
667
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
707
|
-
/* @__PURE__ */ (0,
|
|
708
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
1236
|
+
searchQuery && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: "vpg-clear-search", onClick: () => setSearchQuery(""), children: "\xD7" })
|
|
729
1237
|
] }),
|
|
730
|
-
/* @__PURE__ */ (0,
|
|
731
|
-
/* @__PURE__ */ (0,
|
|
732
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
744
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
757
|
-
allValues.map((value) => /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
1284
|
+
allValues.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "vpg-no-results", children: "No matching values" })
|
|
777
1285
|
] }),
|
|
778
|
-
/* @__PURE__ */ (0,
|
|
779
|
-
/* @__PURE__ */ (0,
|
|
780
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
784
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
794
|
-
/* @__PURE__ */ (0,
|
|
795
|
-
/* @__PURE__ */ (0,
|
|
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
|
|
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
|
|
1314
|
+
var import_tinypivot_core3 = require("@smallwebco/tinypivot-core");
|
|
807
1315
|
var import_react_table = require("@tanstack/react-table");
|
|
808
|
-
var
|
|
1316
|
+
var import_react5 = require("react");
|
|
809
1317
|
var multiSelectFilter = (row, columnId, filterValue) => {
|
|
810
1318
|
if (!filterValue)
|
|
811
1319
|
return true;
|
|
812
|
-
if ((0,
|
|
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,
|
|
837
|
-
const [columnFilters, setColumnFilters] = (0,
|
|
838
|
-
const [columnVisibility, setColumnVisibility] = (0,
|
|
839
|
-
const [globalFilter, setGlobalFilter] = (0,
|
|
840
|
-
const [columnStatsCache, setColumnStatsCache] = (0,
|
|
841
|
-
const dataSignature = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
1370
|
+
const clearStatsCache = (0, import_react5.useCallback)(() => {
|
|
863
1371
|
setColumnStatsCache({});
|
|
864
1372
|
}, []);
|
|
865
|
-
(0,
|
|
1373
|
+
(0, import_react5.useEffect)(() => {
|
|
866
1374
|
clearStatsCache();
|
|
867
1375
|
}, [dataSignature, clearStatsCache]);
|
|
868
|
-
const columnDefs = (0,
|
|
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,
|
|
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,
|
|
1416
|
+
const activeFilters = (0, import_react5.useMemo)(() => {
|
|
909
1417
|
return columnFilters.map((f) => {
|
|
910
1418
|
const filterValue = f.value;
|
|
911
|
-
if (filterValue && (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
1485
|
+
const clearAllFilters = (0, import_react5.useCallback)(() => {
|
|
978
1486
|
table.resetColumnFilters();
|
|
979
1487
|
setGlobalFilter("");
|
|
980
1488
|
setColumnFilters([]);
|
|
981
1489
|
}, [table]);
|
|
982
|
-
const getColumnFilterValues = (0,
|
|
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,
|
|
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,
|
|
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
|
|
1046
|
-
var
|
|
1553
|
+
var import_tinypivot_core4 = require("@smallwebco/tinypivot-core");
|
|
1554
|
+
var import_react6 = require("react");
|
|
1047
1555
|
function exportToCSV(data, columns, options) {
|
|
1048
|
-
(0,
|
|
1556
|
+
(0, import_tinypivot_core4.exportToCSV)(data, columns, options);
|
|
1049
1557
|
}
|
|
1050
1558
|
function exportPivotToCSV(pivotData, rowFields, columnFields, valueFields, options) {
|
|
1051
|
-
(0,
|
|
1559
|
+
(0, import_tinypivot_core4.exportPivotToCSV)(pivotData, rowFields, columnFields, valueFields, options);
|
|
1052
1560
|
}
|
|
1053
1561
|
function copyToClipboard(text, onSuccess, onError) {
|
|
1054
|
-
(0,
|
|
1562
|
+
(0, import_tinypivot_core4.copyToClipboard)(text, onSuccess, onError);
|
|
1055
1563
|
}
|
|
1056
1564
|
function formatSelectionForClipboard(rows, columns, selectionBounds) {
|
|
1057
|
-
return (0,
|
|
1565
|
+
return (0, import_tinypivot_core4.formatSelectionForClipboard)(rows, columns, selectionBounds);
|
|
1058
1566
|
}
|
|
1059
1567
|
function usePagination(data, options = {}) {
|
|
1060
|
-
const [pageSize, setPageSize] = (0,
|
|
1061
|
-
const [currentPage, setCurrentPage] = (0,
|
|
1062
|
-
const totalPages = (0,
|
|
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,
|
|
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,
|
|
1072
|
-
const endIndex = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
1600
|
+
const firstPage = (0, import_react6.useCallback)(() => {
|
|
1093
1601
|
setCurrentPage(1);
|
|
1094
1602
|
}, []);
|
|
1095
|
-
const lastPage = (0,
|
|
1603
|
+
const lastPage = (0, import_react6.useCallback)(() => {
|
|
1096
1604
|
setCurrentPage(totalPages);
|
|
1097
1605
|
}, [totalPages]);
|
|
1098
|
-
const updatePageSize = (0,
|
|
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,
|
|
1119
|
-
const [caseSensitive, setCaseSensitive] = (0,
|
|
1120
|
-
const filteredData = (0,
|
|
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,
|
|
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,
|
|
1152
|
-
const selectedRows = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
1680
|
+
const selectRow = (0, import_react6.useCallback)((index) => {
|
|
1173
1681
|
setSelectedRowIndices((prev) => /* @__PURE__ */ new Set([...prev, index]));
|
|
1174
1682
|
}, []);
|
|
1175
|
-
const deselectRow = (0,
|
|
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,
|
|
1690
|
+
const selectAll = (0, import_react6.useCallback)(() => {
|
|
1183
1691
|
setSelectedRowIndices(new Set(data.map((_, idx) => idx)));
|
|
1184
1692
|
}, [data]);
|
|
1185
|
-
const deselectAll = (0,
|
|
1693
|
+
const deselectAll = (0, import_react6.useCallback)(() => {
|
|
1186
1694
|
setSelectedRowIndices(/* @__PURE__ */ new Set());
|
|
1187
1695
|
}, []);
|
|
1188
|
-
const toggleAll = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
1229
|
-
const [isResizing, setIsResizing] = (0,
|
|
1230
|
-
const [resizingColumn, setResizingColumn] = (0,
|
|
1231
|
-
const startResize = (0,
|
|
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,
|
|
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,
|
|
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
|
|
1283
|
-
var
|
|
1284
|
-
var globalLicenseInfo = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
1820
|
+
(0, import_tinypivot_core5.configureLicenseSecret)(secret);
|
|
1313
1821
|
}
|
|
1314
1822
|
function useLicense() {
|
|
1315
|
-
const [, forceUpdate] = (0,
|
|
1316
|
-
(0,
|
|
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,
|
|
1324
|
-
() => globalDemoMode || (0,
|
|
1831
|
+
const isPro = (0, import_react7.useMemo)(
|
|
1832
|
+
() => globalDemoMode || (0, import_tinypivot_core5.isPro)(licenseInfo),
|
|
1325
1833
|
[licenseInfo]
|
|
1326
1834
|
);
|
|
1327
|
-
const canUsePivot = (0,
|
|
1328
|
-
() => globalDemoMode || (0,
|
|
1835
|
+
const canUsePivot = (0, import_react7.useMemo)(
|
|
1836
|
+
() => globalDemoMode || (0, import_tinypivot_core5.canUsePivot)(licenseInfo),
|
|
1329
1837
|
[licenseInfo]
|
|
1330
1838
|
);
|
|
1331
|
-
const canUseAdvancedAggregations = (0,
|
|
1839
|
+
const canUseAdvancedAggregations = (0, import_react7.useMemo)(
|
|
1332
1840
|
() => globalDemoMode || licenseInfo.features.advancedAggregations,
|
|
1333
1841
|
[licenseInfo]
|
|
1334
1842
|
);
|
|
1335
|
-
const canUsePercentageMode = (0,
|
|
1843
|
+
const canUsePercentageMode = (0, import_react7.useMemo)(
|
|
1336
1844
|
() => globalDemoMode || licenseInfo.features.percentageMode,
|
|
1337
1845
|
[licenseInfo]
|
|
1338
1846
|
);
|
|
1339
|
-
const
|
|
1340
|
-
() => (0,
|
|
1847
|
+
const canUseCharts = (0, import_react7.useMemo)(
|
|
1848
|
+
() => globalDemoMode || (0, import_tinypivot_core5.canUseCharts)(licenseInfo),
|
|
1341
1849
|
[licenseInfo]
|
|
1342
1850
|
);
|
|
1343
|
-
const
|
|
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,
|
|
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
|
|
1364
|
-
var
|
|
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,
|
|
1368
|
-
const [columnFields, setColumnFieldsState] = (0,
|
|
1369
|
-
const [valueFields, setValueFields] = (0,
|
|
1370
|
-
const [showRowTotals, setShowRowTotals] = (0,
|
|
1371
|
-
const [showColumnTotals, setShowColumnTotals] = (0,
|
|
1372
|
-
const [calculatedFields, setCalculatedFields] = (0,
|
|
1373
|
-
const [currentStorageKey, setCurrentStorageKey] = (0,
|
|
1374
|
-
const availableFields = (0,
|
|
1375
|
-
return (0,
|
|
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,
|
|
1378
|
-
return (0,
|
|
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,
|
|
1381
|
-
return (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
1920
|
+
const storageKey = (0, import_tinypivot_core6.generateStorageKey)(newKeys);
|
|
1408
1921
|
if (storageKey !== currentStorageKey) {
|
|
1409
1922
|
setCurrentStorageKey(storageKey);
|
|
1410
|
-
const savedConfig = (0,
|
|
1411
|
-
if (savedConfig && (0,
|
|
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,
|
|
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,
|
|
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,
|
|
1960
|
+
(0, import_tinypivot_core6.savePivotConfig)(currentStorageKey, config);
|
|
1448
1961
|
}, [currentStorageKey, rowFields, columnFields, valueFields, showRowTotals, showColumnTotals, calculatedFields]);
|
|
1449
|
-
const addRowField = (0,
|
|
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,
|
|
1970
|
+
const removeRowField = (0, import_react8.useCallback)((field) => {
|
|
1458
1971
|
setRowFieldsState((prev) => prev.filter((f) => f !== field));
|
|
1459
1972
|
}, []);
|
|
1460
|
-
const setRowFields = (0,
|
|
1973
|
+
const setRowFields = (0, import_react8.useCallback)((fields) => {
|
|
1461
1974
|
setRowFieldsState(fields);
|
|
1462
1975
|
}, []);
|
|
1463
|
-
const addColumnField = (0,
|
|
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,
|
|
1984
|
+
const removeColumnField = (0, import_react8.useCallback)((field) => {
|
|
1472
1985
|
setColumnFieldsState((prev) => prev.filter((f) => f !== field));
|
|
1473
1986
|
}, []);
|
|
1474
|
-
const setColumnFields = (0,
|
|
1987
|
+
const setColumnFields = (0, import_react8.useCallback)((fields) => {
|
|
1475
1988
|
setColumnFieldsState(fields);
|
|
1476
1989
|
}, []);
|
|
1477
|
-
const addValueField = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
2025
|
+
const clearConfig = (0, import_react8.useCallback)(() => {
|
|
1513
2026
|
setRowFieldsState([]);
|
|
1514
2027
|
setColumnFieldsState([]);
|
|
1515
2028
|
setValueFields([]);
|
|
1516
2029
|
}, []);
|
|
1517
|
-
const autoSuggestConfig = (0,
|
|
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,
|
|
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,
|
|
2051
|
+
(0, import_tinypivot_core6.saveCalculatedFields)(updated);
|
|
1539
2052
|
return updated;
|
|
1540
2053
|
});
|
|
1541
2054
|
}, []);
|
|
1542
|
-
const removeCalculatedField = (0,
|
|
2055
|
+
const removeCalculatedField = (0, import_react8.useCallback)((id) => {
|
|
1543
2056
|
setCalculatedFields((prev) => {
|
|
1544
2057
|
const updated = prev.filter((f) => f.id !== id);
|
|
1545
|
-
(0,
|
|
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
|
|
1584
|
-
var
|
|
1585
|
-
var
|
|
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,
|
|
1627
|
-
const [showCalcModal, setShowCalcModal] = (0,
|
|
1628
|
-
const [editingCalcField, setEditingCalcField] = (0,
|
|
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,
|
|
2143
|
+
const isAggregationAvailable = (0, import_react9.useCallback)((agg) => {
|
|
1631
2144
|
return !aggregationRequiresPro(agg) || canUseAdvancedAggregations;
|
|
1632
2145
|
}, [canUseAdvancedAggregations]);
|
|
1633
|
-
const numericFieldNames = (0,
|
|
1634
|
-
const calculatedFieldsAsStats = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
2242
|
+
const handleTotalsToggle = (0, import_react9.useCallback)((checked) => {
|
|
1730
2243
|
onShowRowTotalsChange(checked);
|
|
1731
2244
|
onShowColumnTotalsChange(checked);
|
|
1732
2245
|
}, [onShowRowTotalsChange, onShowColumnTotalsChange]);
|
|
1733
|
-
const openCalcModal = (0,
|
|
2246
|
+
const openCalcModal = (0, import_react9.useCallback)((field) => {
|
|
1734
2247
|
setEditingCalcField(field || null);
|
|
1735
2248
|
setShowCalcModal(true);
|
|
1736
2249
|
}, []);
|
|
1737
|
-
const handleSaveCalcField = (0,
|
|
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,
|
|
2259
|
+
const handleCloseCalcModal = (0, import_react9.useCallback)(() => {
|
|
1747
2260
|
setShowCalcModal(false);
|
|
1748
2261
|
setEditingCalcField(null);
|
|
1749
2262
|
}, []);
|
|
1750
|
-
return /* @__PURE__ */ (0,
|
|
1751
|
-
/* @__PURE__ */ (0,
|
|
1752
|
-
/* @__PURE__ */ (0,
|
|
1753
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
1783
|
-
/* @__PURE__ */ (0,
|
|
1784
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
1794
|
-
/* @__PURE__ */ (0,
|
|
1795
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
1798
|
-
(field.assignedTo === "row" || field.assignedTo === "column") && /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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:
|
|
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,
|
|
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,
|
|
1876
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2392
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "vpg-count", children: unassignedFields.length })
|
|
1880
2393
|
] }) }),
|
|
1881
|
-
/* @__PURE__ */ (0,
|
|
1882
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
1912
|
-
filteredUnassignedFields.map((field) => /* @__PURE__ */ (0,
|
|
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,
|
|
1922
|
-
/* @__PURE__ */ (0,
|
|
1923
|
-
field.isCalculated ? /* @__PURE__ */ (0,
|
|
1924
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
1966
|
-
/* @__PURE__ */ (0,
|
|
1967
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2488
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Totals" })
|
|
1976
2489
|
] }),
|
|
1977
|
-
/* @__PURE__ */ (0,
|
|
1978
|
-
/* @__PURE__ */ (0,
|
|
1979
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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
|
|
1997
|
-
var
|
|
1998
|
-
var
|
|
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,
|
|
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,
|
|
2542
|
+
const isCalculatedField = (0, import_react10.useCallback)((field) => {
|
|
2030
2543
|
return field.startsWith("calc:");
|
|
2031
2544
|
}, []);
|
|
2032
|
-
const [dragOverArea, setDragOverArea] = (0,
|
|
2033
|
-
const [reorderDragSource, setReorderDragSource] = (0,
|
|
2034
|
-
const [reorderDropTarget, setReorderDropTarget] = (0,
|
|
2035
|
-
const [sortDirection, setSortDirection] = (0,
|
|
2036
|
-
const [sortTarget, setSortTarget] = (0,
|
|
2037
|
-
const toggleSort = (0,
|
|
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,
|
|
2046
|
-
const [selectionStart, setSelectionStart] = (0,
|
|
2047
|
-
const [selectionEnd, setSelectionEnd] = (0,
|
|
2048
|
-
const [isSelecting, setIsSelecting] = (0,
|
|
2049
|
-
const [showCopyToast, setShowCopyToast] = (0,
|
|
2050
|
-
const [copyToastMessage, setCopyToastMessage] = (0,
|
|
2051
|
-
const selectionBounds = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
2240
|
-
const filterTooltipDetails = (0,
|
|
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,
|
|
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,
|
|
2786
|
+
const handleDragLeave = (0, import_react10.useCallback)(() => {
|
|
2274
2787
|
setDragOverArea(null);
|
|
2275
2788
|
}, []);
|
|
2276
|
-
const handleDrop = (0,
|
|
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,
|
|
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,
|
|
2830
|
+
const handleChipDragEnd = (0, import_react10.useCallback)(() => {
|
|
2318
2831
|
setReorderDragSource(null);
|
|
2319
2832
|
setReorderDropTarget(null);
|
|
2320
2833
|
}, []);
|
|
2321
|
-
const handleChipDragOver = (0,
|
|
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,
|
|
2844
|
+
const handleChipDragLeave = (0, import_react10.useCallback)(() => {
|
|
2332
2845
|
setReorderDropTarget(null);
|
|
2333
2846
|
}, []);
|
|
2334
|
-
const handleChipDrop = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
2891
|
+
const getRowHeaderLeftOffset = (0, import_react10.useCallback)((fieldIdx) => {
|
|
2379
2892
|
return fieldIdx * rowHeaderColWidth;
|
|
2380
2893
|
}, [rowHeaderColWidth]);
|
|
2381
|
-
return /* @__PURE__ */ (0,
|
|
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,
|
|
2387
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2391
|
-
/* @__PURE__ */ (0,
|
|
2392
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2914
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Pivot Table" })
|
|
2402
2915
|
] }),
|
|
2403
|
-
/* @__PURE__ */ (0,
|
|
2404
|
-
hasActiveFilters && /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
2942
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "vpg-filter-text", children: [
|
|
2430
2943
|
"Filtered:",
|
|
2431
2944
|
" ",
|
|
2432
|
-
/* @__PURE__ */ (0,
|
|
2433
|
-
filteredRowCount !== void 0 && totalRowCount !== void 0 && /* @__PURE__ */ (0,
|
|
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,
|
|
2445
|
-
/* @__PURE__ */ (0,
|
|
2446
|
-
filterTooltipDetails.map((filter) => /* @__PURE__ */ (0,
|
|
2447
|
-
/* @__PURE__ */ (0,
|
|
2448
|
-
/* @__PURE__ */ (0,
|
|
2449
|
-
filter.values.map((val, idx) => /* @__PURE__ */ (0,
|
|
2450
|
-
filter.remaining > 0 && /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
2474
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
2496
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2506
|
-
/* @__PURE__ */ (0,
|
|
2507
|
-
/* @__PURE__ */ (0,
|
|
2508
|
-
] }) }) : /* @__PURE__ */ (0,
|
|
2509
|
-
/* @__PURE__ */ (0,
|
|
2510
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2519
|
-
/* @__PURE__ */ (0,
|
|
2520
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2523
|
-
rowFields.map((field, idx) => /* @__PURE__ */ (0,
|
|
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,
|
|
2535
|
-
/* @__PURE__ */ (0,
|
|
2536
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
2565
|
-
/* @__PURE__ */ (0,
|
|
2566
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2569
|
-
columnFields.map((field, idx) => /* @__PURE__ */ (0,
|
|
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,
|
|
2581
|
-
/* @__PURE__ */ (0,
|
|
2582
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
2611
|
-
/* @__PURE__ */ (0,
|
|
2612
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2615
|
-
valueFields.map((vf) => /* @__PURE__ */ (0,
|
|
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,
|
|
2621
|
-
/* @__PURE__ */ (0,
|
|
2622
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
2641
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
3181
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "Row" }),
|
|
2669
3182
|
" ",
|
|
2670
3183
|
"or",
|
|
2671
3184
|
" ",
|
|
2672
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2678
|
-
/* @__PURE__ */ (0,
|
|
2679
|
-
levelIdx === 0 && (rowFields.length > 0 ? rowFields : ["Rows"]).map((field, fieldIdx) => /* @__PURE__ */ (0,
|
|
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,
|
|
2687
|
-
/* @__PURE__ */ (0,
|
|
2688
|
-
(fieldIdx === rowFields.length - 1 || rowFields.length === 0) && /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
2700
|
-
/* @__PURE__ */ (0,
|
|
2701
|
-
levelIdx === columnHeaderCells.length - 1 && /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
2709
|
-
sortedRowIndices.map((sortedIdx) => /* @__PURE__ */ (0,
|
|
2710
|
-
pivotResult.rowHeaders[sortedIdx].map((val, idx) => /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
2735
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2745
|
-
pivotResult.rowTotals.length > 0 && /* @__PURE__ */ (0,
|
|
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,
|
|
2750
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2759
|
-
/* @__PURE__ */ (0,
|
|
2760
|
-
/* @__PURE__ */ (0,
|
|
2761
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2764
|
-
/* @__PURE__ */ (0,
|
|
2765
|
-
/* @__PURE__ */ (0,
|
|
2766
|
-
/* @__PURE__ */ (0,
|
|
2767
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2770
|
-
/* @__PURE__ */ (0,
|
|
2771
|
-
/* @__PURE__ */ (0,
|
|
2772
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
2779
|
-
/* @__PURE__ */ (0,
|
|
2780
|
-
/* @__PURE__ */ (0,
|
|
2781
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
2831
|
-
const [globalSearchTerm, setGlobalSearchTerm] = (0,
|
|
2832
|
-
const [showSearchInput, setShowSearchInput] = (0,
|
|
2833
|
-
const [currentPage, setCurrentPage] = (0,
|
|
2834
|
-
const [columnWidths, setColumnWidths] = (0,
|
|
2835
|
-
const [resizingColumnId, setResizingColumnId] = (0,
|
|
2836
|
-
const [resizeStartX, setResizeStartX] = (0,
|
|
2837
|
-
const [resizeStartWidth, setResizeStartWidth] = (0,
|
|
2838
|
-
const [gridHeight, setGridHeight] = (0,
|
|
2839
|
-
const [isResizingVertically, setIsResizingVertically] = (0,
|
|
2840
|
-
const [verticalResizeStartY, setVerticalResizeStartY] = (0,
|
|
2841
|
-
const [verticalResizeStartHeight, setVerticalResizeStartHeight] = (0,
|
|
2842
|
-
const [showCopyToast, setShowCopyToast] = (0,
|
|
2843
|
-
const [copyToastMessage, setCopyToastMessage] = (0,
|
|
2844
|
-
const [viewMode, setViewMode] = (0,
|
|
2845
|
-
const [
|
|
2846
|
-
const
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
const [
|
|
2850
|
-
const [
|
|
2851
|
-
const [
|
|
2852
|
-
const [
|
|
2853
|
-
const
|
|
2854
|
-
const
|
|
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,
|
|
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,
|
|
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,
|
|
2934
|
-
const searchFilteredData = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
3481
|
+
(0, import_react11.useEffect)(() => {
|
|
2965
3482
|
setCurrentPage(1);
|
|
2966
3483
|
}, [columnFilters, globalSearchTerm]);
|
|
2967
|
-
const selectionBounds = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
3765
|
+
const closeFilterDropdown = (0, import_react11.useCallback)(() => {
|
|
3249
3766
|
setActiveFilterColumn(null);
|
|
3250
3767
|
}, []);
|
|
3251
|
-
const handleFilter = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
3340
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
3344
|
-
/* @__PURE__ */ (0,
|
|
3345
|
-
showPivot && /* @__PURE__ */ (0,
|
|
3346
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
3386
|
-
enableSearch && /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
3403
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
3458
|
-
/* @__PURE__ */ (0,
|
|
3459
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
3470
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
3493
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
3515
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
4061
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Pivot configured" })
|
|
3524
4062
|
] })
|
|
3525
4063
|
] })
|
|
3526
4064
|
] }),
|
|
3527
|
-
/* @__PURE__ */ (0,
|
|
3528
|
-
viewMode === "grid" && activeFilterCount > 0 && /* @__PURE__ */ (0,
|
|
3529
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
3602
|
-
loading && /* @__PURE__ */ (0,
|
|
3603
|
-
/* @__PURE__ */ (0,
|
|
3604
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
3607
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
4154
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "No data available" })
|
|
3617
4155
|
] }),
|
|
3618
|
-
!loading && data.length > 0 && filteredRowCount === 0 && /* @__PURE__ */ (0,
|
|
3619
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
3629
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
3632
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
3648
|
-
/* @__PURE__ */ (0,
|
|
3649
|
-
/* @__PURE__ */ (0,
|
|
3650
|
-
getSortDirection(colId) && /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
3747
|
-
showPivotConfig && canUsePivot && /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
3802
|
-
/* @__PURE__ */ (0,
|
|
3803
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
3809
|
-
/* @__PURE__ */ (0,
|
|
3810
|
-
totalSearchedRows !== totalRowCount && /* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
3821
|
-
/* @__PURE__ */ (0,
|
|
3822
|
-
/* @__PURE__ */ (0,
|
|
3823
|
-
/* @__PURE__ */ (0,
|
|
3824
|
-
/* @__PURE__ */ (0,
|
|
3825
|
-
] }) : /* @__PURE__ */ (0,
|
|
3826
|
-
/* @__PURE__ */ (0,
|
|
3827
|
-
/* @__PURE__ */ (0,
|
|
3828
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
3835
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
3914
|
-
/* @__PURE__ */ (0,
|
|
3915
|
-
/* @__PURE__ */ (0,
|
|
3916
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
3919
|
-
/* @__PURE__ */ (0,
|
|
3920
|
-
/* @__PURE__ */ (0,
|
|
3921
|
-
/* @__PURE__ */ (0,
|
|
3922
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
3925
|
-
/* @__PURE__ */ (0,
|
|
3926
|
-
/* @__PURE__ */ (0,
|
|
3927
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
3932
|
-
/* @__PURE__ */ (0,
|
|
3933
|
-
/* @__PURE__ */ (0,
|
|
3934
|
-
/* @__PURE__ */ (0,
|
|
3935
|
-
] }) : showWatermark ? /* @__PURE__ */ (0,
|
|
3936
|
-
/* @__PURE__ */ (0,
|
|
3937
|
-
/* @__PURE__ */ (0,
|
|
3938
|
-
/* @__PURE__ */ (0,
|
|
3939
|
-
/* @__PURE__ */ (0,
|
|
3940
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
3946
|
-
/* @__PURE__ */ (0,
|
|
3947
|
-
/* @__PURE__ */ (0,
|
|
3948
|
-
/* @__PURE__ */ (0,
|
|
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,
|
|
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,
|
|
4531
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3963
4532
|
ColumnFilter,
|
|
3964
4533
|
{
|
|
3965
4534
|
columnId: activeFilterColumn,
|