@shohojdhara/atomix 0.5.1 → 0.5.4
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/atomix.config.ts +45 -33
- package/build-tools/webpack-loader.js +5 -4
- package/dist/atomix.css +138 -17
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/build-tools/webpack-loader.js +5 -4
- package/dist/charts.d.ts +23 -23
- package/dist/charts.js +40 -37
- package/dist/charts.js.map +1 -1
- package/dist/config.d.ts +699 -0
- package/dist/config.js +17 -0
- package/dist/config.js.map +1 -0
- package/dist/core.d.ts +2 -2
- package/dist/core.js +111 -50
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +3 -6
- package/dist/forms.js +2 -2
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +1 -1
- package/dist/heavy.js +173 -111
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +1881 -790
- package/dist/index.esm.js +2713 -816
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +2693 -780
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/layout.js +59 -60
- package/dist/layout.js.map +1 -1
- package/dist/theme.d.ts +1390 -276
- package/dist/theme.js +2133 -625
- package/dist/theme.js.map +1 -1
- package/package.json +14 -9
- package/scripts/atomix-cli.js +15 -1
- package/scripts/cli/__tests__/complexity-utils.test.js +24 -0
- package/scripts/cli/__tests__/detector.test.js +50 -0
- package/scripts/cli/__tests__/template-engine.test.js +23 -0
- package/scripts/cli/__tests__/test-setup.js +3 -0
- package/scripts/cli/commands/doctor.js +15 -3
- package/scripts/cli/commands/generate.js +113 -51
- package/scripts/cli/internal/ai-engine.js +30 -10
- package/scripts/cli/internal/complexity-utils.js +60 -0
- package/scripts/cli/internal/component-validator.js +49 -16
- package/scripts/cli/internal/config-loader.js +30 -20
- package/scripts/cli/internal/generator.js +89 -36
- package/scripts/cli/internal/hook-generator.js +5 -2
- package/scripts/cli/internal/itcss-generator.js +16 -12
- package/scripts/cli/templates/next-templates.js +81 -30
- package/scripts/cli/templates/storybook-templates.js +12 -2
- package/scripts/cli/utils/detector.js +45 -7
- package/scripts/cli/utils/diagnostics.js +78 -0
- package/scripts/cli/utils/telemetry.js +13 -0
- package/src/components/Accordion/Accordion.stories.tsx +4 -0
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +1 -1
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +219 -0
- package/src/components/AtomixGlass/glass-utils.ts +1 -1
- package/src/components/Button/Button.tsx +114 -57
- package/src/components/Callout/Callout.tsx +4 -4
- package/src/components/Chart/ChartRenderer.tsx +1 -1
- package/src/components/Chart/DonutChart.tsx +11 -8
- package/src/components/EdgePanel/EdgePanel.tsx +119 -115
- package/src/components/Form/Select.tsx +4 -4
- package/src/components/List/List.tsx +4 -4
- package/src/components/Navigation/SideMenu/SideMenu.tsx +6 -6
- package/src/components/PhotoViewer/PhotoViewerImage.tsx +1 -1
- package/src/components/ProductReview/ProductReview.tsx +4 -2
- package/src/components/Rating/Rating.tsx +4 -2
- package/src/components/SectionIntro/SectionIntro.tsx +4 -2
- package/src/components/Steps/Steps.tsx +1 -1
- package/src/components/Tabs/Tabs.tsx +5 -5
- package/src/components/Testimonial/Testimonial.tsx +4 -2
- package/src/components/VideoPlayer/VideoPlayer.tsx +4 -2
- package/src/layouts/CssGrid/CssGrid.stories.tsx +464 -0
- package/src/layouts/CssGrid/CssGrid.tsx +215 -0
- package/src/layouts/CssGrid/index.ts +8 -0
- package/src/layouts/CssGrid/scripts/CssGrid.js +284 -0
- package/src/layouts/CssGrid/scripts/index.js +43 -0
- package/src/layouts/Grid/scripts/Container.js +139 -0
- package/src/layouts/Grid/scripts/Grid.js +184 -0
- package/src/layouts/Grid/scripts/GridCol.js +273 -0
- package/src/layouts/Grid/scripts/Row.js +154 -0
- package/src/layouts/Grid/scripts/index.js +48 -0
- package/src/layouts/MasonryGrid/MasonryGrid.tsx +71 -59
- package/src/lib/composables/atomix-glass/useGlassSize.ts +1 -1
- package/src/lib/composables/useAccordion.ts +5 -5
- package/src/lib/composables/useAtomixGlass.ts +3 -3
- package/src/lib/composables/useBarChart.ts +2 -2
- package/src/lib/composables/useChart.ts +3 -2
- package/src/lib/composables/useChartToolbar.ts +48 -66
- package/src/lib/composables/useDataTable.ts +1 -1
- package/src/lib/composables/useDatePicker.ts +2 -2
- package/src/lib/composables/useEdgePanel.ts +45 -54
- package/src/lib/composables/useHeroBackgroundSlider.ts +5 -5
- package/src/lib/composables/usePhotoViewer.ts +2 -3
- package/src/lib/composables/usePieChart.ts +1 -1
- package/src/lib/composables/usePopover.ts +151 -139
- package/src/lib/composables/useSideMenu.ts +28 -41
- package/src/lib/composables/useSlider.ts +2 -6
- package/src/lib/composables/useTooltip.ts +2 -2
- package/src/lib/config/index.ts +38 -323
- package/src/lib/config/loader.ts +419 -0
- package/src/lib/config/public-api.ts +43 -0
- package/src/lib/config/types.ts +389 -0
- package/src/lib/config/validator.ts +305 -0
- package/src/lib/theme/adapters/index.ts +1 -1
- package/src/lib/theme/adapters/themeAdapter.ts +358 -229
- package/src/lib/theme/components/ThemeToggle.tsx +276 -0
- package/src/lib/theme/config/configLoader.ts +351 -0
- package/src/lib/theme/config/loader.ts +221 -0
- package/src/lib/theme/core/createTheme.ts +126 -50
- package/src/lib/theme/core/createThemeObject.ts +7 -4
- package/src/lib/theme/devtools/Comparator.tsx +1 -1
- package/src/lib/theme/devtools/Inspector.tsx +1 -1
- package/src/lib/theme/devtools/LiveEditor.tsx +1 -1
- package/src/lib/theme/hooks/useThemeSwitcher.ts +164 -0
- package/src/lib/theme/index.ts +322 -38
- package/src/lib/theme/runtime/ThemeProvider.tsx +45 -11
- package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +44 -393
- package/src/lib/theme/runtime/useTheme.ts +1 -0
- package/src/lib/theme/tokens/tokens.ts +101 -1
- package/src/lib/theme/types.ts +91 -0
- package/src/lib/theme/utils/performanceMonitor.ts +315 -0
- package/src/lib/theme/utils/responsive.ts +280 -0
- package/src/lib/theme/utils/themeUtils.ts +531 -117
- package/src/styles/01-settings/_index.scss +1 -0
- package/src/styles/01-settings/_settings.atomix-glass.scss +174 -0
- package/src/styles/01-settings/_settings.masonry-grid.scss +42 -6
- package/src/styles/02-tools/_tools.glass.scss +6 -0
- package/src/styles/05-objects/_objects.masonry-grid.scss +162 -24
- package/src/styles/06-components/_components.atomix-glass.scss +4 -4
- package/src/lib/composables/useBreadcrumb.ts +0 -81
- package/src/lib/composables/useChartInteractions.ts +0 -123
- package/src/lib/composables/useChartPerformance.ts +0 -347
- package/src/lib/composables/useDropdown.ts +0 -338
- package/src/lib/composables/useModal.ts +0 -110
- package/src/lib/hooks/usePerformanceMonitor.ts +0 -148
- package/src/lib/utils/displacement-generator.ts +0 -92
- package/src/lib/utils/memoryMonitor.ts +0 -191
- package/src/styles/01-settings/_settings.testtypecheck.scss +0 -53
- package/src/styles/01-settings/_settings.typedbutton.scss +0 -53
- package/src/styles/06-components/_components.testbutton.scss +0 -212
- package/src/styles/06-components/_components.testtypecheck.scss +0 -212
- package/src/styles/06-components/_components.typedbutton.scss +0 -212
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import { useCallback, useRef, useState } from 'react';
|
|
2
|
-
|
|
3
|
-
interface InteractionState {
|
|
4
|
-
isDragging: boolean;
|
|
5
|
-
isZooming: boolean;
|
|
6
|
-
lastPointerPos: { x: number; y: number } | null;
|
|
7
|
-
zoomLevel: number;
|
|
8
|
-
panOffset: { x: number; y: number };
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function useChartInteractions() {
|
|
12
|
-
const [state, setState] = useState<InteractionState>({
|
|
13
|
-
isDragging: false,
|
|
14
|
-
isZooming: false,
|
|
15
|
-
lastPointerPos: null,
|
|
16
|
-
zoomLevel: 1,
|
|
17
|
-
panOffset: { x: 0, y: 0 },
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
const wheelTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
21
|
-
const lastWheelTime = useRef(0);
|
|
22
|
-
|
|
23
|
-
// Improved wheel handling for both mouse and trackpad
|
|
24
|
-
const handleWheel = useCallback((event: WheelEvent) => {
|
|
25
|
-
event.preventDefault();
|
|
26
|
-
|
|
27
|
-
const now = Date.now();
|
|
28
|
-
const timeDelta = now - lastWheelTime.current;
|
|
29
|
-
lastWheelTime.current = now;
|
|
30
|
-
|
|
31
|
-
// Detect trackpad vs mouse wheel
|
|
32
|
-
const isTrackpad = Math.abs(event.deltaY) < 50 && timeDelta < 50;
|
|
33
|
-
const sensitivity = isTrackpad ? 0.01 : 0.1;
|
|
34
|
-
|
|
35
|
-
if (wheelTimeoutRef.current) {
|
|
36
|
-
clearTimeout(wheelTimeoutRef.current);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
setState(prev => {
|
|
40
|
-
const rect = (event.target as Element).getBoundingClientRect();
|
|
41
|
-
const centerX = event.clientX - rect.left;
|
|
42
|
-
const centerY = event.clientY - rect.top;
|
|
43
|
-
|
|
44
|
-
// Zoom calculation
|
|
45
|
-
const zoomFactor = 1 - event.deltaY * sensitivity;
|
|
46
|
-
const newZoomLevel = Math.max(0.1, Math.min(10, prev.zoomLevel * zoomFactor));
|
|
47
|
-
|
|
48
|
-
// Pan to zoom center
|
|
49
|
-
const zoomRatio = newZoomLevel / prev.zoomLevel;
|
|
50
|
-
const newPanOffset = {
|
|
51
|
-
x: centerX - (centerX - prev.panOffset.x) * zoomRatio,
|
|
52
|
-
y: centerY - (centerY - prev.panOffset.y) * zoomRatio,
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
return {
|
|
56
|
-
...prev,
|
|
57
|
-
zoomLevel: newZoomLevel,
|
|
58
|
-
panOffset: newPanOffset,
|
|
59
|
-
isZooming: true,
|
|
60
|
-
};
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
wheelTimeoutRef.current = setTimeout(() => {
|
|
64
|
-
setState(prev => ({ ...prev, isZooming: false }));
|
|
65
|
-
}, 150);
|
|
66
|
-
}, []);
|
|
67
|
-
|
|
68
|
-
// Unified pointer events for mouse and touch
|
|
69
|
-
const handlePointerDown = useCallback((event: PointerEvent) => {
|
|
70
|
-
setState(prev => ({
|
|
71
|
-
...prev,
|
|
72
|
-
isDragging: true,
|
|
73
|
-
lastPointerPos: { x: event.clientX, y: event.clientY },
|
|
74
|
-
}));
|
|
75
|
-
(event.target as Element).setPointerCapture(event.pointerId);
|
|
76
|
-
}, []);
|
|
77
|
-
|
|
78
|
-
const handlePointerMove = useCallback((event: PointerEvent) => {
|
|
79
|
-
setState(prev => {
|
|
80
|
-
if (!prev.isDragging || !prev.lastPointerPos) return prev;
|
|
81
|
-
|
|
82
|
-
const deltaX = event.clientX - prev.lastPointerPos.x;
|
|
83
|
-
const deltaY = event.clientY - prev.lastPointerPos.y;
|
|
84
|
-
|
|
85
|
-
return {
|
|
86
|
-
...prev,
|
|
87
|
-
panOffset: {
|
|
88
|
-
x: prev.panOffset.x + deltaX,
|
|
89
|
-
y: prev.panOffset.y + deltaY,
|
|
90
|
-
},
|
|
91
|
-
lastPointerPos: { x: event.clientX, y: event.clientY },
|
|
92
|
-
};
|
|
93
|
-
});
|
|
94
|
-
}, []);
|
|
95
|
-
|
|
96
|
-
const handlePointerUp = useCallback((event: PointerEvent) => {
|
|
97
|
-
setState(prev => ({
|
|
98
|
-
...prev,
|
|
99
|
-
isDragging: false,
|
|
100
|
-
lastPointerPos: null,
|
|
101
|
-
}));
|
|
102
|
-
(event.target as Element).releasePointerCapture(event.pointerId);
|
|
103
|
-
}, []);
|
|
104
|
-
|
|
105
|
-
const resetView = useCallback(() => {
|
|
106
|
-
setState(prev => ({
|
|
107
|
-
...prev,
|
|
108
|
-
zoomLevel: 1,
|
|
109
|
-
panOffset: { x: 0, y: 0 },
|
|
110
|
-
}));
|
|
111
|
-
}, []);
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
state,
|
|
115
|
-
handlers: {
|
|
116
|
-
onWheel: handleWheel,
|
|
117
|
-
onPointerDown: handlePointerDown,
|
|
118
|
-
onPointerMove: handlePointerMove,
|
|
119
|
-
onPointerUp: handlePointerUp,
|
|
120
|
-
},
|
|
121
|
-
resetView,
|
|
122
|
-
};
|
|
123
|
-
}
|
|
@@ -1,347 +0,0 @@
|
|
|
1
|
-
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import { ChartDataPoint, ChartDataset } from '../types/components';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Performance optimization hook for charts
|
|
6
|
-
* Provides memoization, virtualization, and efficient re-rendering
|
|
7
|
-
*/
|
|
8
|
-
export function useChartPerformance() {
|
|
9
|
-
const renderCountRef = useRef(0);
|
|
10
|
-
const lastRenderTimeRef = useRef(Date.now());
|
|
11
|
-
const [performanceMetrics, setPerformanceMetrics] = useState({
|
|
12
|
-
renderCount: 0,
|
|
13
|
-
averageRenderTime: 0,
|
|
14
|
-
lastRenderDuration: 0,
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Memoized chart data processing
|
|
19
|
-
*/
|
|
20
|
-
const processDatasetsOptimized = useCallback((datasets: ChartDataset[]) => {
|
|
21
|
-
const startTime = performance.now();
|
|
22
|
-
|
|
23
|
-
// Process datasets with optimizations
|
|
24
|
-
const processedDatasets = datasets.map(dataset => ({
|
|
25
|
-
...dataset,
|
|
26
|
-
data: dataset.data.map((point, index) => ({
|
|
27
|
-
...point,
|
|
28
|
-
// Add index for efficient lookups
|
|
29
|
-
_index: index,
|
|
30
|
-
// Pre-calculate commonly used values
|
|
31
|
-
_stringValue: point.value.toString(),
|
|
32
|
-
_hasMetadata: Boolean(point.metadata && Object.keys(point.metadata).length > 0),
|
|
33
|
-
})),
|
|
34
|
-
// Pre-calculate dataset statistics
|
|
35
|
-
_stats: {
|
|
36
|
-
min: Math.min(...dataset.data.map(p => p.value)),
|
|
37
|
-
max: Math.max(...dataset.data.map(p => p.value)),
|
|
38
|
-
average: dataset.data.reduce((sum, p) => sum + p.value, 0) / dataset.data.length,
|
|
39
|
-
count: dataset.data.length,
|
|
40
|
-
},
|
|
41
|
-
}));
|
|
42
|
-
|
|
43
|
-
const endTime = performance.now();
|
|
44
|
-
const processingTime = endTime - startTime;
|
|
45
|
-
|
|
46
|
-
// Update performance metrics
|
|
47
|
-
renderCountRef.current += 1;
|
|
48
|
-
const currentTime = Date.now();
|
|
49
|
-
const timeSinceLastRender = currentTime - lastRenderTimeRef.current;
|
|
50
|
-
lastRenderTimeRef.current = currentTime;
|
|
51
|
-
|
|
52
|
-
setPerformanceMetrics(prev => ({
|
|
53
|
-
renderCount: renderCountRef.current,
|
|
54
|
-
averageRenderTime:
|
|
55
|
-
(prev.averageRenderTime * (renderCountRef.current - 1) + processingTime) /
|
|
56
|
-
renderCountRef.current,
|
|
57
|
-
lastRenderDuration: processingTime,
|
|
58
|
-
}));
|
|
59
|
-
|
|
60
|
-
return processedDatasets;
|
|
61
|
-
}, []);
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Optimized scale calculations with caching
|
|
65
|
-
*/
|
|
66
|
-
const createOptimizedScales = useCallback(
|
|
67
|
-
(
|
|
68
|
-
datasets: ChartDataset[],
|
|
69
|
-
width: number,
|
|
70
|
-
height: number,
|
|
71
|
-
padding: { top: number; right: number; bottom: number; left: number }
|
|
72
|
-
) => {
|
|
73
|
-
if (!datasets.length) return null;
|
|
74
|
-
|
|
75
|
-
const innerWidth = width - padding.left - padding.right;
|
|
76
|
-
const innerHeight = height - padding.top - padding.bottom;
|
|
77
|
-
|
|
78
|
-
// Calculate bounds efficiently
|
|
79
|
-
const allValues = datasets.flatMap(dataset => dataset.data.map(d => d.value));
|
|
80
|
-
const minValue = Math.min(...allValues);
|
|
81
|
-
const maxValue = Math.max(...allValues);
|
|
82
|
-
const valueRange = maxValue - minValue;
|
|
83
|
-
|
|
84
|
-
// Pre-calculate scale functions for better performance
|
|
85
|
-
const xScale = (i: number, dataLength: number) =>
|
|
86
|
-
padding.left + (i / (dataLength - 1)) * innerWidth;
|
|
87
|
-
|
|
88
|
-
const yScale = (value: number) =>
|
|
89
|
-
padding.top + innerHeight - ((value - minValue) / valueRange) * innerHeight;
|
|
90
|
-
|
|
91
|
-
return {
|
|
92
|
-
xScale,
|
|
93
|
-
yScale,
|
|
94
|
-
minValue,
|
|
95
|
-
maxValue,
|
|
96
|
-
valueRange,
|
|
97
|
-
innerWidth,
|
|
98
|
-
innerHeight,
|
|
99
|
-
};
|
|
100
|
-
},
|
|
101
|
-
[]
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Virtualization for large datasets
|
|
106
|
-
*/
|
|
107
|
-
const useDataVirtualization = useCallback(
|
|
108
|
-
(
|
|
109
|
-
data: ChartDataPoint[],
|
|
110
|
-
viewportStart: number,
|
|
111
|
-
viewportEnd: number,
|
|
112
|
-
bufferSize: number = 50
|
|
113
|
-
) => {
|
|
114
|
-
if (data.length <= 1000) {
|
|
115
|
-
// No virtualization needed for small datasets
|
|
116
|
-
return {
|
|
117
|
-
visibleData: data,
|
|
118
|
-
startIndex: 0,
|
|
119
|
-
endIndex: data.length - 1,
|
|
120
|
-
isVirtualized: false,
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const start = Math.max(0, viewportStart - bufferSize);
|
|
125
|
-
const end = Math.min(data.length - 1, viewportEnd + bufferSize);
|
|
126
|
-
|
|
127
|
-
return {
|
|
128
|
-
visibleData: data.slice(start, end + 1),
|
|
129
|
-
startIndex: start,
|
|
130
|
-
endIndex: end,
|
|
131
|
-
isVirtualized: true,
|
|
132
|
-
totalLength: data.length,
|
|
133
|
-
};
|
|
134
|
-
},
|
|
135
|
-
[]
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Debounced data updates for real-time charts
|
|
140
|
-
* Returns a debounced function that maintains timeout state across calls
|
|
141
|
-
* Uses a closure to maintain state - each call to useDebouncedUpdates creates
|
|
142
|
-
* a new debounced function with its own persistent timeout state
|
|
143
|
-
*/
|
|
144
|
-
const useDebouncedUpdates = useCallback((updateFunction: () => void, delay: number = 100) => {
|
|
145
|
-
// Use a closure variable to maintain timeout state across multiple calls to the returned function
|
|
146
|
-
// This variable is created once when useDebouncedUpdates is called and persists
|
|
147
|
-
// across all invocations of the returned debounced function
|
|
148
|
-
let timeoutId: NodeJS.Timeout | null = null;
|
|
149
|
-
|
|
150
|
-
const debouncedFn: (() => void) & { cancel: () => void } = () => {
|
|
151
|
-
// Clear any existing timeout before setting a new one
|
|
152
|
-
if (timeoutId !== null) {
|
|
153
|
-
clearTimeout(timeoutId);
|
|
154
|
-
timeoutId = null;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Set new timeout and store the ID
|
|
158
|
-
timeoutId = setTimeout(() => {
|
|
159
|
-
updateFunction();
|
|
160
|
-
timeoutId = null;
|
|
161
|
-
}, delay);
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
// Add cleanup method to cancel pending debounced calls
|
|
165
|
-
debouncedFn.cancel = () => {
|
|
166
|
-
if (timeoutId !== null) {
|
|
167
|
-
clearTimeout(timeoutId);
|
|
168
|
-
timeoutId = null;
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
return debouncedFn;
|
|
173
|
-
}, []);
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Memory-efficient color palette generation using CSS custom properties
|
|
177
|
-
*/
|
|
178
|
-
const generateOptimizedColorPalette = useMemo(() => {
|
|
179
|
-
const baseColors = [
|
|
180
|
-
'var(--atomix-primary)',
|
|
181
|
-
'var(--atomix-secondary)',
|
|
182
|
-
'var(--atomix-success)',
|
|
183
|
-
'var(--atomix-info)',
|
|
184
|
-
'var(--atomix-warning)',
|
|
185
|
-
'var(--atomix-error)',
|
|
186
|
-
'var(--atomix-primary-5)',
|
|
187
|
-
'var(--atomix-primary-7)',
|
|
188
|
-
'var(--atomix-primary-3)',
|
|
189
|
-
'var(--atomix-gray-6)',
|
|
190
|
-
'var(--atomix-gray-8)',
|
|
191
|
-
'var(--atomix-gray-4)',
|
|
192
|
-
'var(--atomix-primary-2)',
|
|
193
|
-
'var(--atomix-primary-8)',
|
|
194
|
-
'var(--atomix-gray-5)',
|
|
195
|
-
'var(--atomix-gray-7)',
|
|
196
|
-
'var(--atomix-primary-4)',
|
|
197
|
-
'var(--atomix-primary-6)',
|
|
198
|
-
];
|
|
199
|
-
|
|
200
|
-
// Pre-generate a large palette to avoid runtime calculations
|
|
201
|
-
const extendedColors: string[] = [];
|
|
202
|
-
for (let i = 0; i < 100; i++) {
|
|
203
|
-
extendedColors.push(baseColors[i % baseColors.length] || '#000000');
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return (index: number) => extendedColors[index % extendedColors.length];
|
|
207
|
-
}, []);
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Optimized animation frame handling
|
|
211
|
-
* Returns animation control functions that maintain state across calls
|
|
212
|
-
* Uses closures to maintain state - each call to useAnimationFrame creates
|
|
213
|
-
* a new animation controller with its own persistent state
|
|
214
|
-
*/
|
|
215
|
-
const useAnimationFrame = useCallback((callback: () => void) => {
|
|
216
|
-
// Use closure variables to maintain animation state across multiple calls
|
|
217
|
-
// These variables are created once when useAnimationFrame is called and persist
|
|
218
|
-
// across all invocations of the returned animation control functions
|
|
219
|
-
let requestId: number | null = null;
|
|
220
|
-
let previousTime: number | null = null;
|
|
221
|
-
|
|
222
|
-
const animate = (time: number) => {
|
|
223
|
-
if (previousTime !== null && previousTime !== undefined) {
|
|
224
|
-
const deltaTime = time - previousTime;
|
|
225
|
-
callback();
|
|
226
|
-
}
|
|
227
|
-
previousTime = time;
|
|
228
|
-
requestId = requestAnimationFrame(animate);
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
const startAnimation = () => {
|
|
232
|
-
// Only start if not already running
|
|
233
|
-
if (requestId === null) {
|
|
234
|
-
requestId = requestAnimationFrame(animate);
|
|
235
|
-
}
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
const stopAnimation = () => {
|
|
239
|
-
if (requestId !== null) {
|
|
240
|
-
cancelAnimationFrame(requestId);
|
|
241
|
-
requestId = null;
|
|
242
|
-
}
|
|
243
|
-
previousTime = null;
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
return { startAnimation, stopAnimation };
|
|
247
|
-
}, []);
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Smart re-rendering based on data changes
|
|
251
|
-
*/
|
|
252
|
-
const shouldUpdateChart = useCallback(
|
|
253
|
-
(prevDatasets: ChartDataset[], newDatasets: ChartDataset[], threshold: number = 0.01) => {
|
|
254
|
-
if (prevDatasets.length !== newDatasets.length) return true;
|
|
255
|
-
|
|
256
|
-
// Check if any significant data changes occurred
|
|
257
|
-
for (let i = 0; i < prevDatasets.length; i++) {
|
|
258
|
-
const prevDataset = prevDatasets[i];
|
|
259
|
-
const newDataset = newDatasets[i];
|
|
260
|
-
if (!prevDataset || !newDataset) continue;
|
|
261
|
-
|
|
262
|
-
const prevData = prevDataset.data;
|
|
263
|
-
const newData = newDataset.data;
|
|
264
|
-
|
|
265
|
-
if (prevData.length !== newData.length) return true;
|
|
266
|
-
|
|
267
|
-
// Check for significant value changes
|
|
268
|
-
for (let j = 0; j < prevData.length; j++) {
|
|
269
|
-
const prevPoint = prevData[j];
|
|
270
|
-
const newPoint = newData[j];
|
|
271
|
-
if (!prevPoint || !newPoint) continue;
|
|
272
|
-
|
|
273
|
-
const valueDiff = Math.abs(prevPoint.value - newPoint.value);
|
|
274
|
-
const relativeChange = valueDiff / Math.abs(prevPoint.value);
|
|
275
|
-
|
|
276
|
-
if (relativeChange > threshold) return true;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
return false;
|
|
281
|
-
},
|
|
282
|
-
[]
|
|
283
|
-
);
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Canvas optimization for better performance
|
|
287
|
-
*/
|
|
288
|
-
const optimizeCanvasRendering = useCallback(
|
|
289
|
-
(
|
|
290
|
-
canvasRef: React.RefObject<HTMLCanvasElement>,
|
|
291
|
-
pixelRatio: number = window.devicePixelRatio || 1
|
|
292
|
-
) => {
|
|
293
|
-
if (!canvasRef.current) return null;
|
|
294
|
-
|
|
295
|
-
const canvas = canvasRef.current;
|
|
296
|
-
const ctx = canvas.getContext('2d');
|
|
297
|
-
|
|
298
|
-
if (!ctx) return null;
|
|
299
|
-
|
|
300
|
-
// Set up high-DPI rendering
|
|
301
|
-
const rect = canvas.getBoundingClientRect();
|
|
302
|
-
canvas.width = rect.width * pixelRatio;
|
|
303
|
-
canvas.height = rect.height * pixelRatio;
|
|
304
|
-
canvas.style.width = rect.width + 'px';
|
|
305
|
-
canvas.style.height = rect.height + 'px';
|
|
306
|
-
ctx.scale(pixelRatio, pixelRatio);
|
|
307
|
-
|
|
308
|
-
// Optimize canvas settings for better performance
|
|
309
|
-
ctx.imageSmoothingEnabled = false;
|
|
310
|
-
ctx.fillStyle = 'transparent';
|
|
311
|
-
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
312
|
-
|
|
313
|
-
return { canvas, ctx, width: rect.width, height: rect.height };
|
|
314
|
-
},
|
|
315
|
-
[]
|
|
316
|
-
);
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* Batch DOM updates for better performance
|
|
320
|
-
*/
|
|
321
|
-
const batchDOMUpdates = useCallback((updates: (() => void)[]) => {
|
|
322
|
-
// Use requestAnimationFrame to batch DOM updates
|
|
323
|
-
requestAnimationFrame(() => {
|
|
324
|
-
updates.forEach(update => update());
|
|
325
|
-
});
|
|
326
|
-
}, []);
|
|
327
|
-
|
|
328
|
-
return {
|
|
329
|
-
// Data processing
|
|
330
|
-
processDatasetsOptimized,
|
|
331
|
-
createOptimizedScales,
|
|
332
|
-
useDataVirtualization,
|
|
333
|
-
|
|
334
|
-
// Performance monitoring
|
|
335
|
-
performanceMetrics,
|
|
336
|
-
shouldUpdateChart,
|
|
337
|
-
|
|
338
|
-
// Rendering optimizations
|
|
339
|
-
generateOptimizedColorPalette,
|
|
340
|
-
optimizeCanvasRendering,
|
|
341
|
-
batchDOMUpdates,
|
|
342
|
-
|
|
343
|
-
// Animation and updates
|
|
344
|
-
useAnimationFrame,
|
|
345
|
-
useDebouncedUpdates,
|
|
346
|
-
};
|
|
347
|
-
}
|