@shohojdhara/atomix 0.2.4 → 0.2.5

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 (211) hide show
  1. package/README.md +19 -0
  2. package/dist/atomix.css +1266 -1412
  3. package/dist/atomix.min.css +3 -3
  4. package/dist/index.d.ts +1232 -876
  5. package/dist/index.esm.js +16212 -26364
  6. package/dist/index.esm.js.map +1 -1
  7. package/dist/index.js +15652 -22298
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.min.js +1 -1
  10. package/dist/index.min.js.map +1 -1
  11. package/dist/themes/applemix.css +15008 -0
  12. package/dist/themes/applemix.min.css +72 -0
  13. package/dist/themes/boomdevs.css +1266 -1413
  14. package/dist/themes/boomdevs.min.css +3 -3
  15. package/dist/themes/esrar.css +1267 -1413
  16. package/dist/themes/esrar.min.css +3 -3
  17. package/dist/themes/flashtrade.css +15159 -0
  18. package/dist/themes/flashtrade.min.css +86 -0
  19. package/dist/themes/mashroom.css +1264 -1410
  20. package/dist/themes/mashroom.min.css +5 -5
  21. package/dist/themes/shaj-default.css +1266 -1412
  22. package/dist/themes/shaj-default.min.css +3 -3
  23. package/package.json +6 -17
  24. package/src/components/Accordion/Accordion.stories.tsx +4 -26
  25. package/src/components/Accordion/Accordion.tsx +21 -12
  26. package/src/components/AtomixGlass/AtomixGlass.test.tsx +106 -72
  27. package/src/components/AtomixGlass/AtomixGlass.tsx +487 -1215
  28. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +400 -0
  29. package/src/components/AtomixGlass/GlassFilter.tsx +156 -0
  30. package/src/components/AtomixGlass/README.md +124 -2
  31. package/src/components/AtomixGlass/atomixGLass.old.tsx +1266 -0
  32. package/src/components/AtomixGlass/glass-utils.ts +263 -0
  33. package/src/components/AtomixGlass/shader-utils.ts +404 -236
  34. package/src/components/AtomixGlass/{AtomixGlass.stories.tsx → stories/AtomixGlass.stories.tsx} +55 -35
  35. package/src/components/AtomixGlass/stories/Examples.stories.tsx +57 -89
  36. package/src/components/AtomixGlass/stories/Modes.stories.tsx +149 -149
  37. package/src/components/AtomixGlass/stories/Playground.stories.tsx +95 -32
  38. package/src/components/AtomixGlass/stories/ShaderVariants.stories.tsx +0 -2
  39. package/src/components/AtomixGlass/stories/shared-components.tsx +9 -18
  40. package/src/components/AtomixGlass/utils.ts +3 -3
  41. package/src/components/Avatar/Avatar.tsx +3 -0
  42. package/src/components/Avatar/AvatarGroup.tsx +2 -1
  43. package/src/components/Badge/Badge.stories.tsx +74 -54
  44. package/src/components/Badge/Badge.tsx +8 -12
  45. package/src/components/Breadcrumb/Breadcrumb.tsx +23 -4
  46. package/src/components/Button/Button.tsx +3 -5
  47. package/src/components/Callout/Callout.stories.tsx +86 -35
  48. package/src/components/Callout/Callout.tsx +4 -0
  49. package/src/components/Card/Card.stories.tsx +89 -85
  50. package/src/components/Card/Card.tsx +15 -4
  51. package/src/components/Card/ElevationCard.tsx +2 -0
  52. package/src/components/Chart/AnimatedChart.tsx +179 -156
  53. package/src/components/Chart/AreaChart.tsx +123 -12
  54. package/src/components/Chart/BarChart.tsx +91 -100
  55. package/src/components/Chart/BaseChart.tsx +80 -0
  56. package/src/components/Chart/BubbleChart.tsx +114 -290
  57. package/src/components/Chart/CandlestickChart.tsx +282 -622
  58. package/src/components/Chart/Chart.stories.tsx +576 -179
  59. package/src/components/Chart/Chart.tsx +374 -75
  60. package/src/components/Chart/ChartRenderer.tsx +371 -220
  61. package/src/components/Chart/ChartToolbar.tsx +372 -61
  62. package/src/components/Chart/ChartTooltip.tsx +33 -18
  63. package/src/components/Chart/DonutChart.tsx +172 -254
  64. package/src/components/Chart/FunnelChart.tsx +169 -240
  65. package/src/components/Chart/GaugeChart.tsx +224 -392
  66. package/src/components/Chart/HeatmapChart.tsx +302 -440
  67. package/src/components/Chart/LineChart.tsx +148 -103
  68. package/src/components/Chart/MultiAxisChart.tsx +267 -395
  69. package/src/components/Chart/PieChart.tsx +114 -64
  70. package/src/components/Chart/RadarChart.tsx +202 -218
  71. package/src/components/Chart/ScatterChart.tsx +111 -97
  72. package/src/components/Chart/TreemapChart.tsx +147 -222
  73. package/src/components/Chart/WaterfallChart.tsx +253 -291
  74. package/src/components/Chart/index.ts +11 -9
  75. package/src/components/Chart/types.ts +85 -9
  76. package/src/components/Chart/utils.ts +66 -0
  77. package/src/components/ColorModeToggle/ColorModeToggle.tsx +6 -3
  78. package/src/components/Countdown/Countdown.tsx +4 -0
  79. package/src/components/DataTable/DataTable.tsx +2 -1
  80. package/src/components/DatePicker/DatePicker.stories.tsx +0 -11
  81. package/src/components/DatePicker/DatePicker.tsx +3 -9
  82. package/src/components/DatePicker/types.ts +5 -0
  83. package/src/components/Dropdown/Dropdown.stories.tsx +32 -25
  84. package/src/components/Dropdown/Dropdown.tsx +26 -28
  85. package/src/components/EdgePanel/EdgePanel.stories.tsx +13 -15
  86. package/src/components/EdgePanel/EdgePanel.tsx +20 -5
  87. package/src/components/Footer/Footer.stories.tsx +187 -60
  88. package/src/components/Footer/Footer.test.tsx +134 -0
  89. package/src/components/Footer/Footer.tsx +133 -34
  90. package/src/components/Footer/FooterLink.tsx +1 -1
  91. package/src/components/Footer/FooterSection.tsx +53 -36
  92. package/src/components/Footer/FooterSocialLink.tsx +32 -29
  93. package/src/components/Footer/README.md +82 -3
  94. package/src/components/Footer/index.ts +1 -1
  95. package/src/components/Form/Checkbox.stories.tsx +13 -5
  96. package/src/components/Form/Checkbox.tsx +3 -6
  97. package/src/components/Form/Form.stories.tsx +10 -3
  98. package/src/components/Form/Form.tsx +2 -0
  99. package/src/components/Form/FormGroup.tsx +2 -1
  100. package/src/components/Form/Input.stories.tsx +12 -11
  101. package/src/components/Form/Input.tsx +97 -95
  102. package/src/components/Form/Radio.stories.tsx +22 -7
  103. package/src/components/Form/Radio.tsx +3 -6
  104. package/src/components/Form/Select.stories.tsx +21 -6
  105. package/src/components/Form/Select.tsx +3 -5
  106. package/src/components/Form/Textarea.stories.tsx +13 -11
  107. package/src/components/Form/Textarea.tsx +88 -86
  108. package/src/components/Hero/Hero.stories.tsx +2 -3
  109. package/src/components/Hero/Hero.tsx +5 -6
  110. package/src/components/Icon/Icon.tsx +12 -1
  111. package/src/components/List/List.tsx +2 -1
  112. package/src/components/List/ListGroup.tsx +2 -1
  113. package/src/components/Messages/Messages.tsx +3 -2
  114. package/src/components/Modal/Modal.stories.tsx +48 -34
  115. package/src/components/Modal/Modal.tsx +19 -23
  116. package/src/components/Navigation/Menu/MegaMenu.tsx +2 -2
  117. package/src/components/Navigation/Menu/Menu.tsx +2 -2
  118. package/src/components/Navigation/Nav/Nav.tsx +6 -1
  119. package/src/components/Navigation/Nav/NavDropdown.tsx +10 -1
  120. package/src/components/Navigation/Navbar/Navbar.tsx +4 -1
  121. package/src/components/Navigation/SideMenu/SideMenu.tsx +3 -2
  122. package/src/components/Pagination/Pagination.stories.tsx +13 -6
  123. package/src/components/Pagination/Pagination.tsx +7 -6
  124. package/src/components/PhotoViewer/PhotoViewer.tsx +2 -1
  125. package/src/components/Popover/Popover.stories.tsx +32 -24
  126. package/src/components/Popover/Popover.tsx +4 -1
  127. package/src/components/ProductReview/ProductReview.tsx +8 -2
  128. package/src/components/Progress/Progress.tsx +2 -1
  129. package/src/components/Rating/Rating.stories.tsx +11 -6
  130. package/src/components/Rating/Rating.tsx +3 -5
  131. package/src/components/River/River.tsx +5 -5
  132. package/src/components/SectionIntro/SectionIntro.tsx +8 -2
  133. package/src/components/Slider/Slider.stories.tsx +4 -4
  134. package/src/components/Slider/Slider.tsx +4 -3
  135. package/src/components/Spinner/Spinner.tsx +2 -1
  136. package/src/components/Steps/Steps.stories.tsx +5 -4
  137. package/src/components/Steps/Steps.tsx +8 -5
  138. package/src/components/Tab/Tab.stories.tsx +4 -3
  139. package/src/components/Tab/Tab.tsx +8 -6
  140. package/src/components/Testimonial/Testimonial.tsx +8 -2
  141. package/src/components/Todo/Todo.tsx +2 -1
  142. package/src/components/Toggle/Toggle.stories.tsx +5 -4
  143. package/src/components/Toggle/Toggle.tsx +8 -5
  144. package/src/components/Tooltip/Tooltip.stories.tsx +40 -30
  145. package/src/components/Tooltip/Tooltip.tsx +9 -2
  146. package/src/components/Upload/Upload.stories.tsx +252 -0
  147. package/src/components/Upload/Upload.tsx +92 -53
  148. package/src/components/VideoPlayer/VideoPlayer.tsx +3 -1
  149. package/src/components/index.ts +0 -4
  150. package/src/layouts/Grid/Grid.stories.tsx +10 -23
  151. package/src/layouts/Grid/Grid.tsx +20 -1
  152. package/src/layouts/Grid/GridCol.tsx +76 -48
  153. package/src/lib/composables/useAtomixGlass.ts +861 -44
  154. package/src/lib/composables/useBarChart.ts +13 -6
  155. package/src/lib/composables/useChart.ts +17 -13
  156. package/src/lib/composables/useChartExport.ts +19 -78
  157. package/src/lib/composables/useChartToolbar.ts +0 -1
  158. package/src/lib/composables/useEdgePanel.ts +111 -103
  159. package/src/lib/composables/useFooter.ts +3 -3
  160. package/src/lib/composables/useGlassContainer.ts +16 -7
  161. package/src/lib/composables/useLineChart.ts +8 -1
  162. package/src/lib/composables/useRiver.ts +5 -0
  163. package/src/lib/composables/useSlider.ts +62 -24
  164. package/src/lib/composables/useVideoPlayer.ts +60 -63
  165. package/src/lib/constants/components.ts +146 -32
  166. package/src/lib/types/components.ts +258 -10
  167. package/src/lib/utils/displacement-generator.ts +55 -49
  168. package/src/lib/utils/icons.ts +1 -1
  169. package/src/lib/utils/index.ts +16 -10
  170. package/src/styles/01-settings/_settings.accordion.scss +19 -19
  171. package/src/styles/01-settings/_settings.animations.scss +5 -5
  172. package/src/styles/01-settings/_settings.avatar-group.scss +1 -1
  173. package/src/styles/01-settings/_settings.avatar.scss +17 -17
  174. package/src/styles/01-settings/_settings.background.scss +1 -4
  175. package/src/styles/01-settings/_settings.badge.scss +1 -1
  176. package/src/styles/01-settings/_settings.breadcrumb.scss +1 -1
  177. package/src/styles/01-settings/_settings.card.scss +1 -1
  178. package/src/styles/01-settings/_settings.chart.scss +65 -2
  179. package/src/styles/01-settings/_settings.dropdown.scss +1 -1
  180. package/src/styles/01-settings/_settings.footer.scss +35 -42
  181. package/src/styles/01-settings/_settings.input.scss +1 -1
  182. package/src/styles/01-settings/_settings.list.scss +1 -1
  183. package/src/styles/01-settings/_settings.rating.scss +1 -1
  184. package/src/styles/01-settings/_settings.tabs.scss +1 -1
  185. package/src/styles/01-settings/_settings.upload.scss +6 -5
  186. package/src/styles/02-tools/_tools.animations.scss +4 -5
  187. package/src/styles/02-tools/_tools.background.scss +1 -13
  188. package/src/styles/02-tools/_tools.glass.scss +0 -1
  189. package/src/styles/02-tools/_tools.utility-api.scss +42 -34
  190. package/src/styles/03-generic/_generic.root.scss +1 -4
  191. package/src/styles/04-elements/_elements.body.scss +0 -1
  192. package/src/styles/06-components/_components.atomix-glass.scss +216 -39
  193. package/src/styles/06-components/_components.badge.scss +6 -8
  194. package/src/styles/06-components/_components.button.scss +8 -3
  195. package/src/styles/06-components/_components.card.scss +2 -14
  196. package/src/styles/06-components/_components.chart.scss +969 -1449
  197. package/src/styles/06-components/_components.dropdown.scss +19 -7
  198. package/src/styles/06-components/_components.edge-panel.scss +4 -2
  199. package/src/styles/06-components/_components.footer.scss +166 -85
  200. package/src/styles/06-components/_components.input.scss +8 -9
  201. package/src/styles/06-components/_components.list.scss +1 -0
  202. package/src/styles/06-components/_components.modal.scss +5 -3
  203. package/src/styles/06-components/_components.skeleton.scss +8 -6
  204. package/src/styles/06-components/_components.upload.scss +219 -4
  205. package/src/styles/06-components/old.chart.styles.scss +1 -30
  206. package/src/styles/99-utilities/_utilities.opacity.scss +1 -1
  207. package/src/styles/99-utilities/_utilities.scss +1 -1
  208. package/src/components/Chart/AdvancedChart.tsx +0 -624
  209. package/src/components/Chart/LineChartNew.tsx +0 -167
  210. package/src/components/Chart/RealTimeChart.tsx +0 -436
  211. package/src/components/DatePicker/DatePicker copy.tsx +0 -551
@@ -1,7 +1,7 @@
1
- import { forwardRef, memo, ReactElement, useCallback } from 'react';
2
- import { ChartProps } from '../../lib/types/components';
3
- import Chart from './Chart';
4
- import ChartRenderer from './ChartRenderer';
1
+ import { forwardRef, memo } from 'react';
2
+ import BaseChart from './BaseChart';
3
+ import ChartTooltip from './ChartTooltip';
4
+ import { ChartProps, ChartRenderContentParams } from './types';
5
5
 
6
6
  export interface FunnelDataPoint {
7
7
  label: string;
@@ -58,11 +58,11 @@ export interface FunnelChartProps extends Omit<ChartProps, 'type' | 'datasets'>
58
58
  */
59
59
  colorScheme?: string[];
60
60
  /**
61
- * Whether to use gradient fills
61
+ * Whether to use gradient
62
62
  */
63
63
  useGradient?: boolean;
64
64
  /**
65
- * Whether to animate segments
65
+ * Whether to animate
66
66
  */
67
67
  animate?: boolean;
68
68
  /**
@@ -78,19 +78,19 @@ export interface FunnelChartProps extends Omit<ChartProps, 'type' | 'datasets'>
78
78
  */
79
79
  valueFormatter?: (value: number) => string;
80
80
  /**
81
- * Whether to show conversion rates between segments
81
+ * Whether to show conversion rates
82
82
  */
83
83
  showConversionRates?: boolean;
84
84
  /**
85
85
  * Conversion rate position
86
86
  */
87
- conversionRatePosition?: 'between' | 'inside';
87
+ conversionRatePosition?: 'between' | 'onSegment';
88
88
  /**
89
- * Whether segments should be proportional to values
89
+ * Whether to use proportional segments
90
90
  */
91
91
  proportional?: boolean;
92
92
  /**
93
- * Minimum segment height/width ratio
93
+ * Minimum segment ratio (0-1)
94
94
  */
95
95
  minSegmentRatio?: number;
96
96
  };
@@ -127,263 +127,192 @@ const FunnelChart = memo(
127
127
  minSegmentRatio = 0.1,
128
128
  } = funnelOptions;
129
129
 
130
- const renderContent = useCallback(
131
- ({ scales, colors, handlers }: { scales: any; colors: any; handlers: any }) => {
132
- if (!funnelData.length) return null;
133
-
134
- const padding = 60;
135
- const chartWidth = scales.width - padding * 2;
136
- const chartHeight = scales.height - padding * 2;
137
-
138
- // Calculate percentages and conversion rates
139
- const maxValue = Math.max(...funnelData.map(d => d.value));
140
- const processedData = funnelData.map((item, index) => {
141
- const percentage = (item.value / maxValue) * 100;
142
- const conversionRate =
143
- index > 0 && funnelData[index - 1]
144
- ? (item.value / funnelData[index - 1]!.value) * 100
145
- : 100;
146
-
147
- return {
148
- ...item,
149
- percentage,
150
- conversionRate,
151
- index,
152
- };
153
- });
154
-
155
- const elements: ReactElement[] = [];
130
+ const renderContent = ({
131
+ scales,
132
+ colors,
133
+ datasets: renderedDatasets,
134
+ handlers,
135
+ hoveredPoint,
136
+ toolbarState,
137
+ config: renderConfig,
138
+ }: ChartRenderContentParams) => {
139
+ if (!funnelData.length) return null;
140
+
141
+ // Use toolbar state if available, fallback to config for backward compatibility
142
+ const showTooltips = toolbarState?.showTooltips ?? renderConfig?.showTooltips ?? true;
143
+ const shouldAnimate = toolbarState?.animationsEnabled ?? renderConfig?.animate ?? animate;
144
+
145
+ const padding = 60;
146
+ const chartWidth = scales.width - padding * 2;
147
+ const chartHeight = scales.height - padding * 2;
148
+
149
+ // Calculate percentages and conversion rates
150
+ const maxValue = Math.max(...funnelData.map(d => d.value));
151
+ const processedData = funnelData.map((item, index) => {
152
+ const percentage = (item.value / maxValue) * 100;
153
+ const conversionRate =
154
+ index > 0 && funnelData[index - 1]
155
+ ? (item.value / funnelData[index - 1]!.value) * 100
156
+ : 100;
157
+
158
+ return {
159
+ ...item,
160
+ percentage,
161
+ conversionRate,
162
+ index,
163
+ };
164
+ });
165
+
166
+ const elements: React.ReactNode[] = [];
167
+
168
+ if (direction === 'vertical') {
169
+ // Vertical funnel
170
+ const segmentHeight =
171
+ (chartHeight - (funnelData.length - 1) * segmentGap) / funnelData.length;
172
+
173
+ processedData.forEach((item, index) => {
174
+ const y = padding + index * (segmentHeight + segmentGap);
175
+
176
+ // Calculate segment width based on value
177
+ let segmentWidth: number;
178
+ if (proportional) {
179
+ const ratio = Math.max(item.percentage / 100, minSegmentRatio);
180
+ segmentWidth = chartWidth * ratio;
181
+ } else {
182
+ // Linear decrease
183
+ const ratio = Math.max(
184
+ 1 - (index / (funnelData.length - 1)) * (1 - neckWidth),
185
+ minSegmentRatio
186
+ );
187
+ segmentWidth = chartWidth * ratio;
188
+ }
156
189
 
157
- if (direction === 'vertical') {
158
- // Vertical funnel
159
- const segmentHeight =
160
- (chartHeight - (funnelData.length - 1) * segmentGap) / funnelData.length;
190
+ const x = padding + (chartWidth - segmentWidth) / 2;
161
191
 
162
- processedData.forEach((item, index) => {
163
- const y = padding + index * (segmentHeight + segmentGap);
192
+ // Determine color
193
+ let segmentColor = item.color || colorScheme[index % colorScheme.length];
164
194
 
165
- // Calculate segment width based on value
166
- let segmentWidth: number;
195
+ // Create trapezoid path
196
+ const nextItem = processedData[index + 1];
197
+ let nextWidth: number;
198
+ if (nextItem) {
167
199
  if (proportional) {
168
- const ratio = Math.max(item.percentage / 100, minSegmentRatio);
169
- segmentWidth = chartWidth * ratio;
200
+ const nextRatio = Math.max(nextItem.percentage / 100, minSegmentRatio);
201
+ nextWidth = chartWidth * nextRatio;
170
202
  } else {
171
- // Linear decrease
172
- const ratio = Math.max(
173
- 1 - (index / (funnelData.length - 1)) * (1 - neckWidth),
203
+ const nextRatio = Math.max(
204
+ 1 - ((index + 1) / (funnelData.length - 1)) * (1 - neckWidth),
174
205
  minSegmentRatio
175
206
  );
176
- segmentWidth = chartWidth * ratio;
177
- }
178
-
179
- const x = padding + (chartWidth - segmentWidth) / 2;
180
-
181
- // Determine color
182
- let segmentColor = item.color || colorScheme[index % colorScheme.length];
183
-
184
- // Create gradient if enabled
185
- if (useGradient) {
186
- const gradientId = `funnel-gradient-${index}`;
187
- elements.push(
188
- <defs key={`gradient-def-${index}`}>
189
- <linearGradient id={gradientId} x1="0%" y1="0%" x2="100%" y2="0%">
190
- <stop offset="0%" stopColor={segmentColor} stopOpacity="0.8" />
191
- <stop offset="100%" stopColor={segmentColor} stopOpacity="1" />
192
- </linearGradient>
193
- </defs>
194
- );
195
- segmentColor = `url(#${gradientId})`;
196
- }
197
-
198
- // Create trapezoid path for funnel segment
199
- let path: string;
200
- if (index === funnelData.length - 1) {
201
- // Last segment (rectangle)
202
- path = `M ${x} ${y} L ${x + segmentWidth} ${y} L ${x + segmentWidth} ${y + segmentHeight} L ${x} ${y + segmentHeight} Z`;
203
- } else {
204
- // Calculate next segment width
205
- const nextItem = processedData[index + 1];
206
- let nextSegmentWidth: number;
207
- if (proportional && nextItem) {
208
- const nextRatio = Math.max(nextItem.percentage / 100, minSegmentRatio);
209
- nextSegmentWidth = chartWidth * nextRatio;
210
- } else {
211
- const nextRatio = Math.max(
212
- 1 - ((index + 1) / (funnelData.length - 1)) * (1 - neckWidth),
213
- minSegmentRatio
214
- );
215
- nextSegmentWidth = chartWidth * nextRatio;
216
- }
217
-
218
- const nextX = padding + (chartWidth - nextSegmentWidth) / 2;
219
-
220
- // Trapezoid path
221
- path = `M ${x} ${y} L ${x + segmentWidth} ${y} L ${nextX + nextSegmentWidth} ${y + segmentHeight} L ${nextX} ${y + segmentHeight} Z`;
207
+ nextWidth = chartWidth * nextRatio;
222
208
  }
223
-
224
- // Segment
225
- elements.push(
209
+ } else {
210
+ nextWidth = segmentWidth * neckWidth;
211
+ }
212
+
213
+ const nextX = padding + (chartWidth - nextWidth) / 2;
214
+ const nextY = y + segmentHeight;
215
+
216
+ // Create trapezoid shape
217
+ const path = `
218
+ M ${x} ${y}
219
+ L ${x + segmentWidth} ${y}
220
+ L ${nextX + nextWidth} ${nextY}
221
+ L ${nextX} ${nextY}
222
+ Z
223
+ `;
224
+
225
+ elements.push(
226
+ <g key={`segment-${index}`}>
226
227
  <path
227
- key={`segment-${index}`}
228
228
  d={path}
229
229
  fill={segmentColor}
230
- className={`c-chart__funnel-segment ${animate ? 'c-chart__funnel-segment--animated' : ''}`}
230
+ className="c-chart__funnel-segment"
231
231
  style={{
232
- animationDelay: animate ? `${index * animationDelay}ms` : '0ms',
232
+ transition: animate
233
+ ? `all ${animationDuration}ms cubic-bezier(0.25, 0.1, 0.25, 1) ${index * animationDelay}ms`
234
+ : 'none',
233
235
  }}
234
- onClick={() => handlers.onDataPointClick?.(item as any, 0, index)}
236
+ onClick={() => handlers.onDataPointClick?.(item, 0, index)}
235
237
  />
236
- );
237
-
238
- // Labels and values
239
- if (showLabels || showValues || showPercentages) {
240
- const centerX = padding + chartWidth / 2;
241
- const centerY = y + segmentHeight / 2;
242
-
243
- let labelX = centerX;
244
- let valueX = centerX;
245
-
246
- if (labelPosition === 'outside') {
247
- labelX = padding + chartWidth + 10;
248
- valueX = padding + chartWidth + 10;
249
- }
250
-
251
- let textElements = [];
252
-
253
- if (showLabels) {
254
- textElements.push(
255
- <text
256
- key={`label-${index}`}
257
- x={labelX}
258
- y={centerY - 5}
259
- textAnchor={labelPosition === 'outside' ? 'start' : 'middle'}
260
- dominantBaseline="middle"
261
- className={`c-chart__funnel-label ${labelPosition === 'inside' ? 'c-chart__funnel-label--inside' : 'c-chart__funnel-label--outside'}`}
262
- >
263
- {item.label}
264
- </text>
265
- );
266
- }
267
-
268
- if (showValues || showPercentages) {
269
- let valueText = '';
270
- if (showValues && showPercentages) {
271
- valueText = `${valueFormatter(item.value)} (${item.percentage.toFixed(1)}%)`;
272
- } else if (showValues) {
273
- valueText = valueFormatter(item.value);
274
- } else {
275
- valueText = `${item.percentage.toFixed(1)}%`;
276
- }
277
-
278
- textElements.push(
279
- <text
280
- key={`value-${index}`}
281
- x={valueX}
282
- y={centerY + (showLabels ? 10 : 0)}
283
- textAnchor={labelPosition === 'outside' ? 'start' : 'middle'}
284
- dominantBaseline="middle"
285
- className={`c-chart__funnel-value ${labelPosition === 'inside' ? 'c-chart__funnel-value--inside' : 'c-chart__funnel-value--outside'}`}
286
- >
287
- {valueText}
288
- </text>
289
- );
290
- }
291
-
292
- elements.push(...textElements);
293
- }
294
-
295
- // Conversion rates
296
- if (showConversionRates && index > 0) {
297
- const conversionY =
298
- conversionRatePosition === 'between' ? y - segmentGap / 2 : y + segmentHeight / 2;
299
-
300
- elements.push(
238
+ {(showLabels || showValues || showPercentages) && (
301
239
  <text
302
- key={`conversion-${index}`}
303
- x={padding + chartWidth / 2}
304
- y={conversionY}
240
+ x={x + segmentWidth / 2}
241
+ y={y + segmentHeight / 2}
305
242
  textAnchor="middle"
306
243
  dominantBaseline="middle"
307
- className="c-chart__funnel-conversion"
244
+ className="c-chart__funnel-label"
308
245
  >
309
- {item.conversionRate.toFixed(1)}%
246
+ {showLabels && item.label}
247
+ {showValues && (
248
+ <tspan x={x + segmentWidth / 2} dy="1.2em">
249
+ {valueFormatter(item.value)}
250
+ </tspan>
251
+ )}
252
+ {showPercentages && (
253
+ <tspan x={x + segmentWidth / 2} dy="1.2em">
254
+ {item.percentage.toFixed(1)}%
255
+ </tspan>
256
+ )}
310
257
  </text>
311
- );
312
- }
313
- });
314
- } else {
315
- // Horizontal funnel (similar logic but rotated)
316
- const segmentWidth =
317
- (chartWidth - (funnelData.length - 1) * segmentGap) / funnelData.length;
318
-
319
- processedData.forEach((item, index) => {
320
- const x = padding + index * (segmentWidth + segmentGap);
258
+ )}
259
+ </g>
260
+ );
321
261
 
322
- // Calculate segment height based on value
323
- let segmentHeight: number;
324
- if (proportional) {
325
- const ratio = Math.max(item.percentage / 100, minSegmentRatio);
326
- segmentHeight = chartHeight * ratio;
327
- } else {
328
- const ratio = Math.max(
329
- 1 - (index / (funnelData.length - 1)) * (1 - neckHeight),
330
- minSegmentRatio
331
- );
332
- segmentHeight = chartHeight * ratio;
333
- }
334
-
335
- const y = padding + (chartHeight - segmentHeight) / 2;
336
-
337
- // Similar implementation for horizontal orientation...
338
- // (Implementation details omitted for brevity but would follow same pattern)
339
- });
340
- }
341
-
342
- return <g>{elements}</g>;
343
- },
344
- [
345
- funnelData,
346
- direction,
347
- showLabels,
348
- showValues,
349
- showPercentages,
350
- labelPosition,
351
- neckWidth,
352
- neckHeight,
353
- segmentGap,
354
- colorScheme,
355
- useGradient,
356
- animate,
357
- animationDuration,
358
- animationDelay,
359
- valueFormatter,
360
- showConversionRates,
361
- conversionRatePosition,
362
- proportional,
363
- minSegmentRatio,
364
- ]
365
- );
366
-
367
- // Convert funnel data to datasets format for ChartRenderer
262
+ // Add conversion rate labels
263
+ if (showConversionRates && nextItem && conversionRatePosition === 'between') {
264
+ elements.push(
265
+ <text
266
+ key={`conversion-${index}`}
267
+ x={x + segmentWidth / 2}
268
+ y={y + segmentHeight + segmentGap / 2}
269
+ textAnchor="middle"
270
+ className="c-chart__funnel-conversion"
271
+ >
272
+ {item.conversionRate.toFixed(1)}%
273
+ </text>
274
+ );
275
+ }
276
+ });
277
+ }
278
+
279
+ return (
280
+ <>
281
+ <g>{elements}</g>
282
+ {showTooltips && hoveredPoint && funnelData[hoveredPoint.pointIndex] && (
283
+ <ChartTooltip
284
+ dataPoint={funnelData[hoveredPoint.pointIndex]}
285
+ datasetLabel="Funnel Data"
286
+ datasetColor={funnelData[hoveredPoint.pointIndex]?.color || colors[hoveredPoint.pointIndex % colors.length]}
287
+ position={{
288
+ x: hoveredPoint.clientX,
289
+ y: hoveredPoint.clientY,
290
+ }}
291
+ visible={true}
292
+ />
293
+ )}
294
+ </>
295
+ );
296
+ };
297
+
298
+ // Convert funnelData to datasets format for BaseChart
368
299
  const datasets = [
369
300
  {
370
301
  label: 'Funnel Data',
371
- data: funnelData.map(item => ({
372
- label: item.label,
373
- value: item.value,
374
- })),
302
+ data: funnelData,
375
303
  },
376
304
  ];
377
305
 
378
306
  return (
379
- <Chart ref={ref} type="funnel" datasets={datasets} config={config} {...props}>
380
- <ChartRenderer
381
- datasets={datasets}
382
- config={config}
383
- onDataPointClick={onDataPointClick}
384
- renderContent={renderContent}
385
- />
386
- </Chart>
307
+ <BaseChart
308
+ ref={ref}
309
+ type="funnel"
310
+ datasets={datasets}
311
+ config={config}
312
+ renderContent={renderContent}
313
+ onDataPointClick={onDataPointClick}
314
+ {...props}
315
+ />
387
316
  );
388
317
  }
389
318
  )