@shohojdhara/atomix 0.6.4 → 0.6.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/dist/atomix.css +117 -38
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/atomix.umd.js +1 -1
- package/dist/atomix.umd.js.map +1 -1
- package/dist/atomix.umd.min.js +1 -1
- package/dist/charts.d.ts +30 -1
- package/dist/charts.js +566 -597
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +30 -1
- package/dist/core.js +600 -624
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +30 -1
- package/dist/forms.js +1122 -1163
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +31 -89
- package/dist/heavy.js +1015 -1045
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +378 -104
- package/dist/index.esm.js +10959 -10837
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +10935 -10812
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Accordion/Accordion.tsx +2 -5
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +14 -16
- package/src/components/AtomixGlass/AtomixGlass.tsx +137 -355
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +32 -249
- package/src/components/AtomixGlass/GlassFilter.tsx +62 -68
- package/src/components/AtomixGlass/README.md +2 -1
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +19 -18
- package/src/components/AtomixGlass/glass-border-styles.test.ts +58 -0
- package/src/components/AtomixGlass/glass-border-styles.ts +136 -0
- package/src/components/AtomixGlass/glass-utils.ts +411 -6
- package/src/components/AtomixGlass/stories/AnimationFeatures.stories.tsx +158 -537
- package/src/components/AtomixGlass/stories/Border.stories.tsx +149 -0
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +229 -89
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +29 -340
- package/src/components/AtomixGlass/stories/argTypes.ts +30 -13
- package/src/components/AtomixGlass/stories/premium-presets.ts +206 -0
- package/src/components/AtomixGlass/stories/shared-components.tsx +52 -8
- package/src/components/Badge/Badge.tsx +4 -4
- package/src/components/Button/Button.tsx +2 -6
- package/src/components/Callout/Callout.test.tsx +4 -3
- package/src/components/Callout/Callout.tsx +2 -5
- package/src/components/Dropdown/Dropdown.tsx +3 -7
- package/src/components/Form/Checkbox.tsx +2 -8
- package/src/components/Form/Input.tsx +2 -9
- package/src/components/Form/Radio.tsx +2 -9
- package/src/components/Form/Select.tsx +2 -7
- package/src/components/Form/Textarea.tsx +2 -9
- package/src/components/Messages/Messages.tsx +2 -8
- package/src/components/Modal/Modal.tsx +4 -5
- package/src/components/Navigation/Nav/Nav.tsx +2 -6
- package/src/components/Navigation/Navbar/Navbar.tsx +2 -9
- package/src/components/Navigation/SideMenu/SideMenu.tsx +2 -6
- package/src/components/Pagination/Pagination.tsx +2 -10
- package/src/components/Popover/Popover.tsx +2 -9
- package/src/components/Progress/Progress.tsx +2 -7
- package/src/components/Rating/Rating.tsx +2 -10
- package/src/components/Spinner/Spinner.tsx +2 -7
- package/src/components/Steps/Steps.tsx +2 -10
- package/src/components/Tabs/Tabs.tsx +2 -9
- package/src/components/Toggle/Toggle.tsx +2 -10
- package/src/components/Tooltip/Tooltip.tsx +2 -5
- package/src/lib/composables/useAtomixGlass.ts +41 -10
- package/src/lib/composables/useAtomixGlassStyles.ts +59 -75
- package/src/lib/composables/usePerformanceMonitor.ts +5 -0
- package/src/lib/constants/components.ts +358 -46
- package/src/lib/types/components.ts +33 -1
- package/src/styles/01-settings/_settings.atomix-glass.scss +66 -28
- package/src/styles/02-tools/_tools.glass.scss +45 -3
- package/src/styles/06-components/_components.atomix-glass.scss +114 -77
- package/src/components/AtomixGlass/deprecated/AtomixGlass.deprecated.tsx +0 -390
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import React, { forwardRef, memo, useMemo, useRef } from 'react';
|
|
2
2
|
import type { AtomixGlassProps } from '../../lib/types/components';
|
|
3
3
|
import { ATOMIX_GLASS } from '../../lib/constants/components';
|
|
4
|
+
import { mergeClassNames } from '../../lib/utils/componentUtils';
|
|
5
|
+
import useForkRef from '../../lib/utils/useForkRef';
|
|
4
6
|
import { AtomixGlassContainer } from './AtomixGlassContainer';
|
|
7
|
+
import {
|
|
8
|
+
buildGlassRootCssVariables,
|
|
9
|
+
getGlassInternalPositionStyles,
|
|
10
|
+
isGlassFixedOrSticky,
|
|
11
|
+
resolveGlassAdjustedSize,
|
|
12
|
+
resolveGlassContainerEffects,
|
|
13
|
+
} from './glass-utils';
|
|
5
14
|
import { useAtomixGlass } from '../../lib/composables/useAtomixGlass';
|
|
6
|
-
// Phase 3: Optimization & Adaptation
|
|
7
15
|
import { useResponsiveGlass } from '../../lib/composables/useResponsiveGlass';
|
|
8
16
|
import { usePerformanceMonitor } from '../../lib/composables/usePerformanceMonitor';
|
|
9
|
-
import { PerformanceDashboard } from './PerformanceDashboard';
|
|
10
17
|
import {
|
|
11
18
|
getDevicePreset,
|
|
12
19
|
MOBILE_OPTIMIZED_BREAKPOINTS,
|
|
@@ -35,6 +42,10 @@ import {
|
|
|
35
42
|
* - Implements focus-ring mixin for accessibility
|
|
36
43
|
* - Supports reduced motion and high contrast preferences
|
|
37
44
|
*
|
|
45
|
+
* Style architecture:
|
|
46
|
+
* - Root (`.c-atomix-glass`): CSS custom properties for layer geometry and motion.
|
|
47
|
+
* - Container (`.c-atomix-glass__container`): layout, z-index, and backdrop-filter.
|
|
48
|
+
*
|
|
38
49
|
* @example
|
|
39
50
|
* // Basic usage with dynamic border-radius extraction
|
|
40
51
|
* <AtomixGlass>
|
|
@@ -92,29 +103,7 @@ import {
|
|
|
92
103
|
* </AtomixGlass>
|
|
93
104
|
*/
|
|
94
105
|
|
|
95
|
-
|
|
96
|
-
declare global {
|
|
97
|
-
interface Window {
|
|
98
|
-
enablePerformanceMonitoring?: boolean;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Helper to merge refs
|
|
103
|
-
function mergeRefs<T = any>(
|
|
104
|
-
...refs: (React.MutableRefObject<T> | React.LegacyRef<T> | undefined | null)[]
|
|
105
|
-
) {
|
|
106
|
-
return (node: T) => {
|
|
107
|
-
refs.forEach(ref => {
|
|
108
|
-
if (typeof ref === 'function') {
|
|
109
|
-
ref(node);
|
|
110
|
-
} else if (ref != null) {
|
|
111
|
-
(ref as React.MutableRefObject<T | null>).current = node;
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Internal implementation with forwardRef
|
|
106
|
+
/** Internal implementation; ref is forwarded to the root wrapper element. */
|
|
118
107
|
const AtomixGlassInner = forwardRef<HTMLDivElement, AtomixGlassProps>(function AtomixGlass(
|
|
119
108
|
{
|
|
120
109
|
children,
|
|
@@ -128,7 +117,7 @@ const AtomixGlassInner = forwardRef<HTMLDivElement, AtomixGlassProps>(function A
|
|
|
128
117
|
mouseOffset: externalMouseOffset,
|
|
129
118
|
mouseContainer = null,
|
|
130
119
|
className = '',
|
|
131
|
-
|
|
120
|
+
|
|
132
121
|
overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT,
|
|
133
122
|
style = {},
|
|
134
123
|
mode = ATOMIX_GLASS.DEFAULTS.MODE,
|
|
@@ -142,7 +131,9 @@ const AtomixGlassInner = forwardRef<HTMLDivElement, AtomixGlassProps>(function A
|
|
|
142
131
|
highContrast = false,
|
|
143
132
|
withoutEffects = false,
|
|
144
133
|
withLiquidBlur = false,
|
|
134
|
+
border,
|
|
145
135
|
withBorder = true,
|
|
136
|
+
debugBorderRadius = false,
|
|
146
137
|
withOverLightLayers = ATOMIX_GLASS.DEFAULTS.ENABLE_OVER_LIGHT_LAYERS,
|
|
147
138
|
debugPerformance = false,
|
|
148
139
|
debugOverLight = false,
|
|
@@ -165,21 +156,18 @@ const AtomixGlassInner = forwardRef<HTMLDivElement, AtomixGlassProps>(function A
|
|
|
165
156
|
const glassRef = useRef<HTMLDivElement>(null);
|
|
166
157
|
const contentRef = useRef<HTMLDivElement>(null);
|
|
167
158
|
const internalWrapperRef = useRef<HTMLDivElement>(null);
|
|
168
|
-
const mergedRef =
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
// real z-index on the root element — that would break the glass effect.
|
|
159
|
+
const mergedRef = useForkRef(ref, internalWrapperRef);
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Style partitioning for backdrop-filter compatibility.
|
|
163
|
+
* - Root (`.c-atomix-glass`): CSS custom properties only (`glassVars`).
|
|
164
|
+
* - Container (`.c-atomix-glass__container`): layout, stacking, and visual styles.
|
|
165
|
+
* Backdrop sampling occurs on `__filter-overlay` inside the container; layout
|
|
166
|
+
* properties must not be applied to the root or the effect will not render correctly.
|
|
167
|
+
*/
|
|
178
168
|
const { zIndex: customZIndex, ...restStyle } = style;
|
|
179
|
-
const isFixedOrSticky =
|
|
180
|
-
propsIsFixedOrSticky || restStyle.position === 'fixed' || restStyle.position === 'sticky';
|
|
169
|
+
const isFixedOrSticky = isGlassFixedOrSticky(propsIsFixedOrSticky, restStyle.position);
|
|
181
170
|
|
|
182
|
-
// Use composable hook for all state and logic
|
|
183
171
|
const {
|
|
184
172
|
isHovered,
|
|
185
173
|
isActive,
|
|
@@ -198,6 +186,7 @@ const AtomixGlassInner = forwardRef<HTMLDivElement, AtomixGlassProps>(function A
|
|
|
198
186
|
handleMouseDown,
|
|
199
187
|
handleMouseUp,
|
|
200
188
|
handleKeyDown,
|
|
189
|
+
resolvedBorder,
|
|
201
190
|
} = useAtomixGlass({
|
|
202
191
|
glassRef,
|
|
203
192
|
contentRef,
|
|
@@ -218,10 +207,12 @@ const AtomixGlassInner = forwardRef<HTMLDivElement, AtomixGlassProps>(function A
|
|
|
218
207
|
blurAmount,
|
|
219
208
|
saturation,
|
|
220
209
|
withLiquidBlur,
|
|
221
|
-
|
|
210
|
+
border,
|
|
211
|
+
withBorder,
|
|
212
|
+
debugBorderRadius,
|
|
213
|
+
|
|
222
214
|
style,
|
|
223
215
|
isFixedOrSticky,
|
|
224
|
-
// Phase 1: Animation System props
|
|
225
216
|
withTimeAnimation,
|
|
226
217
|
animationSpeed,
|
|
227
218
|
withMultiLayerDistortion,
|
|
@@ -231,16 +222,11 @@ const AtomixGlassInner = forwardRef<HTMLDivElement, AtomixGlassProps>(function A
|
|
|
231
222
|
distortionQuality,
|
|
232
223
|
});
|
|
233
224
|
|
|
234
|
-
// ============================================================================
|
|
235
|
-
// Phase 3: Optimization & Adaptation Systems
|
|
236
|
-
// ============================================================================
|
|
237
225
|
|
|
238
|
-
// Get device preset parameters - memoized to prevent recalculation
|
|
239
226
|
const devicePresetParams = useMemo(() => {
|
|
240
227
|
return getDevicePreset(devicePreset);
|
|
241
228
|
}, [devicePreset]);
|
|
242
229
|
|
|
243
|
-
// Responsive breakpoint system - automatically adjusts parameters based on viewport
|
|
244
230
|
useResponsiveGlass({
|
|
245
231
|
baseParams: {
|
|
246
232
|
...devicePresetParams,
|
|
@@ -259,309 +245,142 @@ const AtomixGlassInner = forwardRef<HTMLDivElement, AtomixGlassProps>(function A
|
|
|
259
245
|
debug: false,
|
|
260
246
|
});
|
|
261
247
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
enabled: debugPerformance, // Enable when debugPerformance is true
|
|
248
|
+
usePerformanceMonitor({
|
|
249
|
+
enabled: debugPerformance,
|
|
265
250
|
debug: false,
|
|
266
251
|
showOverlay: false,
|
|
267
252
|
});
|
|
268
253
|
|
|
269
|
-
// Auto-start performance monitoring when debugPerformance is enabled
|
|
270
|
-
React.useEffect(() => {
|
|
271
|
-
if (debugPerformance) {
|
|
272
|
-
toggleMonitoring();
|
|
273
|
-
}
|
|
274
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
275
|
-
}, [debugPerformance]); // Re-run when debugPerformance changes
|
|
276
|
-
|
|
277
254
|
const isOverLight = useMemo(() => overLightConfig.isOverLight, [overLightConfig.isOverLight]);
|
|
278
255
|
|
|
279
256
|
const shouldRenderOverLightLayers = withOverLightLayers && isOverLight;
|
|
280
257
|
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
const { position: p, top: t, left: l, right: r, bottom: b } = restStyle;
|
|
284
|
-
return {
|
|
285
|
-
...(p && { position: p }),
|
|
286
|
-
...(t !== undefined && { top: t }),
|
|
287
|
-
...(l !== undefined && { left: l }),
|
|
288
|
-
...(r !== undefined && { right: r }),
|
|
289
|
-
...(b !== undefined && { bottom: b }),
|
|
290
|
-
};
|
|
291
|
-
}, [isFixedOrSticky, restStyle]);
|
|
292
|
-
|
|
293
|
-
// Calculate base style with transforms
|
|
294
|
-
// When layout is hoisted to the root, strip those props from the container
|
|
295
|
-
const baseStyle = useMemo(() => {
|
|
296
|
-
if (isFixedOrSticky) {
|
|
297
|
-
const { position: _p, top: _t, left: _l, right: _r, bottom: _b, ...visualStyle } = restStyle;
|
|
298
|
-
return {
|
|
299
|
-
...visualStyle,
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
return {
|
|
258
|
+
const containerStyle = useMemo(
|
|
259
|
+
() => ({
|
|
303
260
|
...restStyle,
|
|
304
|
-
|
|
305
|
-
|
|
261
|
+
...(customZIndex !== undefined && { zIndex: customZIndex }),
|
|
262
|
+
}),
|
|
263
|
+
[restStyle, customZIndex]
|
|
264
|
+
);
|
|
306
265
|
|
|
307
|
-
|
|
308
|
-
const componentClassName = [
|
|
266
|
+
const componentClassName = mergeClassNames(
|
|
309
267
|
ATOMIX_GLASS.BASE_CLASS,
|
|
310
268
|
effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`,
|
|
311
269
|
effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`,
|
|
312
270
|
effectiveWithoutEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`,
|
|
313
|
-
className
|
|
314
|
-
|
|
315
|
-
.filter(Boolean)
|
|
316
|
-
.join(' ');
|
|
271
|
+
className
|
|
272
|
+
);
|
|
317
273
|
|
|
318
|
-
// Calculate position and size styles for internal layers
|
|
319
|
-
// When root is fixed/sticky, internal layers use absolute (relative to root)
|
|
320
274
|
const positionStyles = useMemo(
|
|
321
|
-
() => (
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
275
|
+
() => getGlassInternalPositionStyles(isFixedOrSticky, restStyle),
|
|
276
|
+
[isFixedOrSticky, restStyle]
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
const adjustedSize = useMemo(
|
|
280
|
+
() =>
|
|
281
|
+
resolveGlassAdjustedSize({
|
|
282
|
+
width,
|
|
283
|
+
height,
|
|
284
|
+
restStyle,
|
|
285
|
+
glassSize,
|
|
286
|
+
isFixedOrSticky,
|
|
287
|
+
}),
|
|
288
|
+
[width, height, restStyle, glassSize, isFixedOrSticky]
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
const glassVars = useMemo(
|
|
292
|
+
() =>
|
|
293
|
+
buildGlassRootCssVariables({
|
|
294
|
+
effectiveBorderRadius,
|
|
295
|
+
transformStyle,
|
|
296
|
+
adjustedSize,
|
|
297
|
+
isOverLight,
|
|
298
|
+
customZIndex,
|
|
299
|
+
isFixedOrSticky,
|
|
300
|
+
positionStyles,
|
|
301
|
+
restStyle,
|
|
302
|
+
borderWidth: resolvedBorder.width,
|
|
303
|
+
}),
|
|
330
304
|
[
|
|
305
|
+
effectiveBorderRadius,
|
|
306
|
+
transformStyle,
|
|
307
|
+
adjustedSize,
|
|
308
|
+
isOverLight,
|
|
309
|
+
customZIndex,
|
|
331
310
|
isFixedOrSticky,
|
|
332
|
-
|
|
333
|
-
restStyle
|
|
334
|
-
|
|
335
|
-
restStyle.right,
|
|
336
|
-
restStyle.bottom,
|
|
311
|
+
positionStyles,
|
|
312
|
+
restStyle,
|
|
313
|
+
resolvedBorder.width,
|
|
337
314
|
]
|
|
338
315
|
);
|
|
339
316
|
|
|
340
|
-
const
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
positionStyles.position,
|
|
370
|
-
glassSize.width,
|
|
371
|
-
glassSize.height,
|
|
372
|
-
isFixedOrSticky,
|
|
373
|
-
]);
|
|
374
|
-
|
|
375
|
-
// Memoize expensive gradient calculations
|
|
376
|
-
const gradientValues = useMemo(() => {
|
|
377
|
-
const mx = mouseOffset.x;
|
|
378
|
-
const my = mouseOffset.y;
|
|
379
|
-
const absMx = Math.abs(mx);
|
|
380
|
-
const absMy = Math.abs(my);
|
|
381
|
-
const GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
|
|
382
|
-
|
|
383
|
-
return {
|
|
384
|
-
borderGradientAngle: GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER,
|
|
385
|
-
borderStop1: Math.max(
|
|
386
|
-
GRADIENT.BORDER_STOP_1.MIN,
|
|
387
|
-
GRADIENT.BORDER_STOP_1.BASE + my * GRADIENT.BORDER_STOP_1.MULTIPLIER
|
|
388
|
-
),
|
|
389
|
-
borderStop2: Math.min(
|
|
390
|
-
GRADIENT.BORDER_STOP_2.MAX,
|
|
391
|
-
GRADIENT.BORDER_STOP_2.BASE + my * GRADIENT.BORDER_STOP_2.MULTIPLIER
|
|
392
|
-
),
|
|
393
|
-
borderOpacities: [
|
|
394
|
-
GRADIENT.BORDER_OPACITY.BASE_1 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW,
|
|
395
|
-
GRADIENT.BORDER_OPACITY.BASE_2 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH,
|
|
396
|
-
GRADIENT.BORDER_OPACITY.BASE_3 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW,
|
|
397
|
-
GRADIENT.BORDER_OPACITY.BASE_4 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH,
|
|
398
|
-
],
|
|
399
|
-
hoverPositions: {
|
|
400
|
-
hover1: {
|
|
401
|
-
x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
|
|
402
|
-
y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1,
|
|
403
|
-
},
|
|
404
|
-
hover2: {
|
|
405
|
-
x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_2,
|
|
406
|
-
y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_2,
|
|
407
|
-
},
|
|
408
|
-
hover3: {
|
|
409
|
-
x: GRADIENT.CENTER_POSITION + mx * GRADIENT.HOVER_POSITION.MULTIPLIER_3,
|
|
410
|
-
y: GRADIENT.CENTER_POSITION + my * GRADIENT.HOVER_POSITION.MULTIPLIER_3,
|
|
411
|
-
},
|
|
412
|
-
},
|
|
413
|
-
basePosition: {
|
|
414
|
-
x: GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER,
|
|
415
|
-
y: GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER,
|
|
416
|
-
},
|
|
417
|
-
mx,
|
|
418
|
-
my,
|
|
419
|
-
absMx,
|
|
420
|
-
absMy,
|
|
421
|
-
};
|
|
422
|
-
}, [mouseOffset.x, mouseOffset.y]);
|
|
423
|
-
|
|
424
|
-
// Clamp overLight opacities to [0,1]
|
|
425
|
-
const clampedOverLightOpacity = Math.max(0, Math.min(1, overLightConfig?.opacity ?? 0.4));
|
|
426
|
-
const clampedBorderOpacity = Math.max(0, Math.min(1, overLightConfig?.borderOpacity ?? 1));
|
|
427
|
-
|
|
428
|
-
// Memoize opacity calculations
|
|
429
|
-
const opacityValues = useMemo(() => {
|
|
430
|
-
// Use clamped opacity value here
|
|
431
|
-
const overLightOpacity = clampedOverLightOpacity;
|
|
432
|
-
const BASE_OVER_LIGHT_OPACITY = 0.4;
|
|
433
|
-
const OVER_OPACITY_MULTIPLIER = 1.1;
|
|
434
|
-
|
|
435
|
-
return {
|
|
436
|
-
hover1: isHovered || isActive ? 0.5 : 0,
|
|
437
|
-
hover2: isActive ? 0.5 : 0,
|
|
438
|
-
hover3: isHovered ? 0.4 : isActive ? 0.8 : 0,
|
|
439
|
-
base: isOverLight ? overLightOpacity || BASE_OVER_LIGHT_OPACITY : 0,
|
|
440
|
-
over: isOverLight
|
|
441
|
-
? (overLightOpacity || BASE_OVER_LIGHT_OPACITY) * OVER_OPACITY_MULTIPLIER
|
|
442
|
-
: 0,
|
|
443
|
-
};
|
|
444
|
-
}, [isHovered, isActive, isOverLight, clampedOverLightOpacity]);
|
|
445
|
-
|
|
446
|
-
// Memoize CSS variables object
|
|
447
|
-
const glassVars = useMemo(() => {
|
|
448
|
-
const whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE;
|
|
449
|
-
const blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK;
|
|
450
|
-
const {
|
|
451
|
-
borderGradientAngle,
|
|
452
|
-
borderStop1,
|
|
453
|
-
borderStop2,
|
|
454
|
-
borderOpacities,
|
|
455
|
-
hoverPositions,
|
|
456
|
-
basePosition,
|
|
457
|
-
mx,
|
|
458
|
-
my,
|
|
459
|
-
absMx,
|
|
460
|
-
absMy,
|
|
461
|
-
} = gradientValues;
|
|
462
|
-
|
|
463
|
-
return {
|
|
464
|
-
...(customZIndex !== undefined && { '--atomix-glass-base-z-index': customZIndex }),
|
|
465
|
-
'--atomix-glass-radius': `${effectiveBorderRadius}px`,
|
|
466
|
-
'--atomix-glass-transform': transformStyle || 'none',
|
|
467
|
-
'--atomix-glass-container-position': `${!isFixedOrSticky ? positionStyles.position : rootLayoutStyle.position}`,
|
|
468
|
-
'--atomix-glass-position': `${!isFixedOrSticky ? positionStyles.position : rootLayoutStyle.position}`,
|
|
469
|
-
'--atomix-glass-top': `${!isFixedOrSticky ? 0 : (restStyle.top ?? 0)}px`,
|
|
470
|
-
'--atomix-glass-left': `${!isFixedOrSticky ? 0 : (restStyle.left ?? 0)}px`,
|
|
471
|
-
'--atomix-glass-right': !isFixedOrSticky ? 'auto' : (restStyle.right ?? 'auto'),
|
|
472
|
-
'--atomix-glass-bottom': !isFixedOrSticky ? 'auto' : (restStyle.bottom ?? 'auto'),
|
|
473
|
-
'--atomix-glass-width': adjustedSize.width,
|
|
474
|
-
'--atomix-glass-height': adjustedSize.height,
|
|
475
|
-
'--atomix-glass-border-width': 'var(--atomix-spacing-0-5, 0.125rem)',
|
|
476
|
-
'--atomix-glass-blend-mode': isOverLight ? 'multiply' : 'overlay',
|
|
477
|
-
'--atomix-glass-border-gradient-1': `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * clampedBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * clampedBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
|
|
478
|
-
'--atomix-glass-border-gradient-2': `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[2] ?? 1) * clampedBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[3] ?? 1) * clampedBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
|
|
479
|
-
'--atomix-glass-hover-1-opacity': opacityValues.hover1,
|
|
480
|
-
'--atomix-glass-hover-1-gradient': isOverLight
|
|
481
|
-
? `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_END}%)`
|
|
482
|
-
: `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_STOP}%)`,
|
|
483
|
-
'--atomix-glass-hover-2-opacity': opacityValues.hover2,
|
|
484
|
-
'--atomix-glass-hover-2-gradient': isOverLight
|
|
485
|
-
? `radial-gradient(circle at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_END}%)`
|
|
486
|
-
: `radial-gradient(circle at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_STOP}%)`,
|
|
487
|
-
'--atomix-glass-hover-3-opacity': opacityValues.hover3,
|
|
488
|
-
'--atomix-glass-hover-3-gradient': isOverLight
|
|
489
|
-
? `radial-gradient(circle at ${hoverPositions.hover3.x}% ${hoverPositions.hover3.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_END}%)`
|
|
490
|
-
: `radial-gradient(circle at ${hoverPositions.hover3.x}% ${hoverPositions.hover3.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_STOP}%)`,
|
|
491
|
-
'--atomix-glass-base-opacity': opacityValues.base,
|
|
492
|
-
'--atomix-glass-base-gradient': isOverLight
|
|
493
|
-
? `linear-gradient(${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.ANGLE}deg, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_BASE + mx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_BASE + my * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_MULTIPLIER}) ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_BASE + absMx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_MULTIPLIER}) 100%)`
|
|
494
|
-
: `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.WHITE_OPACITY})`,
|
|
495
|
-
'--atomix-glass-overlay-opacity': opacityValues.over,
|
|
496
|
-
'--atomix-glass-overlay-gradient': isOverLight
|
|
497
|
-
? `radial-gradient(circle at ${basePosition.x}% ${basePosition.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + absMx * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_BASE + absMy * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)`
|
|
498
|
-
: `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`,
|
|
499
|
-
'--atomix-glass-overlay-highlight-opacity':
|
|
500
|
-
opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
|
|
501
|
-
'--atomix-glass-overlay-highlight-bg': `radial-gradient(circle at ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_X}% ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_Y}%, rgba(255, 255, 255, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.WHITE_OPACITY}) 0%, transparent ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.STOP}%)`,
|
|
502
|
-
} as React.CSSProperties;
|
|
503
|
-
}, [
|
|
504
|
-
gradientValues,
|
|
505
|
-
opacityValues,
|
|
506
|
-
effectiveBorderRadius,
|
|
507
|
-
transformStyle,
|
|
508
|
-
adjustedSize,
|
|
509
|
-
isOverLight,
|
|
510
|
-
clampedBorderOpacity,
|
|
511
|
-
customZIndex,
|
|
512
|
-
isFixedOrSticky,
|
|
513
|
-
positionStyles.position,
|
|
514
|
-
rootLayoutStyle.position,
|
|
515
|
-
restStyle.top,
|
|
516
|
-
restStyle.left,
|
|
517
|
-
restStyle.right,
|
|
518
|
-
restStyle.bottom,
|
|
519
|
-
]);
|
|
520
|
-
|
|
521
|
-
// ─── Render helpers ──────────────────────────────────────────────────────
|
|
317
|
+
const containerEffects = useMemo(
|
|
318
|
+
() =>
|
|
319
|
+
resolveGlassContainerEffects({
|
|
320
|
+
displacementScale,
|
|
321
|
+
blurAmount,
|
|
322
|
+
saturation,
|
|
323
|
+
aberrationIntensity,
|
|
324
|
+
mode,
|
|
325
|
+
effectiveWithoutEffects,
|
|
326
|
+
effectiveHighContrast,
|
|
327
|
+
isOverLight,
|
|
328
|
+
saturationBoost: overLightConfig.saturationBoost,
|
|
329
|
+
mouseOffset,
|
|
330
|
+
globalMousePosition,
|
|
331
|
+
}),
|
|
332
|
+
[
|
|
333
|
+
displacementScale,
|
|
334
|
+
blurAmount,
|
|
335
|
+
saturation,
|
|
336
|
+
aberrationIntensity,
|
|
337
|
+
mode,
|
|
338
|
+
effectiveWithoutEffects,
|
|
339
|
+
effectiveHighContrast,
|
|
340
|
+
isOverLight,
|
|
341
|
+
overLightConfig.saturationBoost,
|
|
342
|
+
mouseOffset,
|
|
343
|
+
globalMousePosition,
|
|
344
|
+
]
|
|
345
|
+
);
|
|
522
346
|
|
|
523
347
|
const renderHoverLayers = () => (
|
|
524
348
|
<>
|
|
525
|
-
|
|
526
|
-
<div className={ATOMIX_GLASS.
|
|
527
|
-
<div className={ATOMIX_GLASS.
|
|
528
|
-
<div className={ATOMIX_GLASS.HOVER_3_CLASS} />
|
|
349
|
+
<div aria-hidden="true" className={ATOMIX_GLASS.HOVER_1_CLASS} />
|
|
350
|
+
<div aria-hidden="true" className={ATOMIX_GLASS.HOVER_2_CLASS} />
|
|
351
|
+
<div aria-hidden="true" className={ATOMIX_GLASS.HOVER_3_CLASS} />
|
|
529
352
|
</>
|
|
530
353
|
);
|
|
531
354
|
|
|
532
|
-
const
|
|
355
|
+
const backgroundLayerTypes = ['dark', 'black'] as const;
|
|
356
|
+
const renderBackgroundLayer = (layerType: (typeof backgroundLayerTypes)[number]) => (
|
|
533
357
|
<div
|
|
534
|
-
|
|
358
|
+
aria-hidden="true"
|
|
359
|
+
className={mergeClassNames(
|
|
535
360
|
ATOMIX_GLASS.BACKGROUND_LAYER_CLASS,
|
|
536
361
|
layerType === 'dark'
|
|
537
362
|
? ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS
|
|
538
363
|
: ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS,
|
|
539
364
|
isOverLight
|
|
540
365
|
? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS
|
|
541
|
-
: ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS
|
|
542
|
-
|
|
543
|
-
.filter(Boolean)
|
|
544
|
-
.join(' ')}
|
|
366
|
+
: ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS
|
|
367
|
+
)}
|
|
545
368
|
/>
|
|
546
369
|
);
|
|
547
370
|
|
|
548
371
|
const renderOverLightLayers = () => (
|
|
549
372
|
<>
|
|
550
|
-
|
|
551
|
-
<div className={ATOMIX_GLASS.
|
|
552
|
-
<div className={ATOMIX_GLASS.
|
|
553
|
-
{/* Overlay highlight - opacity and background are dynamic, calculated inline */}
|
|
554
|
-
<div className={ATOMIX_GLASS.OVERLAY_HIGHLIGHT_CLASS} />
|
|
373
|
+
<div aria-hidden="true" className={ATOMIX_GLASS.BASE_LAYER_CLASS} />
|
|
374
|
+
<div aria-hidden="true" className={ATOMIX_GLASS.OVERLAY_LAYER_CLASS} />
|
|
375
|
+
<div aria-hidden="true" className={ATOMIX_GLASS.OVERLAY_HIGHLIGHT_CLASS} />
|
|
555
376
|
</>
|
|
556
377
|
);
|
|
557
378
|
|
|
558
379
|
const renderBorderElements = () => (
|
|
559
380
|
<>
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
<span className={ATOMIX_GLASS.
|
|
563
|
-
<span className={ATOMIX_GLASS.BORDER_1_CLASS} />
|
|
564
|
-
<span className={ATOMIX_GLASS.BORDER_2_CLASS} />
|
|
381
|
+
<span aria-hidden="true" className={ATOMIX_GLASS.BORDER_BACKDROP_CLASS} />
|
|
382
|
+
<span aria-hidden="true" className={ATOMIX_GLASS.BORDER_1_CLASS} />
|
|
383
|
+
<span aria-hidden="true" className={ATOMIX_GLASS.BORDER_2_CLASS} />
|
|
565
384
|
</>
|
|
566
385
|
);
|
|
567
386
|
|
|
@@ -570,54 +389,31 @@ const AtomixGlassInner = forwardRef<HTMLDivElement, AtomixGlassProps>(function A
|
|
|
570
389
|
{...rest}
|
|
571
390
|
ref={mergedRef}
|
|
572
391
|
className={componentClassName}
|
|
573
|
-
style={
|
|
392
|
+
style={glassVars}
|
|
574
393
|
role={role || (onClick ? 'button' : undefined)}
|
|
575
394
|
tabIndex={onClick ? (tabIndex ?? 0) : tabIndex}
|
|
576
395
|
aria-label={ariaLabel}
|
|
577
396
|
aria-describedby={ariaDescribedBy}
|
|
578
397
|
aria-disabled={onClick && effectiveWithoutEffects ? true : onClick ? false : undefined}
|
|
579
|
-
aria-pressed={onClick ? isActive : undefined}
|
|
580
398
|
onKeyDown={onClick ? handleKeyDown : undefined}
|
|
581
399
|
>
|
|
582
400
|
<AtomixGlassContainer
|
|
583
401
|
ref={glassRef}
|
|
584
402
|
contentRef={contentRef}
|
|
585
403
|
className={className}
|
|
586
|
-
style={
|
|
404
|
+
style={containerStyle as React.CSSProperties}
|
|
587
405
|
borderRadius={effectiveBorderRadius}
|
|
588
|
-
displacementScale={
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT
|
|
593
|
-
: isOverLight
|
|
594
|
-
? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT
|
|
595
|
-
: displacementScale
|
|
596
|
-
}
|
|
597
|
-
blurAmount={effectiveWithoutEffects ? 0 : blurAmount}
|
|
598
|
-
saturation={
|
|
599
|
-
effectiveHighContrast
|
|
600
|
-
? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST
|
|
601
|
-
: isOverLight
|
|
602
|
-
? saturation * overLightConfig.saturationBoost
|
|
603
|
-
: saturation
|
|
604
|
-
}
|
|
605
|
-
aberrationIntensity={
|
|
606
|
-
effectiveWithoutEffects
|
|
607
|
-
? 0
|
|
608
|
-
: mode === 'shader'
|
|
609
|
-
? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION
|
|
610
|
-
: aberrationIntensity
|
|
611
|
-
}
|
|
406
|
+
displacementScale={containerEffects.displacementScale}
|
|
407
|
+
blurAmount={containerEffects.blurAmount}
|
|
408
|
+
saturation={containerEffects.saturation}
|
|
409
|
+
aberrationIntensity={containerEffects.aberrationIntensity}
|
|
612
410
|
glassSize={glassSize}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
globalMousePosition={effectiveWithoutEffects ? { x: 0, y: 0 } : globalMousePosition}
|
|
411
|
+
mouseOffset={containerEffects.mouseOffset}
|
|
412
|
+
globalMousePosition={containerEffects.globalMousePosition}
|
|
616
413
|
onMouseEnter={handleMouseEnter}
|
|
617
414
|
onMouseLeave={handleMouseLeave}
|
|
618
415
|
onMouseDown={handleMouseDown}
|
|
619
416
|
onMouseUp={handleMouseUp}
|
|
620
|
-
isHovered={isHovered}
|
|
621
417
|
isActive={isActive}
|
|
622
418
|
overLight={isOverLight}
|
|
623
419
|
overLightConfig={{
|
|
@@ -633,7 +429,6 @@ const AtomixGlassInner = forwardRef<HTMLDivElement, AtomixGlassProps>(function A
|
|
|
633
429
|
shaderVariant={shaderVariant}
|
|
634
430
|
withLiquidBlur={withLiquidBlur}
|
|
635
431
|
isFixedOrSticky={isFixedOrSticky}
|
|
636
|
-
// Phase 1: Animation System props
|
|
637
432
|
shaderTime={getShaderTime()}
|
|
638
433
|
withTimeAnimation={withTimeAnimation}
|
|
639
434
|
animationSpeed={animationSpeed}
|
|
@@ -648,32 +443,19 @@ const AtomixGlassInner = forwardRef<HTMLDivElement, AtomixGlassProps>(function A
|
|
|
648
443
|
|
|
649
444
|
{Boolean(onClick) && renderHoverLayers()}
|
|
650
445
|
|
|
651
|
-
{
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
{renderBackgroundLayer('black')}
|
|
446
|
+
{backgroundLayerTypes.map(layerType => (
|
|
447
|
+
<React.Fragment key={layerType}>{renderBackgroundLayer(layerType)}</React.Fragment>
|
|
448
|
+
))}
|
|
655
449
|
{shouldRenderOverLightLayers && renderOverLightLayers()}
|
|
656
450
|
|
|
657
|
-
{
|
|
658
|
-
|
|
659
|
-
{/* Phase 3: Performance Monitoring Dashboard - Only in development with debugPerformance enabled */}
|
|
660
|
-
{debugPerformance && performanceMetrics && (
|
|
661
|
-
<PerformanceDashboard
|
|
662
|
-
metrics={performanceMetrics}
|
|
663
|
-
isVisible={true}
|
|
664
|
-
onClose={() => {}} // No-op, dashboard always visible when debugPerformance is true
|
|
665
|
-
/>
|
|
666
|
-
)}
|
|
451
|
+
{resolvedBorder.enabled && renderBorderElements()}
|
|
667
452
|
</div>
|
|
668
453
|
);
|
|
669
454
|
});
|
|
670
455
|
|
|
671
456
|
AtomixGlassInner.displayName = 'AtomixGlass';
|
|
672
457
|
|
|
673
|
-
/**
|
|
674
|
-
* AtomixGlass - wrapped with React.memo to prevent unnecessary re-renders.
|
|
675
|
-
* Ref is forwarded to the root `<div>` element.
|
|
676
|
-
*/
|
|
458
|
+
/** Memoized public export. Ref targets the root `.c-atomix-glass` wrapper. */
|
|
677
459
|
export const AtomixGlass = memo(AtomixGlassInner);
|
|
678
460
|
|
|
679
461
|
export default AtomixGlass;
|