@rudra-studio/rudra-charts 1.0.1

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.
Files changed (42) hide show
  1. package/README.md +7 -0
  2. package/components/AnimatedLineChart/index.d.ts +29 -0
  3. package/components/AnimatedLineChart/index.js +109 -0
  4. package/components/BubbleChart/index.d.ts +24 -0
  5. package/components/BubbleChart/index.js +126 -0
  6. package/components/CandleStickChart/index.d.ts +24 -0
  7. package/components/CandleStickChart/index.js +116 -0
  8. package/components/DonutChart/index.d.ts +19 -0
  9. package/components/DonutChart/index.js +77 -0
  10. package/components/FunnelChart/index.d.ts +22 -0
  11. package/components/FunnelChart/index.js +105 -0
  12. package/components/GaugeChart/index.d.ts +25 -0
  13. package/components/GaugeChart/index.js +85 -0
  14. package/components/HeatMap/index.d.ts +24 -0
  15. package/components/HeatMap/index.js +146 -0
  16. package/components/Histogram/index.d.ts +20 -0
  17. package/components/Histogram/index.js +158 -0
  18. package/components/HorizontalBarChart/index.d.ts +22 -0
  19. package/components/HorizontalBarChart/index.js +82 -0
  20. package/components/HundredPercentBarChart/index.d.ts +21 -0
  21. package/components/HundredPercentBarChart/index.js +96 -0
  22. package/components/MultiLineChart/index.d.ts +21 -0
  23. package/components/MultiLineChart/index.js +128 -0
  24. package/components/PipelineChart/index.d.ts +26 -0
  25. package/components/PipelineChart/index.js +174 -0
  26. package/components/ScatterPlot/index.d.ts +23 -0
  27. package/components/ScatterPlot/index.js +118 -0
  28. package/components/SpiderChart/index.d.ts +27 -0
  29. package/components/SpiderChart/index.js +169 -0
  30. package/components/StackedArea/index.d.ts +22 -0
  31. package/components/StackedArea/index.js +101 -0
  32. package/components/StackedBarChart/index.d.ts +21 -0
  33. package/components/StackedBarChart/index.js +96 -0
  34. package/components/TreeMap/index.d.ts +19 -0
  35. package/components/TreeMap/index.js +137 -0
  36. package/components/VerticalBarChart/index.d.ts +21 -0
  37. package/components/VerticalBarChart/index.js +97 -0
  38. package/components/WaterfallChart/index.d.ts +26 -0
  39. package/components/WaterfallChart/index.js +147 -0
  40. package/index.d.ts +38 -0
  41. package/index.js +23 -0
  42. package/package.json +46 -0
@@ -0,0 +1,96 @@
1
+ import { useEffect as e, useRef as t, useState as n } from "react";
2
+ import * as r from "d3";
3
+ import { jsx as i } from "react/jsx-runtime";
4
+ //#region src/components/HundredPercentBarChart/index.tsx
5
+ var a = ({ data: a = [
6
+ {
7
+ id: "1",
8
+ category: "Q1",
9
+ mobile: 120,
10
+ desktop: 80,
11
+ tablet: 40
12
+ },
13
+ {
14
+ id: "2",
15
+ category: "Q2",
16
+ mobile: 150,
17
+ desktop: 90,
18
+ tablet: 30
19
+ },
20
+ {
21
+ id: "3",
22
+ category: "Q3",
23
+ mobile: 180,
24
+ desktop: 110,
25
+ tablet: 50
26
+ },
27
+ {
28
+ id: "4",
29
+ category: "Q4",
30
+ mobile: 240,
31
+ desktop: 140,
32
+ tablet: 60
33
+ }
34
+ ], stackKeys: o = [
35
+ "mobile",
36
+ "desktop",
37
+ "tablet"
38
+ ], themeColors: s = [
39
+ "#3b82f6",
40
+ "#10b981",
41
+ "#f59e0b",
42
+ "#ef4444",
43
+ "#8b5cf6"
44
+ ], marginTop: c = 20, marginBottom: l = 40, marginLeft: u = 50, marginRight: d = 20, className: f = "" }) => {
45
+ let p = t(null), m = t(null), [h, g] = n({
46
+ width: 0,
47
+ height: 350
48
+ });
49
+ return e(() => {
50
+ let e = p.current;
51
+ if (!e) return;
52
+ let t = new ResizeObserver((e) => {
53
+ e[0] && g({
54
+ width: e[0].contentRect.width,
55
+ height: e[0].contentRect.height || 350
56
+ });
57
+ });
58
+ return t.observe(e), () => t.unobserve(e);
59
+ }, []), e(() => {
60
+ if (!m.current || h.width === 0 || a.length === 0 || o.length === 0) return;
61
+ let { width: e, height: t } = h, n = r.select(m.current), i = r.stack().keys(o).offset(r.stackOffsetExpand)(a), f = a.map((e) => e.category), p = r.scaleBand().domain(f).range([u, e - d]).padding(.3), g = r.scaleLinear().domain([0, 1]).range([t - l, c]), _ = r.scaleOrdinal().domain(o).range(s);
62
+ n.select(".x-axis").empty() && (n.append("g").attr("class", "axis x-axis"), n.append("g").attr("class", "axis y-axis")), n.select(".x-axis").attr("transform", `translate(0,${t - l})`).transition().duration(500).call(r.axisBottom(p).tickSizeOuter(0)).attr("font-size", "12px").attr("font-family", "ui-sans-serif, system-ui").attr("color", "#64748b").call((e) => e.select(".domain").remove()), n.select(".y-axis").attr("transform", `translate(${u},0)`).transition().duration(500).call(r.axisLeft(g).ticks(5).tickFormat(r.format(".0%")).tickSize(-(e - u - d))).attr("font-size", "12px").attr("font-family", "ui-sans-serif, system-ui").attr("color", "#64748b").call((e) => e.select(".domain").remove()).call((e) => e.selectAll(".tick line").attr("stroke-opacity", .1).attr("stroke-dasharray", "4,4"));
63
+ let v = n.select(".stacks-group");
64
+ v.empty() && (v = n.append("g").attr("class", "stacks-group"));
65
+ let y = v.selectAll(".layer").data(i, (e) => e.key);
66
+ y.exit().remove();
67
+ let b = y.enter().append("g").attr("class", "layer").attr("fill", (e) => _(e.key)).merge(y).transition().duration(500).attr("fill", (e) => _(e.key)).selection().selectAll("rect").data((e) => e, (e) => e.data.id);
68
+ b.exit().transition().duration(300).attr("y", g(0)).attr("height", 0).remove();
69
+ let x = b.enter().append("rect").attr("x", (e) => p(e.data.category) || 0).attr("width", p.bandwidth()).attr("y", g(0)).attr("height", 0).style("cursor", "pointer");
70
+ x.transition().duration(700).delay((e, t) => t * 50).ease(r.easeCubicOut).attr("y", (e) => g(e[1])).attr("height", (e) => g(e[0]) - g(e[1])), b.transition().duration(750).ease(r.easeCubicOut).attr("x", (e) => p(e.data.category) || 0).attr("width", p.bandwidth()).attr("y", (e) => g(e[1])).attr("height", (e) => g(e[0]) - g(e[1])), x.merge(b).on("mouseenter", function() {
71
+ v.selectAll("rect").transition().duration(200).attr("opacity", .4), r.select(this).transition().duration(200).attr("opacity", 1).attr("stroke", "#fff").attr("stroke-width", 2);
72
+ }).on("mouseleave", function() {
73
+ v.selectAll("rect").transition().duration(200).attr("opacity", 1).attr("stroke", "none");
74
+ });
75
+ }, [
76
+ a,
77
+ o,
78
+ h,
79
+ s,
80
+ c,
81
+ l,
82
+ u,
83
+ d
84
+ ]), /* @__PURE__ */ i("div", {
85
+ ref: p,
86
+ className: `w-full min-h-[350px] h-full relative ${f}`,
87
+ children: /* @__PURE__ */ i("svg", {
88
+ ref: m,
89
+ width: "100%",
90
+ height: "100%",
91
+ className: "block absolute inset-0 overflow-visible"
92
+ })
93
+ });
94
+ };
95
+ //#endregion
96
+ export { a as default };
@@ -0,0 +1,21 @@
1
+ import { default as React } from 'react';
2
+ export interface MultiLineDataPoint {
3
+ date: string | Date;
4
+ value: number;
5
+ category: string;
6
+ }
7
+ export interface AnimatedMultiLineChartProps {
8
+ /** The dataset */
9
+ data?: MultiLineDataPoint[];
10
+ /** Default palette for the categories */
11
+ themeColors?: string[];
12
+ /** Stroke width of the lines */
13
+ strokeWidth?: number;
14
+ marginTop?: number;
15
+ marginBottom?: number;
16
+ marginLeft?: number;
17
+ marginRight?: number;
18
+ className?: string;
19
+ }
20
+ export declare const AnimatedMultiLineChart: React.FC<AnimatedMultiLineChartProps>;
21
+ export default AnimatedMultiLineChart;
@@ -0,0 +1,128 @@
1
+ import { useEffect as e, useRef as t, useState as n } from "react";
2
+ import * as r from "d3";
3
+ import { jsx as i } from "react/jsx-runtime";
4
+ //#region src/components/MultiLineChart/index.tsx
5
+ var a = ({ data: a = [
6
+ {
7
+ date: "2023-01-01",
8
+ value: 40,
9
+ category: "Product A"
10
+ },
11
+ {
12
+ date: "2023-02-01",
13
+ value: 55,
14
+ category: "Product A"
15
+ },
16
+ {
17
+ date: "2023-03-01",
18
+ value: 45,
19
+ category: "Product A"
20
+ },
21
+ {
22
+ date: "2023-04-01",
23
+ value: 70,
24
+ category: "Product A"
25
+ },
26
+ {
27
+ date: "2023-01-01",
28
+ value: 60,
29
+ category: "Product B"
30
+ },
31
+ {
32
+ date: "2023-02-01",
33
+ value: 65,
34
+ category: "Product B"
35
+ },
36
+ {
37
+ date: "2023-03-01",
38
+ value: 85,
39
+ category: "Product B"
40
+ },
41
+ {
42
+ date: "2023-04-01",
43
+ value: 100,
44
+ category: "Product B"
45
+ },
46
+ {
47
+ date: "2023-01-01",
48
+ value: 20,
49
+ category: "Product C"
50
+ },
51
+ {
52
+ date: "2023-02-01",
53
+ value: 35,
54
+ category: "Product C"
55
+ },
56
+ {
57
+ date: "2023-03-01",
58
+ value: 25,
59
+ category: "Product C"
60
+ },
61
+ {
62
+ date: "2023-04-01",
63
+ value: 50,
64
+ category: "Product C"
65
+ }
66
+ ], themeColors: o = [
67
+ "#3b82f6",
68
+ "#10b981",
69
+ "#f59e0b",
70
+ "#ef4444",
71
+ "#8b5cf6"
72
+ ], strokeWidth: s = 3, marginTop: c = 20, marginBottom: l = 40, marginLeft: u = 50, marginRight: d = 30, className: f = "" }) => {
73
+ let p = t(null), m = t(null), [h, g] = n({
74
+ width: 0,
75
+ height: 350
76
+ });
77
+ return e(() => {
78
+ let e = p.current;
79
+ if (!e) return;
80
+ let t = new ResizeObserver((e) => {
81
+ e[0] && g({
82
+ width: e[0].contentRect.width,
83
+ height: e[0].contentRect.height || 350
84
+ });
85
+ });
86
+ return t.observe(e), () => t.unobserve(e);
87
+ }, []), e(() => {
88
+ if (!m.current || h.width === 0 || a.length === 0) return;
89
+ let { width: e, height: t } = h, n = r.select(m.current), i = a.map((e) => ({
90
+ ...e,
91
+ parsedDate: e.date instanceof Date ? e.date : new Date(e.date)
92
+ })), f = r.group(i, (e) => e.category), p = Array.from(f.keys()), g = r.scaleTime().domain(r.extent(i, (e) => e.parsedDate)).range([u, e - d]), _ = r.max(i, (e) => e.value) || 100, v = r.scaleLinear().domain([0, _ * 1.1]).nice().range([t - l, c]), y = r.scaleOrdinal().domain(p).range(o);
93
+ n.select(".x-axis").empty() && (n.append("g").attr("class", "axis x-axis"), n.append("g").attr("class", "axis y-axis")), n.select(".x-axis").attr("transform", `translate(0,${t - l})`).transition().duration(500).call(r.axisBottom(g).ticks(Math.max(e / 80, 2)).tickSize(-(t - c - l))).attr("font-size", "12px").attr("font-family", "ui-sans-serif, system-ui").attr("color", "#64748b").call((e) => e.select(".domain").remove()).call((e) => e.selectAll(".tick line").attr("stroke-opacity", .1)), n.select(".y-axis").attr("transform", `translate(${u},0)`).transition().duration(500).call(r.axisLeft(v).ticks(6).tickSize(-(e - u - d))).attr("font-size", "12px").attr("font-family", "ui-sans-serif, system-ui").attr("color", "#64748b").call((e) => e.select(".domain").remove()).call((e) => e.selectAll(".tick line").attr("stroke-opacity", .1));
94
+ let b = r.line().x((e) => g(e.parsedDate)).y((e) => v(e.value)).curve(r.curveMonotoneX), x = n.select(".lines-group");
95
+ x.empty() && (x = n.append("g").attr("class", "lines-group"));
96
+ let S = x.selectAll(".line-path").data(f, (e) => e[0]);
97
+ S.exit().transition().duration(400).style("opacity", 0).remove();
98
+ let C = S.enter().append("path").attr("class", "line-path").attr("fill", "none").attr("stroke", (e) => y(e[0])).attr("stroke-width", s).attr("stroke-linecap", "round").attr("stroke-linejoin", "round").style("cursor", "pointer");
99
+ C.attr("d", (e) => b(e[1])).each(function() {
100
+ let e = this.getTotalLength();
101
+ r.select(this).attr("stroke-dasharray", `${e} ${e}`).attr("stroke-dashoffset", e).transition().duration(1500).ease(r.easeCubicOut).attr("stroke-dashoffset", 0);
102
+ }), S.transition().duration(750).ease(r.easeCubicOut).attr("d", (e) => b(e[1])).attr("stroke", (e) => y(e[0])).attr("stroke-dasharray", null).attr("stroke-dashoffset", null), C.merge(S).on("mouseenter", function() {
103
+ x.selectAll(".line-path").transition().duration(200).style("opacity", .2), r.select(this).raise().transition().duration(200).style("opacity", 1).attr("stroke-width", s + 2);
104
+ }).on("mouseleave", function() {
105
+ x.selectAll(".line-path").transition().duration(200).style("opacity", 1).attr("stroke-width", s);
106
+ });
107
+ }, [
108
+ a,
109
+ h,
110
+ s,
111
+ o,
112
+ c,
113
+ l,
114
+ u,
115
+ d
116
+ ]), /* @__PURE__ */ i("div", {
117
+ ref: p,
118
+ className: `w-full min-h-[350px] h-full relative ${f}`,
119
+ children: /* @__PURE__ */ i("svg", {
120
+ ref: m,
121
+ width: "100%",
122
+ height: "100%",
123
+ className: "block absolute inset-0 overflow-visible"
124
+ })
125
+ });
126
+ };
127
+ //#endregion
128
+ export { a as default };
@@ -0,0 +1,26 @@
1
+ import { default as React } from 'react';
2
+ export type WorkflowStatus = 'success' | 'failed' | 'running' | 'queued';
3
+ export interface WorkflowNode {
4
+ id: string;
5
+ label: string;
6
+ status: WorkflowStatus;
7
+ column: number;
8
+ row: number;
9
+ }
10
+ export interface WorkflowLink {
11
+ source: string;
12
+ target: string;
13
+ }
14
+ export interface AnimatedWorkflowChartProps {
15
+ /** The nodes (jobs/steps) in the pipeline */
16
+ nodes?: WorkflowNode[];
17
+ /** The connections between the nodes */
18
+ links?: WorkflowLink[];
19
+ /** Fixed width of each node card */
20
+ nodeWidth?: number;
21
+ /** Fixed height of each node card */
22
+ nodeHeight?: number;
23
+ className?: string;
24
+ }
25
+ export declare const AnimatedWorkflowChart: React.FC<AnimatedWorkflowChartProps>;
26
+ export default AnimatedWorkflowChart;
@@ -0,0 +1,174 @@
1
+ import { useEffect as e, useRef as t, useState as n } from "react";
2
+ import * as r from "d3";
3
+ import { jsx as i } from "react/jsx-runtime";
4
+ //#region src/components/PipelineChart/index.tsx
5
+ var a = ({ nodes: a = [
6
+ {
7
+ id: "build",
8
+ label: "Build Project",
9
+ status: "success",
10
+ column: 0,
11
+ row: 1
12
+ },
13
+ {
14
+ id: "test-unit",
15
+ label: "Unit Tests",
16
+ status: "success",
17
+ column: 1,
18
+ row: 0
19
+ },
20
+ {
21
+ id: "test-e2e",
22
+ label: "E2E Tests",
23
+ status: "failed",
24
+ column: 1,
25
+ row: 1
26
+ },
27
+ {
28
+ id: "lint",
29
+ label: "Linting",
30
+ status: "success",
31
+ column: 1,
32
+ row: 2
33
+ },
34
+ {
35
+ id: "deploy-staging",
36
+ label: "Deploy Staging",
37
+ status: "running",
38
+ column: 2,
39
+ row: 1
40
+ },
41
+ {
42
+ id: "deploy-prod",
43
+ label: "Deploy Prod",
44
+ status: "queued",
45
+ column: 3,
46
+ row: 1
47
+ }
48
+ ], links: o = [
49
+ {
50
+ source: "build",
51
+ target: "test-unit"
52
+ },
53
+ {
54
+ source: "build",
55
+ target: "test-e2e"
56
+ },
57
+ {
58
+ source: "build",
59
+ target: "lint"
60
+ },
61
+ {
62
+ source: "test-unit",
63
+ target: "deploy-staging"
64
+ },
65
+ {
66
+ source: "test-e2e",
67
+ target: "deploy-staging"
68
+ },
69
+ {
70
+ source: "lint",
71
+ target: "deploy-staging"
72
+ },
73
+ {
74
+ source: "deploy-staging",
75
+ target: "deploy-prod"
76
+ }
77
+ ], nodeWidth: s = 160, nodeHeight: c = 48, className: l = "" }) => {
78
+ let u = t(null), d = t(null), [f, p] = n({
79
+ width: 0,
80
+ height: 400
81
+ });
82
+ return e(() => {
83
+ let e = u.current;
84
+ if (!e) return;
85
+ let t = new ResizeObserver((e) => {
86
+ e[0] && p({
87
+ width: e[0].contentRect.width,
88
+ height: e[0].contentRect.height || 400
89
+ });
90
+ });
91
+ return t.observe(e), () => t.unobserve(e);
92
+ }, []), e(() => {
93
+ if (!d.current || f.width === 0 || a.length === 0) return;
94
+ let { width: e, height: t } = f, n = r.select(d.current), i = r.max(a, (e) => e.column) || 1, l = r.max(a, (e) => e.row) || 1, u = r.scaleLinear().domain([0, i]).range([40, e - 40 - s]), p = r.scaleLinear().domain([0, l]).range([40, t - 40 - c]), m = {
95
+ success: {
96
+ border: "#10b981",
97
+ fill: "#ecfdf5",
98
+ text: "#065f46",
99
+ icon: "#10b981"
100
+ },
101
+ failed: {
102
+ border: "#ef4444",
103
+ fill: "#fef2f2",
104
+ text: "#991b1b",
105
+ icon: "#ef4444"
106
+ },
107
+ running: {
108
+ border: "#3b82f6",
109
+ fill: "#eff6ff",
110
+ text: "#1e40af",
111
+ icon: "#3b82f6"
112
+ },
113
+ queued: {
114
+ border: "#cbd5e1",
115
+ fill: "#f8fafc",
116
+ text: "#64748b",
117
+ icon: "#cbd5e1"
118
+ }
119
+ }, h = n.select(".workflow-group");
120
+ h.empty() && (h = n.append("g").attr("class", "workflow-group"));
121
+ let g = o.map((e) => {
122
+ let t = a.find((t) => t.id === e.source), n = a.find((t) => t.id === e.target);
123
+ return !t || !n ? null : {
124
+ id: `${e.source}-${e.target}`,
125
+ sourceStatus: t.status,
126
+ sourcePos: [u(t.column) + s, p(t.row) + c / 2],
127
+ targetPos: [u(n.column), p(n.row) + c / 2]
128
+ };
129
+ }).filter(Boolean), _ = r.linkHorizontal().source((e) => e.sourcePos).target((e) => e.targetPos), v = h.select(".links-group");
130
+ v.empty() && (v = h.append("g").attr("class", "links-group"));
131
+ let y = v.selectAll(".pipeline-link").data(g, (e) => e.id);
132
+ y.exit().transition().duration(300).style("opacity", 0).remove(), y.enter().append("path").attr("class", "pipeline-link").attr("fill", "none").attr("stroke", (e) => e.sourceStatus === "failed" ? "#fee2e2" : "#e2e8f0").attr("stroke-width", 2).attr("d", _).each(function() {
133
+ let e = this.getTotalLength();
134
+ r.select(this).attr("stroke-dasharray", `${e} ${e}`).attr("stroke-dashoffset", e).transition().duration(1e3).ease(r.easeCubicOut).attr("stroke-dashoffset", 0);
135
+ }), y.transition().duration(750).attr("d", _).attr("stroke-dasharray", null).attr("stroke-dashoffset", null);
136
+ let b = h.select(".nodes-group");
137
+ b.empty() && (b = h.append("g").attr("class", "nodes-group"));
138
+ let x = b.selectAll(".pipeline-node").data(a, (e) => e.id);
139
+ x.exit().transition().duration(300).style("opacity", 0).remove();
140
+ let S = x.enter().append("g").attr("class", "pipeline-node").attr("transform", (e) => `translate(${u(e.column)},${p(e.row)})`).style("opacity", 0).style("cursor", "pointer");
141
+ S.append("rect").attr("class", "node-bg").attr("width", s).attr("height", c).attr("rx", 8).attr("fill", (e) => m[e.status].fill).attr("stroke", (e) => m[e.status].border).attr("stroke-width", 1.5), S.append("circle").attr("class", "node-status-dot").attr("cx", 20).attr("cy", c / 2).attr("r", 5).attr("fill", (e) => m[e.status].icon), S.append("text").attr("class", "node-label").attr("x", 36).attr("y", c / 2).attr("alignment-baseline", "middle").attr("font-size", "13px").attr("font-weight", "600").attr("font-family", "ui-sans-serif, system-ui").attr("fill", (e) => m[e.status].text).text((e) => e.label), S.transition().duration(600).delay((e) => e.column * 150).ease(r.easeBackOut.overshoot(1.2)).style("opacity", 1);
142
+ let C = S.merge(x);
143
+ C.transition().duration(750).ease(r.easeCubicOut).attr("transform", (e) => `translate(${u(e.column)},${p(e.row)})`), C.select(".node-bg").transition().duration(500).attr("fill", (e) => m[e.status].fill).attr("stroke", (e) => m[e.status].border), C.select(".node-status-dot").transition().duration(500).attr("fill", (e) => m[e.status].icon), C.select(".node-label").transition().duration(500).attr("fill", (e) => m[e.status].text).text((e) => e.label), C.each(function(e) {
144
+ let t = r.select(this).select(".node-bg");
145
+ if (e.status === "running") {
146
+ let e = () => {
147
+ t.transition().duration(800).attr("filter", "drop-shadow(0 0 6px rgba(59, 130, 246, 0.5))").attr("stroke-width", 2.5).transition().duration(800).attr("filter", "none").attr("stroke-width", 1.5).on("end", e);
148
+ };
149
+ e();
150
+ } else t.interrupt().attr("filter", "none").attr("stroke-width", 1.5);
151
+ }), C.on("mouseenter", function(e, t) {
152
+ b.selectAll(".pipeline-node").transition().duration(200).style("opacity", .4), r.select(this).transition().duration(200).style("opacity", 1).attr("transform", `translate(${u(t.column)},${p(t.row) - 2})`), v.selectAll(".pipeline-link").transition().duration(200).attr("stroke", (e) => e.id.startsWith(t.id) || e.id.endsWith(t.id) ? "#94a3b8" : "#f1f5f9").attr("stroke-width", (e) => e.id.startsWith(t.id) || e.id.endsWith(t.id) ? 3 : 1);
153
+ }).on("mouseleave", function(e, t) {
154
+ b.selectAll(".pipeline-node").transition().duration(200).style("opacity", 1).attr("transform", (e) => `translate(${u(e.column)},${p(e.row)})`), v.selectAll(".pipeline-link").transition().duration(200).attr("stroke", (e) => e.sourceStatus === "failed" ? "#fee2e2" : "#e2e8f0").attr("stroke-width", 2);
155
+ });
156
+ }, [
157
+ a,
158
+ o,
159
+ f,
160
+ s,
161
+ c
162
+ ]), /* @__PURE__ */ i("div", {
163
+ ref: u,
164
+ className: `w-full min-h-[400px] h-full relative overflow-hidden bg-white rounded-lg border border-slate-200 ${l}`,
165
+ children: /* @__PURE__ */ i("svg", {
166
+ ref: d,
167
+ width: "100%",
168
+ height: "100%",
169
+ className: "block absolute inset-0 overflow-visible"
170
+ })
171
+ });
172
+ };
173
+ //#endregion
174
+ export { a as default };
@@ -0,0 +1,23 @@
1
+ import { default as React } from 'react';
2
+ export interface ScatterDataPoint {
3
+ id: string | number;
4
+ x: number;
5
+ y: number;
6
+ category?: string;
7
+ label?: string;
8
+ }
9
+ export interface AnimatedScatterPlotProps {
10
+ /** The dataset */
11
+ data?: ScatterDataPoint[];
12
+ /** Default palette for the categories */
13
+ themeColors?: string[];
14
+ /** Base radius of the dots */
15
+ dotRadius?: number;
16
+ marginTop?: number;
17
+ marginBottom?: number;
18
+ marginLeft?: number;
19
+ marginRight?: number;
20
+ className?: string;
21
+ }
22
+ export declare const AnimatedScatterPlot: React.FC<AnimatedScatterPlotProps>;
23
+ export default AnimatedScatterPlot;
@@ -0,0 +1,118 @@
1
+ import { useEffect as e, useRef as t, useState as n } from "react";
2
+ import * as r from "d3";
3
+ import { jsx as i } from "react/jsx-runtime";
4
+ //#region src/components/ScatterPlot/index.tsx
5
+ var a = ({ data: a = [
6
+ {
7
+ id: 1,
8
+ x: 120,
9
+ y: 80,
10
+ category: "Group A",
11
+ label: "Campaign 1"
12
+ },
13
+ {
14
+ id: 2,
15
+ x: 250,
16
+ y: 110,
17
+ category: "Group A",
18
+ label: "Campaign 2"
19
+ },
20
+ {
21
+ id: 3,
22
+ x: 340,
23
+ y: 150,
24
+ category: "Group B",
25
+ label: "Campaign 3"
26
+ },
27
+ {
28
+ id: 4,
29
+ x: 480,
30
+ y: 210,
31
+ category: "Group B",
32
+ label: "Campaign 4"
33
+ },
34
+ {
35
+ id: 5,
36
+ x: 590,
37
+ y: 180,
38
+ category: "Group C",
39
+ label: "Campaign 5"
40
+ },
41
+ {
42
+ id: 6,
43
+ x: 720,
44
+ y: 250,
45
+ category: "Group C",
46
+ label: "Campaign 6"
47
+ },
48
+ {
49
+ id: 7,
50
+ x: 810,
51
+ y: 310,
52
+ category: "Group A",
53
+ label: "Campaign 7"
54
+ },
55
+ {
56
+ id: 8,
57
+ x: 950,
58
+ y: 290,
59
+ category: "Group B",
60
+ label: "Campaign 8"
61
+ }
62
+ ], themeColors: o = [
63
+ "#3b82f6",
64
+ "#10b981",
65
+ "#f59e0b",
66
+ "#ef4444",
67
+ "#8b5cf6"
68
+ ], dotRadius: s = 6, marginTop: c = 20, marginBottom: l = 40, marginLeft: u = 50, marginRight: d = 30, className: f = "" }) => {
69
+ let p = t(null), m = t(null), [h, g] = n({
70
+ width: 0,
71
+ height: 350
72
+ });
73
+ return e(() => {
74
+ let e = p.current;
75
+ if (!e) return;
76
+ let t = new ResizeObserver((e) => {
77
+ e[0] && g({
78
+ width: e[0].contentRect.width,
79
+ height: e[0].contentRect.height || 350
80
+ });
81
+ });
82
+ return t.observe(e), () => t.unobserve(e);
83
+ }, []), e(() => {
84
+ if (!m.current || h.width === 0 || a.length === 0) return;
85
+ let { width: e, height: t } = h, n = r.select(m.current), i = r.max(a, (e) => e.x) || 100, f = r.max(a, (e) => e.y) || 100, p = r.scaleLinear().domain([0, i * 1.1]).nice().range([u, e - d]), g = r.scaleLinear().domain([0, f * 1.1]).nice().range([t - l, c]), _ = Array.from(new Set(a.map((e) => e.category || "default"))), v = r.scaleOrdinal().domain(_).range(o);
86
+ n.select(".x-axis").empty() && (n.append("g").attr("class", "axis x-axis"), n.append("g").attr("class", "axis y-axis")), n.select(".x-axis").attr("transform", `translate(0,${t - l})`).transition().duration(500).call(r.axisBottom(p).ticks(8).tickSize(-(t - c - l))).attr("font-size", "12px").attr("font-family", "ui-sans-serif, system-ui").attr("color", "#64748b").call((e) => e.select(".domain").remove()).call((e) => e.selectAll(".tick line").attr("stroke-opacity", .1)), n.select(".y-axis").attr("transform", `translate(${u},0)`).transition().duration(500).call(r.axisLeft(g).ticks(6).tickSize(-(e - u - d))).attr("font-size", "12px").attr("font-family", "ui-sans-serif, system-ui").attr("color", "#64748b").call((e) => e.select(".domain").remove()).call((e) => e.selectAll(".tick line").attr("stroke-opacity", .1));
87
+ let y = n.select(".dots-group");
88
+ y.empty() && (y = n.append("g").attr("class", "dots-group"));
89
+ let b = y.selectAll(".scatter-dot").data(a, (e) => e.id);
90
+ b.exit().transition().duration(300).attr("r", 0).remove();
91
+ let x = b.enter().append("circle").attr("class", "scatter-dot").attr("cx", (e) => p(e.x)).attr("cy", (e) => g(e.y)).attr("r", 0).attr("fill", (e) => v(e.category || "default")).attr("opacity", .8).attr("stroke", "#ffffff").attr("stroke-width", 1.5).style("cursor", "pointer");
92
+ x.transition().duration(600).delay((e, t) => t * 40).ease(r.easeBackOut.overshoot(1.5)).attr("r", s), b.transition().duration(750).ease(r.easeCubicOut).attr("cx", (e) => p(e.x)).attr("cy", (e) => g(e.y)).attr("fill", (e) => v(e.category || "default")).attr("r", s), x.merge(b).on("mouseenter", function() {
93
+ y.selectAll(".scatter-dot").transition().duration(200).attr("opacity", .3), r.select(this).raise().transition().duration(200).attr("opacity", 1).attr("r", s * 1.5).attr("stroke-width", 3);
94
+ }).on("mouseleave", function() {
95
+ y.selectAll(".scatter-dot").transition().duration(200).attr("opacity", .8).attr("r", s).attr("stroke-width", 1.5);
96
+ });
97
+ }, [
98
+ a,
99
+ h,
100
+ s,
101
+ o,
102
+ c,
103
+ l,
104
+ u,
105
+ d
106
+ ]), /* @__PURE__ */ i("div", {
107
+ ref: p,
108
+ className: `w-full min-h-[350px] h-full relative ${f}`,
109
+ children: /* @__PURE__ */ i("svg", {
110
+ ref: m,
111
+ width: "100%",
112
+ height: "100%",
113
+ className: "block absolute inset-0 overflow-visible"
114
+ })
115
+ });
116
+ };
117
+ //#endregion
118
+ export { a as default };
@@ -0,0 +1,27 @@
1
+ import { default as React } from 'react';
2
+ export interface RadarAxis {
3
+ axis: string;
4
+ value: number;
5
+ }
6
+ export interface RadarDataPoint {
7
+ id: string | number;
8
+ category: string;
9
+ axes: RadarAxis[];
10
+ }
11
+ export interface AnimatedRadarChartProps {
12
+ /** The dataset containing the entities and their multi-variable stats. */
13
+ data?: RadarDataPoint[];
14
+ /** Default palette for the overlapping entities */
15
+ themeColors?: string[];
16
+ /** The number of concentric grid levels to draw in the background */
17
+ gridLevels?: number;
18
+ /** The absolute maximum value for the scale (if omitted, calculates from data) */
19
+ maxValue?: number;
20
+ marginTop?: number;
21
+ marginBottom?: number;
22
+ marginLeft?: number;
23
+ marginRight?: number;
24
+ className?: string;
25
+ }
26
+ export declare const AnimatedRadarChart: React.FC<AnimatedRadarChartProps>;
27
+ export default AnimatedRadarChart;