@shohojdhara/atomix 0.2.4 → 0.2.6

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 (214) hide show
  1. package/README.md +19 -0
  2. package/dist/atomix.css +1300 -1418
  3. package/dist/atomix.min.css +3 -3
  4. package/dist/index.d.ts +1259 -874
  5. package/dist/index.esm.js +16256 -26366
  6. package/dist/index.esm.js.map +1 -1
  7. package/dist/index.js +15691 -22295
  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 +15036 -0
  12. package/dist/themes/applemix.min.css +72 -0
  13. package/dist/themes/boomdevs.css +1300 -1419
  14. package/dist/themes/boomdevs.min.css +3 -3
  15. package/dist/themes/esrar.css +1301 -1419
  16. package/dist/themes/esrar.min.css +3 -3
  17. package/dist/themes/flashtrade.css +15187 -0
  18. package/dist/themes/flashtrade.min.css +86 -0
  19. package/dist/themes/mashroom.css +1299 -1417
  20. package/dist/themes/mashroom.min.css +5 -5
  21. package/dist/themes/shaj-default.css +1300 -1418
  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 +485 -1215
  28. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +399 -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.stories.tsx +121 -11
  78. package/src/components/ColorModeToggle/ColorModeToggle.tsx +149 -45
  79. package/src/components/ColorModeToggle/index.ts +1 -1
  80. package/src/components/Countdown/Countdown.tsx +4 -0
  81. package/src/components/DataTable/DataTable.tsx +2 -1
  82. package/src/components/DatePicker/DatePicker.stories.tsx +0 -11
  83. package/src/components/DatePicker/DatePicker.tsx +3 -9
  84. package/src/components/DatePicker/types.ts +5 -0
  85. package/src/components/Dropdown/Dropdown.stories.tsx +32 -25
  86. package/src/components/Dropdown/Dropdown.tsx +26 -28
  87. package/src/components/EdgePanel/EdgePanel.stories.tsx +13 -15
  88. package/src/components/EdgePanel/EdgePanel.tsx +20 -5
  89. package/src/components/Footer/Footer.stories.tsx +187 -60
  90. package/src/components/Footer/Footer.test.tsx +134 -0
  91. package/src/components/Footer/Footer.tsx +133 -34
  92. package/src/components/Footer/FooterLink.tsx +1 -1
  93. package/src/components/Footer/FooterSection.tsx +53 -36
  94. package/src/components/Footer/FooterSocialLink.tsx +32 -29
  95. package/src/components/Footer/README.md +82 -3
  96. package/src/components/Footer/index.ts +1 -1
  97. package/src/components/Form/Checkbox.stories.tsx +13 -5
  98. package/src/components/Form/Checkbox.tsx +3 -6
  99. package/src/components/Form/Form.stories.tsx +10 -3
  100. package/src/components/Form/Form.tsx +2 -0
  101. package/src/components/Form/FormGroup.tsx +2 -1
  102. package/src/components/Form/Input.stories.tsx +12 -11
  103. package/src/components/Form/Input.tsx +97 -95
  104. package/src/components/Form/Radio.stories.tsx +22 -7
  105. package/src/components/Form/Radio.tsx +3 -6
  106. package/src/components/Form/Select.stories.tsx +21 -6
  107. package/src/components/Form/Select.tsx +3 -5
  108. package/src/components/Form/Textarea.stories.tsx +13 -11
  109. package/src/components/Form/Textarea.tsx +88 -86
  110. package/src/components/Hero/Hero.stories.tsx +2 -3
  111. package/src/components/Hero/Hero.tsx +5 -6
  112. package/src/components/Icon/Icon.tsx +12 -1
  113. package/src/components/List/List.tsx +2 -1
  114. package/src/components/List/ListGroup.tsx +2 -1
  115. package/src/components/Messages/Messages.tsx +3 -2
  116. package/src/components/Modal/Modal.stories.tsx +48 -34
  117. package/src/components/Modal/Modal.tsx +19 -23
  118. package/src/components/Navigation/Menu/MegaMenu.tsx +2 -2
  119. package/src/components/Navigation/Menu/Menu.tsx +2 -2
  120. package/src/components/Navigation/Nav/Nav.tsx +6 -1
  121. package/src/components/Navigation/Nav/NavDropdown.tsx +10 -1
  122. package/src/components/Navigation/Navbar/Navbar.tsx +4 -1
  123. package/src/components/Navigation/SideMenu/SideMenu.tsx +3 -2
  124. package/src/components/Pagination/Pagination.stories.tsx +13 -6
  125. package/src/components/Pagination/Pagination.tsx +7 -6
  126. package/src/components/PhotoViewer/PhotoViewer.tsx +2 -1
  127. package/src/components/Popover/Popover.stories.tsx +32 -24
  128. package/src/components/Popover/Popover.tsx +4 -1
  129. package/src/components/ProductReview/ProductReview.tsx +8 -2
  130. package/src/components/Progress/Progress.tsx +2 -1
  131. package/src/components/Rating/Rating.stories.tsx +11 -6
  132. package/src/components/Rating/Rating.tsx +3 -5
  133. package/src/components/River/River.tsx +5 -5
  134. package/src/components/SectionIntro/SectionIntro.tsx +8 -2
  135. package/src/components/Slider/Slider.stories.tsx +4 -4
  136. package/src/components/Slider/Slider.tsx +4 -3
  137. package/src/components/Spinner/Spinner.tsx +2 -1
  138. package/src/components/Steps/Steps.stories.tsx +5 -4
  139. package/src/components/Steps/Steps.tsx +8 -5
  140. package/src/components/Tab/Tab.stories.tsx +4 -3
  141. package/src/components/Tab/Tab.tsx +8 -6
  142. package/src/components/Testimonial/Testimonial.tsx +8 -2
  143. package/src/components/Todo/Todo.tsx +2 -1
  144. package/src/components/Toggle/Toggle.stories.tsx +5 -4
  145. package/src/components/Toggle/Toggle.tsx +8 -5
  146. package/src/components/Tooltip/Tooltip.stories.tsx +40 -30
  147. package/src/components/Tooltip/Tooltip.tsx +9 -2
  148. package/src/components/Upload/Upload.stories.tsx +252 -0
  149. package/src/components/Upload/Upload.tsx +92 -53
  150. package/src/components/VideoPlayer/VideoPlayer.tsx +3 -1
  151. package/src/components/index.ts +0 -4
  152. package/src/layouts/Grid/Grid.stories.tsx +10 -23
  153. package/src/layouts/Grid/Grid.tsx +20 -1
  154. package/src/layouts/Grid/GridCol.tsx +76 -48
  155. package/src/lib/composables/useAtomixGlass.ts +861 -44
  156. package/src/lib/composables/useBarChart.ts +13 -6
  157. package/src/lib/composables/useChart.ts +17 -13
  158. package/src/lib/composables/useChartExport.ts +19 -78
  159. package/src/lib/composables/useChartToolbar.ts +0 -1
  160. package/src/lib/composables/useEdgePanel.ts +111 -103
  161. package/src/lib/composables/useFooter.ts +3 -3
  162. package/src/lib/composables/useGlassContainer.ts +16 -7
  163. package/src/lib/composables/useLineChart.ts +8 -1
  164. package/src/lib/composables/useRiver.ts +5 -0
  165. package/src/lib/composables/useSlider.ts +62 -24
  166. package/src/lib/composables/useVideoPlayer.ts +60 -63
  167. package/src/lib/constants/components.ts +146 -32
  168. package/src/lib/types/components.ts +258 -10
  169. package/src/lib/utils/displacement-generator.ts +55 -49
  170. package/src/lib/utils/icons.ts +1 -1
  171. package/src/lib/utils/index.ts +16 -10
  172. package/src/styles/01-settings/_settings.accordion.scss +19 -19
  173. package/src/styles/01-settings/_settings.animations.scss +5 -5
  174. package/src/styles/01-settings/_settings.avatar-group.scss +1 -1
  175. package/src/styles/01-settings/_settings.avatar.scss +17 -17
  176. package/src/styles/01-settings/_settings.background.scss +1 -4
  177. package/src/styles/01-settings/_settings.badge.scss +1 -1
  178. package/src/styles/01-settings/_settings.breadcrumb.scss +1 -1
  179. package/src/styles/01-settings/_settings.card.scss +1 -1
  180. package/src/styles/01-settings/_settings.chart.scss +65 -2
  181. package/src/styles/01-settings/_settings.dropdown.scss +1 -1
  182. package/src/styles/01-settings/_settings.footer.scss +35 -42
  183. package/src/styles/01-settings/_settings.input.scss +1 -1
  184. package/src/styles/01-settings/_settings.list.scss +1 -1
  185. package/src/styles/01-settings/_settings.rating.scss +1 -1
  186. package/src/styles/01-settings/_settings.tabs.scss +1 -1
  187. package/src/styles/01-settings/_settings.upload.scss +6 -5
  188. package/src/styles/02-tools/_tools.animations.scss +4 -5
  189. package/src/styles/02-tools/_tools.background.scss +1 -13
  190. package/src/styles/02-tools/_tools.glass.scss +0 -1
  191. package/src/styles/02-tools/_tools.utility-api.scss +42 -34
  192. package/src/styles/03-generic/_generic.root.scss +1 -4
  193. package/src/styles/04-elements/_elements.body.scss +0 -1
  194. package/src/styles/06-components/_components.atomix-glass.scss +217 -39
  195. package/src/styles/06-components/_components.badge.scss +6 -8
  196. package/src/styles/06-components/_components.button.scss +8 -3
  197. package/src/styles/06-components/_components.card.scss +2 -14
  198. package/src/styles/06-components/_components.chart.scss +969 -1449
  199. package/src/styles/06-components/_components.color-mode-toggle.scss +43 -6
  200. package/src/styles/06-components/_components.dropdown.scss +19 -7
  201. package/src/styles/06-components/_components.edge-panel.scss +4 -2
  202. package/src/styles/06-components/_components.footer.scss +166 -85
  203. package/src/styles/06-components/_components.input.scss +8 -9
  204. package/src/styles/06-components/_components.list.scss +1 -0
  205. package/src/styles/06-components/_components.modal.scss +5 -3
  206. package/src/styles/06-components/_components.skeleton.scss +8 -6
  207. package/src/styles/06-components/_components.upload.scss +219 -4
  208. package/src/styles/06-components/old.chart.styles.scss +1 -30
  209. package/src/styles/99-utilities/_utilities.opacity.scss +1 -1
  210. package/src/styles/99-utilities/_utilities.scss +1 -1
  211. package/src/components/Chart/AdvancedChart.tsx +0 -624
  212. package/src/components/Chart/LineChartNew.tsx +0 -167
  213. package/src/components/Chart/RealTimeChart.tsx +0 -436
  214. package/src/components/DatePicker/DatePicker copy.tsx +0 -551
@@ -1,7 +1,7 @@
1
- import { forwardRef, memo, useCallback } from 'react';
1
+ import { forwardRef, memo } from 'react';
2
+ import BaseChart from './BaseChart';
2
3
  import { ChartProps } from '../../lib/types/components';
3
- import Chart from './Chart';
4
- import ChartRenderer from './ChartRenderer';
4
+ import { ChartRenderContentParams } from './types';
5
5
 
6
6
  export interface WaterfallDataPoint {
7
7
  label: string;
@@ -97,7 +97,7 @@ const WaterfallChart = memo(
97
97
  ) => {
98
98
  const {
99
99
  showConnectors = true,
100
- connectorColor = '#f9fafb',
100
+ connectorColor = 'var(--atomix-gray-1)',
101
101
  connectorStyle = 'dashed',
102
102
  showValues = true,
103
103
  valuePosition = 'top',
@@ -109,338 +109,299 @@ const WaterfallChart = memo(
109
109
  },
110
110
  barWidth = 0.6,
111
111
  showCumulativeLine = false,
112
- cumulativeLineColor = '#3b82f6',
112
+ cumulativeLineColor = 'var(--atomix-primary)',
113
113
  animate = true,
114
114
  animationDuration = 1000,
115
115
  animationDelay = 100,
116
116
  valueFormatter = value => value.toLocaleString(),
117
117
  showBaseline = true,
118
- baselineColor = '#f3f4f6',
118
+ baselineColor = 'var(--atomix-gray-2)',
119
119
  } = waterfallOptions;
120
120
 
121
- const renderContent = useCallback(
122
- ({
123
- scales,
124
- colors,
125
- handlers,
126
- }: {
127
- scales: { width: number; height: number };
128
- colors: string[];
129
- handlers: {
130
- onDataPointClick?: (dataPoint: any, datasetIndex: number, pointIndex: number) => void;
131
- };
132
- }) => {
133
- if (!waterfallData.length) return null;
134
-
135
- const padding = 60;
136
- const chartWidth = scales.width - padding * 2;
137
- const chartHeight = scales.height - padding * 2;
138
-
139
- // Calculate cumulative values and positions
140
- let cumulativeValue = 0;
141
- const processedData = waterfallData.map((item, index) => {
142
- const startValue =
143
- item.type === 'total' || item.type === 'subtotal' ? 0 : cumulativeValue;
144
-
145
- let endValue: number;
146
- if (item.type === 'total' || item.type === 'subtotal') {
147
- endValue = item.value;
148
- cumulativeValue = item.value;
149
- } else {
150
- endValue = cumulativeValue + item.value;
151
- cumulativeValue = endValue;
152
- }
153
-
154
- return {
155
- ...item,
156
- startValue,
157
- endValue,
158
- cumulativeValue,
159
- index,
160
- };
161
- });
162
-
163
- // Calculate scales
164
- const allValues = processedData.flatMap(d => [d.startValue, d.endValue]);
165
- const minValue = Math.min(0, ...allValues);
166
- const maxValue = Math.max(...allValues);
167
- const valueRange = maxValue - minValue;
168
-
169
- const barWidthPx = (chartWidth / waterfallData.length) * barWidth;
170
- const barSpacing = chartWidth / waterfallData.length;
171
-
172
- const xScale = (index: number) => padding + index * barSpacing + barSpacing / 2;
173
- const yScale = (value: number) =>
174
- padding + chartHeight - ((value - minValue) / valueRange) * chartHeight;
175
-
176
- const elements = [];
177
-
178
- // Baseline
179
- if (showBaseline) {
180
- const baselineY = yScale(0);
181
- elements.push(
182
- <line
183
- key="baseline"
184
- x1={padding}
185
- y1={baselineY}
186
- x2={scales.width - padding}
187
- y2={baselineY}
188
- stroke={baselineColor}
189
- strokeWidth="2"
190
- opacity="0.7"
191
- />
192
- );
121
+ const renderContent = ({
122
+ scales,
123
+ colors,
124
+ datasets: renderedDatasets,
125
+ handlers,
126
+ hoveredPoint,
127
+ toolbarState,
128
+ config: renderConfig,
129
+ }: ChartRenderContentParams) => {
130
+ if (!waterfallData.length) return null;
131
+
132
+ // Use toolbar state if available, fallback to config for backward compatibility
133
+ const shouldAnimate = toolbarState?.animationsEnabled ?? renderConfig?.animate ?? animate;
134
+
135
+ const padding = 60;
136
+ const chartWidth = scales.width - padding * 2;
137
+ const chartHeight = scales.height - padding * 2;
138
+
139
+ // Calculate cumulative values and positions
140
+ let cumulativeValue = 0;
141
+ const processedData = waterfallData.map((item, index) => {
142
+ const startValue =
143
+ item.type === 'total' || item.type === 'subtotal' ? 0 : cumulativeValue;
144
+
145
+ let endValue: number;
146
+ if (item.type === 'total' || item.type === 'subtotal') {
147
+ endValue = item.value;
148
+ cumulativeValue = item.value;
149
+ } else {
150
+ endValue = cumulativeValue + item.value;
151
+ cumulativeValue = endValue;
193
152
  }
194
153
 
195
- // Bars
196
- processedData.forEach((item, index) => {
197
- const x = xScale(index);
198
- const barTop = Math.min(yScale(item.startValue), yScale(item.endValue));
199
- const barBottom = Math.max(yScale(item.startValue), yScale(item.endValue));
200
- const barHeight = barBottom - barTop;
201
-
202
- // Determine bar color
203
- let barColor = item.color;
204
- if (!barColor) {
205
- if (item.type === 'total') barColor = waterfallColors.total;
206
- else if (item.type === 'subtotal') barColor = waterfallColors.subtotal;
207
- else if (item.value >= 0) barColor = waterfallColors.positive;
208
- else barColor = waterfallColors.negative;
209
- }
210
-
211
- // Bar rectangle
212
- elements.push(
213
- <rect
214
- key={`bar-${index}`}
215
- x={x - barWidthPx / 2}
216
- y={barTop}
217
- width={barWidthPx}
218
- height={Math.max(barHeight, 2)}
219
- fill={barColor}
220
- rx="4"
221
- className={`c-chart__waterfall-bar ${animate ? 'c-chart__waterfall-bar--animated' : ''}`}
222
- style={{
223
- animationDelay: animate ? `${index * animationDelay}ms` : '0ms',
224
- }}
225
- onClick={() => handlers.onDataPointClick?.(item as any, 0, index)}
226
- />
227
- );
228
-
229
- // Value labels
230
- if (showValues) {
231
- let labelY = barTop;
232
- let labelValue = item.value;
233
-
234
- if (valuePosition === 'center') {
235
- labelY = barTop + barHeight / 2;
236
- } else if (valuePosition === 'bottom') {
237
- labelY = barBottom + 15;
238
- } else {
239
- labelY = barTop - 5;
240
- }
241
-
242
- // For total/subtotal bars, show the cumulative value
243
- if (item.type === 'total' || item.type === 'subtotal') {
244
- labelValue = item.endValue;
245
- }
246
-
247
- elements.push(
248
- <text
249
- key={`value-${index}`}
250
- x={x}
251
- y={labelY}
252
- textAnchor="middle"
253
- dominantBaseline={valuePosition === 'center' ? 'middle' : 'auto'}
254
- className={`c-chart__waterfall-value ${valuePosition === 'center' ? 'c-chart__waterfall-value--center' : 'c-chart__waterfall-value--outside'}`}
255
- >
256
- {valueFormatter(labelValue)}
257
- </text>
258
- );
259
- }
154
+ return {
155
+ ...item,
156
+ startValue,
157
+ endValue,
158
+ cumulativeValue,
159
+ index,
160
+ };
161
+ });
260
162
 
261
- // Connectors
262
- if (showConnectors && index < processedData.length - 1) {
263
- const nextItem = processedData[index + 1];
264
- if (nextItem) {
265
- const currentEndY = yScale(item.endValue);
266
- const nextStartY = yScale(nextItem.startValue);
267
- const nextX = xScale(index + 1);
268
-
269
- // Only show connector if there's a gap to bridge
270
- if (Math.abs(item.endValue - nextItem.startValue) > 0.01) {
271
- const strokeDasharray =
272
- connectorStyle === 'dashed'
273
- ? '5,5'
274
- : connectorStyle === 'dotted'
275
- ? '2,2'
276
- : 'none';
277
-
278
- elements.push(
279
- <line
280
- key={`connector-${index}`}
281
- x1={x + barWidthPx / 2}
282
- y1={currentEndY}
283
- x2={nextX - barWidthPx / 2}
284
- y2={nextStartY}
285
- stroke={connectorColor}
286
- strokeDasharray={strokeDasharray}
287
- className="c-chart__waterfall-connector"
288
- />
289
- );
290
- }
291
- }
292
- }
293
- });
163
+ // Calculate scales
164
+ const allValues = processedData.flatMap(d => [d.startValue, d.endValue]);
165
+ const minValue = Math.min(0, ...allValues);
166
+ const maxValue = Math.max(...allValues);
167
+ const valueRange = maxValue - minValue;
294
168
 
295
- // Cumulative line
296
- if (showCumulativeLine) {
297
- const linePoints = processedData.map((item, index) => ({
298
- x: xScale(index),
299
- y: yScale(item.cumulativeValue),
300
- }));
169
+ const barWidthPx = (chartWidth / waterfallData.length) * barWidth;
170
+ const barSpacing = chartWidth / waterfallData.length;
301
171
 
302
- const linePath = `M ${linePoints.map(p => `${p.x},${p.y}`).join(' L ')}`;
172
+ const xScale = (index: number) => padding + index * barSpacing + barSpacing / 2;
173
+ const yScale = (value: number) =>
174
+ padding + chartHeight - ((value - minValue) / valueRange) * chartHeight;
303
175
 
304
- elements.push(
305
- <path
306
- key="cumulative-line"
307
- d={linePath}
308
- fill="none"
309
- stroke={cumulativeLineColor}
310
- className="c-chart__waterfall-cumulative-line"
311
- />
312
- );
176
+ const elements = [];
313
177
 
314
- // Line points
315
- linePoints.forEach((point, index) => {
316
- elements.push(
317
- <circle
318
- key={`line-point-${index}`}
319
- cx={point.x}
320
- cy={point.y}
321
- r="4"
322
- fill={cumulativeLineColor}
323
- className="c-chart__waterfall-cumulative-point"
324
- />
325
- );
326
- });
327
- }
328
-
329
- // X-axis
178
+ // Baseline
179
+ if (showBaseline) {
180
+ const baselineY = yScale(0);
330
181
  elements.push(
331
182
  <line
332
- key="x-axis"
183
+ key="baseline"
333
184
  x1={padding}
334
- y1={scales.height - padding}
185
+ y1={baselineY}
335
186
  x2={scales.width - padding}
336
- y2={scales.height - padding}
337
- stroke="var(--atomix-gray-4)"
338
- strokeWidth="2"
187
+ y2={baselineY}
188
+ stroke={baselineColor}
189
+ className="c-chart__axis-line"
190
+ opacity="0.7"
339
191
  />
340
192
  );
193
+ }
194
+
195
+ // Bars
196
+ processedData.forEach((item, index) => {
197
+ const x = xScale(index);
198
+ const barTop = Math.min(yScale(item.startValue), yScale(item.endValue));
199
+ const barBottom = Math.max(yScale(item.startValue), yScale(item.endValue));
200
+ const barHeight = barBottom - barTop;
201
+
202
+ // Determine bar color
203
+ let barColor = item.color;
204
+ if (!barColor) {
205
+ if (item.type === 'total') barColor = waterfallColors.total;
206
+ else if (item.type === 'subtotal') barColor = waterfallColors.subtotal;
207
+ else if (item.value >= 0) barColor = waterfallColors.positive;
208
+ else barColor = waterfallColors.negative;
209
+ }
341
210
 
342
- // Y-axis
211
+ // Bar rectangle
343
212
  elements.push(
344
- <line
345
- key="y-axis"
346
- x1={padding}
347
- y1={padding}
348
- x2={padding}
349
- y2={scales.height - padding}
350
- stroke="var(--atomix-gray-4)"
351
- strokeWidth="2"
213
+ <rect
214
+ key={`bar-${index}`}
215
+ x={x - barWidthPx / 2}
216
+ y={barTop}
217
+ width={barWidthPx}
218
+ height={Math.max(barHeight, 2)}
219
+ fill={barColor}
220
+ className={`c-chart__waterfall-bar ${shouldAnimate ? 'c-chart__waterfall-bar--animated' : ''}`}
221
+ style={{
222
+ animationDelay: shouldAnimate ? `${index * animationDelay}ms` : '0ms',
223
+ }}
224
+ onClick={() => handlers.onDataPointClick?.(item as any, 0, index)}
225
+ onMouseEnter={e => {
226
+ const rect = e.currentTarget.getBoundingClientRect();
227
+ handlers.onPointHover(
228
+ 0,
229
+ index,
230
+ x,
231
+ barTop,
232
+ rect.left + rect.width / 2,
233
+ rect.top + rect.height / 2
234
+ );
235
+ }}
236
+ onMouseLeave={handlers.onPointLeave}
352
237
  />
353
238
  );
354
239
 
355
- // X-axis labels
356
- waterfallData.forEach((item, index) => {
357
- const x = xScale(index);
240
+ // Value labels
241
+ if (showValues) {
242
+ let labelY = barTop;
243
+ let labelValue = item.value;
244
+
245
+ if (valuePosition === 'center') {
246
+ labelY = barTop + barHeight / 2;
247
+ } else if (valuePosition === 'bottom') {
248
+ labelY = barBottom + 15;
249
+ } else {
250
+ labelY = barTop - 5;
251
+ }
252
+
253
+ // For total/subtotal bars, show the cumulative value
254
+ if (item.type === 'total' || item.type === 'subtotal') {
255
+ labelValue = item.endValue;
256
+ }
257
+
358
258
  elements.push(
359
259
  <text
360
- key={`x-label-${index}`}
260
+ key={`value-${index}`}
361
261
  x={x}
362
- y={scales.height - padding + 20}
262
+ y={labelY}
363
263
  textAnchor="middle"
364
- fontSize="11"
365
- fill="var(--atomix-gray-6)"
366
- transform={`rotate(-45, ${x}, ${scales.height - padding + 20})`}
264
+ dominantBaseline={valuePosition === 'center' ? 'middle' : 'auto'}
265
+ className={`c-chart__waterfall-value ${valuePosition === 'center' ? 'c-chart__waterfall-value--center' : 'c-chart__waterfall-value--outside'}`}
367
266
  >
368
- {item.label}
267
+ {valueFormatter(labelValue)}
369
268
  </text>
370
269
  );
371
- });
270
+ }
271
+
272
+ // Connectors
273
+ if (showConnectors && index < processedData.length - 1) {
274
+ const nextItem = processedData[index + 1];
275
+ if (nextItem) {
276
+ const currentEndY = yScale(item.endValue);
277
+ const nextStartY = yScale(nextItem.startValue);
278
+ const nextX = xScale(index + 1);
279
+
280
+ // Only show connector if there's a gap to bridge
281
+ if (Math.abs(item.endValue - nextItem.startValue) > 0.01) {
282
+ const strokeDasharray =
283
+ connectorStyle === 'dashed'
284
+ ? '5,5'
285
+ : connectorStyle === 'dotted'
286
+ ? '2,2'
287
+ : 'none';
288
+
289
+ elements.push(
290
+ <line
291
+ key={`connector-${index}`}
292
+ x1={x + barWidthPx / 2}
293
+ y1={currentEndY}
294
+ x2={nextX - barWidthPx / 2}
295
+ y2={nextStartY}
296
+ stroke={connectorColor}
297
+ strokeDasharray={strokeDasharray}
298
+ className="c-chart__waterfall-connector"
299
+ />
300
+ );
301
+ }
302
+ }
303
+ }
304
+ });
305
+
306
+ // Cumulative line
307
+ if (showCumulativeLine) {
308
+ const linePoints = processedData.map((item, index) => ({
309
+ x: xScale(index),
310
+ y: yScale(item.cumulativeValue),
311
+ }));
372
312
 
373
- // Y-axis labels
374
- const yTicks = 5;
375
- for (let i = 0; i <= yTicks; i++) {
376
- const value = minValue + (i / yTicks) * valueRange;
377
- const y = yScale(value);
313
+ const linePath = `M ${linePoints.map(p => `${p.x},${p.y}`).join(' L ')}`;
378
314
 
315
+ elements.push(
316
+ <path
317
+ key="cumulative-line"
318
+ d={linePath}
319
+ fill="none"
320
+ stroke={cumulativeLineColor}
321
+ className="c-chart__waterfall-cumulative-line"
322
+ />
323
+ );
324
+
325
+ // Line points
326
+ linePoints.forEach((point, index) => {
379
327
  elements.push(
380
- <g key={`y-tick-${i}`}>
381
- <line
382
- x1={padding - 5}
383
- y1={y}
384
- x2={padding}
385
- y2={y}
386
- stroke="var(--atomix-gray-4)"
387
- strokeWidth="1"
388
- />
389
- <text
390
- x={padding - 10}
391
- y={y}
392
- textAnchor="end"
393
- dominantBaseline="middle"
394
- fontSize="11"
395
- fill="var(--atomix-gray-6)"
396
- >
397
- {valueFormatter(value)}
398
- </text>
399
- </g>
328
+ <circle
329
+ key={`line-point-${index}`}
330
+ cx={point.x}
331
+ cy={point.y}
332
+ r="4"
333
+ fill={cumulativeLineColor}
334
+ className="c-chart__waterfall-cumulative-point"
335
+ />
400
336
  );
401
- }
337
+ });
338
+ }
339
+
340
+ // X-axis
341
+ elements.push(
342
+ <line
343
+ key="x-axis"
344
+ x1={padding}
345
+ y1={scales.height - padding}
346
+ x2={scales.width - padding}
347
+ y2={scales.height - padding}
348
+ stroke="var(--atomix-gray-4)"
349
+ strokeWidth="2"
350
+ />
351
+ );
352
+
353
+ // Y-axis
354
+ elements.push(
355
+ <line
356
+ key="y-axis"
357
+ x1={padding}
358
+ y1={padding}
359
+ x2={padding}
360
+ y2={scales.height - padding}
361
+ stroke="var(--atomix-gray-4)"
362
+ className="c-chart__axis-line"
363
+ />
364
+ );
402
365
 
403
- return <g>{elements}</g>;
404
- },
405
- [
406
- waterfallData,
407
- showConnectors,
408
- connectorColor,
409
- connectorStyle,
410
- showValues,
411
- valuePosition,
412
- barWidth,
413
- showCumulativeLine,
414
- cumulativeLineColor,
415
- animate,
416
- animationDuration,
417
- animationDelay,
418
- valueFormatter,
419
- showBaseline,
420
- baselineColor,
421
- ]
422
- );
366
+ // X-axis labels
367
+ processedData.forEach((item, index) => {
368
+ const x = padding + index * barSpacing + barSpacing / 2;
369
+ elements.push(
370
+ <text
371
+ key={`x-label-${index}`}
372
+ x={x}
373
+ y={scales.height - padding + 20}
374
+ textAnchor="middle"
375
+ className="c-chart__axis-label"
376
+ fill="var(--atomix-gray-6)"
377
+ transform={`rotate(-45, ${x}, ${scales.height - padding + 20})`}
378
+ >
379
+ {item.label}
380
+ </text>
381
+ );
382
+ });
423
383
 
424
- // Convert waterfall data to datasets format for ChartRenderer
384
+ return <g>{elements}</g>;
385
+ };
386
+
387
+ // Convert waterfallData to datasets format for BaseChart
425
388
  const datasets = [
426
389
  {
427
390
  label: 'Waterfall Data',
428
- data: waterfallData.map(item => ({
429
- label: item.label,
430
- value: item.value,
431
- })),
391
+ data: waterfallData,
432
392
  },
433
393
  ];
434
394
 
435
395
  return (
436
- <Chart ref={ref} type="waterfall" datasets={datasets} config={config} {...props}>
437
- <ChartRenderer
438
- datasets={datasets}
439
- config={config}
440
- onDataPointClick={onDataPointClick}
441
- renderContent={renderContent}
442
- />
443
- </Chart>
396
+ <BaseChart
397
+ ref={ref}
398
+ type="waterfall"
399
+ datasets={datasets}
400
+ config={config}
401
+ renderContent={renderContent}
402
+ onDataPointClick={onDataPointClick}
403
+ {...props}
404
+ />
444
405
  );
445
406
  }
446
407
  )
@@ -448,3 +409,4 @@ const WaterfallChart = memo(
448
409
 
449
410
  WaterfallChart.displayName = 'WaterfallChart';
450
411
  export default WaterfallChart;
412
+ export type { WaterfallChartProps, WaterfallDataPoint };