lupine.components 1.1.41 → 1.1.43

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 (37) hide show
  1. package/package.json +1 -1
  2. package/src/component-pool/charts/area-chart-demo.tsx +0 -4
  3. package/src/component-pool/charts/area-chart.tsx +5 -2
  4. package/src/component-pool/charts/bar-chart-demo.tsx +1 -4
  5. package/src/component-pool/charts/bar-chart.tsx +5 -2
  6. package/src/component-pool/charts/chart-utils.ts +4 -3
  7. package/src/component-pool/charts/column-chart-demo.tsx +1 -4
  8. package/src/component-pool/charts/column-chart.tsx +5 -2
  9. package/src/component-pool/charts/donut-chart-demo.tsx +2 -5
  10. package/src/component-pool/charts/donut-chart.tsx +1 -23
  11. package/src/component-pool/charts/gauge-chart-demo.tsx +0 -4
  12. package/src/component-pool/charts/gauge-chart.tsx +5 -2
  13. package/src/component-pool/charts/line-chart-demo.tsx +0 -4
  14. package/src/component-pool/charts/line-chart.tsx +5 -2
  15. package/src/component-pool/charts/pie-chart-demo.tsx +4 -10
  16. package/src/component-pool/charts/pie-chart.tsx +78 -61
  17. package/src/component-pool/charts/radar-chart-demo.tsx +0 -3
  18. package/src/component-pool/charts/radar-chart.tsx +40 -5
  19. package/src/component-pool/charts/scatter-chart-demo.tsx +0 -3
  20. package/src/component-pool/charts/scatter-chart.tsx +5 -2
  21. package/src/component-pool/index.ts +1 -0
  22. package/src/component-pool/svg-graph/index.ts +1 -0
  23. package/src/component-pool/svg-graph/svg-graph-demo.tsx +59 -0
  24. package/src/component-pool/svg-graph/svg-graph.ts +166 -0
  25. package/src/component-pool/youtube-player/youtube-player-demo.tsx +4 -4
  26. package/src/component-pool/youtube-player/youtube-player.tsx +90 -14
  27. package/src/components/action-sheet-demo.tsx +12 -0
  28. package/src/components/action-sheet-theme.tsx +150 -0
  29. package/src/components/index.ts +1 -0
  30. package/src/components/menu-bar.tsx +15 -4
  31. package/src/components/menu-sidebar.tsx +24 -12
  32. package/src/components/message-box.tsx +18 -0
  33. package/src/components/popup-menu.tsx +4 -4
  34. package/src/components/tabs.tsx +9 -6
  35. package/src/demo/demo-about.tsx +1 -1
  36. package/src/demo/demo-frame-helper.tsx +8 -1
  37. package/src/demo/demo-registry.ts +2 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lupine.components",
3
- "version": "1.1.41",
3
+ "version": "1.1.43",
4
4
  "license": "MIT",
5
5
  "author": "uuware.com",
6
6
  "homepage": "https://github.com/uuware/lupine.js",
@@ -16,14 +16,12 @@ export const areaChartDemo: DemoStory<any> = {
16
16
  args: {
17
17
  title: 'Company Revenues',
18
18
  width: '100%',
19
- height: '350px',
20
19
  showLegend: true,
21
20
  curved: true,
22
21
  },
23
22
  argTypes: {
24
23
  title: { control: 'text' },
25
24
  width: { control: 'text' },
26
- height: { control: 'text' },
27
25
  showLegend: { control: 'boolean' },
28
26
  curved: { control: 'boolean' },
29
27
  },
@@ -70,7 +68,6 @@ export const areaChartDemo: DemoStory<any> = {
70
68
  data={multiSeriesData}
71
69
  title={args.title}
72
70
  width={args.width}
73
- height={args.height}
74
71
  showLegend={args.showLegend}
75
72
  curved={args.curved}
76
73
  yAxisFormatter={(val) => '$' + val + 'M'}
@@ -84,7 +81,6 @@ export const areaChartDemo: DemoStory<any> = {
84
81
  <AreaChart
85
82
  data={multiSeriesData}
86
83
  title='Straight Area Comparison'
87
- height='300px'
88
84
  showLegend={true}
89
85
  curved={false}
90
86
  yAxisFormatter={(val) => '$' + val + 'M'}
@@ -228,13 +228,16 @@ export const AreaChart = (props: AreaChartProps) => {
228
228
  },
229
229
  };
230
230
 
231
- const styleStr = `width: ${props.width || '100%'}; height: ${props.height || '100%'};`;
231
+ const ratio = props.aspectRatio ?? 16 / 9;
232
+ const paddingTop = `${(1 / ratio) * 100}%`;
233
+
234
+ const styleStr = `width: ${props.width || '100%'};`;
232
235
 
233
236
  return (
234
237
  <div ref={ref} class='&-container' style={styleStr}>
235
238
  {props.title && <div class='chart-title'>{props.title}</div>}
236
239
 
237
- <div style={{ flex: 1, position: 'relative', minHeight: 0 }}>{chartVar.node}</div>
240
+ <div style={{ flex: 1, position: 'relative', minHeight: 0, paddingTop }}>{chartVar.node}</div>
238
241
 
239
242
  {showLegend && (
240
243
  <div class='chart-legend'>
@@ -26,13 +26,11 @@ export const barChartDemo: DemoStory<any> = {
26
26
  args: {
27
27
  title: 'Top Economies',
28
28
  width: '100%',
29
- height: '350px',
30
29
  showLegend: true,
31
30
  },
32
31
  argTypes: {
33
32
  title: { control: 'text' },
34
33
  width: { control: 'text' },
35
- height: { control: 'text' },
36
34
  showLegend: { control: 'boolean' },
37
35
  },
38
36
  render: (args: any) => {
@@ -78,7 +76,6 @@ export const barChartDemo: DemoStory<any> = {
78
76
  data={singleSeriesData}
79
77
  title={args.title}
80
78
  width={args.width}
81
- height={args.height}
82
79
  showLegend={args.showLegend}
83
80
  xAxisFormatter={(val) => '$' + val + 'T'}
84
81
  />
@@ -88,7 +85,7 @@ export const barChartDemo: DemoStory<any> = {
88
85
  <section class='demo-section'>
89
86
  <div class='section-title'>Multi-Series (Grouped Horizontal)</div>
90
87
  <div class='chart-box'>
91
- <BarChart data={multiSeriesData} title='Quarterly Comparison' height='300px' showLegend={true} />
88
+ <BarChart data={multiSeriesData} title='Quarterly Comparison' showLegend={true} />
92
89
  </div>
93
90
  </section>
94
91
  </div>
@@ -197,13 +197,16 @@ export const BarChart = (props: BarChartProps) => {
197
197
  },
198
198
  };
199
199
 
200
- const styleStr = `width: ${props.width || '100%'}; height: ${props.height || '100%'};`;
200
+ const ratio = props.aspectRatio ?? 16 / 9;
201
+ const paddingTop = `${(1 / ratio) * 100}%`;
202
+
203
+ const styleStr = `width: ${props.width || '100%'};`;
201
204
 
202
205
  return (
203
206
  <div ref={ref} class='&-container' style={styleStr}>
204
207
  {props.title && <div class='chart-title'>{props.title}</div>}
205
208
 
206
- <div style={{ flex: 1, position: 'relative', minHeight: 0 }}>{chartVar.node}</div>
209
+ <div style={{ flex: 1, position: 'relative', minHeight: 0, paddingTop }}>{chartVar.node}</div>
207
210
 
208
211
  {showLegend && (
209
212
  <div class='chart-legend'>
@@ -20,8 +20,9 @@ declare global {
20
20
  export const chartCommonCss: CssProps = {
21
21
  position: 'relative',
22
22
  width: '100%',
23
- height: '100%',
24
- minHeight: '200px', // Default min height
23
+ height: 'auto',
24
+ minHeight: '0', // Default min height
25
+ maxHeight: '100%',
25
26
  display: 'flex',
26
27
  flexDirection: 'column',
27
28
 
@@ -113,7 +114,7 @@ export type ChartData = {
113
114
  export type BasicChartProps = {
114
115
  title?: string;
115
116
  data: ChartData;
116
- height?: string | number;
117
+ aspectRatio?: number;
117
118
  width?: string | number;
118
119
  showLegend?: boolean;
119
120
  };
@@ -27,13 +27,11 @@ export const columnChartDemo: DemoStory<any> = {
27
27
  args: {
28
28
  title: 'Monthly Revenue',
29
29
  width: '100%',
30
- height: '350px',
31
30
  showLegend: true,
32
31
  },
33
32
  argTypes: {
34
33
  title: { control: 'text' },
35
34
  width: { control: 'text' },
36
- height: { control: 'text' },
37
35
  showLegend: { control: 'boolean' },
38
36
  },
39
37
  render: (args: any) => {
@@ -79,7 +77,6 @@ export const columnChartDemo: DemoStory<any> = {
79
77
  data={singleSeriesData}
80
78
  title={args.title}
81
79
  width={args.width}
82
- height={args.height}
83
80
  showLegend={args.showLegend}
84
81
  yAxisFormatter={(val) => '$' + val}
85
82
  />
@@ -89,7 +86,7 @@ export const columnChartDemo: DemoStory<any> = {
89
86
  <section class='demo-section'>
90
87
  <div class='section-title'>Multi-Series (Grouped)</div>
91
88
  <div class='chart-box'>
92
- <ColumnChart data={multiSeriesData} title='Quarterly Product Sales' height='300px' showLegend={true} />
89
+ <ColumnChart data={multiSeriesData} title='Quarterly Product Sales' showLegend={true} />
93
90
  </div>
94
91
  </section>
95
92
  </div>
@@ -204,13 +204,16 @@ export const ColumnChart = (props: ColumnChartProps) => {
204
204
  },
205
205
  };
206
206
 
207
- const styleStr = `width: ${props.width || '100%'}; height: ${props.height || '100%'};`;
207
+ const ratio = props.aspectRatio ?? 16 / 9;
208
+ const paddingTop = `${(1 / ratio) * 100}%`;
209
+
210
+ const styleStr = `width: ${props.width || '100%'};`;
208
211
 
209
212
  return (
210
213
  <div ref={ref} class='&-container' style={styleStr}>
211
214
  {props.title && <div class='chart-title'>{props.title}</div>}
212
215
 
213
- <div style={{ flex: 1, position: 'relative', minHeight: 0 }}>{chartVar.node}</div>
216
+ <div style={{ flex: 1, position: 'relative', minHeight: 0, paddingTop }}>{chartVar.node}</div>
214
217
 
215
218
  {showLegend && (
216
219
  <div class='chart-legend'>
@@ -18,14 +18,12 @@ export const donutChartDemo: DemoStory<any> = {
18
18
  args: {
19
19
  title: 'Traffic Sources',
20
20
  width: '100%',
21
- height: '300px',
22
21
  showLegend: true,
23
22
  innerRadiusRatio: 0.6,
24
23
  },
25
24
  argTypes: {
26
25
  title: { control: 'text' },
27
26
  width: { control: 'text' },
28
- height: { control: 'text' },
29
27
  showLegend: { control: 'boolean' },
30
28
  innerRadiusRatio: { control: 'number' },
31
29
  },
@@ -78,7 +76,6 @@ export const donutChartDemo: DemoStory<any> = {
78
76
  data={sampleData}
79
77
  title={args.title}
80
78
  width={args.width}
81
- height={args.height}
82
79
  showLegend={args.showLegend}
83
80
  innerRadiusRatio={args.innerRadiusRatio}
84
81
  />
@@ -89,10 +86,10 @@ export const donutChartDemo: DemoStory<any> = {
89
86
  <div class='section-title'>Variations</div>
90
87
  <div class='grid'>
91
88
  <div class='chart-box'>
92
- <DonutChart data={sampleData} title='Thin Ring' innerRadiusRatio={0.8} height='200px' />
89
+ <DonutChart data={sampleData} title='Thin Ring' innerRadiusRatio={0.8} />
93
90
  </div>
94
91
  <div class='chart-box'>
95
- <DonutChart data={sampleData} title='Thick Ring' innerRadiusRatio={0.3} height='200px' />
92
+ <DonutChart data={sampleData} title='Thick Ring' innerRadiusRatio={0.3} />
96
93
  </div>
97
94
  </div>
98
95
  </section>
@@ -2,27 +2,5 @@ import { PieChartProps, PieChart } from './pie-chart';
2
2
 
3
3
  // Donut Chart is just a Pie Chart with an inner radius wrapper
4
4
  export const DonutChart = (props: Omit<PieChartProps, 'innerRadiusRatio'> & { innerRadiusRatio?: number }) => {
5
- const viewBoxSize = 100; // Assuming a default viewBox size for the wrapper
6
-
7
- return (
8
- <div
9
- style={{
10
- flex: 1,
11
- position: 'relative',
12
- display: 'flex',
13
- justifyContent: 'center',
14
- alignItems: 'center',
15
- minHeight: '0',
16
- }}
17
- >
18
- <svg
19
- className='chart-svg' // Changed 'class' to 'className' for React
20
- style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', overflow: 'visible' }}
21
- viewBox={`0 0 ${viewBoxSize} ${viewBoxSize}`}
22
- preserveAspectRatio='xMidYMid meet'
23
- >
24
- <PieChart {...props} innerRadiusRatio={props.innerRadiusRatio ?? 0.6} />
25
- </svg>
26
- </div>
27
- );
5
+ return <PieChart {...props} innerRadiusRatio={props.innerRadiusRatio ?? 0.6} />;
28
6
  };
@@ -8,13 +8,11 @@ export const gaugeChartDemo: DemoStory<any> = {
8
8
  args: {
9
9
  title: 'Server Load',
10
10
  width: '100%',
11
- height: '350px',
12
11
  value: 65,
13
12
  },
14
13
  argTypes: {
15
14
  title: { control: 'text' },
16
15
  width: { control: 'text' },
17
- height: { control: 'text' },
18
16
  value: { control: 'number' },
19
17
  },
20
18
  render: (args: any) => {
@@ -60,7 +58,6 @@ export const gaugeChartDemo: DemoStory<any> = {
60
58
  liveValue.value = (
61
59
  <GaugeChart
62
60
  title='CPU Usage'
63
- height='300px'
64
61
  value={Math.round(currentValue)}
65
62
  color='#e74c3c'
66
63
  valueFormatter={(v) => v + '%'}
@@ -79,7 +76,6 @@ export const gaugeChartDemo: DemoStory<any> = {
79
76
  <GaugeChart
80
77
  title={args.title}
81
78
  width={args.width}
82
- height={args.height}
83
79
  value={args.value}
84
80
  valueFormatter={(v) => v + '%'}
85
81
  />
@@ -63,13 +63,16 @@ export const GaugeChart = (props: GaugeChartProps) => {
63
63
  globalCssId,
64
64
  };
65
65
 
66
- const styleStr = `width: ${props.width || '100%'}; height: ${props.height || '100%'};`;
66
+ const ratio = props.aspectRatio ?? 16 / 9;
67
+ const paddingTop = `${(1 / ratio) * 100}%`;
68
+
69
+ const styleStr = `width: ${props.width || '100%'};`;
67
70
 
68
71
  return (
69
72
  <div ref={ref} class='&-container' style={styleStr}>
70
73
  {props.title && <div class='chart-title'>{props.title}</div>}
71
74
 
72
- <div style={{ flex: 1, position: 'relative', display: 'flex', justifyContent: 'center', minHeight: 0 }}>
75
+ <div style={{ flex: 1, position: 'relative', display: 'flex', justifyContent: 'center', minHeight: 0, paddingTop }}>
73
76
  <svg
74
77
  class='chart-svg'
75
78
  style={{
@@ -21,14 +21,12 @@ export const lineChartDemo: DemoStory<any> = {
21
21
  args: {
22
22
  title: 'Exchange Rates over Week',
23
23
  width: '100%',
24
- height: '350px',
25
24
  showLegend: true,
26
25
  curved: false,
27
26
  },
28
27
  argTypes: {
29
28
  title: { control: 'text' },
30
29
  width: { control: 'text' },
31
- height: { control: 'text' },
32
30
  showLegend: { control: 'boolean' },
33
31
  curved: { control: 'boolean' },
34
32
  },
@@ -75,7 +73,6 @@ export const lineChartDemo: DemoStory<any> = {
75
73
  data={multiSeriesData}
76
74
  title={args.title}
77
75
  width={args.width}
78
- height={args.height}
79
76
  showLegend={args.showLegend}
80
77
  curved={args.curved}
81
78
  />
@@ -88,7 +85,6 @@ export const lineChartDemo: DemoStory<any> = {
88
85
  <LineChart
89
86
  data={exchangeRatesData}
90
87
  title='Crypto Value 2024'
91
- height='300px'
92
88
  showLegend={true}
93
89
  curved={true}
94
90
  />
@@ -207,13 +207,16 @@ export const LineChart = (props: LineChartProps) => {
207
207
  },
208
208
  };
209
209
 
210
- const styleStr = `width: ${props.width || '100%'}; height: ${props.height || '100%'};`;
210
+ const ratio = props.aspectRatio ?? 16 / 9;
211
+ const paddingTop = `${(1 / ratio) * 100}%`;
212
+
213
+ const styleStr = `width: ${props.width || '100%'};`;
211
214
 
212
215
  return (
213
216
  <div ref={ref} class='&-container' style={styleStr}>
214
217
  {props.title && <div class='chart-title'>{props.title}</div>}
215
218
 
216
- <div style={{ flex: 1, position: 'relative', minHeight: 0 }}>{chartVar.node}</div>
219
+ <div style={{ flex: 1, position: 'relative', minHeight: 0, paddingTop }}>{chartVar.node}</div>
217
220
 
218
221
  {showLegend && (
219
222
  <div class='chart-legend'>
@@ -23,13 +23,11 @@ export const pieChartDemo: DemoStory<any> = {
23
23
  args: {
24
24
  title: 'Fruit Sales',
25
25
  width: '100%',
26
- height: '300px',
27
26
  showLegend: true,
28
27
  },
29
28
  argTypes: {
30
29
  title: { control: 'text' },
31
30
  width: { control: 'text' },
32
- height: { control: 'text' },
33
31
  showLegend: { control: 'boolean' },
34
32
  },
35
33
  render: (args: any) => {
@@ -81,7 +79,6 @@ export const pieChartDemo: DemoStory<any> = {
81
79
  data={sampleData}
82
80
  title={args.title}
83
81
  width={args.width}
84
- height={args.height}
85
82
  showLegend={args.showLegend}
86
83
  />
87
84
  </div>
@@ -91,10 +88,10 @@ export const pieChartDemo: DemoStory<any> = {
91
88
  <div class='section-title'>Variations</div>
92
89
  <div class='grid'>
93
90
  <div class='chart-box'>
94
- <PieChart data={sampleData} title='No Legend' showLegend={false} height='200px' />
91
+ <PieChart data={sampleData} title='No Legend' showLegend={false} />
95
92
  </div>
96
93
  <div class='chart-box'>
97
- <PieChart data={emptyData} title='Empty Data' height='200px' />
94
+ <PieChart data={emptyData} title='Empty Data' />
98
95
  </div>
99
96
  <div class='chart-box'>
100
97
  <PieChart
@@ -103,8 +100,7 @@ export const pieChartDemo: DemoStory<any> = {
103
100
  series: [{ name: 'Lone', data: [100] }],
104
101
  }}
105
102
  title='100% Value'
106
- height='200px'
107
- />
103
+ />
108
104
  </div>
109
105
  <div class='chart-box'>
110
106
  <PieChart
@@ -113,8 +109,7 @@ export const pieChartDemo: DemoStory<any> = {
113
109
  series: [{ name: 'Half', data: [50, 50] }],
114
110
  }}
115
111
  title='50/50 Split'
116
- height='200px'
117
- />
112
+ />
118
113
  </div>
119
114
  </div>
120
115
  </section>
@@ -132,7 +127,6 @@ const data = {
132
127
  data={data}
133
128
  title="Fruit Sales"
134
129
  width="100%"
135
- height="300px"
136
130
  showLegend={true}
137
131
  />
138
132
  `,
@@ -13,78 +13,94 @@ export const PieChart = (props: PieChartProps) => {
13
13
  const showLegend = props.showLegend !== false;
14
14
  const innerRadiusRatio = props.innerRadiusRatio ?? 0;
15
15
 
16
- // Pie chart relies on the first series only
17
- const series = props.data.series[0];
18
- if (!series || !series.data || series.data.length === 0) {
16
+ const seriesList = props.data.series;
17
+ if (!seriesList || seriesList.length === 0) {
19
18
  return <div class='&-container'>No data</div>;
20
19
  }
21
20
 
22
- const values = series.data;
23
- const total = values.reduce((sum, val) => sum + val, 0);
24
-
25
21
  // SVG viewBox settings
26
22
  const viewBoxSize = 200;
27
23
  const center = viewBoxSize / 2;
28
- const radius = (viewBoxSize / 2) * 0.9; // 90% of container to leave margin for stroke/anti-aliasing
29
- const innerRadius = radius * innerRadiusRatio;
30
-
31
- let currentAngle = 0;
32
-
33
- const slices = values.map((val, index) => {
34
- // Prevent 0 area slices. Also handle case where 1 val is 100%
35
- const ratio = total > 0 ? val / total : 0;
36
- const angleDelta = ratio * 360;
37
-
38
- // Fix for 100% slice (SVG arcs don't draw well at exactly 360)
39
- const isFullCircle = angleDelta === 360;
40
- const adjustedAngleDelta = isFullCircle ? 359.99 : angleDelta;
41
-
42
- const startAngle = currentAngle;
43
- const endAngle = currentAngle + adjustedAngleDelta;
44
- currentAngle += adjustedAngleDelta;
45
-
46
- const pathD = describeArc(center, center, radius, startAngle, endAngle, innerRadius);
47
- const color = getChartColor(index);
48
- const label = props.data.labels[index] || `Item ${index + 1}`;
49
-
50
- const handleMouseEnter = (e: any) => {
51
- const percentage = (ratio * 100).toFixed(1) + '%';
52
- Tooltip.show(
53
- e,
54
- <div>
55
- <div style={{ fontWeight: 'bold' }}>{label}</div>
56
- <div>Value: {val}</div>
57
- <div>Share: {percentage}</div>
58
- </div>,
59
- { position: 'auto' }
24
+ const maxRadius = (viewBoxSize / 2) * 0.9; // 90% of container to leave margin for stroke/anti-aliasing
25
+
26
+ const globalInnerRadius = maxRadius * innerRadiusRatio;
27
+ const numSeries = seriesList.length;
28
+ // If only 1 series and innerRadiusRatio is 0, ringThickness is maxRadius.
29
+ // If multiple series, we divide the available space (maxRadius - globalInnerRadius) among them.
30
+ const ringThickness = (maxRadius - globalInnerRadius) / numSeries;
31
+
32
+ const allSlices: any[] = [];
33
+
34
+ seriesList.forEach((series, seriesIndex) => {
35
+ const values = series.data;
36
+ if (!values || values.length === 0) return;
37
+
38
+ const total = values.reduce((sum, val) => sum + val, 0);
39
+ let currentAngle = 0;
40
+
41
+ // Outermost ring is series 0
42
+ const outerR = maxRadius - seriesIndex * ringThickness;
43
+ const innerR = outerR - ringThickness;
44
+
45
+ values.forEach((val, index) => {
46
+ // Prevent 0 area slices. Also handle case where 1 val is 100%
47
+ const ratio = total > 0 ? val / total : 0;
48
+ const angleDelta = ratio * 360;
49
+
50
+ // Fix for 100% slice (SVG arcs don't draw well at exactly 360)
51
+ const isFullCircle = angleDelta === 360;
52
+ const adjustedAngleDelta = isFullCircle ? 359.99 : angleDelta;
53
+
54
+ const startAngle = currentAngle;
55
+ const endAngle = currentAngle + adjustedAngleDelta;
56
+ currentAngle += adjustedAngleDelta;
57
+
58
+ const pathD = describeArc(center, center, outerR, startAngle, endAngle, innerR);
59
+ const color = getChartColor(index);
60
+ const label = props.data.labels[index] || `Item ${index + 1}`;
61
+
62
+ const handleMouseEnter = (e: any) => {
63
+ const percentage = (ratio * 100).toFixed(1) + '%';
64
+ Tooltip.show(
65
+ e,
66
+ <div>
67
+ <div style={{ fontWeight: 'bold' }}>{series.name ? `${series.name} - ` : ''}{label}</div>
68
+ <div>Value: {val}</div>
69
+ <div>Share: {percentage}</div>
70
+ </div>,
71
+ { position: 'auto' }
72
+ );
73
+ e.target.style.opacity = 0.8;
74
+ };
75
+
76
+ const handleMouseLeave = (e: any) => {
77
+ Tooltip.hide();
78
+ e.target.style.opacity = 1;
79
+ };
80
+
81
+ allSlices.push(
82
+ <path
83
+ class='chart-element'
84
+ d={pathD}
85
+ fill={color}
86
+ stroke='var(--primary-bg-color)' // border color between slices
87
+ stroke-width={isFullCircle ? '0' : '1'}
88
+ onMouseEnter={handleMouseEnter}
89
+ onMouseLeave={handleMouseLeave}
90
+ style={{ transition: 'opacity 0.2s' }}
91
+ />
60
92
  );
61
- // Optional: highlight slice
62
- e.target.style.opacity = 0.8;
63
- };
64
-
65
- const handleMouseLeave = (e: any) => {
66
- Tooltip.hide();
67
- e.target.style.opacity = 1;
68
- };
69
-
70
- return (
71
- <path
72
- class='chart-element'
73
- d={pathD}
74
- fill={color}
75
- stroke='var(--primary-bg-color)' // border color between slices
76
- stroke-width={isFullCircle ? '0' : '1'}
77
- onMouseEnter={handleMouseEnter}
78
- onMouseLeave={handleMouseLeave}
79
- />
80
- );
93
+ });
81
94
  });
82
95
 
83
96
  const ref: RefProps = {
84
97
  globalCssId,
85
98
  };
86
99
 
87
- const styleStr = `width: ${props.width || '100%'}; height: ${props.height || '100%'}; min-height: 200px;`;
100
+ const ratio = props.aspectRatio ?? 16 / 9;
101
+ const paddingTop = `${(1 / ratio) * 100}%`;
102
+
103
+ const styleStr = `width: ${props.width || '100%'}; min-height: 200px;`;
88
104
 
89
105
  return (
90
106
  <div ref={ref} class='&-container' style={styleStr}>
@@ -98,6 +114,7 @@ export const PieChart = (props: PieChartProps) => {
98
114
  justifyContent: 'center',
99
115
  alignItems: 'center',
100
116
  minHeight: '0',
117
+ paddingTop,
101
118
  }}
102
119
  >
103
120
  <svg
@@ -106,13 +123,13 @@ export const PieChart = (props: PieChartProps) => {
106
123
  viewBox={`0 0 ${viewBoxSize} ${viewBoxSize}`}
107
124
  preserveAspectRatio='xMidYMid meet'
108
125
  >
109
- <g>{slices}</g>
126
+ <g>{allSlices}</g>
110
127
  </svg>
111
128
  </div>
112
129
 
113
130
  {showLegend && (
114
131
  <div class='chart-legend'>
115
- {values.map((_, i) => (
132
+ {props.data.labels.map((_, i) => (
116
133
  <div class='legend-item'>
117
134
  <div class='legend-color' style={{ backgroundColor: getChartColor(i) }} />
118
135
  <div>{props.data.labels[i] || `Item ${i + 1}`}</div>
@@ -16,13 +16,11 @@ export const radarChartDemo: DemoStory<any> = {
16
16
  args: {
17
17
  title: 'Character Stats',
18
18
  width: '100%',
19
- height: '400px',
20
19
  showLegend: true,
21
20
  },
22
21
  argTypes: {
23
22
  title: { control: 'text' },
24
23
  width: { control: 'text' },
25
- height: { control: 'text' },
26
24
  showLegend: { control: 'boolean' },
27
25
  },
28
26
  render: (args: any) => {
@@ -68,7 +66,6 @@ export const radarChartDemo: DemoStory<any> = {
68
66
  data={statsData}
69
67
  title={args.title}
70
68
  width={args.width}
71
- height={args.height}
72
69
  showLegend={args.showLegend}
73
70
  />
74
71
  </div>