@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,624 +0,0 @@
1
- import { forwardRef, memo, useCallback, useEffect, useMemo, useState } from 'react';
2
- import { CHART } from '../../lib/constants/components';
3
- import Chart from './Chart';
4
- import { ChartDataPoint, ChartProps } from './types';
5
-
6
- interface AdvancedChartProps extends Omit<ChartProps, 'type'> {
7
- /**
8
- * Advanced chart specific options
9
- */
10
- advancedOptions?: {
11
- /**
12
- * Chart type for advanced rendering
13
- */
14
- chartType?: 'line' | 'area' | 'bar' | 'mixed';
15
-
16
- /**
17
- * Whether to enable real-time updates
18
- */
19
- realTime?: boolean;
20
-
21
- /**
22
- * Update interval in milliseconds for real-time data
23
- */
24
- updateInterval?: number;
25
-
26
- /**
27
- * Whether to show advanced tooltips
28
- */
29
- advancedTooltips?: boolean;
30
-
31
- /**
32
- * Whether to enable data point selection
33
- */
34
- enableSelection?: boolean;
35
-
36
- /**
37
- * Maximum number of selected points
38
- */
39
- maxSelections?: number;
40
-
41
- /**
42
- * Whether to show trend lines
43
- */
44
- showTrendLines?: boolean;
45
-
46
- /**
47
- * Whether to show moving averages
48
- */
49
- showMovingAverages?: boolean;
50
-
51
- /**
52
- * Period for moving average calculation
53
- */
54
- movingAveragePeriod?: number;
55
-
56
- /**
57
- * Whether to enable data export
58
- */
59
- enableExport?: boolean;
60
-
61
- /**
62
- * Export formats
63
- */
64
- exportFormats?: ('png' | 'svg' | 'csv' | 'json')[];
65
-
66
- /**
67
- * Whether to show data table
68
- */
69
- showDataTable?: boolean;
70
-
71
- /**
72
- * Whether to enable annotations
73
- */
74
- enableAnnotations?: boolean;
75
-
76
- /**
77
- * Custom annotations
78
- */
79
- annotations?: Array<{
80
- x: number;
81
- y: number;
82
- label: string;
83
- color?: string;
84
- type?: 'point' | 'line' | 'area';
85
- }>;
86
- };
87
- }
88
-
89
- const AdvancedChart = memo(
90
- forwardRef<HTMLDivElement, AdvancedChartProps>(
91
- (
92
- {
93
- datasets = [],
94
- config = {},
95
- advancedOptions = {
96
- chartType: 'line',
97
- realTime: false,
98
- updateInterval: 1000,
99
- advancedTooltips: true,
100
- enableSelection: false,
101
- maxSelections: 5,
102
- showTrendLines: false,
103
- showMovingAverages: false,
104
- movingAveragePeriod: 7,
105
- enableExport: false,
106
- exportFormats: ['png', 'svg'],
107
- showDataTable: false,
108
- enableAnnotations: false,
109
- annotations: [],
110
- },
111
- onDataPointClick,
112
- ...props
113
- },
114
- ref
115
- ) => {
116
- const [selectedPoints, setSelectedPoints] = useState<Set<string>>(new Set());
117
- const [realTimeData, setRealTimeData] = useState(datasets);
118
- const [hoveredPoint, setHoveredPoint] = useState<{
119
- datasetIndex: number;
120
- pointIndex: number;
121
- x: number;
122
- y: number;
123
- value: number;
124
- label: string;
125
- } | null>(null);
126
-
127
- // Real-time data simulation
128
- useEffect(() => {
129
- if (!advancedOptions.realTime) return undefined;
130
-
131
- const interval = setInterval(() => {
132
- setRealTimeData(prevData =>
133
- prevData.map(dataset => ({
134
- ...dataset,
135
- data: dataset.data.map(point => ({
136
- ...point,
137
- value: point.value + (Math.random() - 0.5) * 10,
138
- })),
139
- }))
140
- );
141
- }, advancedOptions.updateInterval);
142
-
143
- return () => clearInterval(interval);
144
- }, [advancedOptions.realTime, advancedOptions.updateInterval]);
145
-
146
- // Calculate moving average
147
- const calculateMovingAverage = useCallback((data: ChartDataPoint[], period: number) => {
148
- const result: ChartDataPoint[] = [];
149
-
150
- for (let i = period - 1; i < data.length; i++) {
151
- const sum = data
152
- .slice(i - period + 1, i + 1)
153
- .reduce((acc, point) => acc + point.value, 0);
154
- const average = sum / period;
155
-
156
- const currentPoint = data[i];
157
- if (currentPoint) {
158
- result.push({
159
- label: currentPoint.label,
160
- value: average,
161
- color: 'rgba(255, 255, 255, 0.5)',
162
- });
163
- }
164
- }
165
-
166
- return result;
167
- }, []);
168
-
169
- // Handle point selection
170
- const handlePointSelect = useCallback(
171
- (datasetIndex: number, pointIndex: number) => {
172
- if (!advancedOptions.enableSelection) return;
173
-
174
- const pointKey = `${datasetIndex}-${pointIndex}`;
175
- const newSelectedPoints = new Set(selectedPoints);
176
-
177
- if (newSelectedPoints.has(pointKey)) {
178
- newSelectedPoints.delete(pointKey);
179
- } else {
180
- if (newSelectedPoints.size >= (advancedOptions.maxSelections || 5)) {
181
- const firstKey = newSelectedPoints.values().next().value;
182
- if (firstKey) {
183
- newSelectedPoints.delete(firstKey);
184
- }
185
- }
186
- newSelectedPoints.add(pointKey);
187
- }
188
-
189
- setSelectedPoints(newSelectedPoints);
190
- },
191
- [selectedPoints, advancedOptions.enableSelection, advancedOptions.maxSelections]
192
- );
193
-
194
- // Export chart data
195
- const exportChart = useCallback(
196
- (format: string) => {
197
- if (!advancedOptions.enableExport) return;
198
-
199
- const chartElement = document.querySelector('.c-chart__canvas svg') as SVGElement;
200
- if (!chartElement) return;
201
-
202
- switch (format) {
203
- case 'png':
204
- // Convert SVG to PNG
205
- const svgData = new XMLSerializer().serializeToString(chartElement);
206
- const canvas = document.createElement('canvas');
207
- const ctx = canvas.getContext('2d');
208
- const img = new Image();
209
-
210
- img.onload = () => {
211
- canvas.width = img.width;
212
- canvas.height = img.height;
213
- ctx?.drawImage(img, 0, 0);
214
-
215
- const link = document.createElement('a');
216
- link.download = 'chart.png';
217
- link.href = canvas.toDataURL();
218
- link.click();
219
- };
220
-
221
- img.src = 'data:image/svg+xml;base64,' + btoa(svgData);
222
- break;
223
-
224
- case 'svg':
225
- const svgBlob = new Blob([chartElement.outerHTML], { type: 'image/svg+xml' });
226
- const svgUrl = URL.createObjectURL(svgBlob);
227
- const svgLink = document.createElement('a');
228
- svgLink.href = svgUrl;
229
- svgLink.download = 'chart.svg';
230
- svgLink.click();
231
- break;
232
-
233
- case 'csv':
234
- const csvContent = datasets
235
- .map(dataset =>
236
- dataset.data.map(point => `${point.label},${point.value}`).join('\n')
237
- )
238
- .join('\n');
239
- const csvBlob = new Blob([csvContent], { type: 'text/csv' });
240
- const csvUrl = URL.createObjectURL(csvBlob);
241
- const csvLink = document.createElement('a');
242
- csvLink.href = csvUrl;
243
- csvLink.download = 'chart-data.csv';
244
- csvLink.click();
245
- break;
246
- }
247
- },
248
- [datasets, advancedOptions.enableExport]
249
- );
250
-
251
- // Calculate chart content
252
- const chartContent = useMemo(() => {
253
- if (!realTimeData.length) return null;
254
-
255
- const width = 800;
256
- const height = 400;
257
- const padding = { top: 20, right: 30, bottom: 40, left: 50 };
258
- const innerWidth = width - padding.left - padding.right;
259
- const innerHeight = height - padding.top - padding.bottom;
260
-
261
- // Calculate scales
262
- const allValues = realTimeData.flatMap(dataset => dataset.data.map(d => d.value));
263
- const minValue = config.yAxis?.min ?? Math.min(0, ...allValues);
264
- const maxValue = config.yAxis?.max ?? Math.max(...allValues);
265
-
266
- const xScale = (i: number) => {
267
- const firstDataset = realTimeData[0];
268
- if (!firstDataset?.data?.length) return padding.left;
269
- return padding.left + (i / (firstDataset.data.length - 1)) * innerWidth;
270
- };
271
- const yScale = (value: number) =>
272
- padding.top + innerHeight - ((value - minValue) / (maxValue - minValue)) * innerHeight;
273
-
274
- // Generate chart elements based on type
275
- const chartElements = realTimeData.map((dataset, datasetIndex) => {
276
- const color = dataset.color || `var(--atomix-color-${datasetIndex + 1})`;
277
- const elements = [];
278
-
279
- // Main data line/area
280
- if (advancedOptions.chartType === 'line' || advancedOptions.chartType === 'area') {
281
- const points = dataset.data.map((point, i) => ({
282
- x: xScale(i),
283
- y: yScale(point.value),
284
- }));
285
-
286
- const pathData = points
287
- .map((point, i) => (i === 0 ? `M ${point.x},${point.y}` : `L ${point.x},${point.y}`))
288
- .join(' ');
289
-
290
- if (advancedOptions.chartType === 'area') {
291
- elements.push(
292
- <path
293
- key={`area-${datasetIndex}`}
294
- d={`${pathData} L ${xScale(dataset.data.length - 1)},${yScale(minValue)} L ${xScale(0)},${yScale(minValue)} Z`}
295
- fill={color}
296
- opacity={0.2}
297
- />
298
- );
299
- }
300
-
301
- elements.push(
302
- <path
303
- key={`line-${datasetIndex}`}
304
- d={pathData}
305
- stroke={color}
306
- fill="none"
307
- strokeWidth={2}
308
- strokeLinecap="round"
309
- strokeLinejoin="round"
310
- />
311
- );
312
- }
313
-
314
- // Data points
315
- dataset.data.forEach((point, pointIndex) => {
316
- const x = xScale(pointIndex);
317
- const y = yScale(point.value);
318
- const pointKey = `${datasetIndex}-${pointIndex}`;
319
- const isSelected = selectedPoints.has(pointKey);
320
- const isHovered =
321
- hoveredPoint?.datasetIndex === datasetIndex &&
322
- hoveredPoint?.pointIndex === pointIndex;
323
-
324
- elements.push(
325
- <circle
326
- key={`point-${datasetIndex}-${pointIndex}`}
327
- cx={x}
328
- cy={y}
329
- r={isSelected ? 6 : isHovered ? 5 : 4}
330
- fill={isSelected ? 'var(--atomix-primary-500)' : color}
331
- stroke="#ffffff"
332
- strokeWidth={isSelected ? 3 : 2}
333
- className={CHART.DATA_POINT_CLASS}
334
- onClick={() => {
335
- handlePointSelect(datasetIndex, pointIndex);
336
- onDataPointClick?.(point, datasetIndex, pointIndex);
337
- }}
338
- onMouseEnter={() =>
339
- setHoveredPoint({
340
- datasetIndex,
341
- pointIndex,
342
- x,
343
- y,
344
- value: point.value,
345
- label: point.label,
346
- })
347
- }
348
- onMouseLeave={() => setHoveredPoint(null)}
349
- style={{
350
- cursor: 'pointer',
351
- transition: 'r 0.2s ease-in-out, fill 0.2s ease-in-out',
352
- }}
353
- />
354
- );
355
- });
356
-
357
- // Moving average line
358
- if (advancedOptions.showMovingAverages) {
359
- const movingAvgData = calculateMovingAverage(
360
- dataset.data,
361
- advancedOptions.movingAveragePeriod || 7
362
- );
363
- const movingAvgPoints = movingAvgData.map((point, i) => ({
364
- x: xScale(i + (advancedOptions.movingAveragePeriod || 7) - 1),
365
- y: yScale(point.value),
366
- }));
367
-
368
- const movingAvgPath = movingAvgPoints
369
- .map((point, i) => (i === 0 ? `M ${point.x},${point.y}` : `L ${point.x},${point.y}`))
370
- .join(' ');
371
-
372
- elements.push(
373
- <path
374
- key={`moving-avg-${datasetIndex}`}
375
- d={movingAvgPath}
376
- stroke={color}
377
- fill="none"
378
- strokeWidth={1}
379
- strokeDasharray="5,5"
380
- opacity={0.7}
381
- />
382
- );
383
- }
384
-
385
- return elements;
386
- });
387
-
388
- // Annotations
389
- const annotations =
390
- advancedOptions.annotations?.map((annotation, i) => (
391
- <g key={`annotation-${i}`}>
392
- <circle
393
- cx={xScale(annotation.x)}
394
- cy={yScale(annotation.y)}
395
- r={4}
396
- fill={annotation.color || '#ef4444'}
397
- stroke="#ffffff"
398
- strokeWidth={2}
399
- />
400
- <text
401
- x={xScale(annotation.x) + 10}
402
- y={yScale(annotation.y) - 10}
403
- fill="#111827"
404
- fontSize="12"
405
- fontWeight="bold"
406
- >
407
- {annotation.label}
408
- </text>
409
- </g>
410
- )) || [];
411
-
412
- return (
413
- <svg
414
- width="100%"
415
- height="100%"
416
- viewBox={`0 0 ${width} ${height}`}
417
- preserveAspectRatio="xMidYMid meet"
418
- >
419
- {/* Grid */}
420
- <g className={CHART.GRID_CLASS}>
421
- {Array.from({ length: 5 }).map((_, i) => {
422
- const value = minValue + ((maxValue - minValue) * i) / 4;
423
- return (
424
- <line
425
- key={`grid-${i}`}
426
- x1={padding.left}
427
- y1={yScale(value)}
428
- x2={width - padding.right}
429
- y2={yScale(value)}
430
- stroke="#e5e7eb"
431
- strokeWidth={1}
432
- strokeDasharray="4,4"
433
- opacity={0.3}
434
- />
435
- );
436
- })}
437
- </g>
438
-
439
- {/* Chart elements */}
440
- {chartElements.flat()}
441
- {annotations}
442
-
443
- {/* Axes */}
444
- <g className={`${CHART.AXIS_CLASS} ${CHART.AXIS_CLASS}--x`}>
445
- {realTimeData[0]?.data?.map((point, i) => (
446
- <text
447
- key={`x-label-${i}`}
448
- x={xScale(i)}
449
- y={height - 10}
450
- textAnchor="middle"
451
- fontSize="12"
452
- fill="#374151"
453
- >
454
- {point.label}
455
- </text>
456
- ))}
457
- </g>
458
-
459
- <g className={`${CHART.AXIS_CLASS} ${CHART.AXIS_CLASS}--y`}>
460
- {Array.from({ length: 5 }).map((_, i) => {
461
- const value = minValue + ((maxValue - minValue) * i) / 4;
462
- return (
463
- <text
464
- key={`y-label-${i}`}
465
- x={padding.left - 10}
466
- y={yScale(value)}
467
- textAnchor="end"
468
- dominantBaseline="middle"
469
- fontSize="12"
470
- fill="#374151"
471
- >
472
- {value.toFixed(value % 1 === 0 ? 0 : 1)}
473
- </text>
474
- );
475
- })}
476
- </g>
477
- </svg>
478
- );
479
- }, [
480
- realTimeData,
481
- config,
482
- advancedOptions,
483
- selectedPoints,
484
- hoveredPoint,
485
- calculateMovingAverage,
486
- handlePointSelect,
487
- onDataPointClick,
488
- ]);
489
-
490
- // Advanced tooltip
491
- const advancedTooltip = useMemo(() => {
492
- if (!advancedOptions.advancedTooltips || !hoveredPoint) return null;
493
-
494
- return (
495
- <div
496
- className="advanced-tooltip"
497
- style={{
498
- position: 'absolute',
499
- left: hoveredPoint.x + 10,
500
- top: hoveredPoint.y - 10,
501
- background: 'var(--atomix-surface)',
502
- border: '1px solid #e5e7eb',
503
- borderRadius: 'var(--radius-md)',
504
- padding: '0.5rem',
505
- fontSize: 'var(--font-size-sm)',
506
- boxShadow: 'var(--shadow-lg)',
507
- zIndex: 1000,
508
- pointerEvents: 'none',
509
- }}
510
- >
511
- <div style={{ fontWeight: 'bold', marginBottom: 'var(--space-1)' }}>
512
- {hoveredPoint.label}
513
- </div>
514
- <div>Value: {hoveredPoint.value}</div>
515
- <div>Dataset: {realTimeData[hoveredPoint.datasetIndex]?.label}</div>
516
- </div>
517
- );
518
- }, [hoveredPoint, advancedOptions.advancedTooltips, realTimeData]);
519
-
520
- // Export controls
521
- const exportControls = useMemo(() => {
522
- if (!advancedOptions.enableExport) return null;
523
-
524
- return (
525
- <div className="chart-export-controls" style={{ marginTop: 'var(--space-3)' }}>
526
- <div style={{ display: 'flex', gap: '0.5rem' }}>
527
- {advancedOptions.exportFormats?.map(format => (
528
- <button
529
- key={format}
530
- onClick={() => exportChart(format)}
531
- style={{
532
- padding: 'var(--space-1) 0.5rem',
533
- background: 'var(--atomix-surface)',
534
- border: '1px solid #e5e7eb',
535
- borderRadius: 'var(--radius-sm)',
536
- fontSize: 'var(--font-size-sm)',
537
- cursor: 'pointer',
538
- }}
539
- >
540
- Export {format.toUpperCase()}
541
- </button>
542
- ))}
543
- </div>
544
- </div>
545
- );
546
- }, [advancedOptions.enableExport, advancedOptions.exportFormats, exportChart]);
547
-
548
- // Data table
549
- const dataTable = useMemo(() => {
550
- if (!advancedOptions.showDataTable || !realTimeData.length) return null;
551
-
552
- return (
553
- <div className="chart-data-table" style={{ marginTop: 'var(--space-3)' }}>
554
- <table style={{ width: '100%', borderCollapse: 'collapse' }}>
555
- <thead>
556
- <tr>
557
- <th
558
- style={{
559
- padding: '0.5rem',
560
- textAlign: 'left',
561
- borderBottom: '1px solid #e5e7eb',
562
- }}
563
- >
564
- Label
565
- </th>
566
- {realTimeData.map((dataset, i) => (
567
- <th
568
- key={i}
569
- style={{
570
- padding: '0.5rem',
571
- textAlign: 'left',
572
- borderBottom: '1px solid #e5e7eb',
573
- }}
574
- >
575
- {dataset.label}
576
- </th>
577
- ))}
578
- </tr>
579
- </thead>
580
- <tbody>
581
- {realTimeData[0]?.data?.map((_, pointIndex) => (
582
- <tr key={pointIndex}>
583
- <td
584
- style={{
585
- padding: '0.5rem',
586
- borderBottom: '1px solid #e5e7eb',
587
- }}
588
- >
589
- {realTimeData[0]?.data?.[pointIndex]?.label}
590
- </td>
591
- {realTimeData.map((dataset, datasetIndex) => (
592
- <td
593
- key={datasetIndex}
594
- style={{
595
- padding: '0.5rem',
596
- borderBottom: '1px solid #e5e7eb',
597
- }}
598
- >
599
- {dataset.data[pointIndex]?.value.toFixed(2)}
600
- </td>
601
- ))}
602
- </tr>
603
- ))}
604
- </tbody>
605
- </table>
606
- </div>
607
- );
608
- }, [advancedOptions.showDataTable, realTimeData]);
609
-
610
- return (
611
- <Chart ref={ref} type="advanced" datasets={realTimeData} config={config} {...props}>
612
- {chartContent}
613
- {advancedTooltip}
614
- {exportControls}
615
- {dataTable}
616
- </Chart>
617
- );
618
- }
619
- )
620
- );
621
-
622
- AdvancedChart.displayName = 'AdvancedChart';
623
- export default AdvancedChart;
624
- export type { AdvancedChartProps };