@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.
- package/README.md +19 -0
- package/dist/atomix.css +1266 -1412
- package/dist/atomix.min.css +3 -3
- package/dist/index.d.ts +1232 -876
- package/dist/index.esm.js +16212 -26364
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +15652 -22298
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/themes/applemix.css +15008 -0
- package/dist/themes/applemix.min.css +72 -0
- package/dist/themes/boomdevs.css +1266 -1413
- package/dist/themes/boomdevs.min.css +3 -3
- package/dist/themes/esrar.css +1267 -1413
- package/dist/themes/esrar.min.css +3 -3
- package/dist/themes/flashtrade.css +15159 -0
- package/dist/themes/flashtrade.min.css +86 -0
- package/dist/themes/mashroom.css +1264 -1410
- package/dist/themes/mashroom.min.css +5 -5
- package/dist/themes/shaj-default.css +1266 -1412
- package/dist/themes/shaj-default.min.css +3 -3
- package/package.json +6 -17
- package/src/components/Accordion/Accordion.stories.tsx +4 -26
- package/src/components/Accordion/Accordion.tsx +21 -12
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +106 -72
- package/src/components/AtomixGlass/AtomixGlass.tsx +487 -1215
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +400 -0
- package/src/components/AtomixGlass/GlassFilter.tsx +156 -0
- package/src/components/AtomixGlass/README.md +124 -2
- package/src/components/AtomixGlass/atomixGLass.old.tsx +1266 -0
- package/src/components/AtomixGlass/glass-utils.ts +263 -0
- package/src/components/AtomixGlass/shader-utils.ts +404 -236
- package/src/components/AtomixGlass/{AtomixGlass.stories.tsx → stories/AtomixGlass.stories.tsx} +55 -35
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +57 -89
- package/src/components/AtomixGlass/stories/Modes.stories.tsx +149 -149
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +95 -32
- package/src/components/AtomixGlass/stories/ShaderVariants.stories.tsx +0 -2
- package/src/components/AtomixGlass/stories/shared-components.tsx +9 -18
- package/src/components/AtomixGlass/utils.ts +3 -3
- package/src/components/Avatar/Avatar.tsx +3 -0
- package/src/components/Avatar/AvatarGroup.tsx +2 -1
- package/src/components/Badge/Badge.stories.tsx +74 -54
- package/src/components/Badge/Badge.tsx +8 -12
- package/src/components/Breadcrumb/Breadcrumb.tsx +23 -4
- package/src/components/Button/Button.tsx +3 -5
- package/src/components/Callout/Callout.stories.tsx +86 -35
- package/src/components/Callout/Callout.tsx +4 -0
- package/src/components/Card/Card.stories.tsx +89 -85
- package/src/components/Card/Card.tsx +15 -4
- package/src/components/Card/ElevationCard.tsx +2 -0
- package/src/components/Chart/AnimatedChart.tsx +179 -156
- package/src/components/Chart/AreaChart.tsx +123 -12
- package/src/components/Chart/BarChart.tsx +91 -100
- package/src/components/Chart/BaseChart.tsx +80 -0
- package/src/components/Chart/BubbleChart.tsx +114 -290
- package/src/components/Chart/CandlestickChart.tsx +282 -622
- package/src/components/Chart/Chart.stories.tsx +576 -179
- package/src/components/Chart/Chart.tsx +374 -75
- package/src/components/Chart/ChartRenderer.tsx +371 -220
- package/src/components/Chart/ChartToolbar.tsx +372 -61
- package/src/components/Chart/ChartTooltip.tsx +33 -18
- package/src/components/Chart/DonutChart.tsx +172 -254
- package/src/components/Chart/FunnelChart.tsx +169 -240
- package/src/components/Chart/GaugeChart.tsx +224 -392
- package/src/components/Chart/HeatmapChart.tsx +302 -440
- package/src/components/Chart/LineChart.tsx +148 -103
- package/src/components/Chart/MultiAxisChart.tsx +267 -395
- package/src/components/Chart/PieChart.tsx +114 -64
- package/src/components/Chart/RadarChart.tsx +202 -218
- package/src/components/Chart/ScatterChart.tsx +111 -97
- package/src/components/Chart/TreemapChart.tsx +147 -222
- package/src/components/Chart/WaterfallChart.tsx +253 -291
- package/src/components/Chart/index.ts +11 -9
- package/src/components/Chart/types.ts +85 -9
- package/src/components/Chart/utils.ts +66 -0
- package/src/components/ColorModeToggle/ColorModeToggle.tsx +6 -3
- package/src/components/Countdown/Countdown.tsx +4 -0
- package/src/components/DataTable/DataTable.tsx +2 -1
- package/src/components/DatePicker/DatePicker.stories.tsx +0 -11
- package/src/components/DatePicker/DatePicker.tsx +3 -9
- package/src/components/DatePicker/types.ts +5 -0
- package/src/components/Dropdown/Dropdown.stories.tsx +32 -25
- package/src/components/Dropdown/Dropdown.tsx +26 -28
- package/src/components/EdgePanel/EdgePanel.stories.tsx +13 -15
- package/src/components/EdgePanel/EdgePanel.tsx +20 -5
- package/src/components/Footer/Footer.stories.tsx +187 -60
- package/src/components/Footer/Footer.test.tsx +134 -0
- package/src/components/Footer/Footer.tsx +133 -34
- package/src/components/Footer/FooterLink.tsx +1 -1
- package/src/components/Footer/FooterSection.tsx +53 -36
- package/src/components/Footer/FooterSocialLink.tsx +32 -29
- package/src/components/Footer/README.md +82 -3
- package/src/components/Footer/index.ts +1 -1
- package/src/components/Form/Checkbox.stories.tsx +13 -5
- package/src/components/Form/Checkbox.tsx +3 -6
- package/src/components/Form/Form.stories.tsx +10 -3
- package/src/components/Form/Form.tsx +2 -0
- package/src/components/Form/FormGroup.tsx +2 -1
- package/src/components/Form/Input.stories.tsx +12 -11
- package/src/components/Form/Input.tsx +97 -95
- package/src/components/Form/Radio.stories.tsx +22 -7
- package/src/components/Form/Radio.tsx +3 -6
- package/src/components/Form/Select.stories.tsx +21 -6
- package/src/components/Form/Select.tsx +3 -5
- package/src/components/Form/Textarea.stories.tsx +13 -11
- package/src/components/Form/Textarea.tsx +88 -86
- package/src/components/Hero/Hero.stories.tsx +2 -3
- package/src/components/Hero/Hero.tsx +5 -6
- package/src/components/Icon/Icon.tsx +12 -1
- package/src/components/List/List.tsx +2 -1
- package/src/components/List/ListGroup.tsx +2 -1
- package/src/components/Messages/Messages.tsx +3 -2
- package/src/components/Modal/Modal.stories.tsx +48 -34
- package/src/components/Modal/Modal.tsx +19 -23
- package/src/components/Navigation/Menu/MegaMenu.tsx +2 -2
- package/src/components/Navigation/Menu/Menu.tsx +2 -2
- package/src/components/Navigation/Nav/Nav.tsx +6 -1
- package/src/components/Navigation/Nav/NavDropdown.tsx +10 -1
- package/src/components/Navigation/Navbar/Navbar.tsx +4 -1
- package/src/components/Navigation/SideMenu/SideMenu.tsx +3 -2
- package/src/components/Pagination/Pagination.stories.tsx +13 -6
- package/src/components/Pagination/Pagination.tsx +7 -6
- package/src/components/PhotoViewer/PhotoViewer.tsx +2 -1
- package/src/components/Popover/Popover.stories.tsx +32 -24
- package/src/components/Popover/Popover.tsx +4 -1
- package/src/components/ProductReview/ProductReview.tsx +8 -2
- package/src/components/Progress/Progress.tsx +2 -1
- package/src/components/Rating/Rating.stories.tsx +11 -6
- package/src/components/Rating/Rating.tsx +3 -5
- package/src/components/River/River.tsx +5 -5
- package/src/components/SectionIntro/SectionIntro.tsx +8 -2
- package/src/components/Slider/Slider.stories.tsx +4 -4
- package/src/components/Slider/Slider.tsx +4 -3
- package/src/components/Spinner/Spinner.tsx +2 -1
- package/src/components/Steps/Steps.stories.tsx +5 -4
- package/src/components/Steps/Steps.tsx +8 -5
- package/src/components/Tab/Tab.stories.tsx +4 -3
- package/src/components/Tab/Tab.tsx +8 -6
- package/src/components/Testimonial/Testimonial.tsx +8 -2
- package/src/components/Todo/Todo.tsx +2 -1
- package/src/components/Toggle/Toggle.stories.tsx +5 -4
- package/src/components/Toggle/Toggle.tsx +8 -5
- package/src/components/Tooltip/Tooltip.stories.tsx +40 -30
- package/src/components/Tooltip/Tooltip.tsx +9 -2
- package/src/components/Upload/Upload.stories.tsx +252 -0
- package/src/components/Upload/Upload.tsx +92 -53
- package/src/components/VideoPlayer/VideoPlayer.tsx +3 -1
- package/src/components/index.ts +0 -4
- package/src/layouts/Grid/Grid.stories.tsx +10 -23
- package/src/layouts/Grid/Grid.tsx +20 -1
- package/src/layouts/Grid/GridCol.tsx +76 -48
- package/src/lib/composables/useAtomixGlass.ts +861 -44
- package/src/lib/composables/useBarChart.ts +13 -6
- package/src/lib/composables/useChart.ts +17 -13
- package/src/lib/composables/useChartExport.ts +19 -78
- package/src/lib/composables/useChartToolbar.ts +0 -1
- package/src/lib/composables/useEdgePanel.ts +111 -103
- package/src/lib/composables/useFooter.ts +3 -3
- package/src/lib/composables/useGlassContainer.ts +16 -7
- package/src/lib/composables/useLineChart.ts +8 -1
- package/src/lib/composables/useRiver.ts +5 -0
- package/src/lib/composables/useSlider.ts +62 -24
- package/src/lib/composables/useVideoPlayer.ts +60 -63
- package/src/lib/constants/components.ts +146 -32
- package/src/lib/types/components.ts +258 -10
- package/src/lib/utils/displacement-generator.ts +55 -49
- package/src/lib/utils/icons.ts +1 -1
- package/src/lib/utils/index.ts +16 -10
- package/src/styles/01-settings/_settings.accordion.scss +19 -19
- package/src/styles/01-settings/_settings.animations.scss +5 -5
- package/src/styles/01-settings/_settings.avatar-group.scss +1 -1
- package/src/styles/01-settings/_settings.avatar.scss +17 -17
- package/src/styles/01-settings/_settings.background.scss +1 -4
- package/src/styles/01-settings/_settings.badge.scss +1 -1
- package/src/styles/01-settings/_settings.breadcrumb.scss +1 -1
- package/src/styles/01-settings/_settings.card.scss +1 -1
- package/src/styles/01-settings/_settings.chart.scss +65 -2
- package/src/styles/01-settings/_settings.dropdown.scss +1 -1
- package/src/styles/01-settings/_settings.footer.scss +35 -42
- package/src/styles/01-settings/_settings.input.scss +1 -1
- package/src/styles/01-settings/_settings.list.scss +1 -1
- package/src/styles/01-settings/_settings.rating.scss +1 -1
- package/src/styles/01-settings/_settings.tabs.scss +1 -1
- package/src/styles/01-settings/_settings.upload.scss +6 -5
- package/src/styles/02-tools/_tools.animations.scss +4 -5
- package/src/styles/02-tools/_tools.background.scss +1 -13
- package/src/styles/02-tools/_tools.glass.scss +0 -1
- package/src/styles/02-tools/_tools.utility-api.scss +42 -34
- package/src/styles/03-generic/_generic.root.scss +1 -4
- package/src/styles/04-elements/_elements.body.scss +0 -1
- package/src/styles/06-components/_components.atomix-glass.scss +216 -39
- package/src/styles/06-components/_components.badge.scss +6 -8
- package/src/styles/06-components/_components.button.scss +8 -3
- package/src/styles/06-components/_components.card.scss +2 -14
- package/src/styles/06-components/_components.chart.scss +969 -1449
- package/src/styles/06-components/_components.dropdown.scss +19 -7
- package/src/styles/06-components/_components.edge-panel.scss +4 -2
- package/src/styles/06-components/_components.footer.scss +166 -85
- package/src/styles/06-components/_components.input.scss +8 -9
- package/src/styles/06-components/_components.list.scss +1 -0
- package/src/styles/06-components/_components.modal.scss +5 -3
- package/src/styles/06-components/_components.skeleton.scss +8 -6
- package/src/styles/06-components/_components.upload.scss +219 -4
- package/src/styles/06-components/old.chart.styles.scss +1 -30
- package/src/styles/99-utilities/_utilities.opacity.scss +1 -1
- package/src/styles/99-utilities/_utilities.scss +1 -1
- package/src/components/Chart/AdvancedChart.tsx +0 -624
- package/src/components/Chart/LineChartNew.tsx +0 -167
- package/src/components/Chart/RealTimeChart.tsx +0 -436
- 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
|
-
(
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
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 (
|
|
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 =>
|
|
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(
|
|
306
|
+
`mailto:?subject=${encodeURIComponent(message)}&body=${encodeURIComponent(`${message} ${url}`)}`,
|
|
301
307
|
'_blank'
|
|
302
308
|
);
|
|
303
309
|
break;
|
|
304
310
|
case 'copy-link':
|
|
305
|
-
|
|
311
|
+
if (navigator.clipboard) {
|
|
306
312
|
await navigator.clipboard.writeText(url);
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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
|
+
}
|
|
@@ -98,135 +98,143 @@ export function useEdgePanel(initialProps?: Partial<EdgePanelProps>) {
|
|
|
98
98
|
/**
|
|
99
99
|
* Open the panel
|
|
100
100
|
*/
|
|
101
|
-
const openPanel = useCallback(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
|
|
109
|
-
if (mode !== 'none') {
|
|
142
|
+
// Set transform or opacity based on animation type
|
|
110
143
|
if (useFadeAnimation) {
|
|
111
|
-
|
|
112
|
-
containerRef.current.
|
|
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
|
-
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
-
|
|
150
|
-
|
|
151
|
-
adjustBodyPadding();
|
|
156
|
+
if (defaultProps.onOpenChange) {
|
|
157
|
+
defaultProps.onOpenChange(true);
|
|
152
158
|
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
|
|
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(
|
|
164
|
-
|
|
165
|
-
|
|
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
|
-
|
|
168
|
-
if (mode !== 'none') {
|
|
200
|
+
// Set transform or opacity based on animation type
|
|
169
201
|
if (useFadeAnimation) {
|
|
170
|
-
|
|
171
|
-
containerRef.current.
|
|
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
|
-
//
|
|
183
|
-
containerRef.current.
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
205
|
+
// Then set transform
|
|
206
|
+
containerRef.current.style.transform = position
|
|
207
|
+
? EDGE_PANEL.TRANSFORM_VALUES[position]
|
|
208
|
+
: '';
|
|
209
|
+
}
|
|
187
210
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
-
|
|
197
|
-
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
219
|
+
setTimeout(() => {
|
|
220
|
+
setIsOpen(false);
|
|
221
|
+
document.body.classList.remove('is-edgepanel-open');
|
|
209
222
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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
|
-
|
|
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>({
|
|
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 =
|
|
93
|
-
|
|
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
|
-
(
|
|
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
|
[]
|