@shohojdhara/atomix 0.4.5 → 0.4.7

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 (54) hide show
  1. package/dist/atomix.css +70 -33
  2. package/dist/atomix.css.map +1 -1
  3. package/dist/atomix.min.css +2 -2
  4. package/dist/atomix.min.css.map +1 -1
  5. package/dist/charts.d.ts +93 -109
  6. package/dist/charts.js +273 -371
  7. package/dist/charts.js.map +1 -1
  8. package/dist/core.js +183 -184
  9. package/dist/core.js.map +1 -1
  10. package/dist/forms.js +183 -184
  11. package/dist/forms.js.map +1 -1
  12. package/dist/heavy.js +183 -184
  13. package/dist/heavy.js.map +1 -1
  14. package/dist/index.d.ts +7 -51
  15. package/dist/index.esm.js +281 -470
  16. package/dist/index.esm.js.map +1 -1
  17. package/dist/index.js +287 -476
  18. package/dist/index.js.map +1 -1
  19. package/dist/index.min.js +1 -1
  20. package/dist/index.min.js.map +1 -1
  21. package/package.json +1 -1
  22. package/src/components/AtomixGlass/AtomixGlass.tsx +60 -38
  23. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +6 -35
  24. package/src/components/AtomixGlass/glass-utils.ts +27 -14
  25. package/src/components/AtomixGlass/stories/Overview.stories.tsx +19 -21
  26. package/src/components/AtomixGlass/stories/Playground.stories.tsx +1162 -515
  27. package/src/components/AtomixGlass/stories/shared-components.tsx +11 -3
  28. package/src/components/Chart/BubbleChart.tsx +6 -2
  29. package/src/components/Chart/Chart.stories.tsx +108 -96
  30. package/src/components/Chart/ChartToolbar.tsx +6 -4
  31. package/src/components/Chart/ChartTooltip.tsx +5 -4
  32. package/src/components/Chart/GaugeChart.tsx +20 -12
  33. package/src/components/Chart/HeatmapChart.tsx +53 -23
  34. package/src/components/Chart/TreemapChart.tsx +44 -15
  35. package/src/components/Chart/index.ts +0 -2
  36. package/src/components/Chart/types.ts +4 -4
  37. package/src/components/Navigation/Navbar/Navbar.tsx +13 -5
  38. package/src/components/index.ts +0 -1
  39. package/src/lib/composables/index.ts +1 -2
  40. package/src/lib/composables/useAtomixGlass.ts +246 -222
  41. package/src/lib/composables/useAtomixGlassStyles.ts +46 -23
  42. package/src/lib/constants/components.ts +3 -1
  43. package/src/styles/01-settings/_settings.chart.scss +13 -13
  44. package/src/styles/06-components/_components.atomix-glass.scss +45 -20
  45. package/src/styles/06-components/_components.chart.scss +23 -5
  46. package/src/components/Chart/AnimatedChart.tsx +0 -230
  47. package/src/lib/composables/atomix-glass/useGlassBackgroundDetection.ts +0 -329
  48. package/src/lib/composables/atomix-glass/useGlassCornerRadius.ts +0 -82
  49. package/src/lib/composables/atomix-glass/useGlassMouseTracking.ts +0 -153
  50. package/src/lib/composables/atomix-glass/useGlassOverLight.ts +0 -198
  51. package/src/lib/composables/atomix-glass/useGlassState.ts +0 -112
  52. package/src/lib/composables/atomix-glass/useGlassTransforms.ts +0 -160
  53. package/src/lib/composables/glass-styles.ts +0 -302
  54. package/src/lib/composables/useGlassContainer.ts +0 -177
@@ -1,198 +0,0 @@
1
- import { useCallback, useMemo } from 'react';
2
- import { calculateMouseInfluence } from '../../../components/AtomixGlass/glass-utils';
3
- import type {
4
- MousePosition,
5
- OverLightConfig,
6
- OverLightObjectConfig,
7
- } from '../../types/components';
8
-
9
- interface UseGlassOverLightProps {
10
- overLight: OverLightConfig;
11
- detectedOverLight: boolean;
12
- mouseOffset: MousePosition;
13
- isHovered: boolean;
14
- isActive: boolean;
15
- debugOverLight?: boolean;
16
- }
17
-
18
- export function useGlassOverLight({
19
- overLight,
20
- detectedOverLight,
21
- mouseOffset,
22
- isHovered,
23
- isActive,
24
- debugOverLight = false,
25
- }: UseGlassOverLightProps) {
26
- /**
27
- * Get effective overLight value based on configuration
28
- * - boolean: returns the boolean value directly
29
- * - 'auto': returns detectedOverLight (auto-detected from background)
30
- * - object: returns detectedOverLight (auto-detected, but config object provides customization)
31
- */
32
- const getEffectiveOverLight = useCallback(() => {
33
- if (typeof overLight === 'boolean') {
34
- return overLight;
35
- }
36
- if (overLight === 'auto') {
37
- return detectedOverLight;
38
- }
39
- if (typeof overLight === 'object' && overLight !== null) {
40
- return detectedOverLight;
41
- }
42
- // Default to false for safety when overLight is undefined or invalid
43
- return false;
44
- }, [overLight, detectedOverLight]);
45
-
46
- /**
47
- * Validate and clamp a numeric config value
48
- * @param value - The value to validate
49
- * @param min - Minimum allowed value
50
- * @param max - Maximum allowed value
51
- * @param defaultValue - Default value if validation fails
52
- * @returns Validated and clamped value
53
- */
54
- const validateConfigValue = useCallback(
55
- (value: unknown, min: number, max: number, defaultValue: number): number => {
56
- if (typeof value !== 'number' || isNaN(value) || !isFinite(value)) {
57
- return defaultValue;
58
- }
59
- return Math.min(max, Math.max(min, value));
60
- },
61
- []
62
- );
63
-
64
- const overLightConfig = useMemo(() => {
65
- const isOverLight = getEffectiveOverLight();
66
- const mouseInfluence = calculateMouseInfluence(mouseOffset);
67
- const hoverIntensity = isHovered ? 1.4 : 1;
68
- const activeIntensity = isActive ? 1.6 : 1;
69
-
70
- // More robust overlight configuration with better defaults and clamping
71
- const baseOpacity = isOverLight
72
- ? Math.min(0.6, Math.max(0.2, 0.5 * hoverIntensity * activeIntensity))
73
- : 0;
74
-
75
- const baseConfig = {
76
- isOverLight,
77
- threshold: 0.7,
78
- opacity: baseOpacity,
79
- contrast: Math.min(1.6, Math.max(1.0, 1.4 + mouseInfluence * 0.1)),
80
- brightness: Math.min(1.1, Math.max(0.8, 0.9 + mouseInfluence * 0.05)),
81
- saturationBoost: 1.3, // Fixed value — dynamic saturation amplifies perceived displacement
82
- shadowIntensity: Math.min(1.2, Math.max(0.5, 0.9 + mouseInfluence * 0.2)),
83
- borderOpacity: Math.min(1.0, Math.max(0.3, 0.7 + mouseInfluence * 0.1)),
84
- };
85
-
86
- if (typeof overLight === 'object' && overLight !== null) {
87
- const objConfig = overLight as OverLightObjectConfig;
88
-
89
- // Validate and apply object config values with proper clamping
90
- const validatedThreshold = validateConfigValue(
91
- objConfig.threshold,
92
- 0.1,
93
- 1.0,
94
- baseConfig.threshold
95
- );
96
- const validatedOpacity = validateConfigValue(objConfig.opacity, 0.1, 1.0, baseConfig.opacity);
97
- const validatedContrast = validateConfigValue(
98
- objConfig.contrast,
99
- 0.5,
100
- 2.5,
101
- baseConfig.contrast
102
- );
103
- const validatedBrightness = validateConfigValue(
104
- objConfig.brightness,
105
- 0.5,
106
- 2.0,
107
- baseConfig.brightness
108
- );
109
- const validatedSaturationBoost = validateConfigValue(
110
- objConfig.saturationBoost,
111
- 0.5,
112
- 3.0,
113
- baseConfig.saturationBoost
114
- );
115
-
116
- const finalConfig = {
117
- ...baseConfig,
118
- threshold: validatedThreshold,
119
- opacity: validatedOpacity * hoverIntensity * activeIntensity,
120
- contrast: Math.min(1.6, validatedContrast + mouseInfluence * 0.1),
121
- brightness: Math.min(1.1, validatedBrightness + mouseInfluence * 0.05),
122
- saturationBoost: validatedSaturationBoost, // Use validated value directly, no mouse influence
123
- };
124
-
125
- // Debug logging
126
- if (
127
- (typeof process === 'undefined' || process.env?.NODE_ENV !== 'production') &&
128
- debugOverLight
129
- ) {
130
- console.log('[AtomixGlass] OverLight Config:', {
131
- isOverLight,
132
- config: {
133
- threshold: finalConfig.threshold.toFixed(3),
134
- opacity: finalConfig.opacity.toFixed(3),
135
- contrast: finalConfig.contrast.toFixed(3),
136
- brightness: finalConfig.brightness.toFixed(3),
137
- saturationBoost: finalConfig.saturationBoost.toFixed(3),
138
- shadowIntensity: finalConfig.shadowIntensity.toFixed(3),
139
- borderOpacity: finalConfig.borderOpacity.toFixed(3),
140
- },
141
- input: {
142
- threshold: objConfig.threshold,
143
- opacity: objConfig.opacity,
144
- contrast: objConfig.contrast,
145
- brightness: objConfig.brightness,
146
- saturationBoost: objConfig.saturationBoost,
147
- },
148
- dynamic: {
149
- mouseInfluence: mouseInfluence.toFixed(3),
150
- hoverIntensity: hoverIntensity.toFixed(3),
151
- activeIntensity: activeIntensity.toFixed(3),
152
- },
153
- timestamp: new Date().toISOString(),
154
- });
155
- }
156
-
157
- return finalConfig;
158
- }
159
-
160
- // Debug logging for non-object configs
161
- if (
162
- (typeof process === 'undefined' || process.env?.NODE_ENV !== 'production') &&
163
- debugOverLight
164
- ) {
165
- console.log('[AtomixGlass] OverLight Config:', {
166
- isOverLight,
167
- configType: typeof overLight === 'boolean' ? (overLight ? 'true' : 'false') : overLight,
168
- config: {
169
- threshold: baseConfig.threshold.toFixed(3),
170
- opacity: baseConfig.opacity.toFixed(3),
171
- contrast: baseConfig.contrast.toFixed(3),
172
- brightness: baseConfig.brightness.toFixed(3),
173
- saturationBoost: baseConfig.saturationBoost.toFixed(3),
174
- shadowIntensity: baseConfig.shadowIntensity.toFixed(3),
175
- borderOpacity: baseConfig.borderOpacity.toFixed(3),
176
- },
177
- dynamic: {
178
- mouseInfluence: mouseInfluence.toFixed(3),
179
- hoverIntensity: hoverIntensity.toFixed(3),
180
- activeIntensity: activeIntensity.toFixed(3),
181
- },
182
- timestamp: new Date().toISOString(),
183
- });
184
- }
185
-
186
- return baseConfig;
187
- }, [
188
- overLight,
189
- getEffectiveOverLight,
190
- mouseOffset,
191
- isHovered,
192
- isActive,
193
- validateConfigValue,
194
- debugOverLight,
195
- ]);
196
-
197
- return { overLightConfig };
198
- }
@@ -1,112 +0,0 @@
1
- import { useCallback, useEffect, useMemo, useState } from 'react';
2
- import type { AtomixGlassProps } from '../../types/components';
3
-
4
- interface UseGlassStateProps {
5
- reducedMotion?: boolean;
6
- highContrast?: boolean;
7
- withoutEffects?: boolean;
8
- onClick?: () => void;
9
- }
10
-
11
- export function useGlassState({
12
- reducedMotion = false,
13
- highContrast = false,
14
- withoutEffects = false,
15
- onClick,
16
- }: UseGlassStateProps) {
17
- const [isHovered, setIsHovered] = useState(false);
18
- const [isActive, setIsActive] = useState(false);
19
- const [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(false);
20
- const [userPrefersHighContrast, setUserPrefersHighContrast] = useState(false);
21
-
22
- // Media query handlers
23
- useEffect(() => {
24
- if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {
25
- return undefined;
26
- }
27
-
28
- try {
29
- const mediaQueryReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
30
- const mediaQueryHighContrast = window.matchMedia('(prefers-contrast: high)');
31
-
32
- setUserPrefersReducedMotion(mediaQueryReducedMotion.matches);
33
- setUserPrefersHighContrast(mediaQueryHighContrast.matches);
34
-
35
- const handleReducedMotionChange = (e: MediaQueryListEvent) => {
36
- setUserPrefersReducedMotion(e.matches);
37
- };
38
-
39
- const handleHighContrastChange = (e: MediaQueryListEvent) => {
40
- setUserPrefersHighContrast(e.matches);
41
- };
42
-
43
- if (mediaQueryReducedMotion.addEventListener) {
44
- mediaQueryReducedMotion.addEventListener('change', handleReducedMotionChange);
45
- mediaQueryHighContrast.addEventListener('change', handleHighContrastChange);
46
- } else if (mediaQueryReducedMotion.addListener) {
47
- mediaQueryReducedMotion.addListener(handleReducedMotionChange);
48
- mediaQueryHighContrast.addListener(handleHighContrastChange);
49
- }
50
-
51
- return () => {
52
- try {
53
- if (mediaQueryReducedMotion.removeEventListener) {
54
- mediaQueryReducedMotion.removeEventListener('change', handleReducedMotionChange);
55
- mediaQueryHighContrast.removeEventListener('change', handleHighContrastChange);
56
- } else if (mediaQueryReducedMotion.removeListener) {
57
- mediaQueryReducedMotion.removeListener(handleReducedMotionChange);
58
- mediaQueryHighContrast.removeListener(handleHighContrastChange);
59
- }
60
- } catch (cleanupError) {
61
- console.error('AtomixGlass: Error cleaning up media query listeners:', cleanupError);
62
- }
63
- };
64
- } catch (error) {
65
- console.error('AtomixGlass: Error setting up media queries:', error);
66
- return undefined;
67
- }
68
- }, []);
69
-
70
- const effectiveReducedMotion = useMemo(
71
- () => reducedMotion || userPrefersReducedMotion,
72
- [reducedMotion, userPrefersReducedMotion]
73
- );
74
-
75
- const effectiveHighContrast = useMemo(
76
- () => highContrast || userPrefersHighContrast,
77
- [highContrast, userPrefersHighContrast]
78
- );
79
-
80
- const effectiveWithoutEffects = useMemo(
81
- () => withoutEffects || effectiveReducedMotion,
82
- [withoutEffects, effectiveReducedMotion]
83
- );
84
-
85
- const handleMouseEnter = useCallback(() => setIsHovered(true), []);
86
- const handleMouseLeave = useCallback(() => setIsHovered(false), []);
87
- const handleMouseDown = useCallback(() => setIsActive(true), []);
88
- const handleMouseUp = useCallback(() => setIsActive(false), []);
89
-
90
- const handleKeyDown = useCallback(
91
- (e: React.KeyboardEvent<HTMLDivElement>) => {
92
- if (onClick && (e.key === 'Enter' || e.key === ' ')) {
93
- e.preventDefault();
94
- onClick();
95
- }
96
- },
97
- [onClick]
98
- );
99
-
100
- return {
101
- isHovered,
102
- isActive,
103
- effectiveReducedMotion,
104
- effectiveHighContrast,
105
- effectiveWithoutEffects,
106
- handleMouseEnter,
107
- handleMouseLeave,
108
- handleMouseDown,
109
- handleMouseUp,
110
- handleKeyDown,
111
- };
112
- }
@@ -1,160 +0,0 @@
1
- import React, { useCallback, useMemo } from 'react';
2
- import { ATOMIX_GLASS } from '../../constants/components';
3
- import {
4
- calculateDistance,
5
- calculateElementCenter,
6
- validateGlassSize,
7
- } from '../../../components/AtomixGlass/glass-utils';
8
- import type { GlassSize, MousePosition, OverLightConfig } from '../../types/components';
9
-
10
- const { CONSTANTS } = ATOMIX_GLASS;
11
-
12
- interface UseGlassTransformsProps {
13
- glassRef: React.RefObject<HTMLDivElement>;
14
- globalMousePosition: MousePosition;
15
- glassSize: GlassSize;
16
- overLight: OverLightConfig;
17
- detectedOverLight: boolean;
18
- elasticity?: number;
19
- effectiveWithoutEffects?: boolean;
20
- isActive?: boolean;
21
- onClick?: () => void;
22
- }
23
-
24
- export function useGlassTransforms({
25
- glassRef,
26
- globalMousePosition,
27
- glassSize,
28
- overLight,
29
- detectedOverLight,
30
- elasticity = 0.05,
31
- effectiveWithoutEffects = false,
32
- isActive = false,
33
- onClick,
34
- }: UseGlassTransformsProps) {
35
- const calculateDirectionalScale = useCallback(() => {
36
- // Disable directional scaling if overLight is active (to prevent zooming/distorting the premium glass effect)
37
- const isOverLightActive =
38
- overLight === true ||
39
- (overLight === 'auto' && detectedOverLight) ||
40
- (typeof overLight === 'object' && overLight !== null && detectedOverLight);
41
-
42
- if (isOverLightActive) {
43
- return 'scale(1)';
44
- }
45
-
46
- if (
47
- !globalMousePosition.x ||
48
- !globalMousePosition.y ||
49
- !glassRef.current ||
50
- !validateGlassSize(glassSize)
51
- ) {
52
- return 'scale(1)';
53
- }
54
-
55
- const rect = glassRef.current.getBoundingClientRect();
56
- const center = calculateElementCenter(rect);
57
- const deltaX = globalMousePosition.x - center.x;
58
- const deltaY = globalMousePosition.y - center.y;
59
-
60
- const edgeDistanceX = Math.max(0, Math.abs(deltaX) - glassSize.width / 2);
61
- const edgeDistanceY = Math.max(0, Math.abs(deltaY) - glassSize.height / 2);
62
- const edgeDistance = calculateDistance({ x: edgeDistanceX, y: edgeDistanceY }, { x: 0, y: 0 });
63
-
64
- if (edgeDistance > CONSTANTS.ACTIVATION_ZONE) {
65
- return 'scale(1)';
66
- }
67
-
68
- const fadeInFactor = 1 - edgeDistance / CONSTANTS.ACTIVATION_ZONE;
69
- const centerDistance = calculateDistance(globalMousePosition, center);
70
-
71
- if (centerDistance === 0) {
72
- return 'scale(1)';
73
- }
74
-
75
- const normalizedX = deltaX / centerDistance;
76
- const normalizedY = deltaY / centerDistance;
77
- const stretchIntensity = Math.min(centerDistance / 300, 1) * elasticity * fadeInFactor;
78
-
79
- const scaleX =
80
- 1 +
81
- Math.abs(normalizedX) * stretchIntensity * 0.3 -
82
- Math.abs(normalizedY) * stretchIntensity * 0.15;
83
- const scaleY =
84
- 1 +
85
- Math.abs(normalizedY) * stretchIntensity * 0.3 -
86
- Math.abs(normalizedX) * stretchIntensity * 0.15;
87
-
88
- return `scaleX(${Math.max(0.8, scaleX)}) scaleY(${Math.max(0.8, scaleY)})`;
89
- }, [globalMousePosition, elasticity, glassSize, glassRef, overLight, detectedOverLight]);
90
-
91
- const calculateFadeInFactor = useCallback(() => {
92
- if (
93
- !globalMousePosition.x ||
94
- !globalMousePosition.y ||
95
- !glassRef.current ||
96
- !validateGlassSize(glassSize)
97
- ) {
98
- return 0;
99
- }
100
-
101
- const rect = glassRef.current.getBoundingClientRect();
102
- const center = calculateElementCenter(rect);
103
-
104
- const edgeDistanceX = Math.max(
105
- 0,
106
- Math.abs(globalMousePosition.x - center.x) - glassSize.width / 2
107
- );
108
- const edgeDistanceY = Math.max(
109
- 0,
110
- Math.abs(globalMousePosition.y - center.y) - glassSize.height / 2
111
- );
112
- const edgeDistance = calculateDistance({ x: edgeDistanceX, y: edgeDistanceY }, { x: 0, y: 0 });
113
-
114
- return edgeDistance > CONSTANTS.ACTIVATION_ZONE
115
- ? 0
116
- : 1 - edgeDistance / CONSTANTS.ACTIVATION_ZONE;
117
- }, [globalMousePosition, glassSize, glassRef]);
118
-
119
- const calculateElasticTranslation = useCallback(() => {
120
- if (!glassRef.current) {
121
- return { x: 0, y: 0 };
122
- }
123
-
124
- const fadeInFactor = calculateFadeInFactor();
125
- const rect = glassRef.current.getBoundingClientRect();
126
- const center = calculateElementCenter(rect);
127
-
128
- return {
129
- x: (globalMousePosition.x - center.x) * elasticity * 0.1 * fadeInFactor,
130
- y: (globalMousePosition.y - center.y) * elasticity * 0.1 * fadeInFactor,
131
- };
132
- }, [globalMousePosition, elasticity, calculateFadeInFactor, glassRef]);
133
-
134
- const elasticTranslation = useMemo(() => {
135
- if (effectiveWithoutEffects) {
136
- return { x: 0, y: 0 };
137
- }
138
- return calculateElasticTranslation();
139
- }, [calculateElasticTranslation, effectiveWithoutEffects]);
140
-
141
- const directionalScale = useMemo(() => {
142
- if (effectiveWithoutEffects) {
143
- return 'scale(1)';
144
- }
145
- return calculateDirectionalScale();
146
- }, [calculateDirectionalScale, effectiveWithoutEffects]);
147
-
148
- const transformStyle = useMemo(() => {
149
- if (effectiveWithoutEffects) {
150
- return isActive && Boolean(onClick) ? 'scale(0.98)' : 'scale(1)';
151
- }
152
- return `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? 'scale(0.96)' : directionalScale}`;
153
- }, [elasticTranslation, isActive, onClick, directionalScale, effectiveWithoutEffects]);
154
-
155
- return {
156
- elasticTranslation,
157
- directionalScale,
158
- transformStyle,
159
- };
160
- }