@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
@@ -273,14 +273,21 @@ export function useBarChart(datasets: ChartDataset[], options: BarChartOptions =
273
273
 
274
274
  // Bar hover handlers
275
275
  const handleBarHover = useCallback(
276
- (datasetIndex: number, pointIndex: number, chartX: number, chartY: number, clientX: number, clientY: number) => {
277
- setHoveredBar({
278
- datasetIndex,
279
- pointIndex,
280
- chartX,
276
+ (
277
+ datasetIndex: number,
278
+ pointIndex: number,
279
+ chartX: number,
280
+ chartY: number,
281
+ clientX: number,
282
+ clientY: number
283
+ ) => {
284
+ setHoveredBar({
285
+ datasetIndex,
286
+ pointIndex,
287
+ chartX,
281
288
  chartY,
282
289
  clientX,
283
- clientY
290
+ clientY,
284
291
  });
285
292
  },
286
293
  []
@@ -286,14 +286,20 @@ export function useChart(initialProps?: Partial<ChartProps>) {
286
286
  const rect = (event.target as Element).getBoundingClientRect();
287
287
 
288
288
  // Single touch - pan (only if pan is enabled)
289
- if (touches.length === 1 && touches[0] && prev.isDragging && prev.dragStart && prev.panEnabled) {
289
+ if (
290
+ touches.length === 1 &&
291
+ touches[0] &&
292
+ prev.isDragging &&
293
+ prev.dragStart &&
294
+ prev.panEnabled
295
+ ) {
290
296
  const x = touches[0].x - rect.left;
291
297
  const y = touches[0].y - rect.top;
292
-
298
+
293
299
  // Use previous touch position for delta calculation if available
294
300
  const prevTouch = prev.touchState.touches[0];
295
301
  let deltaX, deltaY;
296
-
302
+
297
303
  if (prevTouch) {
298
304
  // Calculate delta from previous touch position
299
305
  const prevX = prevTouch.x - rect.left;
@@ -325,7 +331,7 @@ export function useChart(initialProps?: Partial<ChartProps>) {
325
331
  },
326
332
  };
327
333
  }
328
-
334
+
329
335
  // Update touch state even if no panning occurred
330
336
  return {
331
337
  ...prev,
@@ -511,11 +517,11 @@ export function useChart(initialProps?: Partial<ChartProps>) {
511
517
  datasets: ChartDataset[],
512
518
  width: number = CHART.DEFAULT_WIDTH,
513
519
  height: number = CHART.DEFAULT_HEIGHT,
514
- padding: { top: number; right: number; bottom: number; left: number } = {
515
- top: 20,
516
- right: 20,
517
- bottom: 30,
518
- left: 40
520
+ padding: { top: number; right: number; bottom: number; left: number } = {
521
+ top: 20,
522
+ right: 20,
523
+ bottom: 30,
524
+ left: 40,
519
525
  },
520
526
  config?: ChartProps['config']
521
527
  ): ChartScales | null => {
@@ -541,9 +547,7 @@ export function useChart(initialProps?: Partial<ChartProps>) {
541
547
 
542
548
  const yScale = (value: number) => {
543
549
  // Invert Y axis (SVG coordinates start from top)
544
- return (
545
- padding.top + innerHeight - ((value - minValue) / valueRange) * innerHeight
546
- );
550
+ return padding.top + innerHeight - ((value - minValue) / valueRange) * innerHeight;
547
551
  };
548
552
 
549
553
  return {
@@ -876,7 +880,7 @@ export function useChartPerformance(
876
880
  return datasets.map(dataset => {
877
881
  const values = dataset.data?.map(d => d.value).filter(v => typeof v === 'number') || [];
878
882
  const validValues = values.length > 0 ? values : [0];
879
-
883
+
880
884
  return {
881
885
  label: dataset.label,
882
886
  dataLength: dataset.data?.length || 0,
@@ -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
+ }
@@ -138,7 +138,6 @@ export function useChartToolbar(
138
138
  grid: false,
139
139
  };
140
140
 
141
-
142
141
  default:
143
142
  return baseDefaults;
144
143
  }
@@ -98,135 +98,143 @@ export function useEdgePanel(initialProps?: Partial<EdgePanelProps>) {
98
98
  /**
99
99
  * Open the panel
100
100
  */
101
- const openPanel = useCallback((useFadeAnimation = false) => {
102
- setIsOpen(true);
103
- document.body.classList.add('is-edgepanel-open');
104
-
105
- if (containerRef.current) {
106
- const { mode } = defaultProps;
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);
139
+ }
140
+ }
107
141
 
108
- // Only add animation if not in 'none' mode
109
- if (mode !== 'none') {
142
+ // Set transform or opacity based on animation type
110
143
  if (useFadeAnimation) {
111
- // Add fade animation class
112
- containerRef.current.classList.add('is-fade-animating');
113
-
114
- // Force a reflow before starting the animation
115
- void containerRef.current.offsetHeight;
116
-
117
- // Remove animation class after animation completes
118
- const container = containerRef.current;
119
- setTimeout(() => {
120
- if (container) {
121
- container.classList.remove('is-fade-animating');
122
- }
123
- }, EDGE_PANEL.ANIMATION_DURATION);
144
+ containerRef.current.style.opacity = '1';
145
+ containerRef.current.style.transform = ''; // Remove transform for fade
124
146
  } else {
125
- // Add transform animation class
126
- containerRef.current.classList.add('is-animating');
127
-
128
- // Force a reflow before starting the animation
129
- void containerRef.current.offsetHeight;
130
-
131
- // Remove animation class after animation completes
132
- const container = containerRef.current;
133
- setTimeout(() => {
134
- if (container) {
135
- container.classList.remove('is-animating');
136
- }
137
- }, EDGE_PANEL.ANIMATION_DURATION);
147
+ containerRef.current.style.transform = 'translate(0)';
138
148
  }
139
- }
140
149
 
141
- // Set transform or opacity based on animation type
142
- if (useFadeAnimation) {
143
- containerRef.current.style.opacity = '1';
144
- containerRef.current.style.transform = ''; // Remove transform for fade
145
- } else {
146
- containerRef.current.style.transform = 'translate(0)';
150
+ // If push mode, adjust body padding
151
+ if (defaultProps.mode === 'push') {
152
+ adjustBodyPadding();
153
+ }
147
154
  }
148
155
 
149
- // If push mode, adjust body padding
150
- if (defaultProps.mode === 'push') {
151
- adjustBodyPadding();
156
+ if (defaultProps.onOpenChange) {
157
+ defaultProps.onOpenChange(true);
152
158
  }
153
- }
154
-
155
- if (defaultProps.onOpenChange) {
156
- defaultProps.onOpenChange(true);
157
- }
158
- }, [defaultProps, adjustBodyPadding]);
159
+ },
160
+ [defaultProps, adjustBodyPadding]
161
+ );
159
162
 
160
163
  /**
161
164
  * Close the panel
162
165
  */
163
- const closePanel = useCallback((useFadeAnimation = false) => {
164
- if (containerRef.current) {
165
- const { position, mode } = defaultProps;
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);
197
+ }
198
+ }
166
199
 
167
- // Only add animation if not in 'none' mode
168
- if (mode !== 'none') {
200
+ // Set transform or opacity based on animation type
169
201
  if (useFadeAnimation) {
170
- // Add fade out animation class
171
- containerRef.current.classList.add('is-fade-animating-out');
172
-
173
- // Capture container for setTimeout
174
- const container = containerRef.current;
175
-
176
- setTimeout(() => {
177
- if (container) {
178
- container.classList.remove('is-fade-animating-out');
179
- }
180
- }, EDGE_PANEL.ANIMATION_DURATION);
202
+ containerRef.current.style.opacity = '0';
203
+ containerRef.current.style.transform = ''; // Remove transform for fade
181
204
  } else {
182
- // Add transform animation class
183
- containerRef.current.classList.add('is-animating-out');
184
-
185
- // Capture container for setTimeout
186
- const container = containerRef.current;
205
+ // Then set transform
206
+ containerRef.current.style.transform = position
207
+ ? EDGE_PANEL.TRANSFORM_VALUES[position]
208
+ : '';
209
+ }
187
210
 
188
- setTimeout(() => {
189
- if (container) {
190
- container.classList.remove('is-animating-out');
191
- }
192
- }, EDGE_PANEL.ANIMATION_DURATION);
211
+ // Reset body padding if push mode
212
+ if (defaultProps.mode === 'push') {
213
+ resetBodyPadding();
193
214
  }
194
- }
195
215
 
196
- // Set transform or opacity based on animation type
197
- if (useFadeAnimation) {
198
- containerRef.current.style.opacity = '0';
199
- containerRef.current.style.transform = ''; // Remove transform for fade
200
- } else {
201
- // Then set transform
202
- containerRef.current.style.transform = position ? EDGE_PANEL.TRANSFORM_VALUES[position] : '';
203
- }
216
+ // Wait for animation to complete before hiding
217
+ const hideDelay = mode === 'none' ? 0 : EDGE_PANEL.ANIMATION_DURATION;
204
218
 
205
- // Reset body padding if push mode
206
- if (defaultProps.mode === 'push') {
207
- resetBodyPadding();
208
- }
219
+ setTimeout(() => {
220
+ setIsOpen(false);
221
+ document.body.classList.remove('is-edgepanel-open');
209
222
 
210
- // Wait for animation to complete before hiding
211
- const hideDelay = mode === 'none' ? 0 : EDGE_PANEL.ANIMATION_DURATION;
212
-
213
- setTimeout(() => {
223
+ if (defaultProps.onOpenChange) {
224
+ defaultProps.onOpenChange(false);
225
+ }
226
+ }, hideDelay);
227
+ } else {
214
228
  setIsOpen(false);
215
229
  document.body.classList.remove('is-edgepanel-open');
216
230
 
217
231
  if (defaultProps.onOpenChange) {
218
232
  defaultProps.onOpenChange(false);
219
233
  }
220
- }, hideDelay);
221
- } else {
222
- setIsOpen(false);
223
- document.body.classList.remove('is-edgepanel-open');
224
-
225
- if (defaultProps.onOpenChange) {
226
- defaultProps.onOpenChange(false);
227
234
  }
228
- }
229
- }, [defaultProps, resetBodyPadding]);
235
+ },
236
+ [defaultProps, resetBodyPadding]
237
+ );
230
238
 
231
239
  /**
232
240
  * Handle Escape key press
@@ -304,4 +312,4 @@ export function useEdgePanel(initialProps?: Partial<EdgePanelProps>) {
304
312
  closePanel,
305
313
  handleBackdropClick,
306
314
  };
307
- }
315
+ }
@@ -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;
@@ -253,7 +253,14 @@ export function useLineChart(datasets: ChartDataset[], options: LineChartOptions
253
253
 
254
254
  // Point hover handlers
255
255
  const handlePointHover = useCallback(
256
- (datasetIndex: number, pointIndex: number, x: number, y: number, clientX: number, clientY: number) => {
256
+ (
257
+ datasetIndex: number,
258
+ pointIndex: number,
259
+ x: number,
260
+ y: number,
261
+ clientX: number,
262
+ clientY: number
263
+ ) => {
257
264
  setHoveredPoint({ datasetIndex, pointIndex, x, y, clientX, clientY });
258
265
  },
259
266
  []
@@ -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
  */