@shohojdhara/atomix 0.2.3 → 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 (225) hide show
  1. package/README.md +19 -0
  2. package/dist/atomix.css +1703 -1544
  3. package/dist/atomix.min.css +4 -4
  4. package/dist/index.d.ts +1465 -963
  5. package/dist/index.esm.js +16289 -25908
  6. package/dist/index.esm.js.map +1 -1
  7. package/dist/index.js +15650 -21780
  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 +1608 -1450
  14. package/dist/themes/boomdevs.min.css +5 -5
  15. package/dist/themes/esrar.css +1702 -1543
  16. package/dist/themes/esrar.min.css +4 -4
  17. package/dist/themes/flashtrade.css +15159 -0
  18. package/dist/themes/flashtrade.min.css +86 -0
  19. package/dist/themes/mashroom.css +1699 -1540
  20. package/dist/themes/mashroom.min.css +7 -7
  21. package/dist/themes/shaj-default.css +1693 -1534
  22. package/dist/themes/shaj-default.min.css +4 -4
  23. package/package.json +6 -17
  24. package/src/components/Accordion/Accordion.stories.tsx +662 -21
  25. package/src/components/Accordion/Accordion.tsx +21 -14
  26. package/src/components/AtomixGlass/AtomixGlass.test.tsx +106 -72
  27. package/src/components/AtomixGlass/AtomixGlass.tsx +529 -1195
  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 +792 -68
  34. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +1250 -0
  35. package/src/components/AtomixGlass/stories/Examples.stories.tsx +5768 -0
  36. package/src/components/AtomixGlass/stories/Modes.stories.tsx +1065 -0
  37. package/src/components/AtomixGlass/stories/Playground.stories.tsx +1129 -0
  38. package/src/components/AtomixGlass/stories/ShaderVariants.stories.tsx +395 -0
  39. package/src/components/AtomixGlass/stories/shared-components.tsx +301 -0
  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 +76 -55
  44. package/src/components/Badge/Badge.tsx +12 -14
  45. package/src/components/Breadcrumb/Breadcrumb.tsx +23 -4
  46. package/src/components/Button/Button.stories.tsx +501 -20
  47. package/src/components/Button/Button.tsx +5 -8
  48. package/src/components/Callout/Callout.stories.tsx +86 -35
  49. package/src/components/Callout/Callout.tsx +31 -9
  50. package/src/components/Card/Card.stories.tsx +565 -2
  51. package/src/components/Card/Card.tsx +15 -4
  52. package/src/components/Card/ElevationCard.tsx +2 -0
  53. package/src/components/Chart/AnimatedChart.tsx +179 -156
  54. package/src/components/Chart/AreaChart.tsx +123 -12
  55. package/src/components/Chart/BarChart.tsx +91 -100
  56. package/src/components/Chart/BaseChart.tsx +80 -0
  57. package/src/components/Chart/BubbleChart.tsx +114 -290
  58. package/src/components/Chart/CandlestickChart.tsx +282 -622
  59. package/src/components/Chart/Chart.stories.tsx +576 -179
  60. package/src/components/Chart/Chart.tsx +374 -75
  61. package/src/components/Chart/ChartRenderer.tsx +371 -220
  62. package/src/components/Chart/ChartToolbar.tsx +372 -61
  63. package/src/components/Chart/ChartTooltip.tsx +33 -18
  64. package/src/components/Chart/DonutChart.tsx +172 -254
  65. package/src/components/Chart/FunnelChart.tsx +169 -240
  66. package/src/components/Chart/GaugeChart.tsx +224 -392
  67. package/src/components/Chart/HeatmapChart.tsx +302 -440
  68. package/src/components/Chart/LineChart.tsx +148 -103
  69. package/src/components/Chart/MultiAxisChart.tsx +267 -395
  70. package/src/components/Chart/PieChart.tsx +114 -64
  71. package/src/components/Chart/RadarChart.tsx +202 -218
  72. package/src/components/Chart/ScatterChart.tsx +111 -97
  73. package/src/components/Chart/TreemapChart.tsx +147 -222
  74. package/src/components/Chart/WaterfallChart.tsx +253 -291
  75. package/src/components/Chart/index.ts +11 -9
  76. package/src/components/Chart/types.ts +85 -9
  77. package/src/components/Chart/utils.ts +66 -0
  78. package/src/components/ColorModeToggle/ColorModeToggle.tsx +6 -3
  79. package/src/components/Countdown/Countdown.tsx +4 -0
  80. package/src/components/DataTable/DataTable.tsx +2 -1
  81. package/src/components/DatePicker/DatePicker.stories.tsx +689 -12
  82. package/src/components/DatePicker/DatePicker.tsx +3 -9
  83. package/src/components/DatePicker/types.ts +5 -0
  84. package/src/components/Dropdown/Dropdown.stories.tsx +32 -25
  85. package/src/components/Dropdown/Dropdown.tsx +26 -28
  86. package/src/components/EdgePanel/EdgePanel.stories.tsx +473 -2
  87. package/src/components/EdgePanel/EdgePanel.tsx +101 -13
  88. package/src/components/Footer/Footer.stories.tsx +187 -60
  89. package/src/components/Footer/Footer.test.tsx +134 -0
  90. package/src/components/Footer/Footer.tsx +133 -34
  91. package/src/components/Footer/FooterLink.tsx +1 -1
  92. package/src/components/Footer/FooterSection.tsx +53 -36
  93. package/src/components/Footer/FooterSocialLink.tsx +32 -29
  94. package/src/components/Footer/README.md +82 -3
  95. package/src/components/Footer/index.ts +1 -1
  96. package/src/components/Form/Checkbox.stories.tsx +13 -5
  97. package/src/components/Form/Checkbox.tsx +3 -6
  98. package/src/components/Form/Form.stories.tsx +10 -3
  99. package/src/components/Form/Form.tsx +2 -0
  100. package/src/components/Form/FormGroup.tsx +2 -1
  101. package/src/components/Form/Input.stories.tsx +12 -11
  102. package/src/components/Form/Input.tsx +97 -95
  103. package/src/components/Form/Radio.stories.tsx +22 -7
  104. package/src/components/Form/Radio.tsx +3 -6
  105. package/src/components/Form/Select.stories.tsx +21 -6
  106. package/src/components/Form/Select.tsx +3 -5
  107. package/src/components/Form/Textarea.stories.tsx +13 -11
  108. package/src/components/Form/Textarea.tsx +88 -86
  109. package/src/components/Hero/Hero.stories.tsx +2 -3
  110. package/src/components/Hero/Hero.tsx +5 -6
  111. package/src/components/Icon/Icon.tsx +12 -1
  112. package/src/components/List/List.tsx +2 -1
  113. package/src/components/List/ListGroup.tsx +2 -1
  114. package/src/components/Messages/Messages.stories.tsx +113 -0
  115. package/src/components/Messages/Messages.tsx +52 -9
  116. package/src/components/Modal/Modal.stories.tsx +48 -32
  117. package/src/components/Modal/Modal.tsx +19 -24
  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.stories.tsx +469 -0
  121. package/src/components/Navigation/Nav/Nav.tsx +22 -4
  122. package/src/components/Navigation/Nav/NavDropdown.tsx +10 -1
  123. package/src/components/Navigation/Navbar/Navbar.stories.tsx +413 -0
  124. package/src/components/Navigation/Navbar/Navbar.tsx +70 -29
  125. package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +340 -0
  126. package/src/components/Navigation/SideMenu/SideMenu.tsx +29 -2
  127. package/src/components/Pagination/Pagination.stories.tsx +13 -6
  128. package/src/components/Pagination/Pagination.tsx +7 -6
  129. package/src/components/PhotoViewer/PhotoViewer.tsx +2 -1
  130. package/src/components/Popover/Popover.stories.tsx +32 -24
  131. package/src/components/Popover/Popover.tsx +4 -1
  132. package/src/components/ProductReview/ProductReview.tsx +8 -2
  133. package/src/components/Progress/Progress.tsx +19 -3
  134. package/src/components/Rating/Rating.stories.tsx +11 -6
  135. package/src/components/Rating/Rating.tsx +3 -5
  136. package/src/components/River/River.tsx +5 -5
  137. package/src/components/SectionIntro/SectionIntro.tsx +8 -2
  138. package/src/components/Slider/Slider.stories.tsx +4 -4
  139. package/src/components/Slider/Slider.tsx +4 -3
  140. package/src/components/Spinner/Spinner.tsx +19 -3
  141. package/src/components/Steps/Steps.stories.tsx +5 -4
  142. package/src/components/Steps/Steps.tsx +8 -5
  143. package/src/components/Tab/Tab.stories.tsx +4 -3
  144. package/src/components/Tab/Tab.tsx +8 -6
  145. package/src/components/Testimonial/Testimonial.tsx +8 -2
  146. package/src/components/Todo/Todo.tsx +2 -1
  147. package/src/components/Toggle/Toggle.stories.tsx +5 -4
  148. package/src/components/Toggle/Toggle.tsx +8 -5
  149. package/src/components/Tooltip/Tooltip.stories.tsx +40 -30
  150. package/src/components/Tooltip/Tooltip.tsx +9 -2
  151. package/src/components/Upload/Upload.stories.tsx +252 -0
  152. package/src/components/Upload/Upload.tsx +92 -53
  153. package/src/components/VideoPlayer/VideoPlayer.tsx +3 -1
  154. package/src/components/index.ts +0 -4
  155. package/src/layouts/Grid/Grid.stories.tsx +10 -23
  156. package/src/layouts/Grid/Grid.tsx +20 -1
  157. package/src/layouts/Grid/GridCol.tsx +76 -48
  158. package/src/lib/composables/useAtomixGlass.ts +861 -44
  159. package/src/lib/composables/useBarChart.ts +21 -4
  160. package/src/lib/composables/useChart.ts +227 -370
  161. package/src/lib/composables/useChartExport.ts +19 -78
  162. package/src/lib/composables/useChartToolbar.ts +11 -21
  163. package/src/lib/composables/useEdgePanel.ts +125 -71
  164. package/src/lib/composables/useFooter.ts +3 -3
  165. package/src/lib/composables/useGlassContainer.ts +16 -7
  166. package/src/lib/composables/useLineChart.ts +11 -2
  167. package/src/lib/composables/usePieChart.ts +4 -14
  168. package/src/lib/composables/useRiver.ts +5 -0
  169. package/src/lib/composables/useSlider.ts +62 -24
  170. package/src/lib/composables/useVideoPlayer.ts +60 -63
  171. package/src/lib/constants/components.ts +147 -32
  172. package/src/lib/types/components.ts +355 -25
  173. package/src/lib/utils/displacement-generator.ts +55 -49
  174. package/src/lib/utils/icons.ts +1 -1
  175. package/src/lib/utils/index.ts +16 -10
  176. package/src/styles/01-settings/_settings.accordion.scss +19 -19
  177. package/src/styles/01-settings/_settings.animations.scss +5 -5
  178. package/src/styles/01-settings/_settings.avatar-group.scss +1 -1
  179. package/src/styles/01-settings/_settings.avatar.scss +17 -17
  180. package/src/styles/01-settings/_settings.background.scss +0 -3
  181. package/src/styles/01-settings/_settings.badge.scss +1 -1
  182. package/src/styles/01-settings/_settings.breadcrumb.scss +1 -1
  183. package/src/styles/01-settings/_settings.card.scss +1 -1
  184. package/src/styles/01-settings/_settings.chart.scss +65 -2
  185. package/src/styles/01-settings/_settings.dropdown.scss +1 -1
  186. package/src/styles/01-settings/_settings.edge-panel.scss +1 -1
  187. package/src/styles/01-settings/_settings.footer.scss +35 -42
  188. package/src/styles/01-settings/_settings.input.scss +1 -1
  189. package/src/styles/01-settings/_settings.list.scss +1 -1
  190. package/src/styles/01-settings/_settings.rating.scss +1 -1
  191. package/src/styles/01-settings/_settings.tabs.scss +1 -1
  192. package/src/styles/01-settings/_settings.upload.scss +6 -5
  193. package/src/styles/02-tools/_tools.animations.scss +4 -5
  194. package/src/styles/02-tools/_tools.background.scss +1 -13
  195. package/src/styles/02-tools/_tools.glass.scss +0 -1
  196. package/src/styles/02-tools/_tools.utility-api.scss +91 -48
  197. package/src/styles/03-generic/_generic.root.scss +1 -4
  198. package/src/styles/04-elements/_elements.body.scss +0 -1
  199. package/src/styles/06-components/_components.atomix-glass.scss +249 -0
  200. package/src/styles/06-components/_components.badge.scss +8 -23
  201. package/src/styles/06-components/_components.button.scss +8 -3
  202. package/src/styles/06-components/_components.callout.scss +10 -5
  203. package/src/styles/06-components/_components.card.scss +2 -14
  204. package/src/styles/06-components/_components.chart.scss +969 -1449
  205. package/src/styles/06-components/_components.dropdown.scss +19 -7
  206. package/src/styles/06-components/_components.edge-panel.scss +103 -0
  207. package/src/styles/06-components/_components.footer.scss +166 -85
  208. package/src/styles/06-components/_components.input.scss +8 -9
  209. package/src/styles/06-components/_components.list.scss +1 -0
  210. package/src/styles/06-components/_components.messages.scss +176 -0
  211. package/src/styles/06-components/_components.modal.scss +16 -4
  212. package/src/styles/06-components/_components.navbar.scss +12 -1
  213. package/src/styles/06-components/_components.side-menu.scss +5 -0
  214. package/src/styles/06-components/_components.skeleton.scss +8 -6
  215. package/src/styles/06-components/_components.upload.scss +219 -4
  216. package/src/styles/06-components/old.chart.styles.scss +1 -30
  217. package/src/styles/99-utilities/_index.scss +1 -0
  218. package/src/styles/99-utilities/_utilities.glass-fixes.scss +1 -0
  219. package/src/styles/99-utilities/_utilities.scss +1 -1
  220. package/src/components/AtomixGlass/AtomixGlass.stories.tsx +0 -3011
  221. package/src/components/AtomixGlass/AtomixGlassComprehensivePreview.stories.tsx +0 -1369
  222. package/src/components/Chart/AdvancedChart.tsx +0 -624
  223. package/src/components/Chart/LineChartNew.tsx +0 -167
  224. package/src/components/Chart/RealTimeChart.tsx +0 -436
  225. package/src/components/DatePicker/DatePicker copy.tsx +0 -551
@@ -178,9 +178,15 @@ export function useChartExport() {
178
178
  rows.push(row);
179
179
  });
180
180
 
181
- // Convert to CSV string
181
+ // Convert to CSV string with sanitization
182
182
  const csvContent = rows
183
- .map(row => row.map(cell => `"${cell.replace(/"/g, '""')}"`).join(','))
183
+ .map(row => row.map(cell => {
184
+ // Sanitize cell content to prevent CSV injection
185
+ const sanitized = String(cell).replace(/[\r\n\t]/g, ' ').replace(/"/g, '""');
186
+ // Prevent formula injection by prefixing dangerous characters
187
+ const dangerous = /^[=+\-@]/;
188
+ return `"${dangerous.test(sanitized) ? `'${sanitized}` : sanitized}"`;
189
+ }).join(','))
184
190
  .join('\n');
185
191
 
186
192
  // Download
@@ -297,17 +303,21 @@ export function useChartExport() {
297
303
  break;
298
304
  case 'email':
299
305
  window.open(
300
- `mailto:?subject=${encodeURIComponent('Chart Share')}&body=${encodeURIComponent(`${message}\n\n${url}`)}`,
306
+ `mailto:?subject=${encodeURIComponent(message)}&body=${encodeURIComponent(`${message} ${url}`)}`,
301
307
  '_blank'
302
308
  );
303
309
  break;
304
310
  case 'copy-link':
305
- try {
311
+ if (navigator.clipboard) {
306
312
  await navigator.clipboard.writeText(url);
307
- // You might want to show a toast notification here
308
- console.log('Link copied to clipboard');
309
- } catch (error) {
310
- console.error('Failed to copy link:', error);
313
+ } else {
314
+ // Fallback for older browsers
315
+ const textArea = document.createElement('textarea');
316
+ textArea.value = url;
317
+ document.body.appendChild(textArea);
318
+ textArea.select();
319
+ document.execCommand('copy');
320
+ document.body.removeChild(textArea);
311
321
  }
312
322
  break;
313
323
  }
@@ -316,77 +326,8 @@ export function useChartExport() {
316
326
  []
317
327
  );
318
328
 
319
- // Copy chart as image to clipboard
320
- const copyToClipboard = useCallback(
321
- async (svgElement: SVGSVGElement, options: Partial<ExportOptions> = {}): Promise<void> => {
322
- try {
323
- const canvas = await svgToCanvas(svgElement, { format: 'png', ...options });
324
-
325
- canvas.toBlob(async blob => {
326
- if (blob && navigator.clipboard && window.ClipboardItem) {
327
- try {
328
- await navigator.clipboard.write([new ClipboardItem({ 'image/png': blob })]);
329
- console.log('Chart copied to clipboard');
330
- } catch (error) {
331
- console.error('Failed to copy to clipboard:', error);
332
- }
333
- }
334
- }, 'image/png');
335
- } catch (error) {
336
- console.error('Failed to copy chart:', error);
337
- throw error;
338
- }
339
- },
340
- [svgToCanvas]
341
- );
342
-
343
- // Print chart
344
- const printChart = useCallback(
345
- async (svgElement: SVGSVGElement, options: Partial<ExportOptions> = {}): Promise<void> => {
346
- try {
347
- const canvas = await svgToCanvas(svgElement, { format: 'png', ...options });
348
- const dataUrl = canvas.toDataURL('image/png');
349
-
350
- const printWindow = window.open('', '_blank');
351
- if (printWindow) {
352
- printWindow.document.write(`
353
- <html>
354
- <head>
355
- <title>Chart Print</title>
356
- <style>
357
- body { margin: 0; padding: 20px; text-align: center; }
358
- img { max-width: 100%; height: auto; }
359
- </style>
360
- </head>
361
- <body>
362
- <img src="${dataUrl}" alt="Chart" />
363
- </body>
364
- </html>
365
- `);
366
- printWindow.document.close();
367
- printWindow.focus();
368
- printWindow.print();
369
- }
370
- } catch (error) {
371
- console.error('Failed to print chart:', error);
372
- throw error;
373
- }
374
- },
375
- [svgToCanvas]
376
- );
377
-
378
329
  return {
379
330
  exportChart,
380
331
  shareChart,
381
- copyToClipboard,
382
- printChart,
383
-
384
- // Individual export methods
385
- exportAsPNG,
386
- exportAsSVG,
387
- exportAsPDF,
388
- exportAsCSV,
389
- exportAsJSON,
390
- exportAsXLSX,
391
332
  };
392
- }
333
+ }
@@ -1,4 +1,4 @@
1
- import { useCallback, useEffect, useState } from 'react';
1
+ import { useCallback, useEffect, useMemo, useState } from 'react';
2
2
  import { ChartToolbarAction, ChartToolbarGroup } from '../../components/Chart/ChartToolbar';
3
3
  import { ChartType } from '../../components/Chart/types';
4
4
 
@@ -107,10 +107,16 @@ export function useChartToolbar(
107
107
  case 'line':
108
108
  case 'area':
109
109
  case 'bar':
110
+ case 'horizontal-bar':
110
111
  case 'scatter':
112
+ case 'bubble':
113
+ case 'funnel':
114
+ case 'waterfall':
115
+ case 'candlestick':
111
116
  return {
112
117
  ...baseDefaults,
113
118
  zoom: true,
119
+ pan: true,
114
120
  reset: true,
115
121
  };
116
122
 
@@ -132,31 +138,15 @@ export function useChartToolbar(
132
138
  grid: false,
133
139
  };
134
140
 
135
- case 'heatmap':
136
- case 'treemap':
137
- return {
138
- ...baseDefaults,
139
- zoom: true,
140
- pan: true,
141
- grid: false,
142
- };
143
-
144
- case 'candlestick':
145
- return {
146
- ...baseDefaults,
147
- zoom: true,
148
- pan: true,
149
- reset: true,
150
- grid: true,
151
- };
152
-
153
141
  default:
154
142
  return baseDefaults;
155
143
  }
156
144
  }, [chartType]);
157
145
 
158
- // Merge configurations
159
- const finalDefaults = { ...getChartDefaults(), ...defaults };
146
+ // Merge configurations with memoization
147
+ const finalDefaults = useMemo(() => {
148
+ return { ...getChartDefaults(), ...defaults };
149
+ }, [getChartDefaults, defaults]);
160
150
 
161
151
  const enhancedHandlers = {
162
152
  onRefresh: useCallback(() => {
@@ -16,6 +16,7 @@ export function useEdgePanel(initialProps?: Partial<EdgePanelProps>) {
16
16
  backdrop: true,
17
17
  closeOnBackdropClick: true,
18
18
  closeOnEscape: true,
19
+ glass: undefined,
19
20
  ...initialProps,
20
21
  };
21
22
 
@@ -97,94 +98,143 @@ export function useEdgePanel(initialProps?: Partial<EdgePanelProps>) {
97
98
  /**
98
99
  * Open the panel
99
100
  */
100
- const openPanel = useCallback(() => {
101
- setIsOpen(true);
102
- document.body.classList.add('is-edgepanel-open');
103
-
104
- if (containerRef.current) {
105
- const { mode } = defaultProps;
106
-
107
- // Only add animation if not in 'none' mode
108
- if (mode !== 'none') {
109
- // Add animation class first
110
- containerRef.current.classList.add('is-animating');
111
-
112
- // Force a reflow before starting the animation
113
- void containerRef.current.offsetHeight;
114
-
115
- // Remove animation class after animation completes
116
- const container = containerRef.current;
117
- setTimeout(() => {
118
- if (container) {
119
- container.classList.remove('is-animating');
101
+ const openPanel = useCallback(
102
+ (useFadeAnimation = false) => {
103
+ setIsOpen(true);
104
+ document.body.classList.add('is-edgepanel-open');
105
+
106
+ if (containerRef.current) {
107
+ const { mode } = defaultProps;
108
+
109
+ // Only add animation if not in 'none' mode
110
+ if (mode !== 'none') {
111
+ if (useFadeAnimation) {
112
+ // Add fade animation class
113
+ containerRef.current.classList.add('is-fade-animating');
114
+
115
+ // Force a reflow before starting the animation
116
+ void containerRef.current.offsetHeight;
117
+
118
+ // Remove animation class after animation completes
119
+ const container = containerRef.current;
120
+ setTimeout(() => {
121
+ if (container) {
122
+ container.classList.remove('is-fade-animating');
123
+ }
124
+ }, EDGE_PANEL.ANIMATION_DURATION);
125
+ } else {
126
+ // Add transform animation class
127
+ containerRef.current.classList.add('is-animating');
128
+
129
+ // Force a reflow before starting the animation
130
+ void containerRef.current.offsetHeight;
131
+
132
+ // Remove animation class after animation completes
133
+ const container = containerRef.current;
134
+ setTimeout(() => {
135
+ if (container) {
136
+ container.classList.remove('is-animating');
137
+ }
138
+ }, EDGE_PANEL.ANIMATION_DURATION);
120
139
  }
121
- }, EDGE_PANEL.ANIMATION_DURATION);
122
- }
140
+ }
123
141
 
124
- // Then set transform
125
- containerRef.current.style.transform = 'translate(0)';
142
+ // Set transform or opacity based on animation type
143
+ if (useFadeAnimation) {
144
+ containerRef.current.style.opacity = '1';
145
+ containerRef.current.style.transform = ''; // Remove transform for fade
146
+ } else {
147
+ containerRef.current.style.transform = 'translate(0)';
148
+ }
126
149
 
127
- // If push mode, adjust body padding
128
- if (defaultProps.mode === 'push') {
129
- adjustBodyPadding();
150
+ // If push mode, adjust body padding
151
+ if (defaultProps.mode === 'push') {
152
+ adjustBodyPadding();
153
+ }
130
154
  }
131
- }
132
155
 
133
- if (defaultProps.onOpenChange) {
134
- defaultProps.onOpenChange(true);
135
- }
136
- }, [defaultProps, adjustBodyPadding]);
156
+ if (defaultProps.onOpenChange) {
157
+ defaultProps.onOpenChange(true);
158
+ }
159
+ },
160
+ [defaultProps, adjustBodyPadding]
161
+ );
137
162
 
138
163
  /**
139
164
  * Close the panel
140
165
  */
141
- const closePanel = useCallback(() => {
142
- if (containerRef.current) {
143
- const { position, mode } = defaultProps;
144
-
145
- // Only add animation if not in 'none' mode
146
- if (mode !== 'none') {
147
- // Add animation class first
148
- containerRef.current.classList.add('is-animating-out');
149
-
150
- // Capture container for setTimeout
151
- const container = containerRef.current;
152
-
153
- setTimeout(() => {
154
- if (container) {
155
- container.classList.remove('is-animating-out');
166
+ const closePanel = useCallback(
167
+ (useFadeAnimation = false) => {
168
+ if (containerRef.current) {
169
+ const { position, mode } = defaultProps;
170
+
171
+ // Only add animation if not in 'none' mode
172
+ if (mode !== 'none') {
173
+ if (useFadeAnimation) {
174
+ // Add fade out animation class
175
+ containerRef.current.classList.add('is-fade-animating-out');
176
+
177
+ // Capture container for setTimeout
178
+ const container = containerRef.current;
179
+
180
+ setTimeout(() => {
181
+ if (container) {
182
+ container.classList.remove('is-fade-animating-out');
183
+ }
184
+ }, EDGE_PANEL.ANIMATION_DURATION);
185
+ } else {
186
+ // Add transform animation class
187
+ containerRef.current.classList.add('is-animating-out');
188
+
189
+ // Capture container for setTimeout
190
+ const container = containerRef.current;
191
+
192
+ setTimeout(() => {
193
+ if (container) {
194
+ container.classList.remove('is-animating-out');
195
+ }
196
+ }, EDGE_PANEL.ANIMATION_DURATION);
156
197
  }
157
- }, EDGE_PANEL.ANIMATION_DURATION);
158
- }
198
+ }
159
199
 
160
- // Then set transform
161
- containerRef.current.style.transform = position ? EDGE_PANEL.TRANSFORM_VALUES[position] : '';
200
+ // Set transform or opacity based on animation type
201
+ if (useFadeAnimation) {
202
+ containerRef.current.style.opacity = '0';
203
+ containerRef.current.style.transform = ''; // Remove transform for fade
204
+ } else {
205
+ // Then set transform
206
+ containerRef.current.style.transform = position
207
+ ? EDGE_PANEL.TRANSFORM_VALUES[position]
208
+ : '';
209
+ }
162
210
 
163
- // Reset body padding if push mode
164
- if (defaultProps.mode === 'push') {
165
- resetBodyPadding();
166
- }
211
+ // Reset body padding if push mode
212
+ if (defaultProps.mode === 'push') {
213
+ resetBodyPadding();
214
+ }
167
215
 
168
- // Wait for animation to complete before hiding
169
- const hideDelay = mode === 'none' ? 0 : EDGE_PANEL.ANIMATION_DURATION;
216
+ // Wait for animation to complete before hiding
217
+ const hideDelay = mode === 'none' ? 0 : EDGE_PANEL.ANIMATION_DURATION;
218
+
219
+ setTimeout(() => {
220
+ setIsOpen(false);
221
+ document.body.classList.remove('is-edgepanel-open');
170
222
 
171
- setTimeout(() => {
223
+ if (defaultProps.onOpenChange) {
224
+ defaultProps.onOpenChange(false);
225
+ }
226
+ }, hideDelay);
227
+ } else {
172
228
  setIsOpen(false);
173
229
  document.body.classList.remove('is-edgepanel-open');
174
230
 
175
231
  if (defaultProps.onOpenChange) {
176
232
  defaultProps.onOpenChange(false);
177
233
  }
178
- }, hideDelay);
179
- } else {
180
- setIsOpen(false);
181
- document.body.classList.remove('is-edgepanel-open');
182
-
183
- if (defaultProps.onOpenChange) {
184
- defaultProps.onOpenChange(false);
185
234
  }
186
- }
187
- }, [defaultProps, resetBodyPadding]);
235
+ },
236
+ [defaultProps, resetBodyPadding]
237
+ );
188
238
 
189
239
  /**
190
240
  * Handle Escape key press
@@ -232,9 +282,13 @@ export function useEdgePanel(initialProps?: Partial<EdgePanelProps>) {
232
282
 
233
283
  if (!isOpen && (mode === 'slide' || mode === 'push') && position) {
234
284
  containerRef.current.style.transform = EDGE_PANEL.TRANSFORM_VALUES[position];
285
+ // Set initial opacity for fade animations
286
+ if (defaultProps.glass) {
287
+ containerRef.current.style.opacity = '0';
288
+ }
235
289
  }
236
290
  }
237
- }, [defaultProps.mode, defaultProps.position, isOpen]);
291
+ }, [defaultProps.mode, defaultProps.position, defaultProps.glass, isOpen]);
238
292
 
239
293
  /**
240
294
  * Sync with prop changes
@@ -242,12 +296,12 @@ export function useEdgePanel(initialProps?: Partial<EdgePanelProps>) {
242
296
  useEffect(() => {
243
297
  if (defaultProps.isOpen !== undefined && defaultProps.isOpen !== isOpen) {
244
298
  if (defaultProps.isOpen) {
245
- openPanel();
299
+ openPanel(!!defaultProps.glass);
246
300
  } else {
247
- closePanel();
301
+ closePanel(!!defaultProps.glass);
248
302
  }
249
303
  }
250
- }, [defaultProps.isOpen, closePanel, isOpen, openPanel]);
304
+ }, [defaultProps.isOpen, closePanel, isOpen, openPanel, defaultProps.glass]);
251
305
 
252
306
  return {
253
307
  isOpen,
@@ -14,8 +14,6 @@ export interface UseFooterOptions {
14
14
  className?: string;
15
15
  }
16
16
 
17
-
18
-
19
17
  export function useFooter(options: UseFooterOptions = {}) {
20
18
  const {
21
19
  layout = FOOTER.DEFAULTS.LAYOUT,
@@ -38,6 +36,7 @@ export function useFooter(options: UseFooterOptions = {}) {
38
36
  `c-footer--${variant}`,
39
37
  FOOTER.CLASSES[size.toUpperCase() as keyof typeof FOOTER.CLASSES] || FOOTER.CLASSES.MD,
40
38
  sticky && FOOTER.CLASSES.STICKY,
39
+ showNewsletter && 'c-footer--with-newsletter',
41
40
  className,
42
41
  ];
43
42
  return classes.filter(Boolean).join(' ');
@@ -81,5 +80,6 @@ export function useFooter(options: UseFooterOptions = {}) {
81
80
  handleNewsletterSubmit,
82
81
  handleBackToTop,
83
82
  socialLinks,
83
+ showNewsletter,
84
84
  };
85
- }
85
+ }
@@ -18,7 +18,10 @@ export function useGlassContainer(props: GlassContainerProps) {
18
18
  const [isHovered, setIsHovered] = useState(false);
19
19
  const [isActive, setIsActive] = useState(false);
20
20
  const [currentGlassSize, setCurrentGlassSize] = useState(glassSize);
21
- const [internalGlobalMousePos, setInternalGlobalMousePos] = useState<MousePosition>({ x: 0, y: 0 });
21
+ const [internalGlobalMousePos, setInternalGlobalMousePos] = useState<MousePosition>({
22
+ x: 0,
23
+ y: 0,
24
+ });
22
25
  const [internalMouseOffset, setInternalMouseOffset] = useState<MousePosition>({ x: 0, y: 0 });
23
26
 
24
27
  // Use external mouse position if provided, otherwise use internal
@@ -29,7 +32,7 @@ export function useGlassContainer(props: GlassContainerProps) {
29
32
  const handleMouseMove = useCallback(
30
33
  (e: MouseEvent) => {
31
34
  const container = mouseContainer?.current || glassRef.current;
32
- if (!container) return;
35
+ if (!container) return undefined;
33
36
 
34
37
  const rect = container.getBoundingClientRect();
35
38
  const centerX = rect.left + rect.width / 2;
@@ -50,10 +53,10 @@ export function useGlassContainer(props: GlassContainerProps) {
50
53
 
51
54
  // Set up mouse tracking if no external mouse position is provided
52
55
  useEffect(() => {
53
- if (externalGlobalMousePos && externalMouseOffset) return;
56
+ if (externalGlobalMousePos && externalMouseOffset) return undefined;
54
57
 
55
58
  const container = mouseContainer?.current || glassRef.current;
56
- if (!container) return;
59
+ if (!container) return undefined;
57
60
 
58
61
  container.addEventListener('mousemove', handleMouseMove);
59
62
  return () => container.removeEventListener('mousemove', handleMouseMove);
@@ -89,8 +92,14 @@ export function useGlassContainer(props: GlassContainerProps) {
89
92
  const normalizedY = deltaY / centerDistance;
90
93
  const stretchIntensity = Math.min(centerDistance / 300, 1) * elasticity * fadeInFactor;
91
94
 
92
- const scaleX = 1 + Math.abs(normalizedX) * stretchIntensity * 0.3 - Math.abs(normalizedY) * stretchIntensity * 0.15;
93
- const scaleY = 1 + Math.abs(normalizedY) * stretchIntensity * 0.3 - Math.abs(normalizedX) * stretchIntensity * 0.15;
95
+ const scaleX =
96
+ 1 +
97
+ Math.abs(normalizedX) * stretchIntensity * 0.3 -
98
+ Math.abs(normalizedY) * stretchIntensity * 0.15;
99
+ const scaleY =
100
+ 1 +
101
+ Math.abs(normalizedY) * stretchIntensity * 0.3 -
102
+ Math.abs(normalizedX) * stretchIntensity * 0.15;
94
103
 
95
104
  return `scaleX(${Math.max(0.8, scaleX)}) scaleY(${Math.max(0.8, scaleY)})`;
96
105
  }, [globalMousePos, elasticity, currentGlassSize]);
@@ -165,4 +174,4 @@ export function useGlassContainer(props: GlassContainerProps) {
165
174
  };
166
175
  }
167
176
 
168
- export default useGlassContainer;
177
+ export default useGlassContainer;
@@ -122,6 +122,8 @@ export function useLineChart(datasets: ChartDataset[], options: LineChartOptions
122
122
  pointIndex: number;
123
123
  x: number;
124
124
  y: number;
125
+ clientX?: number;
126
+ clientY?: number;
125
127
  } | null>(null);
126
128
 
127
129
  // Calculate moving averages
@@ -251,8 +253,15 @@ export function useLineChart(datasets: ChartDataset[], options: LineChartOptions
251
253
 
252
254
  // Point hover handlers
253
255
  const handlePointHover = useCallback(
254
- (datasetIndex: number, pointIndex: number, x: number, y: number) => {
255
- setHoveredPoint({ datasetIndex, pointIndex, x, y });
256
+ (
257
+ datasetIndex: number,
258
+ pointIndex: number,
259
+ x: number,
260
+ y: number,
261
+ clientX: number,
262
+ clientY: number
263
+ ) => {
264
+ setHoveredPoint({ datasetIndex, pointIndex, x, y, clientX, clientY });
256
265
  },
257
266
  []
258
267
  );
@@ -245,20 +245,10 @@ export function usePieChart(data: ChartDataPoint[], options: PieChartOptions = {
245
245
  requestAnimationFrame(animate);
246
246
  }, [options.enableAnimations, options.animationDuration]);
247
247
 
248
- // Slice interaction handlers
249
- const handleSliceHover = useCallback(
250
- (index: number, clientX?: number, clientY?: number) => {
251
- if (!options.enableHoverEffects) return;
252
- setHoveredSlice(index);
253
-
254
- // Store client coordinates for tooltip positioning
255
- if (clientX !== undefined && clientY !== undefined && slices[index]) {
256
- slices[index].clientX = clientX;
257
- slices[index].clientY = clientY;
258
- }
259
- },
260
- [options.enableHoverEffects, slices]
261
- );
248
+ // Slice hover handlers
249
+ const handleSliceHover = useCallback((index: number, clientX: number, clientY: number) => {
250
+ setHoveredSlice(index);
251
+ }, []);
262
252
 
263
253
  const handleSliceLeave = useCallback(() => {
264
254
  setHoveredSlice(null);
@@ -70,6 +70,11 @@ export interface RiverProps {
70
70
  */
71
71
  className?: string;
72
72
 
73
+ /**
74
+ * Inline style for the component
75
+ */
76
+ style?: React.CSSProperties;
77
+
73
78
  /**
74
79
  * Background image source
75
80
  */