react-open-source-grid 1.6.6 → 1.7.0
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/assets/{index-CQcTDWao.css → index-90D-dENa.css} +1 -1
- package/dist/assets/{index-DgcHJP8T.js → index-Ds2EPIvF.js} +206 -91
- package/dist/assets/index.js +1 -1
- package/dist/assets/{layoutPersistence-BOTIXT8B.js → layoutPersistence-CTemzqZG.js} +1 -1
- package/dist/index.html +2 -2
- package/dist/lib/charts/ChartOverlay.d.ts +20 -0
- package/dist/lib/charts/QuickChart.d.ts +22 -0
- package/dist/lib/charts/index.d.ts +12 -0
- package/dist/lib/charts/rangeToChart.d.ts +23 -0
- package/dist/lib/charts/types.d.ts +63 -0
- package/dist/lib/components/ChartsDemo.d.ts +9 -0
- package/dist/lib/index.cjs +496 -0
- package/dist/lib/index.css +215 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +506 -0
- package/package.json +5 -3
package/dist/lib/index.js
CHANGED
|
@@ -13515,10 +13515,511 @@ function renderMarkdownPreview(markdown) {
|
|
|
13515
13515
|
}
|
|
13516
13516
|
return html;
|
|
13517
13517
|
}
|
|
13518
|
+
|
|
13519
|
+
// src/charts/rangeToChart.ts
|
|
13520
|
+
function normalizeRange(range) {
|
|
13521
|
+
const startRow = Math.min(range.start.rowIndex, range.end.rowIndex);
|
|
13522
|
+
const endRow = Math.max(range.start.rowIndex, range.end.rowIndex);
|
|
13523
|
+
const startCol = Math.min(range.start.colIndex, range.end.colIndex);
|
|
13524
|
+
const endCol = Math.max(range.start.colIndex, range.end.colIndex);
|
|
13525
|
+
return { startRow, endRow, startCol, endCol };
|
|
13526
|
+
}
|
|
13527
|
+
function isNumeric(value) {
|
|
13528
|
+
if (value === null || value === void 0 || value === "") {
|
|
13529
|
+
return false;
|
|
13530
|
+
}
|
|
13531
|
+
const num = Number(value);
|
|
13532
|
+
return !isNaN(num) && isFinite(num);
|
|
13533
|
+
}
|
|
13534
|
+
function toNumber2(value) {
|
|
13535
|
+
if (isNumeric(value)) {
|
|
13536
|
+
return Number(value);
|
|
13537
|
+
}
|
|
13538
|
+
return 0;
|
|
13539
|
+
}
|
|
13540
|
+
function generateChartId() {
|
|
13541
|
+
return `chart-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
13542
|
+
}
|
|
13543
|
+
var DEFAULT_COLORS = [
|
|
13544
|
+
"#8884d8",
|
|
13545
|
+
// blue
|
|
13546
|
+
"#82ca9d",
|
|
13547
|
+
// green
|
|
13548
|
+
"#ffc658",
|
|
13549
|
+
// yellow
|
|
13550
|
+
"#ff7c7c",
|
|
13551
|
+
// red
|
|
13552
|
+
"#a28fd0",
|
|
13553
|
+
// purple
|
|
13554
|
+
"#ff9f40",
|
|
13555
|
+
// orange
|
|
13556
|
+
"#4bc0c0",
|
|
13557
|
+
// teal
|
|
13558
|
+
"#ff6384"
|
|
13559
|
+
// pink
|
|
13560
|
+
];
|
|
13561
|
+
function buildChartConfigFromRange(options) {
|
|
13562
|
+
const {
|
|
13563
|
+
range,
|
|
13564
|
+
rows,
|
|
13565
|
+
columns,
|
|
13566
|
+
chartType,
|
|
13567
|
+
useFirstColumnAsCategory = true,
|
|
13568
|
+
title,
|
|
13569
|
+
theme = "light"
|
|
13570
|
+
} = options;
|
|
13571
|
+
const normalized = normalizeRange(range);
|
|
13572
|
+
const { startRow, endRow, startCol, endCol } = normalized;
|
|
13573
|
+
if (startRow < 0 || endRow >= rows.length) {
|
|
13574
|
+
throw new Error("Invalid row range");
|
|
13575
|
+
}
|
|
13576
|
+
if (startCol < 0 || endCol >= columns.length) {
|
|
13577
|
+
throw new Error("Invalid column range");
|
|
13578
|
+
}
|
|
13579
|
+
const selectedRows = rows.slice(startRow, endRow + 1);
|
|
13580
|
+
const selectedColumns = columns.slice(startCol, endCol + 1);
|
|
13581
|
+
let categoryColumnIndex = 0;
|
|
13582
|
+
let dataColumnStartIndex = 0;
|
|
13583
|
+
if (useFirstColumnAsCategory && selectedColumns.length > 1) {
|
|
13584
|
+
categoryColumnIndex = 0;
|
|
13585
|
+
dataColumnStartIndex = 1;
|
|
13586
|
+
} else {
|
|
13587
|
+
categoryColumnIndex = -1;
|
|
13588
|
+
dataColumnStartIndex = 0;
|
|
13589
|
+
}
|
|
13590
|
+
const xLabels = [];
|
|
13591
|
+
if (categoryColumnIndex >= 0) {
|
|
13592
|
+
const categoryField = selectedColumns[categoryColumnIndex].field;
|
|
13593
|
+
selectedRows.forEach((row) => {
|
|
13594
|
+
const value = row[categoryField];
|
|
13595
|
+
xLabels.push(value !== null && value !== void 0 ? String(value) : "");
|
|
13596
|
+
});
|
|
13597
|
+
} else {
|
|
13598
|
+
for (let i = 0; i < selectedRows.length; i++) {
|
|
13599
|
+
xLabels.push(i + 1);
|
|
13600
|
+
}
|
|
13601
|
+
}
|
|
13602
|
+
const series = [];
|
|
13603
|
+
const dataColumns = selectedColumns.slice(dataColumnStartIndex);
|
|
13604
|
+
dataColumns.forEach((column, index) => {
|
|
13605
|
+
const seriesData = [];
|
|
13606
|
+
const field = column.field;
|
|
13607
|
+
let hasNumericData = false;
|
|
13608
|
+
selectedRows.forEach((row) => {
|
|
13609
|
+
const value = row[field];
|
|
13610
|
+
if (isNumeric(value)) {
|
|
13611
|
+
hasNumericData = true;
|
|
13612
|
+
seriesData.push(toNumber2(value));
|
|
13613
|
+
} else {
|
|
13614
|
+
seriesData.push(0);
|
|
13615
|
+
}
|
|
13616
|
+
});
|
|
13617
|
+
if (hasNumericData) {
|
|
13618
|
+
series.push({
|
|
13619
|
+
name: column.headerName || field,
|
|
13620
|
+
data: seriesData,
|
|
13621
|
+
color: DEFAULT_COLORS[index % DEFAULT_COLORS.length]
|
|
13622
|
+
});
|
|
13623
|
+
}
|
|
13624
|
+
});
|
|
13625
|
+
if (series.length === 0) {
|
|
13626
|
+
throw new Error("No numeric data found in the selected range");
|
|
13627
|
+
}
|
|
13628
|
+
if (chartType === "pie") {
|
|
13629
|
+
if (series.length === 1) {
|
|
13630
|
+
} else {
|
|
13631
|
+
const summedData = new Array(xLabels.length).fill(0);
|
|
13632
|
+
series.forEach((s) => {
|
|
13633
|
+
s.data.forEach((value, idx) => {
|
|
13634
|
+
summedData[idx] += value;
|
|
13635
|
+
});
|
|
13636
|
+
});
|
|
13637
|
+
series.length = 0;
|
|
13638
|
+
series.push({
|
|
13639
|
+
name: "Total",
|
|
13640
|
+
data: summedData,
|
|
13641
|
+
color: DEFAULT_COLORS[0]
|
|
13642
|
+
});
|
|
13643
|
+
}
|
|
13644
|
+
}
|
|
13645
|
+
return {
|
|
13646
|
+
id: generateChartId(),
|
|
13647
|
+
type: chartType,
|
|
13648
|
+
title: title || `${chartType.charAt(0).toUpperCase() + chartType.slice(1)} Chart`,
|
|
13649
|
+
xLabels,
|
|
13650
|
+
series,
|
|
13651
|
+
theme
|
|
13652
|
+
};
|
|
13653
|
+
}
|
|
13654
|
+
function updateChartType(config, newType) {
|
|
13655
|
+
var _a;
|
|
13656
|
+
return {
|
|
13657
|
+
...config,
|
|
13658
|
+
type: newType,
|
|
13659
|
+
title: ((_a = config.title) == null ? void 0 : _a.replace(
|
|
13660
|
+
/^(Line|Bar|Area|Pie)/i,
|
|
13661
|
+
newType.charAt(0).toUpperCase() + newType.slice(1)
|
|
13662
|
+
)) || `${newType.charAt(0).toUpperCase() + newType.slice(1)} Chart`
|
|
13663
|
+
};
|
|
13664
|
+
}
|
|
13665
|
+
function updateChartTheme(config, newTheme) {
|
|
13666
|
+
return {
|
|
13667
|
+
...config,
|
|
13668
|
+
theme: newTheme
|
|
13669
|
+
};
|
|
13670
|
+
}
|
|
13671
|
+
|
|
13672
|
+
// src/charts/QuickChart.tsx
|
|
13673
|
+
import React35, { useRef as useRef20 } from "react";
|
|
13674
|
+
import {
|
|
13675
|
+
LineChart,
|
|
13676
|
+
Line,
|
|
13677
|
+
BarChart,
|
|
13678
|
+
Bar,
|
|
13679
|
+
AreaChart,
|
|
13680
|
+
Area,
|
|
13681
|
+
PieChart,
|
|
13682
|
+
Pie,
|
|
13683
|
+
Cell,
|
|
13684
|
+
XAxis,
|
|
13685
|
+
YAxis,
|
|
13686
|
+
CartesianGrid,
|
|
13687
|
+
Tooltip as Tooltip2,
|
|
13688
|
+
Legend,
|
|
13689
|
+
ResponsiveContainer
|
|
13690
|
+
} from "recharts";
|
|
13691
|
+
import { toPng } from "html-to-image";
|
|
13692
|
+
var QuickChart = ({
|
|
13693
|
+
config,
|
|
13694
|
+
onClose,
|
|
13695
|
+
onChangeType,
|
|
13696
|
+
onToggleTheme,
|
|
13697
|
+
allowTypeSwitch = true,
|
|
13698
|
+
allowThemeSwitch = true,
|
|
13699
|
+
width = 600,
|
|
13700
|
+
height = 400
|
|
13701
|
+
}) => {
|
|
13702
|
+
const chartRef = useRef20(null);
|
|
13703
|
+
const theme = config.theme || "light";
|
|
13704
|
+
const transformedData = config.xLabels.map((label, index) => {
|
|
13705
|
+
const dataPoint = { name: label };
|
|
13706
|
+
config.series.forEach((series) => {
|
|
13707
|
+
dataPoint[series.name] = series.data[index] || 0;
|
|
13708
|
+
});
|
|
13709
|
+
return dataPoint;
|
|
13710
|
+
});
|
|
13711
|
+
const pieData = config.series.length > 0 ? config.xLabels.map((label, index) => ({
|
|
13712
|
+
name: label,
|
|
13713
|
+
value: config.series[0].data[index] || 0
|
|
13714
|
+
})) : [];
|
|
13715
|
+
const handleExportPNG = async () => {
|
|
13716
|
+
if (!chartRef.current) return;
|
|
13717
|
+
try {
|
|
13718
|
+
const dataUrl = await toPng(chartRef.current, {
|
|
13719
|
+
quality: 1,
|
|
13720
|
+
pixelRatio: 2,
|
|
13721
|
+
backgroundColor: theme === "dark" ? "#1a1a1a" : "#ffffff"
|
|
13722
|
+
});
|
|
13723
|
+
const link = document.createElement("a");
|
|
13724
|
+
link.download = `${config.title || "chart"}-${Date.now()}.png`;
|
|
13725
|
+
link.href = dataUrl;
|
|
13726
|
+
link.click();
|
|
13727
|
+
} catch (error) {
|
|
13728
|
+
console.error("Failed to export chart:", error);
|
|
13729
|
+
}
|
|
13730
|
+
};
|
|
13731
|
+
const chartTypeIcon = (type) => {
|
|
13732
|
+
switch (type) {
|
|
13733
|
+
case "line":
|
|
13734
|
+
return "\u{1F4C8}";
|
|
13735
|
+
case "bar":
|
|
13736
|
+
return "\u{1F4CA}";
|
|
13737
|
+
case "area":
|
|
13738
|
+
return "\u{1F4C9}";
|
|
13739
|
+
case "pie":
|
|
13740
|
+
return "\u{1F967}";
|
|
13741
|
+
default:
|
|
13742
|
+
return "\u{1F4CA}";
|
|
13743
|
+
}
|
|
13744
|
+
};
|
|
13745
|
+
const renderChart = () => {
|
|
13746
|
+
const commonProps = {
|
|
13747
|
+
data: config.type === "pie" ? pieData : transformedData,
|
|
13748
|
+
margin: { top: 5, right: 30, left: 20, bottom: 5 }
|
|
13749
|
+
};
|
|
13750
|
+
const axisProps = {
|
|
13751
|
+
stroke: theme === "dark" ? "#888" : "#666"
|
|
13752
|
+
};
|
|
13753
|
+
const gridProps = {
|
|
13754
|
+
strokeDasharray: "3 3",
|
|
13755
|
+
stroke: theme === "dark" ? "#333" : "#ddd"
|
|
13756
|
+
};
|
|
13757
|
+
switch (config.type) {
|
|
13758
|
+
case "line":
|
|
13759
|
+
return /* @__PURE__ */ React35.createElement(ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ React35.createElement(LineChart, { ...commonProps }, /* @__PURE__ */ React35.createElement(CartesianGrid, { ...gridProps }), /* @__PURE__ */ React35.createElement(XAxis, { dataKey: "name", ...axisProps }), /* @__PURE__ */ React35.createElement(YAxis, { ...axisProps }), /* @__PURE__ */ React35.createElement(
|
|
13760
|
+
Tooltip2,
|
|
13761
|
+
{
|
|
13762
|
+
contentStyle: {
|
|
13763
|
+
backgroundColor: theme === "dark" ? "#2a2a2a" : "#fff",
|
|
13764
|
+
border: `1px solid ${theme === "dark" ? "#444" : "#ccc"}`,
|
|
13765
|
+
color: theme === "dark" ? "#fff" : "#000"
|
|
13766
|
+
}
|
|
13767
|
+
}
|
|
13768
|
+
), /* @__PURE__ */ React35.createElement(Legend, null), config.series.map((series) => /* @__PURE__ */ React35.createElement(
|
|
13769
|
+
Line,
|
|
13770
|
+
{
|
|
13771
|
+
key: series.name,
|
|
13772
|
+
type: "monotone",
|
|
13773
|
+
dataKey: series.name,
|
|
13774
|
+
stroke: series.color,
|
|
13775
|
+
strokeWidth: 2,
|
|
13776
|
+
dot: { r: 4 },
|
|
13777
|
+
activeDot: { r: 6 }
|
|
13778
|
+
}
|
|
13779
|
+
))));
|
|
13780
|
+
case "bar":
|
|
13781
|
+
return /* @__PURE__ */ React35.createElement(ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ React35.createElement(BarChart, { ...commonProps }, /* @__PURE__ */ React35.createElement(CartesianGrid, { ...gridProps }), /* @__PURE__ */ React35.createElement(XAxis, { dataKey: "name", ...axisProps }), /* @__PURE__ */ React35.createElement(YAxis, { ...axisProps }), /* @__PURE__ */ React35.createElement(
|
|
13782
|
+
Tooltip2,
|
|
13783
|
+
{
|
|
13784
|
+
contentStyle: {
|
|
13785
|
+
backgroundColor: theme === "dark" ? "#2a2a2a" : "#fff",
|
|
13786
|
+
border: `1px solid ${theme === "dark" ? "#444" : "#ccc"}`,
|
|
13787
|
+
color: theme === "dark" ? "#fff" : "#000"
|
|
13788
|
+
}
|
|
13789
|
+
}
|
|
13790
|
+
), /* @__PURE__ */ React35.createElement(Legend, null), config.series.map((series) => /* @__PURE__ */ React35.createElement(Bar, { key: series.name, dataKey: series.name, fill: series.color }))));
|
|
13791
|
+
case "area":
|
|
13792
|
+
return /* @__PURE__ */ React35.createElement(ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ React35.createElement(AreaChart, { ...commonProps }, /* @__PURE__ */ React35.createElement(CartesianGrid, { ...gridProps }), /* @__PURE__ */ React35.createElement(XAxis, { dataKey: "name", ...axisProps }), /* @__PURE__ */ React35.createElement(YAxis, { ...axisProps }), /* @__PURE__ */ React35.createElement(
|
|
13793
|
+
Tooltip2,
|
|
13794
|
+
{
|
|
13795
|
+
contentStyle: {
|
|
13796
|
+
backgroundColor: theme === "dark" ? "#2a2a2a" : "#fff",
|
|
13797
|
+
border: `1px solid ${theme === "dark" ? "#444" : "#ccc"}`,
|
|
13798
|
+
color: theme === "dark" ? "#fff" : "#000"
|
|
13799
|
+
}
|
|
13800
|
+
}
|
|
13801
|
+
), /* @__PURE__ */ React35.createElement(Legend, null), config.series.map((series) => /* @__PURE__ */ React35.createElement(
|
|
13802
|
+
Area,
|
|
13803
|
+
{
|
|
13804
|
+
key: series.name,
|
|
13805
|
+
type: "monotone",
|
|
13806
|
+
dataKey: series.name,
|
|
13807
|
+
fill: series.color,
|
|
13808
|
+
stroke: series.color,
|
|
13809
|
+
fillOpacity: 0.6
|
|
13810
|
+
}
|
|
13811
|
+
))));
|
|
13812
|
+
case "pie":
|
|
13813
|
+
return /* @__PURE__ */ React35.createElement(ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ React35.createElement(PieChart, null, /* @__PURE__ */ React35.createElement(
|
|
13814
|
+
Pie,
|
|
13815
|
+
{
|
|
13816
|
+
data: pieData,
|
|
13817
|
+
cx: "50%",
|
|
13818
|
+
cy: "50%",
|
|
13819
|
+
labelLine: false,
|
|
13820
|
+
label: ({ name, percent }) => `${name}: ${(percent * 100).toFixed(0)}%`,
|
|
13821
|
+
outerRadius: Math.min(height, width) / 4,
|
|
13822
|
+
fill: "#8884d8",
|
|
13823
|
+
dataKey: "value"
|
|
13824
|
+
},
|
|
13825
|
+
pieData.map((_, index) => {
|
|
13826
|
+
var _a;
|
|
13827
|
+
return /* @__PURE__ */ React35.createElement(
|
|
13828
|
+
Cell,
|
|
13829
|
+
{
|
|
13830
|
+
key: `cell-${index}`,
|
|
13831
|
+
fill: ((_a = config.series[0]) == null ? void 0 : _a.color) || ["#8884d8", "#82ca9d", "#ffc658", "#ff7c7c", "#a28fd0"][index % 5]
|
|
13832
|
+
}
|
|
13833
|
+
);
|
|
13834
|
+
})
|
|
13835
|
+
), /* @__PURE__ */ React35.createElement(
|
|
13836
|
+
Tooltip2,
|
|
13837
|
+
{
|
|
13838
|
+
contentStyle: {
|
|
13839
|
+
backgroundColor: theme === "dark" ? "#2a2a2a" : "#fff",
|
|
13840
|
+
border: `1px solid ${theme === "dark" ? "#444" : "#ccc"}`,
|
|
13841
|
+
color: theme === "dark" ? "#fff" : "#000"
|
|
13842
|
+
}
|
|
13843
|
+
}
|
|
13844
|
+
), /* @__PURE__ */ React35.createElement(Legend, null)));
|
|
13845
|
+
default:
|
|
13846
|
+
return /* @__PURE__ */ React35.createElement("div", null, "Unsupported chart type");
|
|
13847
|
+
}
|
|
13848
|
+
};
|
|
13849
|
+
return /* @__PURE__ */ React35.createElement(
|
|
13850
|
+
"div",
|
|
13851
|
+
{
|
|
13852
|
+
ref: chartRef,
|
|
13853
|
+
className: `quick-chart quick-chart--${theme}`,
|
|
13854
|
+
style: { width, height }
|
|
13855
|
+
},
|
|
13856
|
+
/* @__PURE__ */ React35.createElement("div", { className: "quick-chart__header" }, /* @__PURE__ */ React35.createElement("h3", { className: "quick-chart__title" }, config.title), /* @__PURE__ */ React35.createElement("div", { className: "quick-chart__controls" }, allowTypeSwitch && onChangeType && /* @__PURE__ */ React35.createElement("div", { className: "quick-chart__type-selector" }, ["line", "bar", "area", "pie"].map((type) => /* @__PURE__ */ React35.createElement(
|
|
13857
|
+
"button",
|
|
13858
|
+
{
|
|
13859
|
+
key: type,
|
|
13860
|
+
className: `quick-chart__type-btn ${config.type === type ? "quick-chart__type-btn--active" : ""}`,
|
|
13861
|
+
onClick: () => onChangeType(type),
|
|
13862
|
+
title: `${type.charAt(0).toUpperCase() + type.slice(1)} Chart`,
|
|
13863
|
+
"aria-label": `Switch to ${type} chart`
|
|
13864
|
+
},
|
|
13865
|
+
chartTypeIcon(type)
|
|
13866
|
+
))), allowThemeSwitch && onToggleTheme && /* @__PURE__ */ React35.createElement(
|
|
13867
|
+
"button",
|
|
13868
|
+
{
|
|
13869
|
+
className: "quick-chart__btn",
|
|
13870
|
+
onClick: onToggleTheme,
|
|
13871
|
+
title: "Toggle theme",
|
|
13872
|
+
"aria-label": "Toggle theme"
|
|
13873
|
+
},
|
|
13874
|
+
theme === "dark" ? "\u2600\uFE0F" : "\u{1F319}"
|
|
13875
|
+
), /* @__PURE__ */ React35.createElement(
|
|
13876
|
+
"button",
|
|
13877
|
+
{
|
|
13878
|
+
className: "quick-chart__btn",
|
|
13879
|
+
onClick: handleExportPNG,
|
|
13880
|
+
title: "Export as PNG",
|
|
13881
|
+
"aria-label": "Export chart as PNG"
|
|
13882
|
+
},
|
|
13883
|
+
"\u{1F4E5}"
|
|
13884
|
+
), onClose && /* @__PURE__ */ React35.createElement(
|
|
13885
|
+
"button",
|
|
13886
|
+
{
|
|
13887
|
+
className: "quick-chart__btn quick-chart__close",
|
|
13888
|
+
onClick: onClose,
|
|
13889
|
+
title: "Close",
|
|
13890
|
+
"aria-label": "Close chart"
|
|
13891
|
+
},
|
|
13892
|
+
"\xD7"
|
|
13893
|
+
))),
|
|
13894
|
+
/* @__PURE__ */ React35.createElement("div", { className: "quick-chart__body" }, renderChart())
|
|
13895
|
+
);
|
|
13896
|
+
};
|
|
13897
|
+
|
|
13898
|
+
// src/charts/ChartOverlay.tsx
|
|
13899
|
+
import React36, { useEffect as useEffect17, useRef as useRef21, useState as useState26 } from "react";
|
|
13900
|
+
var ChartOverlay = ({
|
|
13901
|
+
config,
|
|
13902
|
+
onClose,
|
|
13903
|
+
onChangeType,
|
|
13904
|
+
onToggleTheme,
|
|
13905
|
+
position = "bottom-right",
|
|
13906
|
+
draggable = true
|
|
13907
|
+
}) => {
|
|
13908
|
+
const overlayRef = useRef21(null);
|
|
13909
|
+
const [isDragging, setIsDragging] = useState26(false);
|
|
13910
|
+
const [dragOffset, setDragOffset] = useState26({ x: 0, y: 0 });
|
|
13911
|
+
const [chartPosition, setChartPosition] = useState26({ x: 0, y: 0 });
|
|
13912
|
+
const [dimensions] = useState26({ width: 600, height: 400 });
|
|
13913
|
+
useEffect17(() => {
|
|
13914
|
+
if (!overlayRef.current) return;
|
|
13915
|
+
const updatePosition = () => {
|
|
13916
|
+
const viewport = {
|
|
13917
|
+
width: window.innerWidth,
|
|
13918
|
+
height: window.innerHeight
|
|
13919
|
+
};
|
|
13920
|
+
let x = 0;
|
|
13921
|
+
let y = 0;
|
|
13922
|
+
switch (position) {
|
|
13923
|
+
case "top-right":
|
|
13924
|
+
x = viewport.width - dimensions.width - 40;
|
|
13925
|
+
y = 40;
|
|
13926
|
+
break;
|
|
13927
|
+
case "top-left":
|
|
13928
|
+
x = 40;
|
|
13929
|
+
y = 40;
|
|
13930
|
+
break;
|
|
13931
|
+
case "bottom-right":
|
|
13932
|
+
x = viewport.width - dimensions.width - 40;
|
|
13933
|
+
y = viewport.height - dimensions.height - 40;
|
|
13934
|
+
break;
|
|
13935
|
+
case "bottom-left":
|
|
13936
|
+
x = 40;
|
|
13937
|
+
y = viewport.height - dimensions.height - 40;
|
|
13938
|
+
break;
|
|
13939
|
+
case "center":
|
|
13940
|
+
x = (viewport.width - dimensions.width) / 2;
|
|
13941
|
+
y = (viewport.height - dimensions.height) / 2;
|
|
13942
|
+
break;
|
|
13943
|
+
}
|
|
13944
|
+
setChartPosition({ x, y });
|
|
13945
|
+
};
|
|
13946
|
+
updatePosition();
|
|
13947
|
+
window.addEventListener("resize", updatePosition);
|
|
13948
|
+
return () => window.removeEventListener("resize", updatePosition);
|
|
13949
|
+
}, [position, dimensions]);
|
|
13950
|
+
const handleMouseDown = (e) => {
|
|
13951
|
+
if (!draggable) return;
|
|
13952
|
+
if (e.target.closest(".quick-chart__body")) return;
|
|
13953
|
+
setIsDragging(true);
|
|
13954
|
+
setDragOffset({
|
|
13955
|
+
x: e.clientX - chartPosition.x,
|
|
13956
|
+
y: e.clientY - chartPosition.y
|
|
13957
|
+
});
|
|
13958
|
+
};
|
|
13959
|
+
useEffect17(() => {
|
|
13960
|
+
if (!isDragging) return;
|
|
13961
|
+
const handleMouseMove = (e) => {
|
|
13962
|
+
const newX = e.clientX - dragOffset.x;
|
|
13963
|
+
const newY = e.clientY - dragOffset.y;
|
|
13964
|
+
const maxX = window.innerWidth - dimensions.width;
|
|
13965
|
+
const maxY = window.innerHeight - dimensions.height;
|
|
13966
|
+
setChartPosition({
|
|
13967
|
+
x: Math.max(0, Math.min(newX, maxX)),
|
|
13968
|
+
y: Math.max(0, Math.min(newY, maxY))
|
|
13969
|
+
});
|
|
13970
|
+
};
|
|
13971
|
+
const handleMouseUp = () => {
|
|
13972
|
+
setIsDragging(false);
|
|
13973
|
+
};
|
|
13974
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
13975
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
13976
|
+
return () => {
|
|
13977
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
13978
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
13979
|
+
};
|
|
13980
|
+
}, [isDragging, dragOffset, dimensions]);
|
|
13981
|
+
useEffect17(() => {
|
|
13982
|
+
const handleKeyDown = (e) => {
|
|
13983
|
+
if (e.key === "Escape") {
|
|
13984
|
+
onClose();
|
|
13985
|
+
}
|
|
13986
|
+
};
|
|
13987
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
13988
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
13989
|
+
}, [onClose]);
|
|
13990
|
+
return /* @__PURE__ */ React36.createElement("div", { className: "chart-overlay" }, /* @__PURE__ */ React36.createElement("div", { className: "chart-overlay__backdrop", onClick: onClose }), /* @__PURE__ */ React36.createElement(
|
|
13991
|
+
"div",
|
|
13992
|
+
{
|
|
13993
|
+
ref: overlayRef,
|
|
13994
|
+
className: `chart-overlay__container ${isDragging ? "chart-overlay__container--dragging" : ""} ${draggable ? "chart-overlay__container--draggable" : ""}`,
|
|
13995
|
+
style: {
|
|
13996
|
+
left: chartPosition.x,
|
|
13997
|
+
top: chartPosition.y,
|
|
13998
|
+
width: dimensions.width,
|
|
13999
|
+
height: dimensions.height
|
|
14000
|
+
},
|
|
14001
|
+
onMouseDown: handleMouseDown
|
|
14002
|
+
},
|
|
14003
|
+
/* @__PURE__ */ React36.createElement(
|
|
14004
|
+
QuickChart,
|
|
14005
|
+
{
|
|
14006
|
+
config,
|
|
14007
|
+
onClose,
|
|
14008
|
+
onChangeType,
|
|
14009
|
+
onToggleTheme,
|
|
14010
|
+
allowTypeSwitch: true,
|
|
14011
|
+
allowThemeSwitch: true,
|
|
14012
|
+
width: dimensions.width,
|
|
14013
|
+
height: dimensions.height
|
|
14014
|
+
}
|
|
14015
|
+
)
|
|
14016
|
+
));
|
|
14017
|
+
};
|
|
13518
14018
|
export {
|
|
13519
14019
|
AdvancedFilterBuilder,
|
|
13520
14020
|
BadgeCell,
|
|
13521
14021
|
ButtonCell,
|
|
14022
|
+
ChartOverlay,
|
|
13522
14023
|
ColumnChooser,
|
|
13523
14024
|
ColumnFilters,
|
|
13524
14025
|
CurrencyCell,
|
|
@@ -13544,6 +14045,7 @@ export {
|
|
|
13544
14045
|
PivotToolbar,
|
|
13545
14046
|
PriorityIndicator,
|
|
13546
14047
|
ProgressBar,
|
|
14048
|
+
QuickChart,
|
|
13547
14049
|
Rating,
|
|
13548
14050
|
RichSelectEditor,
|
|
13549
14051
|
ServerAdapter,
|
|
@@ -13555,6 +14057,7 @@ export {
|
|
|
13555
14057
|
VirtualScroller,
|
|
13556
14058
|
WebSocketMockFeed,
|
|
13557
14059
|
alpineTheme,
|
|
14060
|
+
buildChartConfigFromRange,
|
|
13558
14061
|
buildPivot,
|
|
13559
14062
|
buildTreeFromFlat,
|
|
13560
14063
|
collapseAllNodes,
|
|
@@ -13593,11 +14096,14 @@ export {
|
|
|
13593
14096
|
isTreeNode,
|
|
13594
14097
|
loadDensityMode,
|
|
13595
14098
|
materialTheme,
|
|
14099
|
+
normalizeRange,
|
|
13596
14100
|
parseFormattedNumber,
|
|
13597
14101
|
quartzTheme,
|
|
13598
14102
|
saveDensityMode,
|
|
13599
14103
|
themes,
|
|
13600
14104
|
toggleNodeExpansion,
|
|
14105
|
+
updateChartTheme,
|
|
14106
|
+
updateChartType,
|
|
13601
14107
|
useDensityMode,
|
|
13602
14108
|
useEditorAutoFocus,
|
|
13603
14109
|
useEditorClickOutside,
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-open-source-grid",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.7.0",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"description": "A high-performance React DataGrid component with advanced features like virtual scrolling, infinite scrolling, tree data, market data mode, and more",
|
|
6
|
+
"description": "A high-performance React DataGrid component with advanced features like virtual scrolling, infinite scrolling, tree data, market data mode, integrated charts, and more",
|
|
7
7
|
"main": "./dist/lib/index.cjs",
|
|
8
8
|
"module": "./dist/lib/index.js",
|
|
9
9
|
"types": "./dist/lib/index.d.ts",
|
|
@@ -71,10 +71,12 @@
|
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@types/react-syntax-highlighter": "^15.5.13",
|
|
73
73
|
"exceljs": "^4.4.0",
|
|
74
|
+
"html-to-image": "^1.11.11",
|
|
74
75
|
"react": "^19.2.0",
|
|
75
76
|
"react-dom": "^19.2.0",
|
|
76
77
|
"react-router-dom": "^7.9.6",
|
|
77
|
-
"react-syntax-highlighter": "^16.1.0"
|
|
78
|
+
"react-syntax-highlighter": "^16.1.0",
|
|
79
|
+
"recharts": "^2.10.3"
|
|
78
80
|
},
|
|
79
81
|
"devDependencies": {
|
|
80
82
|
"@eslint/js": "^9.39.1",
|