@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,25 @@
1
+ import { default as React } from 'react';
2
+ export interface GaugeZone {
3
+ start: number;
4
+ end: number;
5
+ color: string;
6
+ }
7
+ export interface AnimatedGaugeChartProps {
8
+ /** The current value to display */
9
+ value?: number;
10
+ /** The minimum value of the gauge */
11
+ min?: number;
12
+ /** The maximum value of the gauge */
13
+ max?: number;
14
+ /** Color-coded segments for the gauge track */
15
+ zones?: GaugeZone[];
16
+ /** Unit text displayed below the value (e.g., "mph", "kW", "Users") */
17
+ unit?: string;
18
+ marginTop?: number;
19
+ marginBottom?: number;
20
+ marginLeft?: number;
21
+ marginRight?: number;
22
+ className?: string;
23
+ }
24
+ export declare const AnimatedGaugeChart: React.FC<AnimatedGaugeChartProps>;
25
+ export default AnimatedGaugeChart;
@@ -0,0 +1,85 @@
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/GaugeChart/index.tsx
5
+ var a = ({ value: a = 78, min: o = 0, max: s = 100, zones: c = [
6
+ {
7
+ start: 0,
8
+ end: 50,
9
+ color: "#10b981"
10
+ },
11
+ {
12
+ start: 50,
13
+ end: 80,
14
+ color: "#f59e0b"
15
+ },
16
+ {
17
+ start: 80,
18
+ end: 100,
19
+ color: "#ef4444"
20
+ }
21
+ ], unit: l = "Score", marginTop: u = 30, marginBottom: d = 30, marginLeft: f = 30, marginRight: p = 30, className: m = "" }) => {
22
+ let h = t(null), g = t(null), [_, v] = n({
23
+ width: 0,
24
+ height: 250
25
+ });
26
+ return e(() => {
27
+ let e = h.current;
28
+ if (!e) return;
29
+ let t = new ResizeObserver((e) => {
30
+ if (e[0]) {
31
+ let t = e[0].contentRect.width;
32
+ v({
33
+ width: t,
34
+ height: Math.max(250, t / 2 + u + d)
35
+ });
36
+ }
37
+ });
38
+ return t.observe(e), () => t.unobserve(e);
39
+ }, [u, d]), e(() => {
40
+ if (!g.current || _.width === 0) return;
41
+ let { width: e, height: t } = _, n = r.select(g.current), i = e / 2, m = t - d, h = Math.min((e - f - p) / 2, m - u), v = Math.max(o, Math.min(a, s)), y = r.scaleLinear().domain([o, s]).range([-Math.PI / 2, Math.PI / 2]), b = r.arc().innerRadius(h * .75).outerRadius(h).startAngle((e) => y(e.start)).endAngle((e) => y(e.end)).cornerRadius(2).padAngle(.02), x = n.select(".track-group");
42
+ x.empty() && (x = n.append("g").attr("class", "track-group")), x.attr("transform", `translate(${i}, ${m})`);
43
+ let S = x.selectAll(".zone").data(c, (e) => `${e.start}-${e.end}`);
44
+ S.exit().remove(), S.enter().append("path").attr("class", "zone").attr("fill", (e) => e.color).attr("opacity", 0).attr("d", b).transition().duration(500).delay((e, t) => t * 100).attr("opacity", .9), S.transition().duration(500).attr("d", b).attr("fill", (e) => e.color);
45
+ let C = n.select(".labels-group");
46
+ C.empty() && (C = n.append("g").attr("class", "labels-group")), C.attr("transform", `translate(${i}, ${m})`);
47
+ let w = C.select(".min-label");
48
+ w.empty() && (w = C.append("text").attr("class", "min-label")), w.attr("x", -h + 10).attr("y", 20).attr("text-anchor", "middle").attr("font-size", "12px").attr("font-family", "ui-sans-serif, system-ui").attr("fill", "#64748b").text(o);
49
+ let T = C.select(".max-label");
50
+ T.empty() && (T = C.append("text").attr("class", "max-label")), T.attr("x", h - 10).attr("y", 20).attr("text-anchor", "middle").attr("font-size", "12px").attr("font-family", "ui-sans-serif, system-ui").attr("fill", "#64748b").text(s);
51
+ let E = n.select(".needle-group");
52
+ E.empty() && (E = n.append("g").attr("class", "needle-group"), E.append("circle").attr("class", "needle-base").attr("cx", 0).attr("cy", 0).attr("r", 8).attr("fill", "#1e293b"), E.append("path").attr("class", "needle-pointer").attr("fill", "#1e293b").attr("stroke", "#ffffff").attr("stroke-width", 1.5)), E.attr("transform", `translate(${i}, ${m})`), E.select(".needle-pointer").attr("d", `M -4 0 L 0 ${-h * .85} L 4 0 Z`);
53
+ let D = y(v) * 180 / Math.PI;
54
+ E.select(".needle-pointer").transition().duration(1200).ease(r.easeElasticOut.amplitude(1.2).period(.6)).attrTween("transform", function() {
55
+ let e = r.select(this).attr("transform"), t = e ? parseFloat(e.replace(/rotate\(([^)]+)\)/, "$1")) : y(o) * 180 / Math.PI, n = r.interpolateNumber(t, D);
56
+ return function(e) {
57
+ return `rotate(${n(e)})`;
58
+ };
59
+ });
60
+ let O = n.select(".readout-group");
61
+ O.empty() && (O = n.append("g").attr("class", "readout-group"), O.append("text").attr("class", "readout-value").attr("text-anchor", "middle").attr("font-weight", "700").attr("font-family", "ui-sans-serif, system-ui").attr("fill", "#0f172a"), O.append("text").attr("class", "readout-unit").attr("text-anchor", "middle").attr("font-weight", "500").attr("font-family", "ui-sans-serif, system-ui").attr("fill", "#64748b")), O.attr("transform", `translate(${i}, ${m - h * .2})`), O.select(".readout-value").attr("font-size", `${Math.max(24, h * .25)}px`).text(v.toLocaleString()), O.select(".readout-unit").attr("y", Math.max(16, h * .15)).attr("font-size", `${Math.max(12, h * .08)}px`).text(l);
62
+ }, [
63
+ a,
64
+ o,
65
+ s,
66
+ c,
67
+ l,
68
+ _,
69
+ u,
70
+ d,
71
+ f,
72
+ p
73
+ ]), /* @__PURE__ */ i("div", {
74
+ ref: h,
75
+ className: `w-full relative ${m}`,
76
+ children: /* @__PURE__ */ i("svg", {
77
+ ref: g,
78
+ width: "100%",
79
+ height: _.height,
80
+ className: "block overflow-visible"
81
+ })
82
+ });
83
+ };
84
+ //#endregion
85
+ export { a as default };
@@ -0,0 +1,24 @@
1
+ import { default as React } from 'react';
2
+ export interface HeatmapDataPoint {
3
+ id: string | number;
4
+ xCategory: string;
5
+ yCategory: string;
6
+ value: number;
7
+ }
8
+ export interface AnimatedHeatmapProps {
9
+ /** The matrix dataset. */
10
+ data?: HeatmapDataPoint[];
11
+ /** * A two-color array representing the lowest and highest value colors.
12
+ * D3 will automatically interpolate all the shades in between.
13
+ */
14
+ colorRange?: [string, string];
15
+ /** Space between the matrix cells */
16
+ cellPadding?: number;
17
+ marginTop?: number;
18
+ marginBottom?: number;
19
+ marginLeft?: number;
20
+ marginRight?: number;
21
+ className?: string;
22
+ }
23
+ export declare const AnimatedHeatmap: React.FC<AnimatedHeatmapProps>;
24
+ export default AnimatedHeatmap;
@@ -0,0 +1,146 @@
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/HeatMap/index.tsx
5
+ var a = ({ data: a = [
6
+ {
7
+ id: 1,
8
+ xCategory: "Mon",
9
+ yCategory: "Morning",
10
+ value: 12
11
+ },
12
+ {
13
+ id: 2,
14
+ xCategory: "Mon",
15
+ yCategory: "Afternoon",
16
+ value: 45
17
+ },
18
+ {
19
+ id: 3,
20
+ xCategory: "Mon",
21
+ yCategory: "Evening",
22
+ value: 78
23
+ },
24
+ {
25
+ id: 4,
26
+ xCategory: "Tue",
27
+ yCategory: "Morning",
28
+ value: 15
29
+ },
30
+ {
31
+ id: 5,
32
+ xCategory: "Tue",
33
+ yCategory: "Afternoon",
34
+ value: 50
35
+ },
36
+ {
37
+ id: 6,
38
+ xCategory: "Tue",
39
+ yCategory: "Evening",
40
+ value: 92
41
+ },
42
+ {
43
+ id: 7,
44
+ xCategory: "Wed",
45
+ yCategory: "Morning",
46
+ value: 18
47
+ },
48
+ {
49
+ id: 8,
50
+ xCategory: "Wed",
51
+ yCategory: "Afternoon",
52
+ value: 65
53
+ },
54
+ {
55
+ id: 9,
56
+ xCategory: "Wed",
57
+ yCategory: "Evening",
58
+ value: 85
59
+ },
60
+ {
61
+ id: 10,
62
+ xCategory: "Thu",
63
+ yCategory: "Morning",
64
+ value: 20
65
+ },
66
+ {
67
+ id: 11,
68
+ xCategory: "Thu",
69
+ yCategory: "Afternoon",
70
+ value: 70
71
+ },
72
+ {
73
+ id: 12,
74
+ xCategory: "Thu",
75
+ yCategory: "Evening",
76
+ value: 110
77
+ },
78
+ {
79
+ id: 13,
80
+ xCategory: "Fri",
81
+ yCategory: "Morning",
82
+ value: 25
83
+ },
84
+ {
85
+ id: 14,
86
+ xCategory: "Fri",
87
+ yCategory: "Afternoon",
88
+ value: 85
89
+ },
90
+ {
91
+ id: 15,
92
+ xCategory: "Fri",
93
+ yCategory: "Evening",
94
+ value: 140
95
+ }
96
+ ], colorRange: o = ["#f1f5f9", "#3b82f6"], cellPadding: s = .08, marginTop: c = 20, marginBottom: l = 30, marginLeft: u = 70, marginRight: d = 20, className: f = "" }) => {
97
+ let p = t(null), m = t(null), [h, g] = n({
98
+ width: 0,
99
+ height: 350
100
+ });
101
+ return e(() => {
102
+ let e = p.current;
103
+ if (!e) return;
104
+ let t = new ResizeObserver((e) => {
105
+ e[0] && g({
106
+ width: e[0].contentRect.width,
107
+ height: e[0].contentRect.height || 350
108
+ });
109
+ });
110
+ return t.observe(e), () => t.unobserve(e);
111
+ }, []), e(() => {
112
+ if (!m.current || h.width === 0 || a.length === 0) return;
113
+ let { width: e, height: t } = h, n = r.select(m.current), i = Array.from(new Set(a.map((e) => e.xCategory))), f = Array.from(new Set(a.map((e) => e.yCategory))), p = r.min(a, (e) => e.value) || 0, g = r.max(a, (e) => e.value) || 100, _ = r.scaleBand().domain(i).range([u, e - d]).padding(s), v = r.scaleBand().domain(f).range([c, t - l]).padding(s), y = r.scaleLinear().domain([p, g]).range(o);
114
+ 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(_).tickSizeOuter(0)).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").remove()), n.select(".y-axis").attr("transform", `translate(${u},0)`).transition().duration(500).call(r.axisLeft(v).tickSizeOuter(0)).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").remove());
115
+ let b = n.select(".cells-group");
116
+ b.empty() && (b = n.append("g").attr("class", "cells-group"));
117
+ let x = b.selectAll(".cell").data(a, (e) => e.id);
118
+ x.exit().transition().duration(300).attr("opacity", 0).remove();
119
+ let S = x.enter().append("rect").attr("class", "cell").attr("x", (e) => _(e.xCategory) || 0).attr("y", (e) => v(e.yCategory) || 0).attr("width", _.bandwidth()).attr("height", v.bandwidth()).attr("fill", (e) => y(e.value)).attr("rx", 6).attr("ry", 6).attr("opacity", 0).style("cursor", "pointer");
120
+ S.transition().duration(600).delay((e) => (i.indexOf(e.xCategory) + f.indexOf(e.yCategory)) * 40).ease(r.easeCubicOut).attr("opacity", 1), x.transition().duration(750).ease(r.easeCubicOut).attr("x", (e) => _(e.xCategory) || 0).attr("y", (e) => v(e.yCategory) || 0).attr("width", _.bandwidth()).attr("height", v.bandwidth()).attr("fill", (e) => y(e.value)), S.merge(x).on("mouseenter", function() {
121
+ b.selectAll(".cell").transition().duration(200).attr("opacity", .5), r.select(this).raise().transition().duration(200).attr("opacity", 1).attr("stroke", "#0f172a").attr("stroke-width", 2);
122
+ }).on("mouseleave", function() {
123
+ b.selectAll(".cell").transition().duration(200).attr("opacity", 1).attr("stroke", "none");
124
+ });
125
+ }, [
126
+ a,
127
+ h,
128
+ o,
129
+ s,
130
+ c,
131
+ l,
132
+ u,
133
+ d
134
+ ]), /* @__PURE__ */ i("div", {
135
+ ref: p,
136
+ className: `w-full min-h-[350px] h-full relative ${f}`,
137
+ children: /* @__PURE__ */ i("svg", {
138
+ ref: m,
139
+ width: "100%",
140
+ height: "100%",
141
+ className: "block absolute inset-0 overflow-visible"
142
+ })
143
+ });
144
+ };
145
+ //#endregion
146
+ export { a as default };
@@ -0,0 +1,20 @@
1
+ import { default as React } from 'react';
2
+ export interface HistogramDataPoint {
3
+ id: string | number;
4
+ value: number;
5
+ }
6
+ export interface AnimatedHistogramProps {
7
+ /** The raw, continuous dataset to be binned. */
8
+ data?: HistogramDataPoint[];
9
+ /** Default palette (uses the first color for the bins) */
10
+ themeColors?: string[];
11
+ /** The approximate number of bins (columns) to divide the data into */
12
+ targetBins?: number;
13
+ marginTop?: number;
14
+ marginBottom?: number;
15
+ marginLeft?: number;
16
+ marginRight?: number;
17
+ className?: string;
18
+ }
19
+ export declare const AnimatedHistogram: React.FC<AnimatedHistogramProps>;
20
+ export default AnimatedHistogram;
@@ -0,0 +1,158 @@
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/Histogram/index.tsx
5
+ var a = ({ data: a = [
6
+ {
7
+ id: 1,
8
+ value: 18
9
+ },
10
+ {
11
+ id: 2,
12
+ value: 19
13
+ },
14
+ {
15
+ id: 3,
16
+ value: 21
17
+ },
18
+ {
19
+ id: 4,
20
+ value: 22
21
+ },
22
+ {
23
+ id: 5,
24
+ value: 22
25
+ },
26
+ {
27
+ id: 6,
28
+ value: 23
29
+ },
30
+ {
31
+ id: 7,
32
+ value: 24
33
+ },
34
+ {
35
+ id: 8,
36
+ value: 24
37
+ },
38
+ {
39
+ id: 9,
40
+ value: 24
41
+ },
42
+ {
43
+ id: 10,
44
+ value: 25
45
+ },
46
+ {
47
+ id: 11,
48
+ value: 25
49
+ },
50
+ {
51
+ id: 12,
52
+ value: 26
53
+ },
54
+ {
55
+ id: 13,
56
+ value: 26
57
+ },
58
+ {
59
+ id: 14,
60
+ value: 27
61
+ },
62
+ {
63
+ id: 15,
64
+ value: 28
65
+ },
66
+ {
67
+ id: 16,
68
+ value: 28
69
+ },
70
+ {
71
+ id: 17,
72
+ value: 29
73
+ },
74
+ {
75
+ id: 18,
76
+ value: 31
77
+ },
78
+ {
79
+ id: 19,
80
+ value: 32
81
+ },
82
+ {
83
+ id: 20,
84
+ value: 35
85
+ },
86
+ {
87
+ id: 21,
88
+ value: 38
89
+ },
90
+ {
91
+ id: 22,
92
+ value: 42
93
+ },
94
+ {
95
+ id: 23,
96
+ value: 45
97
+ },
98
+ {
99
+ id: 24,
100
+ value: 55
101
+ }
102
+ ], themeColors: o = [
103
+ "#8b5cf6",
104
+ "#3b82f6",
105
+ "#10b981",
106
+ "#f59e0b",
107
+ "#ef4444"
108
+ ], targetBins: s = 10, marginTop: c = 20, marginBottom: l = 40, marginLeft: u = 40, marginRight: d = 20, className: f = "" }) => {
109
+ let p = t(null), m = t(null), [h, g] = n({
110
+ width: 0,
111
+ height: 350
112
+ });
113
+ return e(() => {
114
+ let e = p.current;
115
+ if (!e) return;
116
+ let t = new ResizeObserver((e) => {
117
+ e[0] && g({
118
+ width: e[0].contentRect.width,
119
+ height: e[0].contentRect.height || 350
120
+ });
121
+ });
122
+ return t.observe(e), () => t.unobserve(e);
123
+ }, []), e(() => {
124
+ if (!m.current || h.width === 0 || a.length === 0) return;
125
+ let { width: e, height: t } = h, n = r.select(m.current), i = r.extent(a, (e) => e.value), f = r.scaleLinear().domain(i).nice().range([u, e - d]), p = r.bin().value((e) => e.value).domain(f.domain()).thresholds(f.ticks(s))(a), g = r.max(p, (e) => e.length) || 10, _ = r.scaleLinear().domain([0, g]).nice().range([t - l, c]);
126
+ 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(f).ticks(s)).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(_).ticks(Math.min(g, 5)).tickFormat(r.format("d")).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"));
127
+ let v = n.select(".bins-group");
128
+ v.empty() && (v = n.append("g").attr("class", "bins-group"));
129
+ let y = v.selectAll(".bin").data(p, (e) => e.x0 || 0);
130
+ y.exit().transition().duration(300).attr("y", _(0)).attr("height", 0).remove();
131
+ let b = y.enter().append("rect").attr("class", "bin").attr("x", (e) => f(e.x0 || 0) + 1).attr("width", (e) => Math.max(0, f(e.x1 || 0) - f(e.x0 || 0) - 1)).attr("y", _(0)).attr("height", 0).attr("fill", o[0]).attr("rx", 2).style("cursor", "pointer");
132
+ b.transition().duration(700).delay((e, t) => t * 30).ease(r.easeCubicOut).attr("y", (e) => _(e.length)).attr("height", (e) => _(0) - _(e.length)), y.transition().duration(750).ease(r.easeCubicOut).attr("x", (e) => f(e.x0 || 0) + 1).attr("width", (e) => Math.max(0, f(e.x1 || 0) - f(e.x0 || 0) - 1)).attr("y", (e) => _(e.length)).attr("height", (e) => _(0) - _(e.length)).attr("fill", o[0]), b.merge(y).on("mouseenter", function() {
133
+ v.selectAll(".bin").transition().duration(200).attr("opacity", .4), r.select(this).transition().duration(200).attr("opacity", 1).attr("filter", "brightness(1.1)");
134
+ }).on("mouseleave", function() {
135
+ v.selectAll(".bin").transition().duration(200).attr("opacity", 1).attr("filter", "none");
136
+ });
137
+ }, [
138
+ a,
139
+ h,
140
+ s,
141
+ o,
142
+ c,
143
+ l,
144
+ u,
145
+ d
146
+ ]), /* @__PURE__ */ i("div", {
147
+ ref: p,
148
+ className: `w-full min-h-[350px] h-full relative ${f}`,
149
+ children: /* @__PURE__ */ i("svg", {
150
+ ref: m,
151
+ width: "100%",
152
+ height: "100%",
153
+ className: "block absolute inset-0 overflow-visible"
154
+ })
155
+ });
156
+ };
157
+ //#endregion
158
+ export { a as default };
@@ -0,0 +1,22 @@
1
+ import { default as React } from 'react';
2
+ export interface HorizontalChartData {
3
+ label: string;
4
+ value: number;
5
+ }
6
+ export interface AnimatedHorizontalBarChartProps {
7
+ /** The dataset */
8
+ data?: HorizontalChartData[];
9
+ /** Visual customization */
10
+ barColor?: string;
11
+ hoverColor?: string;
12
+ /** Format the number label (e.g., '$' or '%') */
13
+ valuePrefix?: string;
14
+ valueSuffix?: string;
15
+ marginTop?: number;
16
+ marginBottom?: number;
17
+ marginLeft?: number;
18
+ marginRight?: number;
19
+ className?: string;
20
+ }
21
+ export declare const AnimatedHorizontalBarChart: React.FC<AnimatedHorizontalBarChartProps>;
22
+ export default AnimatedHorizontalBarChart;
@@ -0,0 +1,82 @@
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/HorizontalBarChart/index.tsx
5
+ var a = ({ data: a = [
6
+ {
7
+ label: "United States",
8
+ value: 850
9
+ },
10
+ {
11
+ label: "United Kingdom",
12
+ value: 620
13
+ },
14
+ {
15
+ label: "Germany",
16
+ value: 480
17
+ },
18
+ {
19
+ label: "Australia",
20
+ value: 310
21
+ },
22
+ {
23
+ label: "Japan",
24
+ value: 250
25
+ }
26
+ ], barColor: o = "#3b82f6", hoverColor: s = "#2563eb", valuePrefix: c = "", valueSuffix: l = "", marginTop: u = 20, marginBottom: d = 30, marginLeft: f = 120, marginRight: p = 60, className: m = "" }) => {
27
+ let h = t(null), g = t(null), [_, v] = n({
28
+ width: 0,
29
+ height: 350
30
+ });
31
+ return e(() => {
32
+ let e = h.current;
33
+ if (!e) return;
34
+ let t = new ResizeObserver((e) => {
35
+ e[0] && v({
36
+ width: e[0].contentRect.width,
37
+ height: e[0].contentRect.height || 350
38
+ });
39
+ });
40
+ return t.observe(e), () => t.unobserve(e);
41
+ }, []), e(() => {
42
+ if (!g.current || _.width === 0 || a.length === 0) return;
43
+ let { width: e, height: t } = _, n = r.select(g.current), i = [...a].sort((e, t) => t.value - e.value), m = r.scaleLinear().domain([0, r.max(i, (e) => e.value) || 100]).nice().range([f, e - p]), h = r.scaleBand().domain(i.map((e) => e.label)).range([u, t - d]).padding(.25);
44
+ n.select(".y-axis").empty() && (n.append("g").attr("class", "axis y-axis"), n.append("g").attr("class", "axis x-axis")), n.select(".y-axis").attr("transform", `translate(${f},0)`).transition().duration(500).call(r.axisLeft(h).tickSizeOuter(0)).attr("font-size", "13px").attr("font-weight", "500").attr("font-family", "ui-sans-serif, system-ui").attr("color", "#334155").call((e) => e.select(".domain").remove()).call((e) => e.selectAll(".tick line").remove()), n.select(".x-axis").attr("transform", `translate(0,${t - d})`).transition().duration(500).call(r.axisBottom(m).ticks(5)).attr("font-size", "11px").attr("font-family", "ui-sans-serif, system-ui").attr("color", "#94a3b8").call((e) => e.select(".domain").remove()).call((e) => e.selectAll(".tick line").attr("y2", -(t - u - d)).attr("stroke-opacity", .1));
45
+ let v = n.select(".bars-group");
46
+ v.empty() && (v = n.append("g").attr("class", "bars-group"));
47
+ let y = v.selectAll(".bar").data(i, (e) => e.label);
48
+ y.exit().transition().duration(400).attr("width", 0).style("opacity", 0).remove();
49
+ let b = y.enter().append("rect").attr("class", "bar").attr("x", m(0)).attr("y", (e) => h(e.label)).attr("height", h.bandwidth()).attr("width", 0).attr("fill", o).attr("rx", 4).attr("ry", 4);
50
+ b.on("mouseenter", function() {
51
+ r.select(this).transition().duration(200).attr("fill", s);
52
+ }).on("mouseleave", function() {
53
+ r.select(this).transition().duration(200).attr("fill", o);
54
+ }), b.merge(y).transition().duration(800).ease(r.easeCubicOut).attr("y", (e) => h(e.label)).attr("height", h.bandwidth()).attr("width", (e) => m(e.value) - m(0)).attr("fill", o);
55
+ let x = n.select(".labels-group");
56
+ x.empty() && (x = n.append("g").attr("class", "labels-group"));
57
+ let S = x.selectAll(".value-label").data(i, (e) => e.label);
58
+ S.exit().remove(), S.enter().append("text").attr("class", "value-label").attr("x", m(0) + 10).attr("y", (e) => h(e.label) + h.bandwidth() / 2).attr("dy", "0.35em").attr("font-size", "12px").attr("font-weight", "600").attr("font-family", "ui-sans-serif, system-ui").attr("fill", "#64748b").style("opacity", 0).text((e) => `${c}${e.value}${l}`).merge(S).transition().duration(800).ease(r.easeCubicOut).attr("y", (e) => h(e.label) + h.bandwidth() / 2).attr("x", (e) => m(e.value) + 10).style("opacity", 1).text((e) => `${c}${e.value.toLocaleString()}${l}`);
59
+ }, [
60
+ a,
61
+ _,
62
+ o,
63
+ s,
64
+ c,
65
+ l,
66
+ u,
67
+ d,
68
+ f,
69
+ p
70
+ ]), /* @__PURE__ */ i("div", {
71
+ ref: h,
72
+ className: `w-full min-h-[300px] h-full relative ${m}`,
73
+ children: /* @__PURE__ */ i("svg", {
74
+ ref: g,
75
+ width: "100%",
76
+ height: "100%",
77
+ className: "block absolute inset-0 overflow-visible"
78
+ })
79
+ });
80
+ };
81
+ //#endregion
82
+ export { a as default };
@@ -0,0 +1,21 @@
1
+ import { default as React } from 'react';
2
+ export interface HundredPercentDataPoint {
3
+ id: string | number;
4
+ category: string;
5
+ [key: string]: any;
6
+ }
7
+ export interface AnimatedHundredPercentBarChartProps {
8
+ /** The dataset containing the categories and their sub-components. */
9
+ data?: HundredPercentDataPoint[];
10
+ /** The exact keys in the data objects that should be stacked on top of each other. */
11
+ stackKeys?: string[];
12
+ /** Default palette for the stacked layers */
13
+ themeColors?: string[];
14
+ marginTop?: number;
15
+ marginBottom?: number;
16
+ marginLeft?: number;
17
+ marginRight?: number;
18
+ className?: string;
19
+ }
20
+ export declare const AnimatedHundredPercentBarChart: React.FC<AnimatedHundredPercentBarChartProps>;
21
+ export default AnimatedHundredPercentBarChart;