@shohojdhara/atomix 0.4.1 → 0.4.3
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 +9351 -9259
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +4 -4
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.d.ts +12 -19
- package/dist/charts.js +555 -358
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +21 -24
- package/dist/core.js +435 -265
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +11 -18
- package/dist/forms.js +411 -257
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +14 -21
- package/dist/heavy.js +409 -254
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +38 -41
- package/dist/index.esm.js +731 -487
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +733 -492
- 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/scripts/atomix-cli.js +34 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +82 -54
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +17 -18
- package/src/components/AtomixGlass/README.md +5 -5
- package/src/components/AtomixGlass/stories/Customization.stories.tsx +2 -2
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +42 -42
- package/src/components/AtomixGlass/stories/Modes.stories.tsx +5 -5
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +3 -3
- package/src/components/AtomixGlass/stories/Performance.stories.tsx +2 -2
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +45 -45
- package/src/components/AtomixGlass/stories/Shaders.stories.tsx +3 -3
- package/src/components/Badge/Badge.stories.tsx +1 -1
- package/src/components/Badge/Badge.tsx +1 -1
- package/src/components/Breadcrumb/Breadcrumb.tsx +90 -77
- package/src/components/Breadcrumb/index.ts +2 -2
- package/src/components/Button/Button.stories.tsx +1 -1
- package/src/components/Button/Button.tsx +2 -1
- package/src/components/Button/README.md +2 -2
- package/src/components/Callout/Callout.test.tsx +3 -3
- package/src/components/Callout/Callout.tsx +2 -2
- package/src/components/Callout/README.md +2 -2
- package/src/components/Card/Card.tsx +31 -11
- package/src/components/Chart/Chart.stories.tsx +1 -1
- package/src/components/Chart/Chart.tsx +5 -5
- package/src/components/Chart/TreemapChart.tsx +37 -29
- package/src/components/DatePicker/readme.md +3 -3
- package/src/components/Dropdown/Dropdown.stories.tsx +1 -1
- package/src/components/Dropdown/Dropdown.tsx +276 -273
- package/src/components/EdgePanel/EdgePanel.stories.tsx +7 -7
- package/src/components/Footer/FooterLink.tsx +2 -2
- package/src/components/Form/Checkbox.stories.tsx +1 -1
- package/src/components/Form/Checkbox.tsx +1 -1
- package/src/components/Form/Input.stories.tsx +1 -1
- package/src/components/Form/Input.tsx +1 -1
- package/src/components/Form/Radio.stories.tsx +1 -1
- package/src/components/Form/Radio.tsx +1 -1
- package/src/components/Form/Select.stories.tsx +1 -1
- package/src/components/Form/Select.tsx +1 -1
- package/src/components/Form/Textarea.stories.tsx +1 -1
- package/src/components/Form/Textarea.tsx +1 -1
- package/src/components/Hero/Hero.stories.tsx +2 -2
- package/src/components/Hero/Hero.tsx +2 -2
- package/src/components/Messages/Messages.stories.tsx +1 -1
- package/src/components/Messages/Messages.tsx +2 -2
- package/src/components/Modal/Modal.stories.tsx +1 -1
- package/src/components/Navigation/Nav/Nav.stories.tsx +2 -2
- package/src/components/Navigation/Nav/Nav.tsx +1 -1
- package/src/components/Navigation/Nav/NavItem.tsx +6 -3
- package/src/components/Navigation/Navbar/Navbar.stories.tsx +3 -3
- package/src/components/Navigation/Navbar/Navbar.tsx +1 -1
- package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +2 -2
- package/src/components/Navigation/SideMenu/SideMenu.tsx +1 -1
- package/src/components/Pagination/Pagination.stories.tsx +1 -1
- package/src/components/Pagination/Pagination.tsx +1 -1
- package/src/components/Popover/Popover.stories.tsx +1 -1
- package/src/components/Popover/Popover.tsx +1 -1
- package/src/components/Progress/Progress.tsx +1 -1
- package/src/components/Rating/Rating.stories.tsx +1 -1
- package/src/components/Rating/Rating.test.tsx +73 -0
- package/src/components/Rating/Rating.tsx +25 -37
- package/src/components/Spinner/Spinner.tsx +1 -1
- package/src/components/Steps/Steps.stories.tsx +1 -1
- package/src/components/Steps/Steps.tsx +2 -2
- package/src/components/Tabs/Tabs.stories.tsx +1 -1
- package/src/components/Tabs/Tabs.tsx +1 -1
- package/src/components/Todo/Todo.tsx +0 -1
- package/src/components/Toggle/Toggle.stories.tsx +1 -1
- package/src/components/Toggle/Toggle.tsx +1 -1
- package/src/components/Tooltip/Tooltip.stories.tsx +1 -1
- package/src/components/VideoPlayer/VideoPlayer.stories.tsx +2 -2
- package/src/lib/composables/__tests__/useAtomixGlassPerf.test.tsx +88 -0
- package/src/lib/composables/__tests__/useChart.test.ts +50 -0
- package/src/lib/composables/__tests__/useChart.test.tsx +139 -0
- package/src/lib/composables/__tests__/useHeroBackgroundSlider.test.tsx +59 -0
- package/src/lib/composables/__tests__/useSliderAutoplay.test.tsx +68 -0
- package/src/lib/composables/atomix-glass/useGlassBackgroundDetection.ts +329 -0
- package/src/lib/composables/atomix-glass/useGlassCornerRadius.ts +82 -0
- package/src/lib/composables/atomix-glass/useGlassMouseTracking.ts +153 -0
- package/src/lib/composables/atomix-glass/useGlassOverLight.ts +198 -0
- package/src/lib/composables/atomix-glass/useGlassSize.ts +117 -0
- package/src/lib/composables/atomix-glass/useGlassState.ts +112 -0
- package/src/lib/composables/atomix-glass/useGlassTransforms.ts +160 -0
- package/src/lib/composables/glass-styles.ts +302 -0
- package/src/lib/composables/index.ts +0 -4
- package/src/lib/composables/useAtomixGlass.ts +331 -522
- package/src/lib/composables/useAtomixGlassStyles.ts +307 -0
- package/src/lib/composables/useBarChart.ts +1 -1
- package/src/lib/composables/useBreadcrumb.ts +6 -6
- package/src/lib/composables/useChart.ts +104 -21
- package/src/lib/composables/useHeroBackgroundSlider.ts +16 -7
- package/src/lib/composables/useSlider.ts +66 -34
- package/src/lib/theme/devtools/CLI.ts +1 -1
- package/src/lib/theme/utils/__tests__/themeUtils.test.ts +213 -0
- package/src/lib/types/components.ts +18 -21
- package/src/lib/utils/__tests__/dom.test.ts +100 -0
- package/src/lib/utils/__tests__/fontPreloader.test.ts +102 -0
- package/src/styles/02-tools/_tools.breakpoints.scss +1 -1
- package/src/styles/02-tools/_tools.utility-api.scss +6 -6
- package/src/styles/06-components/_components.accordion.scss +0 -2
- package/src/styles/06-components/_components.chart.scss +0 -1
- package/src/styles/06-components/_components.dropdown.scss +0 -1
- package/src/styles/06-components/_components.edge-panel.scss +0 -2
- package/src/styles/06-components/_components.photoviewer.scss +0 -1
- package/src/styles/06-components/_components.river.scss +0 -1
- package/src/styles/06-components/_components.slider.scss +0 -3
- package/src/styles/99-utilities/_utilities.glass-fixes.scss +0 -1
- package/src/styles/99-utilities/_utilities.text.scss +1 -0
package/dist/index.js
CHANGED
|
@@ -1972,7 +1972,7 @@ function useAccordion(initialProps) {
|
|
|
1972
1972
|
};
|
|
1973
1973
|
}
|
|
1974
1974
|
|
|
1975
|
-
const {CONSTANTS: CONSTANTS$
|
|
1975
|
+
const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
|
|
1976
1976
|
if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
|
|
1977
1977
|
const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
|
|
1978
1978
|
return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
@@ -1985,36 +1985,36 @@ const {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
|
|
|
1985
1985
|
}, calculateMouseInfluence = mouseOffset => {
|
|
1986
1986
|
if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
|
|
1987
1987
|
// Bounded calculation — keeps the glass effect subtle and stable
|
|
1988
|
-
const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$
|
|
1988
|
+
const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$2.MOUSE_INFLUENCE_DIVISOR;
|
|
1989
1989
|
return Math.min(.8, influence);
|
|
1990
1990
|
// Tighter cap to prevent blur/filter blow-out
|
|
1991
|
-
}, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$
|
|
1991
|
+
}, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$2.MIN_BLUR : Math.max(CONSTANTS$2.MIN_BLUR, Math.min(50, value)), validateGlassSize = size => size && "number" == typeof size.width && "number" == typeof size.height && size.width > 0 && size.height > 0 && size.width <= CONSTANTS$2.MAX_SIZE && size.height <= CONSTANTS$2.MAX_SIZE, parseBorderRadiusValue = value => {
|
|
1992
1992
|
if ("number" == typeof value) return Math.max(0, value);
|
|
1993
|
-
if ("string" != typeof value || !value.trim()) return CONSTANTS$
|
|
1993
|
+
if ("string" != typeof value || !value.trim()) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
1994
1994
|
const trimmedValue = value.trim();
|
|
1995
1995
|
// Handle px values
|
|
1996
1996
|
if (trimmedValue.endsWith("px")) {
|
|
1997
1997
|
const parsed = parseFloat(trimmedValue);
|
|
1998
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
1998
|
+
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
|
|
1999
1999
|
}
|
|
2000
2000
|
// Handle rem values (assume 16px = 1rem)
|
|
2001
2001
|
if (trimmedValue.endsWith("rem")) {
|
|
2002
2002
|
const parsed = parseFloat(trimmedValue);
|
|
2003
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
2003
|
+
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
2004
2004
|
}
|
|
2005
2005
|
// Handle em values (assume 16px = 1em for simplicity)
|
|
2006
2006
|
if (trimmedValue.endsWith("em")) {
|
|
2007
2007
|
const parsed = parseFloat(trimmedValue);
|
|
2008
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
2008
|
+
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
2009
2009
|
}
|
|
2010
2010
|
// Handle percentage (convert to approximate px value, assuming 200px container)
|
|
2011
2011
|
if (trimmedValue.endsWith("%")) {
|
|
2012
2012
|
const parsed = parseFloat(trimmedValue);
|
|
2013
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
2013
|
+
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
|
|
2014
2014
|
}
|
|
2015
2015
|
// Handle unitless numbers
|
|
2016
2016
|
const numValue = parseFloat(trimmedValue);
|
|
2017
|
-
return isNaN(numValue) ? CONSTANTS$
|
|
2017
|
+
return isNaN(numValue) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
|
|
2018
2018
|
}, extractBorderRadiusFromElement = element => {
|
|
2019
2019
|
if (!element || !element.props) return null;
|
|
2020
2020
|
// Check inline styles first (highest priority)
|
|
@@ -2030,11 +2030,11 @@ const {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
|
|
|
2030
2030
|
// If element has children, recursively check them
|
|
2031
2031
|
if (element.props.children) {
|
|
2032
2032
|
const childRadius = extractBorderRadiusFromChildren(element.props.children);
|
|
2033
|
-
if (childRadius > 0 && childRadius !== CONSTANTS$
|
|
2033
|
+
if (childRadius > 0 && childRadius !== CONSTANTS$2.DEFAULT_CORNER_RADIUS) return childRadius;
|
|
2034
2034
|
}
|
|
2035
2035
|
return null;
|
|
2036
2036
|
}, extractBorderRadiusFromChildren = children => {
|
|
2037
|
-
if (!children) return CONSTANTS$
|
|
2037
|
+
if (!children) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
2038
2038
|
try {
|
|
2039
2039
|
const childArray = React__default.default.Children.toArray(children);
|
|
2040
2040
|
for (let i = 0; i < childArray.length; i++) {
|
|
@@ -2047,7 +2047,7 @@ const {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
|
|
|
2047
2047
|
} catch (error) {
|
|
2048
2048
|
// Silently handle errors
|
|
2049
2049
|
}
|
|
2050
|
-
return CONSTANTS$
|
|
2050
|
+
return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
2051
2051
|
}, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
|
|
2052
2052
|
switch (mode) {
|
|
2053
2053
|
case "standard":
|
|
@@ -2218,10 +2218,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2218
2218
|
}, globalMousePosition: globalMousePosition = {
|
|
2219
2219
|
x: 0,
|
|
2220
2220
|
y: 0
|
|
2221
|
-
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isHovered: isHovered = !1, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {},
|
|
2221
|
+
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isHovered: isHovered = !1, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0, padding: padding = "0 0", glassSize: glassSize = {
|
|
2222
2222
|
width: 0,
|
|
2223
2223
|
height: 0
|
|
2224
|
-
}, onClick: onClick, mode: mode = "standard",
|
|
2224
|
+
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
|
|
2225
2225
|
// Generate a stable, deterministic ID for SSR compatibility
|
|
2226
2226
|
// Use a module-level counter that's consistent across server and client
|
|
2227
2227
|
const filterId = React.useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = React.useState(""), shaderGeneratorRef = React.useRef(null), shaderUtilsRef = React.useRef(null), shaderDebounceTimeoutRef = React.useRef(null);
|
|
@@ -2333,7 +2333,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2333
2333
|
flowBlur: 1.2 * blurAmount
|
|
2334
2334
|
};
|
|
2335
2335
|
// Enhanced validation for liquid blur
|
|
2336
|
-
if (!
|
|
2336
|
+
if (!withLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
|
|
2337
2337
|
try {
|
|
2338
2338
|
const mouseInfluence = calculateMouseInfluence(mouseOffset), maxBlur = 2 * blurAmount, baseBlur = Math.min(maxBlur, blurAmount + mouseInfluence * blurAmount * .15), edgeIntensity = .15 * mouseInfluence, edgeBlur = Math.min(maxBlur, baseBlur * (.8 + .4 * edgeIntensity)), centerIntensity = .1 * mouseInfluence, centerBlur = Math.min(maxBlur, baseBlur * (.3 + .3 * centerIntensity)), flowBlur = Math.min(maxBlur, 1.2 * baseBlur);
|
|
2339
2339
|
// NOTE: hover/active multipliers intentionally omitted here —
|
|
@@ -2348,14 +2348,14 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2348
2348
|
return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
|
|
2349
2349
|
defaultBlur;
|
|
2350
2350
|
}
|
|
2351
|
-
}), [
|
|
2351
|
+
}), [ withLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = React.useMemo((() => {
|
|
2352
2352
|
try {
|
|
2353
2353
|
const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), validatedBaseBlur = "number" != typeof liquidBlur.baseBlur || isNaN(liquidBlur.baseBlur) ? 0 : liquidBlur.baseBlur, validatedEdgeBlur = "number" != typeof liquidBlur.edgeBlur || isNaN(liquidBlur.edgeBlur) ? 0 : liquidBlur.edgeBlur, validatedCenterBlur = "number" != typeof liquidBlur.centerBlur || isNaN(liquidBlur.centerBlur) ? 0 : liquidBlur.centerBlur, validatedFlowBlur = "number" != typeof liquidBlur.flowBlur || isNaN(liquidBlur.flowBlur) ? 0 : liquidBlur.flowBlur, area = rectCache ? rectCache.width * rectCache.height : 0;
|
|
2354
2354
|
// Validate blur values before using them
|
|
2355
|
-
return !
|
|
2355
|
+
return !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? {
|
|
2356
2356
|
backdropFilter: `blur(${clampBlur(Math.max(validatedBaseBlur, .8 * validatedEdgeBlur, 1.1 * validatedCenterBlur, .9 * validatedFlowBlur))}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1.05}) brightness(${overLightConfig?.brightness || 1.05})`
|
|
2357
2357
|
} : {
|
|
2358
|
-
backdropFilter: `blur(${clampBlur(.4 * validatedBaseBlur + .25 * validatedEdgeBlur + .15 * validatedCenterBlur + .2 * validatedFlowBlur)}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1
|
|
2358
|
+
backdropFilter: `blur(${clampBlur(.4 * validatedBaseBlur + .25 * validatedEdgeBlur + .15 * validatedCenterBlur + .2 * validatedFlowBlur)}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1}) brightness(${overLightConfig?.brightness || 1})`
|
|
2359
2359
|
};
|
|
2360
2360
|
// Single-pass fallback: stronger radius to match perceived blur of multi-pass
|
|
2361
2361
|
} catch (error) {
|
|
@@ -2364,7 +2364,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2364
2364
|
backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
|
|
2365
2365
|
};
|
|
2366
2366
|
}
|
|
2367
|
-
}), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion,
|
|
2367
|
+
}), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur ]), containerVars = React.useMemo((() => {
|
|
2368
2368
|
try {
|
|
2369
2369
|
// Safe extraction of mouse offset values
|
|
2370
2370
|
const mx = mouseOffset && "number" == typeof mouseOffset.x && !isNaN(mouseOffset.x) ? mouseOffset.x : 0, my = mouseOffset && "number" == typeof mouseOffset.y && !isNaN(mouseOffset.y) ? mouseOffset.y : 0;
|
|
@@ -2372,10 +2372,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2372
2372
|
"--atomix-glass-container-width": `${glassSize?.width}`,
|
|
2373
2373
|
"--atomix-glass-container-height": `${glassSize?.height}`,
|
|
2374
2374
|
"--atomix-glass-container-padding": padding || "0 0",
|
|
2375
|
-
"--atomix-glass-container-radius": `${"number" != typeof
|
|
2375
|
+
"--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`,
|
|
2376
2376
|
"--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
|
|
2377
2377
|
"--atomix-glass-container-shadow": overLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.4 + .002 * mx) * (overLightConfig?.shadowIntensity || 1)})`, `inset 0 -1px 0 rgba(0, 0, 0, ${(.2 + .001 * Math.abs(my)) * (overLightConfig?.shadowIntensity || 1)})`, `inset 0 0 20px rgba(0, 0, 0, ${(.08 + .001 * Math.abs(mx + my)) * (overLightConfig?.shadowIntensity || 1)})`, `0 2px 12px rgba(0, 0, 0, ${(.12 + .002 * Math.abs(my)) * (overLightConfig?.shadowIntensity || 1)})` ].join(", ") : "0 0 20px rgba(0, 0, 0, 0.15) inset, 0 4px 8px rgba(0, 0, 0, 0.08) inset",
|
|
2378
|
-
"--atomix-glass-container-shadow-opacity":
|
|
2378
|
+
"--atomix-glass-container-shadow-opacity": effectiveWithoutEffects ? 0 : 1,
|
|
2379
2379
|
// Background and shadow values use design token-aligned RGB values
|
|
2380
2380
|
"--atomix-glass-container-bg": overLight ? `linear-gradient(${180 + .5 * mx}deg, rgba(255, 255, 255, 0.1) 0%, transparent 20%, transparent 80%, rgba(0, 0, 0, 0.05) 100%)` : "none",
|
|
2381
2381
|
"--atomix-glass-container-text-shadow": overLight ? "0px 2px 12px rgba(0, 0, 0, 0)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
|
|
@@ -2393,14 +2393,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2393
2393
|
"--atomix-glass-container-text-shadow": "none"
|
|
2394
2394
|
};
|
|
2395
2395
|
}
|
|
2396
|
-
}), [ glassSize, padding,
|
|
2397
|
-
el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
|
|
2398
|
-
el.style.setProperty("transition-delay", "0s", "important"));
|
|
2399
|
-
};
|
|
2396
|
+
}), [ glassSize, padding, borderRadius, backdropStyle, mouseOffset, overLight, effectiveWithoutEffects ]);
|
|
2400
2397
|
return jsxRuntime.jsx("div", {
|
|
2401
2398
|
ref: el => {
|
|
2402
2399
|
// Apply force no-transition
|
|
2403
|
-
setForceNoTransition(el),
|
|
2404
2400
|
// Handle forwarded ref
|
|
2405
2401
|
"function" == typeof ref ? ref(el) : ref && (ref.current = el);
|
|
2406
2402
|
},
|
|
@@ -2435,7 +2431,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2435
2431
|
aberrationIntensity: "number" != typeof aberrationIntensity || isNaN(aberrationIntensity) ? 0 : aberrationIntensity,
|
|
2436
2432
|
shaderMapUrl: shaderMapUrl
|
|
2437
2433
|
}), jsxRuntime.jsx("div", {
|
|
2438
|
-
ref:
|
|
2434
|
+
ref: el => {
|
|
2435
|
+
el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
|
|
2436
|
+
el.style.setProperty("transition-delay", "0s", "important"));
|
|
2437
|
+
},
|
|
2439
2438
|
className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
|
|
2440
2439
|
style: {
|
|
2441
2440
|
filter: `url(#${filterId})`,
|
|
@@ -2552,7 +2551,128 @@ class {
|
|
|
2552
2551
|
*/ getSubscriberCount() {
|
|
2553
2552
|
return this.listeners.size;
|
|
2554
2553
|
}
|
|
2555
|
-
},
|
|
2554
|
+
}, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
|
|
2555
|
+
if (!wrapperElement && !containerElement) return;
|
|
2556
|
+
const {mouseOffset: mouseOffset, globalMousePosition: globalMousePosition, glassSize: glassSize, isHovered: isHovered, isActive: isActive, isOverLight: isOverLight, baseOverLightConfig: baseOverLightConfig, effectiveBorderRadius: effectiveBorderRadius, effectiveWithoutEffects: effectiveWithoutEffects, effectiveReducedMotion: effectiveReducedMotion, elasticity: elasticity, directionalScale: directionalScale, onClick: onClick, withLiquidBlur: withLiquidBlur, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, padding: padding = ATOMIX_GLASS.DEFAULTS.PADDING} = params, mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, overLightConfig = {
|
|
2557
|
+
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
2558
|
+
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
2559
|
+
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
2560
|
+
shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
|
|
2561
|
+
borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
|
|
2562
|
+
saturationBoost: baseOverLightConfig.saturationBoost
|
|
2563
|
+
};
|
|
2564
|
+
// Calculate mouse influence
|
|
2565
|
+
// Calculate elastic translation
|
|
2566
|
+
let elasticTranslation = {
|
|
2567
|
+
x: 0,
|
|
2568
|
+
y: 0
|
|
2569
|
+
};
|
|
2570
|
+
if (!effectiveWithoutEffects && wrapperElement) {
|
|
2571
|
+
const rect = wrapperElement.getBoundingClientRect(), center = calculateElementCenter(rect);
|
|
2572
|
+
// Calculate fade in factor
|
|
2573
|
+
let fadeInFactor = 0;
|
|
2574
|
+
if (globalMousePosition.x && globalMousePosition.y && validateGlassSize(glassSize)) {
|
|
2575
|
+
const edgeDistanceX = Math.max(0, Math.abs(globalMousePosition.x - center.x) - glassSize.width / 2), edgeDistanceY = Math.max(0, Math.abs(globalMousePosition.y - center.y) - glassSize.height / 2), edgeDistance = calculateDistance({
|
|
2576
|
+
x: edgeDistanceX,
|
|
2577
|
+
y: edgeDistanceY
|
|
2578
|
+
}, {
|
|
2579
|
+
x: 0,
|
|
2580
|
+
y: 0
|
|
2581
|
+
});
|
|
2582
|
+
fadeInFactor = edgeDistance > ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE;
|
|
2583
|
+
}
|
|
2584
|
+
elasticTranslation = {
|
|
2585
|
+
x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
|
|
2586
|
+
y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
|
|
2587
|
+
};
|
|
2588
|
+
}
|
|
2589
|
+
const transformStyle = effectiveWithoutEffects ? isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)" : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? "scale(0.96)" : directionalScale}`;
|
|
2590
|
+
// Update Wrapper Styles (glassVars)
|
|
2591
|
+
if (wrapperElement) {
|
|
2592
|
+
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT, borderGradientAngle = GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER, borderStop1 = Math.max(GRADIENT.BORDER_STOP_1.MIN, GRADIENT.BORDER_STOP_1.BASE + my * GRADIENT.BORDER_STOP_1.MULTIPLIER), borderStop2 = Math.min(GRADIENT.BORDER_STOP_2.MAX, GRADIENT.BORDER_STOP_2.BASE + my * GRADIENT.BORDER_STOP_2.MULTIPLIER), borderOpacities = [ GRADIENT.BORDER_OPACITY.BASE_1 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW, GRADIENT.BORDER_OPACITY.BASE_2 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH, GRADIENT.BORDER_OPACITY.BASE_3 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW, GRADIENT.BORDER_OPACITY.BASE_4 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH ], configBorderOpacity = overLightConfig.borderOpacity, whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, hoverPositions = {
|
|
2593
|
+
hover1: {
|
|
2594
|
+
x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
|
|
2595
|
+
y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
|
|
2596
|
+
},
|
|
2597
|
+
hover2: {
|
|
2598
|
+
x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_2,
|
|
2599
|
+
y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_2
|
|
2600
|
+
},
|
|
2601
|
+
hover3: {
|
|
2602
|
+
x: GRADIENT.CENTER_POSITION + mx * GRADIENT.HOVER_POSITION.MULTIPLIER_3,
|
|
2603
|
+
y: GRADIENT.CENTER_POSITION + my * GRADIENT.HOVER_POSITION.MULTIPLIER_3
|
|
2604
|
+
}
|
|
2605
|
+
}, basePosition = {
|
|
2606
|
+
x: GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER,
|
|
2607
|
+
y: GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER
|
|
2608
|
+
}, opacityValues = {
|
|
2609
|
+
hover1: isHovered || isActive ? .5 : 0,
|
|
2610
|
+
hover2: isActive ? .5 : 0,
|
|
2611
|
+
hover3: isHovered ? .4 : isActive ? .8 : 0,
|
|
2612
|
+
base: isOverLight ? overLightConfig.opacity : 0,
|
|
2613
|
+
over: isOverLight ? 1.1 * overLightConfig.opacity : 0
|
|
2614
|
+
}, style = wrapperElement.style;
|
|
2615
|
+
style.setProperty("--atomix-glass-transform", transformStyle || "none"),
|
|
2616
|
+
// Gradients
|
|
2617
|
+
style.setProperty("--atomix-glass-border-gradient-1", `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`),
|
|
2618
|
+
style.setProperty("--atomix-glass-border-gradient-2", `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[2] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[3] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`),
|
|
2619
|
+
// Hover gradients
|
|
2620
|
+
style.setProperty("--atomix-glass-hover-1-gradient", isOverLight ? `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}%)` : `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}%)`),
|
|
2621
|
+
style.setProperty("--atomix-glass-hover-2-gradient", isOverLight ? `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}%)` : `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}%)`),
|
|
2622
|
+
style.setProperty("--atomix-glass-hover-3-gradient", isOverLight ? `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}%)` : `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}%)`),
|
|
2623
|
+
style.setProperty("--atomix-glass-base-gradient", isOverLight ? `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%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.WHITE_OPACITY})`),
|
|
2624
|
+
style.setProperty("--atomix-glass-overlay-gradient", isOverLight ? `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%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`),
|
|
2625
|
+
// Opacities
|
|
2626
|
+
style.setProperty("--atomix-glass-hover-1-opacity", opacityValues.hover1.toString()),
|
|
2627
|
+
style.setProperty("--atomix-glass-hover-2-opacity", opacityValues.hover2.toString()),
|
|
2628
|
+
style.setProperty("--atomix-glass-hover-3-opacity", opacityValues.hover3.toString()),
|
|
2629
|
+
style.setProperty("--atomix-glass-base-opacity", opacityValues.base.toString()),
|
|
2630
|
+
style.setProperty("--atomix-glass-overlay-opacity", opacityValues.over.toString()),
|
|
2631
|
+
style.setProperty("--atomix-glass-overlay-highlight-opacity", (opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER).toString()),
|
|
2632
|
+
// Other
|
|
2633
|
+
style.setProperty("--atomix-glass-blend-mode", isOverLight ? "multiply" : "overlay"),
|
|
2634
|
+
style.setProperty("--atomix-glass-radius", `${effectiveBorderRadius}px`);
|
|
2635
|
+
}
|
|
2636
|
+
// Update Container Styles (containerVars)
|
|
2637
|
+
if (containerElement) {
|
|
2638
|
+
const mx = mouseOffset.x, my = mouseOffset.y, EDGE_BLUR_MULTIPLIER = 1.25, CENTER_BLUR_MULTIPLIER = 1.1, FLOW_BLUR_MULTIPLIER = 1.2, MOUSE_INFLUENCE_BLUR_FACTOR = .15, EDGE_INTENSITY_MOUSE_FACTOR = .15, CENTER_INTENSITY_MOUSE_FACTOR = .1, MAX_BLUR_RELATIVE = 2, rect = containerElement.getBoundingClientRect();
|
|
2639
|
+
let liquidBlur = {
|
|
2640
|
+
baseBlur: blurAmount,
|
|
2641
|
+
edgeBlur: blurAmount * EDGE_BLUR_MULTIPLIER,
|
|
2642
|
+
centerBlur: blurAmount * CENTER_BLUR_MULTIPLIER,
|
|
2643
|
+
flowBlur: blurAmount * FLOW_BLUR_MULTIPLIER
|
|
2644
|
+
};
|
|
2645
|
+
if (withLiquidBlur && rect) {
|
|
2646
|
+
const mouseInfluence = calculateMouseInfluence(mouseOffset), maxBlur = blurAmount * MAX_BLUR_RELATIVE, baseBlur = Math.min(maxBlur, blurAmount + mouseInfluence * blurAmount * MOUSE_INFLUENCE_BLUR_FACTOR), edgeIntensity = mouseInfluence * EDGE_INTENSITY_MOUSE_FACTOR, edgeBlur = Math.min(maxBlur, baseBlur * (.8 + .4 * edgeIntensity)), centerIntensity = mouseInfluence * CENTER_INTENSITY_MOUSE_FACTOR, centerBlur = Math.min(maxBlur, baseBlur * (.3 + .3 * centerIntensity)), flowBlur = Math.min(maxBlur, baseBlur * FLOW_BLUR_MULTIPLIER);
|
|
2647
|
+
liquidBlur = {
|
|
2648
|
+
baseBlur: clampBlur(baseBlur),
|
|
2649
|
+
edgeBlur: clampBlur(edgeBlur),
|
|
2650
|
+
centerBlur: clampBlur(centerBlur),
|
|
2651
|
+
flowBlur: clampBlur(flowBlur)
|
|
2652
|
+
};
|
|
2653
|
+
}
|
|
2654
|
+
// Backdrop filter
|
|
2655
|
+
let backdropFilterString = `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`;
|
|
2656
|
+
const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), area = rect ? rect.width * rect.height : 0;
|
|
2657
|
+
backdropFilterString = !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? `blur(${clampBlur(Math.max(liquidBlur.baseBlur, .8 * liquidBlur.edgeBlur, 1.1 * liquidBlur.centerBlur, .9 * liquidBlur.flowBlur))}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig.contrast}) brightness(${overLightConfig.brightness})` : `blur(${clampBlur(.4 * liquidBlur.baseBlur + .25 * liquidBlur.edgeBlur + .15 * liquidBlur.centerBlur + .2 * liquidBlur.flowBlur)}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig.contrast}) brightness(${overLightConfig.brightness})`;
|
|
2658
|
+
// Container variables
|
|
2659
|
+
const style = containerElement.style;
|
|
2660
|
+
style.setProperty("--atomix-glass-container-width", `${glassSize.width}`), style.setProperty("--atomix-glass-container-height", `${glassSize.height}`),
|
|
2661
|
+
style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
|
|
2662
|
+
style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
|
|
2663
|
+
// Shadows
|
|
2664
|
+
style.setProperty("--atomix-glass-container-shadow", isOverLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.4 + .002 * mx) * (overLightConfig.shadowIntensity || 1)})`, `inset 0 -1px 0 rgba(0, 0, 0, ${(.2 + .001 * Math.abs(my)) * (overLightConfig.shadowIntensity || 1)})`, `inset 0 0 20px rgba(0, 0, 0, ${(.08 + .001 * Math.abs(mx + my)) * (overLightConfig.shadowIntensity || 1)})`, `0 2px 12px rgba(0, 0, 0, ${(.12 + .002 * Math.abs(my)) * (overLightConfig.shadowIntensity || 1)})` ].join(", ") : "0 0 20px rgba(0, 0, 0, 0.15) inset, 0 4px 8px rgba(0, 0, 0, 0.08) inset"),
|
|
2665
|
+
style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
|
|
2666
|
+
style.setProperty("--atomix-glass-container-bg", isOverLight ? `linear-gradient(${180 + .5 * mx}deg, rgba(255, 255, 255, 0.1) 0%, transparent 20%, transparent 80%, rgba(0, 0, 0, 0.05) 100%)` : "none"),
|
|
2667
|
+
style.setProperty("--atomix-glass-container-text-shadow", isOverLight ? "0px 2px 12px rgba(0, 0, 0, 0)" : "0px 2px 12px rgba(0, 0, 0, 0.4)"),
|
|
2668
|
+
style.setProperty("--atomix-glass-container-box-shadow", isOverLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0px 12px 40px rgba(0, 0, 0, 0.25)");
|
|
2669
|
+
}
|
|
2670
|
+
}, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
|
|
2671
|
+
|
|
2672
|
+
/**
|
|
2673
|
+
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
2674
|
+
* to avoid React re-renders on mouse movement.
|
|
2675
|
+
*/ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
|
|
2556
2676
|
parentElement && backgroundDetectionCache.set(parentElement, {
|
|
2557
2677
|
result: result,
|
|
2558
2678
|
timestamp: Date.now(),
|
|
@@ -2565,18 +2685,74 @@ class {
|
|
|
2565
2685
|
* Composable hook for AtomixGlass component logic
|
|
2566
2686
|
* Manages all state, calculations, and event handlers
|
|
2567
2687
|
*/
|
|
2568
|
-
function useAtomixGlass({glassRef: glassRef, contentRef: contentRef,
|
|
2688
|
+
function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef: wrapperRef, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, elasticity: elasticity = .05, onClick: onClick, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, debugPerformance: debugPerformance = !1, children: children, blurAmount: blurAmount, saturation: saturation, padding: padding, withLiquidBlur: withLiquidBlur}) {
|
|
2569
2689
|
// State
|
|
2570
|
-
const [isHovered, setIsHovered] = React.useState(!1), [isActive, setIsActive] = React.useState(!1),
|
|
2571
|
-
width: 270,
|
|
2572
|
-
height: 69
|
|
2573
|
-
}), [internalGlobalMousePosition, setInternalGlobalMousePosition] = React.useState({
|
|
2690
|
+
const [isHovered, setIsHovered] = React.useState(!1), [isActive, setIsActive] = React.useState(!1), cachedRectRef = React.useRef(null), internalGlobalMousePositionRef = React.useRef({
|
|
2574
2691
|
x: 0,
|
|
2575
2692
|
y: 0
|
|
2576
|
-
}),
|
|
2693
|
+
}), internalMouseOffsetRef = React.useRef({
|
|
2577
2694
|
x: 0,
|
|
2578
2695
|
y: 0
|
|
2579
|
-
}), [
|
|
2696
|
+
}), [dynamicBorderRadius, setDynamicCornerRadius] = React.useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = React.useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = React.useState(!1), [detectedOverLight, setDetectedOverLight] = React.useState(!1), effectiveBorderRadius = React.useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
|
|
2697
|
+
const [glassSize, setGlassSize] = React.useState({
|
|
2698
|
+
width: 270,
|
|
2699
|
+
height: 69
|
|
2700
|
+
});
|
|
2701
|
+
return React.useEffect((() => {
|
|
2702
|
+
const isValidElement = element => null !== element && element instanceof HTMLElement && element.isConnected;
|
|
2703
|
+
let rafId = null, lastSize = {
|
|
2704
|
+
width: 0,
|
|
2705
|
+
height: 0
|
|
2706
|
+
}, lastCornerRadius = effectiveBorderRadius;
|
|
2707
|
+
const updateGlassSize = (forceUpdate = !1) => {
|
|
2708
|
+
null !== rafId && cancelAnimationFrame(rafId), rafId = requestAnimationFrame((() => {
|
|
2709
|
+
if (!isValidElement(glassRef.current)) return void (rafId = null);
|
|
2710
|
+
const rect = glassRef.current.getBoundingClientRect();
|
|
2711
|
+
if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
|
|
2712
|
+
// Measure actual rendered size without artificial offsets to avoid feedback loops
|
|
2713
|
+
const newSize = {
|
|
2714
|
+
width: Math.round(rect.width),
|
|
2715
|
+
height: Math.round(rect.height)
|
|
2716
|
+
}, cornerRadiusChanged = lastCornerRadius !== effectiveBorderRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
|
|
2717
|
+
var size;
|
|
2718
|
+
(forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS$1.MAX_SIZE && size.height <= CONSTANTS$1.MAX_SIZE && (lastSize = newSize,
|
|
2719
|
+
lastCornerRadius = effectiveBorderRadius, setGlassSize(newSize)), rafId = null;
|
|
2720
|
+
}));
|
|
2721
|
+
};
|
|
2722
|
+
let resizeTimeoutId = null;
|
|
2723
|
+
const debouncedResizeHandler = () => {
|
|
2724
|
+
resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
|
|
2725
|
+
}, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
|
|
2726
|
+
let resizeObserver = null, resizeDebounceTimeout = null;
|
|
2727
|
+
// ResizeObserver has 98%+ browser support, no need for fallback
|
|
2728
|
+
if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
|
|
2729
|
+
resizeObserver = new ResizeObserver((entries => {
|
|
2730
|
+
for (const entry of entries) if (entry.target === glassRef.current) {
|
|
2731
|
+
// Update cached rect when size changes
|
|
2732
|
+
glassRef.current && cachedRectRef && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
|
|
2733
|
+
// Debounce resize updates to match RAF timing (16ms)
|
|
2734
|
+
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
|
|
2735
|
+
break;
|
|
2736
|
+
}
|
|
2737
|
+
})), resizeObserver.observe(glassRef.current);
|
|
2738
|
+
} catch (error) {
|
|
2739
|
+
console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
|
|
2740
|
+
}
|
|
2741
|
+
return window.addEventListener("resize", debouncedResizeHandler, {
|
|
2742
|
+
passive: !0
|
|
2743
|
+
}), () => {
|
|
2744
|
+
clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
|
|
2745
|
+
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
|
|
2746
|
+
resizeObserver?.disconnect();
|
|
2747
|
+
};
|
|
2748
|
+
}), [ effectiveBorderRadius, glassRef, cachedRectRef ]), {
|
|
2749
|
+
glassSize: glassSize
|
|
2750
|
+
};
|
|
2751
|
+
}({
|
|
2752
|
+
glassRef: glassRef,
|
|
2753
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
2754
|
+
cachedRectRef: cachedRectRef
|
|
2755
|
+
}), effectiveReducedMotion = React.useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveHighContrast = React.useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveWithoutEffects = React.useMemo((() => withoutEffects || effectiveReducedMotion), [ withoutEffects, effectiveReducedMotion ]), globalMousePosition = externalGlobalMousePosition || internalGlobalMousePositionRef.current, mouseOffset = externalMouseOffset || internalMouseOffsetRef.current;
|
|
2580
2756
|
// Extract border-radius from children
|
|
2581
2757
|
React.useEffect((() => {
|
|
2582
2758
|
const extractRadius = () => {
|
|
@@ -2607,13 +2783,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
2607
2783
|
}
|
|
2608
2784
|
null !== extractedRadius && extractedRadius > 0 && setDynamicCornerRadius(extractedRadius);
|
|
2609
2785
|
} catch (error) {
|
|
2610
|
-
"undefined" != typeof process && "production" === process.env?.NODE_ENV || !
|
|
2786
|
+
"undefined" != typeof process && "production" === process.env?.NODE_ENV || !debugBorderRadius || console.error("[AtomixGlass] Error extracting corner radius:", error);
|
|
2611
2787
|
}
|
|
2612
2788
|
};
|
|
2613
2789
|
extractRadius();
|
|
2614
2790
|
const timeoutId = setTimeout(extractRadius, 100);
|
|
2615
2791
|
return () => clearTimeout(timeoutId);
|
|
2616
|
-
}), [ children,
|
|
2792
|
+
}), [ children, debugBorderRadius, contentRef ]),
|
|
2617
2793
|
// Media query handlers and background detection
|
|
2618
2794
|
React.useEffect((() => {
|
|
2619
2795
|
if (("auto" === overLight || "object" == typeof overLight && null !== overLight) && glassRef.current) {
|
|
@@ -2669,72 +2845,52 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
2669
2845
|
const rgb = bgColor.match(/\d+/g);
|
|
2670
2846
|
if (rgb && rgb.length >= 3) {
|
|
2671
2847
|
const r = Number(rgb[0]), g = Number(rgb[1]), b = Number(rgb[2]);
|
|
2672
|
-
|
|
2673
|
-
if (!isNaN(r) && !isNaN(g) && !isNaN(b) && isFinite(r) && isFinite(g) && isFinite(b) && r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255 && (r > 10 || g > 10 || b > 10)) {
|
|
2848
|
+
if (!isNaN(r) && !isNaN(g) && !isNaN(b) && (r > 10 || g > 10 || b > 10)) {
|
|
2674
2849
|
const luminance = (.299 * r + .587 * g + .114 * b) / 255;
|
|
2675
2850
|
!isNaN(luminance) && isFinite(luminance) && (totalLuminance += luminance, validSamples++,
|
|
2676
2851
|
hasValidBackground = !0);
|
|
2677
2852
|
}
|
|
2678
2853
|
}
|
|
2679
2854
|
}
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
// For image backgrounds, assume medium luminance
|
|
2683
|
-
totalLuminance += .5, validSamples++, hasValidBackground = !0);
|
|
2855
|
+
bgImage && "none" !== bgImage && "initial" !== bgImage && (totalLuminance += .5,
|
|
2856
|
+
validSamples++, hasValidBackground = !0);
|
|
2684
2857
|
} catch (styleError) {
|
|
2685
|
-
|
|
2858
|
+
// Silently continue
|
|
2686
2859
|
}
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
// Exit loop if currentElement becomes null
|
|
2690
|
-
currentElement = currentElement.parentElement, depth++;
|
|
2860
|
+
if (!currentElement) break;
|
|
2861
|
+
currentElement = currentElement.parentElement, depth++;
|
|
2691
2862
|
}
|
|
2692
|
-
|
|
2693
|
-
if (hasValidBackground && validSamples > 0) {
|
|
2863
|
+
if (hasValidBackground && validSamples > 0) {
|
|
2694
2864
|
const avgLuminance = totalLuminance / validSamples;
|
|
2695
2865
|
if (!isNaN(avgLuminance) && isFinite(avgLuminance)) {
|
|
2696
2866
|
let threshold = .7;
|
|
2697
|
-
|
|
2698
|
-
// If overLight is an object, use its threshold property with validation
|
|
2699
|
-
if ("object" == typeof overLight && null !== overLight) {
|
|
2867
|
+
if ("object" == typeof overLight && null !== overLight) {
|
|
2700
2868
|
const objConfig = overLight;
|
|
2701
2869
|
if (void 0 !== objConfig.threshold) {
|
|
2702
|
-
const configThreshold = "number"
|
|
2870
|
+
const configThreshold = "number" != typeof objConfig.threshold || isNaN(objConfig.threshold) ? .7 : objConfig.threshold;
|
|
2703
2871
|
threshold = Math.min(.9, Math.max(.1, configThreshold));
|
|
2704
2872
|
}
|
|
2705
2873
|
}
|
|
2706
2874
|
const isOverLightDetected = avgLuminance > threshold;
|
|
2707
|
-
|
|
2708
|
-
setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
|
|
2875
|
+
setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
|
|
2709
2876
|
setDetectedOverLight(isOverLightDetected);
|
|
2710
2877
|
} else {
|
|
2711
|
-
// Invalid luminance calculation, default to false
|
|
2712
2878
|
const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
|
|
2713
2879
|
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
|
|
2714
2880
|
setDetectedOverLight(result);
|
|
2715
2881
|
}
|
|
2716
2882
|
} else {
|
|
2717
|
-
// Default to false if no valid background found
|
|
2718
2883
|
const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
|
|
2719
2884
|
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
|
|
2720
2885
|
setDetectedOverLight(result);
|
|
2721
2886
|
}
|
|
2722
2887
|
} catch (error) {
|
|
2723
|
-
|
|
2724
|
-
"undefined" != typeof process && "development" !== process.env?.NODE_ENV || console.warn("AtomixGlass: Error detecting background brightness:", error);
|
|
2725
|
-
const result = !1;
|
|
2726
|
-
if (element && element.parentElement) {
|
|
2727
|
-
const threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
|
|
2728
|
-
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold);
|
|
2729
|
-
}
|
|
2730
|
-
setDetectedOverLight(result);
|
|
2888
|
+
setDetectedOverLight(!1);
|
|
2731
2889
|
}
|
|
2732
2890
|
}), 150);
|
|
2733
2891
|
return () => clearTimeout(timeoutId);
|
|
2734
2892
|
}
|
|
2735
|
-
if ("boolean" == typeof overLight &&
|
|
2736
|
-
// For boolean values, disable auto-detection
|
|
2737
|
-
setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
|
|
2893
|
+
if ("boolean" == typeof overLight && setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
|
|
2738
2894
|
const mediaQueryReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"), mediaQueryHighContrast = window.matchMedia("(prefers-contrast: high)");
|
|
2739
2895
|
setUserPrefersReducedMotion(mediaQueryReducedMotion.matches), setUserPrefersHighContrast(mediaQueryHighContrast.matches);
|
|
2740
2896
|
const handleReducedMotionChange = e => {
|
|
@@ -2745,64 +2901,54 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
2745
2901
|
return mediaQueryReducedMotion.addEventListener ? (mediaQueryReducedMotion.addEventListener("change", handleReducedMotionChange),
|
|
2746
2902
|
mediaQueryHighContrast.addEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.addListener && (mediaQueryReducedMotion.addListener(handleReducedMotionChange),
|
|
2747
2903
|
mediaQueryHighContrast.addListener(handleHighContrastChange)), () => {
|
|
2748
|
-
|
|
2749
|
-
mediaQueryReducedMotion.removeEventListener ? (mediaQueryReducedMotion.removeEventListener("change", handleReducedMotionChange),
|
|
2750
|
-
mediaQueryHighContrast.removeEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.removeListener && (mediaQueryReducedMotion.removeListener(handleReducedMotionChange),
|
|
2751
|
-
mediaQueryHighContrast.removeListener(handleHighContrastChange));
|
|
2752
|
-
} catch (cleanupError) {
|
|
2753
|
-
console.error("AtomixGlass: Error cleaning up media query listeners:", cleanupError);
|
|
2754
|
-
}
|
|
2904
|
+
// ignore
|
|
2755
2905
|
};
|
|
2756
2906
|
} catch (error) {
|
|
2757
|
-
return
|
|
2907
|
+
return;
|
|
2758
2908
|
}
|
|
2759
2909
|
}), [ overLight, glassRef, debugOverLight ]);
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
y: (globalPos.y - center.y) / rect.height * 100
|
|
2910
|
+
/**
|
|
2911
|
+
* Get effective overLight value based on configuration
|
|
2912
|
+
*/
|
|
2913
|
+
const getEffectiveOverLight = React.useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = React.useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []), baseOverLightConfig = React.useMemo((() => {
|
|
2914
|
+
const isOverLight = getEffectiveOverLight(), baseConfig = {
|
|
2915
|
+
isOverLight: isOverLight,
|
|
2916
|
+
threshold: .7,
|
|
2917
|
+
opacity: isOverLight ? Math.min(.6, Math.max(.2, .5)) : 0,
|
|
2918
|
+
contrast: 1,
|
|
2919
|
+
// Base contrast
|
|
2920
|
+
brightness: 1,
|
|
2921
|
+
// Base brightness
|
|
2922
|
+
saturationBoost: 1.3,
|
|
2923
|
+
shadowIntensity: .9,
|
|
2924
|
+
borderOpacity: .7
|
|
2776
2925
|
};
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
return;
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
|
|
2926
|
+
if ("object" == typeof overLight && null !== overLight) {
|
|
2927
|
+
const objConfig = overLight, validatedThreshold = validateConfigValue(objConfig.threshold, .1, 1, baseConfig.threshold), validatedOpacity = validateConfigValue(objConfig.opacity, .1, 1, baseConfig.opacity), validatedContrast = validateConfigValue(objConfig.contrast, .5, 2.5, baseConfig.contrast), validatedBrightness = validateConfigValue(objConfig.brightness, .5, 2, baseConfig.brightness), validatedSaturationBoost = validateConfigValue(objConfig.saturationBoost, .5, 3, baseConfig.saturationBoost);
|
|
2928
|
+
return {
|
|
2929
|
+
...baseConfig,
|
|
2930
|
+
threshold: validatedThreshold,
|
|
2931
|
+
opacity: validatedOpacity,
|
|
2932
|
+
contrast: validatedContrast,
|
|
2933
|
+
brightness: validatedBrightness,
|
|
2934
|
+
saturationBoost: validatedSaturationBoost
|
|
2935
|
+
};
|
|
2936
|
+
}
|
|
2937
|
+
return baseConfig;
|
|
2938
|
+
}), [ overLight, getEffectiveOverLight, validateConfigValue ]), overLightConfig = React.useMemo((() => {
|
|
2939
|
+
const mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1;
|
|
2940
|
+
return {
|
|
2941
|
+
isOverLight: baseOverLightConfig.isOverLight,
|
|
2942
|
+
threshold: baseOverLightConfig.threshold,
|
|
2943
|
+
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
2944
|
+
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
2945
|
+
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
2946
|
+
saturationBoost: baseOverLightConfig.saturationBoost,
|
|
2947
|
+
shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
|
|
2948
|
+
borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence))
|
|
2801
2949
|
};
|
|
2802
|
-
}), [
|
|
2803
|
-
|
|
2804
|
-
const calculateDirectionalScale = React.useCallback((() => {
|
|
2805
|
-
if (!0 === overLight || "auto" === overLight && detectedOverLight || "object" == typeof overLight && null !== overLight && detectedOverLight) return "scale(1)";
|
|
2950
|
+
}), [ baseOverLightConfig, mouseOffset, isHovered, isActive ]), updateRectRef = React.useRef(null), calculateDirectionalScale = React.useCallback((() => {
|
|
2951
|
+
if (baseOverLightConfig.isOverLight) return "scale(1)";
|
|
2806
2952
|
if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return "scale(1)";
|
|
2807
2953
|
const rect = glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect), deltaX = globalMousePosition.x - center.x, deltaY = globalMousePosition.y - center.y, edgeDistanceX = Math.max(0, Math.abs(deltaX) - glassSize.width / 2), edgeDistanceY = Math.max(0, Math.abs(deltaY) - glassSize.height / 2), edgeDistance = calculateDistance({
|
|
2808
2954
|
x: edgeDistanceX,
|
|
@@ -2816,7 +2962,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
2816
2962
|
if (0 === centerDistance) return "scale(1)";
|
|
2817
2963
|
const normalizedX = deltaX / centerDistance, normalizedY = deltaY / centerDistance, stretchIntensity = Math.min(centerDistance / 300, 1) * elasticity * fadeInFactor, scaleX = 1 + Math.abs(normalizedX) * stretchIntensity * .3 - Math.abs(normalizedY) * stretchIntensity * .15, scaleY = 1 + Math.abs(normalizedY) * stretchIntensity * .3 - Math.abs(normalizedX) * stretchIntensity * .15;
|
|
2818
2964
|
return `scaleX(${Math.max(.8, scaleX)}) scaleY(${Math.max(.8, scaleY)})`;
|
|
2819
|
-
}), [ globalMousePosition, elasticity, glassSize, glassRef,
|
|
2965
|
+
}), [ globalMousePosition, elasticity, glassSize, glassRef, baseOverLightConfig ]), calculateFadeInFactor = React.useCallback((() => {
|
|
2820
2966
|
if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return 0;
|
|
2821
2967
|
const rect = glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect), edgeDistanceX = Math.max(0, Math.abs(globalMousePosition.x - center.x) - glassSize.width / 2), edgeDistanceY = Math.max(0, Math.abs(globalMousePosition.y - center.y) - glassSize.height / 2), edgeDistance = calculateDistance({
|
|
2822
2968
|
x: edgeDistanceX,
|
|
@@ -2836,122 +2982,110 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
2836
2982
|
x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
|
|
2837
2983
|
y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
|
|
2838
2984
|
};
|
|
2839
|
-
}), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = React.useMemo((() =>
|
|
2985
|
+
}), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = React.useMemo((() => effectiveWithoutEffects ? {
|
|
2840
2986
|
x: 0,
|
|
2841
2987
|
y: 0
|
|
2842
|
-
} : calculateElasticTranslation()), [ calculateElasticTranslation,
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
const
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
|
|
2855
|
-
// Measure actual rendered size without artificial offsets to avoid feedback loops
|
|
2856
|
-
const newSize = {
|
|
2857
|
-
width: Math.round(rect.width),
|
|
2858
|
-
height: Math.round(rect.height)
|
|
2859
|
-
}, cornerRadiusChanged = lastCornerRadius !== effectiveCornerRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
|
|
2860
|
-
var size;
|
|
2861
|
-
(forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS.MAX_SIZE && size.height <= CONSTANTS.MAX_SIZE && (lastSize = newSize,
|
|
2862
|
-
lastCornerRadius = effectiveCornerRadius, setGlassSize(newSize)), rafId = null;
|
|
2863
|
-
}));
|
|
2864
|
-
};
|
|
2865
|
-
let resizeTimeoutId = null;
|
|
2866
|
-
const debouncedResizeHandler = () => {
|
|
2867
|
-
resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
|
|
2868
|
-
}, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
|
|
2869
|
-
let resizeObserver = null, resizeDebounceTimeout = null;
|
|
2870
|
-
// ResizeObserver has 98%+ browser support, no need for fallback
|
|
2871
|
-
if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
|
|
2872
|
-
resizeObserver = new ResizeObserver((entries => {
|
|
2873
|
-
for (const entry of entries) if (entry.target === glassRef.current) {
|
|
2874
|
-
// Update cached rect when size changes
|
|
2875
|
-
glassRef.current && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
|
|
2876
|
-
// Debounce resize updates to match RAF timing (16ms)
|
|
2877
|
-
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
|
|
2878
|
-
break;
|
|
2879
|
-
}
|
|
2880
|
-
})), resizeObserver.observe(glassRef.current);
|
|
2881
|
-
} catch (error) {
|
|
2882
|
-
console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
|
|
2883
|
-
}
|
|
2884
|
-
return window.addEventListener("resize", debouncedResizeHandler, {
|
|
2885
|
-
passive: !0
|
|
2886
|
-
}), () => {
|
|
2887
|
-
clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
|
|
2888
|
-
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
|
|
2889
|
-
resizeObserver?.disconnect();
|
|
2988
|
+
} : calculateElasticTranslation()), [ calculateElasticTranslation, effectiveWithoutEffects ]), directionalScale = React.useMemo((() => effectiveWithoutEffects ? "scale(1)" : calculateDirectionalScale()), [ calculateDirectionalScale, effectiveWithoutEffects ]), transformStyle = React.useMemo((() => effectiveWithoutEffects ? isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)" : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? "scale(0.96)" : directionalScale}`), [ elasticTranslation, isActive, onClick, directionalScale, effectiveWithoutEffects ]), handleGlobalMousePosition = React.useCallback((globalPos => {
|
|
2989
|
+
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
2990
|
+
if (effectiveWithoutEffects) return;
|
|
2991
|
+
const container = mouseContainer?.current || glassRef.current;
|
|
2992
|
+
if (!container) return;
|
|
2993
|
+
// Use cached rect if available, otherwise get new one
|
|
2994
|
+
let rect = cachedRectRef.current;
|
|
2995
|
+
if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
|
|
2996
|
+
cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
|
|
2997
|
+
const center = calculateElementCenter(rect), newOffset = {
|
|
2998
|
+
x: (globalPos.x - center.x) / rect.width * 100,
|
|
2999
|
+
y: (globalPos.y - center.y) / rect.height * 100
|
|
2890
3000
|
};
|
|
2891
|
-
|
|
2892
|
-
|
|
3001
|
+
// Calculate offset relative to this container
|
|
3002
|
+
// Store in refs instead of state
|
|
3003
|
+
internalMouseOffsetRef.current = newOffset, internalGlobalMousePositionRef.current = globalPos,
|
|
3004
|
+
// Imperative style update
|
|
3005
|
+
updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
|
|
3006
|
+
mouseOffset: newOffset,
|
|
3007
|
+
globalMousePosition: globalPos,
|
|
3008
|
+
glassSize: glassSize,
|
|
3009
|
+
isHovered: isHovered,
|
|
3010
|
+
isActive: isActive,
|
|
3011
|
+
isOverLight: baseOverLightConfig.isOverLight,
|
|
3012
|
+
baseOverLightConfig: baseOverLightConfig,
|
|
3013
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
3014
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
3015
|
+
effectiveReducedMotion: effectiveReducedMotion,
|
|
3016
|
+
elasticity: elasticity,
|
|
3017
|
+
directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
|
|
3018
|
+
// Simplified directional scale for fast path
|
|
3019
|
+
onClick: onClick,
|
|
3020
|
+
withLiquidBlur: withLiquidBlur,
|
|
3021
|
+
blurAmount: blurAmount,
|
|
3022
|
+
saturation: saturation,
|
|
3023
|
+
padding: padding
|
|
3024
|
+
});
|
|
3025
|
+
}), [ mouseContainer, glassRef, wrapperRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects, glassSize, isHovered, isActive, baseOverLightConfig, effectiveBorderRadius, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding ]);
|
|
2893
3026
|
/**
|
|
2894
|
-
*
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
const
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
3027
|
+
* Validate and clamp a numeric config value
|
|
3028
|
+
*/
|
|
3029
|
+
// Subscribe to shared mouse tracker
|
|
3030
|
+
React.useEffect((() => {
|
|
3031
|
+
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
3032
|
+
if (effectiveWithoutEffects) return;
|
|
3033
|
+
const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
|
|
3034
|
+
let resizeObserver = null;
|
|
3035
|
+
return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
|
|
3036
|
+
null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
|
|
3037
|
+
const container = mouseContainer?.current || glassRef.current;
|
|
3038
|
+
container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
|
|
3039
|
+
}));
|
|
3040
|
+
})), resizeObserver.observe(container)), () => {
|
|
3041
|
+
unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
|
|
3042
|
+
updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
|
|
2910
3043
|
};
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
3044
|
+
}), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]),
|
|
3045
|
+
// Also call updateStyles on other state changes (hover, active, etc)
|
|
3046
|
+
React.useEffect((() => {
|
|
3047
|
+
updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
|
|
3048
|
+
mouseOffset: externalMouseOffset || internalMouseOffsetRef.current,
|
|
3049
|
+
globalMousePosition: externalGlobalMousePosition || internalGlobalMousePositionRef.current,
|
|
3050
|
+
glassSize: glassSize,
|
|
3051
|
+
isHovered: isHovered,
|
|
3052
|
+
isActive: isActive,
|
|
3053
|
+
isOverLight: baseOverLightConfig.isOverLight,
|
|
3054
|
+
baseOverLightConfig: baseOverLightConfig,
|
|
3055
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
3056
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
3057
|
+
effectiveReducedMotion: effectiveReducedMotion,
|
|
3058
|
+
elasticity: elasticity,
|
|
3059
|
+
directionalScale: directionalScale,
|
|
3060
|
+
onClick: onClick,
|
|
3061
|
+
withLiquidBlur: withLiquidBlur,
|
|
3062
|
+
blurAmount: blurAmount,
|
|
3063
|
+
saturation: saturation,
|
|
3064
|
+
padding: padding
|
|
3065
|
+
});
|
|
3066
|
+
}), [ isHovered, isActive, glassSize, baseOverLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, directionalScale, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, padding, onClick ]);
|
|
3067
|
+
// Event handlers
|
|
3068
|
+
const handleMouseEnter = React.useCallback((() => setIsHovered(!0)), []), handleMouseLeave = React.useCallback((() => setIsHovered(!1)), []), handleMouseDown = React.useCallback((() => setIsActive(!0)), []), handleMouseUp = React.useCallback((() => setIsActive(!1)), []), handleMouseMove = React.useCallback((_e => {}), []), handleKeyDown = React.useCallback((e => {
|
|
2926
3069
|
!onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
|
|
2927
|
-
}), [ onClick ])
|
|
2928
|
-
|
|
2929
|
-
* Validate and clamp a numeric config value
|
|
2930
|
-
* @param value - The value to validate
|
|
2931
|
-
* @param min - Minimum allowed value
|
|
2932
|
-
* @param max - Maximum allowed value
|
|
2933
|
-
* @param defaultValue - Default value if validation fails
|
|
2934
|
-
* @returns Validated and clamped value
|
|
2935
|
-
*/ return {
|
|
2936
|
-
// State
|
|
3070
|
+
}), [ onClick ]);
|
|
3071
|
+
return {
|
|
2937
3072
|
isHovered: isHovered,
|
|
2938
3073
|
isActive: isActive,
|
|
2939
3074
|
glassSize: glassSize,
|
|
2940
|
-
|
|
2941
|
-
|
|
3075
|
+
dynamicBorderRadius: dynamicBorderRadius,
|
|
3076
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
2942
3077
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
2943
3078
|
effectiveHighContrast: effectiveHighContrast,
|
|
2944
|
-
|
|
3079
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
2945
3080
|
detectedOverLight: detectedOverLight,
|
|
2946
3081
|
globalMousePosition: globalMousePosition,
|
|
3082
|
+
// This is now static (refs or props) unless prop changes
|
|
2947
3083
|
mouseOffset: mouseOffset,
|
|
2948
|
-
//
|
|
3084
|
+
// This is now static (refs or props) unless prop changes
|
|
2949
3085
|
overLightConfig: overLightConfig,
|
|
2950
|
-
// Transform calculations
|
|
2951
3086
|
elasticTranslation: elasticTranslation,
|
|
2952
3087
|
directionalScale: directionalScale,
|
|
2953
3088
|
transformStyle: transformStyle,
|
|
2954
|
-
// Event handlers
|
|
2955
3089
|
handleMouseEnter: handleMouseEnter,
|
|
2956
3090
|
handleMouseLeave: handleMouseLeave,
|
|
2957
3091
|
handleMouseDown: handleMouseDown,
|
|
@@ -2990,7 +3124,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
2990
3124
|
*
|
|
2991
3125
|
* @example
|
|
2992
3126
|
* // Manual border-radius override
|
|
2993
|
-
* <AtomixGlass
|
|
3127
|
+
* <AtomixGlass borderRadius={20}>
|
|
2994
3128
|
* <div>Content with 20px glass radius</div>
|
|
2995
3129
|
* </AtomixGlass>
|
|
2996
3130
|
*
|
|
@@ -3031,37 +3165,48 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
3031
3165
|
* <AtomixGlass overLight="auto" debugOverLight={true}>
|
|
3032
3166
|
* <div>Content with debug logging enabled</div>
|
|
3033
3167
|
* </AtomixGlass>
|
|
3034
|
-
*/ function AtomixGlass({children: children, displacementScale: displacementScale = ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, aberrationIntensity: aberrationIntensity = ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY,
|
|
3035
|
-
const glassRef = React.useRef(null), contentRef = React.useRef(null), {isHovered: isHovered, isActive: isActive, glassSize: glassSize,
|
|
3168
|
+
*/ function AtomixGlass({children: children, displacementScale: displacementScale = ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, aberrationIntensity: aberrationIntensity = ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer = null, className: className = "", padding: padding = ATOMIX_GLASS.DEFAULTS.PADDING, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, style: style = {}, mode: mode = ATOMIX_GLASS.DEFAULTS.MODE, onClick: onClick, shaderVariant: shaderVariant = "liquidGlass", "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, role: role, tabIndex: tabIndex, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, withLiquidBlur: withLiquidBlur = !1, withBorder: withBorder = !0, withOverLightLayers: withOverLightLayers = ATOMIX_GLASS.DEFAULTS.ENABLE_OVER_LIGHT_LAYERS, debugPerformance: debugPerformance = !1, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, height: height, width: width, ...rest}) {
|
|
3169
|
+
const glassRef = React.useRef(null), contentRef = React.useRef(null), {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
|
|
3036
3170
|
glassRef: glassRef,
|
|
3037
3171
|
contentRef: contentRef,
|
|
3038
|
-
|
|
3172
|
+
borderRadius: borderRadius,
|
|
3039
3173
|
globalMousePosition: externalGlobalMousePosition,
|
|
3040
3174
|
mouseOffset: externalMouseOffset,
|
|
3041
3175
|
mouseContainer: mouseContainer,
|
|
3042
3176
|
overLight: overLight,
|
|
3043
3177
|
reducedMotion: reducedMotion,
|
|
3044
3178
|
highContrast: highContrast,
|
|
3045
|
-
|
|
3179
|
+
withoutEffects: withoutEffects,
|
|
3046
3180
|
elasticity: elasticity,
|
|
3047
3181
|
onClick: onClick,
|
|
3048
|
-
|
|
3182
|
+
debugBorderRadius: debugBorderRadius,
|
|
3049
3183
|
debugOverLight: debugOverLight,
|
|
3050
|
-
|
|
3051
|
-
children: children
|
|
3052
|
-
|
|
3184
|
+
debugPerformance: debugPerformance,
|
|
3185
|
+
children: children,
|
|
3186
|
+
blurAmount: blurAmount,
|
|
3187
|
+
saturation: saturation,
|
|
3188
|
+
withLiquidBlur: withLiquidBlur,
|
|
3189
|
+
padding: padding,
|
|
3190
|
+
style: style
|
|
3191
|
+
}), isOverLight = React.useMemo((() => overLightConfig?.isOverLight), [ overLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, baseStyle = {
|
|
3053
3192
|
...style,
|
|
3054
|
-
...!
|
|
3193
|
+
...!effectiveWithoutEffects && {
|
|
3055
3194
|
transform: transformStyle
|
|
3056
3195
|
}
|
|
3057
|
-
}, componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`,
|
|
3196
|
+
}, componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveWithoutEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className ].filter(Boolean).join(" "), positionStyles = React.useMemo((() => ({
|
|
3058
3197
|
position: style.position || "absolute",
|
|
3059
3198
|
top: style.top || 0,
|
|
3060
3199
|
left: style.left || 0
|
|
3061
|
-
})), [ style.position, style.top, style.left ]), adjustedSize = React.useMemo((() =>
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3200
|
+
})), [ style.position, style.top, style.left ]), adjustedSize = React.useMemo((() => {
|
|
3201
|
+
const resolveSize = (propValue, styleValue, measuredSize) => {
|
|
3202
|
+
const explicitSize = propValue ?? styleValue;
|
|
3203
|
+
return void 0 !== explicitSize ? "number" == typeof explicitSize ? `${explicitSize}px` : explicitSize : "fixed" === positionStyles.position ? `${Math.max(measuredSize, 0)}px` : "100%";
|
|
3204
|
+
};
|
|
3205
|
+
return {
|
|
3206
|
+
width: resolveSize(width, style.width, glassSize.width),
|
|
3207
|
+
height: resolveSize(height, style.height, glassSize.height)
|
|
3208
|
+
};
|
|
3209
|
+
}), [ width, height, style.width, style.height, positionStyles.position, glassSize.width, glassSize.height ]), gradientValues = React.useMemo((() => {
|
|
3065
3210
|
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
|
|
3066
3211
|
return {
|
|
3067
3212
|
borderGradientAngle: GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER,
|
|
@@ -3103,13 +3248,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
3103
3248
|
}), [ isHovered, isActive, isOverLight, overLightConfig.opacity ]), glassVars = React.useMemo((() => {
|
|
3104
3249
|
const whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, {borderGradientAngle: borderGradientAngle, borderStop1: borderStop1, borderStop2: borderStop2, borderOpacities: borderOpacities, hoverPositions: hoverPositions, basePosition: basePosition, mx: mx, my: my, absMx: absMx, absMy: absMy} = gradientValues, configBorderOpacity = overLightConfig?.borderOpacity ?? 1;
|
|
3105
3250
|
return {
|
|
3106
|
-
"--atomix-glass-radius": `${
|
|
3251
|
+
"--atomix-glass-radius": `${effectiveBorderRadius}px`,
|
|
3107
3252
|
"--atomix-glass-transform": transformStyle || "none",
|
|
3108
3253
|
"--atomix-glass-position": positionStyles.position,
|
|
3109
3254
|
"--atomix-glass-top": "fixed" !== positionStyles.top ? `${positionStyles.top}px` : "0",
|
|
3110
3255
|
"--atomix-glass-left": "fixed" !== positionStyles.left ? `${positionStyles.left}px` : "0",
|
|
3111
|
-
"--atomix-glass-width":
|
|
3112
|
-
"--atomix-glass-height":
|
|
3256
|
+
"--atomix-glass-width": adjustedSize.width,
|
|
3257
|
+
"--atomix-glass-height": adjustedSize.height,
|
|
3113
3258
|
"--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.09375rem)",
|
|
3114
3259
|
"--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay",
|
|
3115
3260
|
"--atomix-glass-border-gradient-1": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
|
|
@@ -3125,24 +3270,25 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
3125
3270
|
"--atomix-glass-overlay-opacity": opacityValues.over,
|
|
3126
3271
|
"--atomix-glass-overlay-gradient": isOverLight ? `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%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`
|
|
3127
3272
|
};
|
|
3128
|
-
}), [ gradientValues, opacityValues,
|
|
3273
|
+
}), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, positionStyles, adjustedSize, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsxRuntime.jsx("div", {
|
|
3129
3274
|
className: [ ATOMIX_GLASS.BACKGROUND_LAYER_CLASS, "dark" === layerType ? ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS, isOverLight ? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS ].filter(Boolean).join(" "),
|
|
3130
3275
|
style: {
|
|
3131
3276
|
...positionStyles,
|
|
3132
3277
|
height: adjustedSize.height,
|
|
3133
3278
|
width: adjustedSize.width,
|
|
3134
|
-
borderRadius: `${
|
|
3279
|
+
borderRadius: `${effectiveBorderRadius}px`,
|
|
3135
3280
|
transform: baseStyle.transform
|
|
3136
3281
|
}
|
|
3137
3282
|
});
|
|
3138
3283
|
return jsxRuntime.jsxs("div", {
|
|
3284
|
+
...rest,
|
|
3139
3285
|
className: componentClassName,
|
|
3140
3286
|
style: glassVars,
|
|
3141
3287
|
role: role || (onClick ? "button" : void 0),
|
|
3142
3288
|
tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
|
|
3143
3289
|
"aria-label": ariaLabel,
|
|
3144
3290
|
"aria-describedby": ariaDescribedBy,
|
|
3145
|
-
"aria-disabled": !(!onClick || !
|
|
3291
|
+
"aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
|
|
3146
3292
|
"aria-pressed": !(!onClick || !isActive) || !onClick && void 0,
|
|
3147
3293
|
onKeyDown: onClick ? handleKeyDown : void 0,
|
|
3148
3294
|
children: [ jsxRuntime.jsx(AtomixGlassContainer, {
|
|
@@ -3150,18 +3296,18 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
3150
3296
|
contentRef: contentRef,
|
|
3151
3297
|
className: className,
|
|
3152
3298
|
style: baseStyle,
|
|
3153
|
-
|
|
3154
|
-
displacementScale:
|
|
3155
|
-
blurAmount:
|
|
3299
|
+
borderRadius: effectiveBorderRadius,
|
|
3300
|
+
displacementScale: effectiveWithoutEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
|
|
3301
|
+
blurAmount: effectiveWithoutEffects ? 0 : blurAmount,
|
|
3156
3302
|
saturation: effectiveHighContrast ? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST : isOverLight ? saturation * overLightConfig.saturationBoost : saturation,
|
|
3157
|
-
aberrationIntensity:
|
|
3303
|
+
aberrationIntensity: effectiveWithoutEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
|
|
3158
3304
|
glassSize: glassSize,
|
|
3159
3305
|
padding: padding,
|
|
3160
|
-
mouseOffset:
|
|
3306
|
+
mouseOffset: effectiveWithoutEffects ? {
|
|
3161
3307
|
x: 0,
|
|
3162
3308
|
y: 0
|
|
3163
3309
|
} : mouseOffset,
|
|
3164
|
-
globalMousePosition:
|
|
3310
|
+
globalMousePosition: effectiveWithoutEffects ? {
|
|
3165
3311
|
x: 0,
|
|
3166
3312
|
y: 0
|
|
3167
3313
|
} : globalMousePosition,
|
|
@@ -3181,11 +3327,11 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
3181
3327
|
onClick: onClick,
|
|
3182
3328
|
mode: mode,
|
|
3183
3329
|
transform: baseStyle.transform,
|
|
3184
|
-
|
|
3330
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
3185
3331
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
3186
3332
|
shaderVariant: shaderVariant,
|
|
3187
3333
|
elasticity: elasticity,
|
|
3188
|
-
|
|
3334
|
+
withLiquidBlur: withLiquidBlur,
|
|
3189
3335
|
children: children
|
|
3190
3336
|
}), Boolean(onClick) && jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
3191
3337
|
children: [ jsxRuntime.jsx("div", {
|
|
@@ -3207,11 +3353,19 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
3207
3353
|
background: `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}%)`
|
|
3208
3354
|
}
|
|
3209
3355
|
}) ]
|
|
3210
|
-
}),
|
|
3356
|
+
}), withBorder && jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
3211
3357
|
children: [ jsxRuntime.jsx("span", {
|
|
3212
|
-
className: ATOMIX_GLASS.BORDER_1_CLASS
|
|
3358
|
+
className: ATOMIX_GLASS.BORDER_1_CLASS,
|
|
3359
|
+
style: {
|
|
3360
|
+
width: glassSize.width,
|
|
3361
|
+
height: glassSize.height
|
|
3362
|
+
}
|
|
3213
3363
|
}), jsxRuntime.jsx("span", {
|
|
3214
|
-
className: ATOMIX_GLASS.BORDER_2_CLASS
|
|
3364
|
+
className: ATOMIX_GLASS.BORDER_2_CLASS,
|
|
3365
|
+
style: {
|
|
3366
|
+
width: glassSize.width,
|
|
3367
|
+
height: glassSize.height
|
|
3368
|
+
}
|
|
3215
3369
|
}) ]
|
|
3216
3370
|
}) ]
|
|
3217
3371
|
});
|
|
@@ -3821,7 +3975,7 @@ const Badge = React.memo((({label: label, variant: variant = "primary", size: s
|
|
|
3821
3975
|
// Default glass settings for badges
|
|
3822
3976
|
const defaultGlassProps = {
|
|
3823
3977
|
displacementScale: 20,
|
|
3824
|
-
|
|
3978
|
+
borderRadius: ref.current?.getBoundingClientRect().width ? ref.current?.getBoundingClientRect().width / 2 : 16,
|
|
3825
3979
|
className: "c-badge--glass",
|
|
3826
3980
|
elasticity: 0
|
|
3827
3981
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
@@ -3942,7 +4096,7 @@ const useBlock = () => ({
|
|
|
3942
4096
|
* ```
|
|
3943
4097
|
*/ Block.displayName = "Block";
|
|
3944
4098
|
|
|
3945
|
-
const BreadcrumbItem = React.forwardRef((({children: children, href: href, active: active, icon: icon, onClick: onClick, className: className = "", style: style, linkAs:
|
|
4099
|
+
const BreadcrumbItem = React.forwardRef((({children: children, href: href, active: active, icon: icon, onClick: onClick, className: className = "", style: style, linkAs: linkAs, linkProps: linkProps = {}, ...props}, ref) => {
|
|
3946
4100
|
const itemClasses = [ BREADCRUMB.CLASSES.ITEM, active ? BREADCRUMB.CLASSES.ACTIVE : "", className ].filter(Boolean).join(" "), linkContent = jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
3947
4101
|
children: [ icon && jsxRuntime.jsx("span", {
|
|
3948
4102
|
className: "c-breadcrumb__icon",
|
|
@@ -3954,20 +4108,18 @@ const BreadcrumbItem = React.forwardRef((({children: children, href: href, acti
|
|
|
3954
4108
|
style: style,
|
|
3955
4109
|
// Apply style to the link as per legacy behavior
|
|
3956
4110
|
...linkProps
|
|
3957
|
-
};
|
|
4111
|
+
}, LinkComponent = linkAs;
|
|
3958
4112
|
return jsxRuntime.jsx("li", {
|
|
3959
4113
|
ref: ref,
|
|
3960
4114
|
className: itemClasses,
|
|
3961
4115
|
style: style,
|
|
3962
4116
|
...props,
|
|
3963
|
-
children: href && !active ? LinkComponent ? (
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
});
|
|
3970
|
-
})() : jsxRuntime.jsx("a", {
|
|
4117
|
+
children: href && !active ? linkAs && LinkComponent ? jsxRuntime.jsx(LinkComponent, {
|
|
4118
|
+
href: href,
|
|
4119
|
+
to: href,
|
|
4120
|
+
...commonLinkProps,
|
|
4121
|
+
children: linkContent
|
|
4122
|
+
}) : jsxRuntime.jsx("a", {
|
|
3971
4123
|
href: href,
|
|
3972
4124
|
...commonLinkProps,
|
|
3973
4125
|
children: linkContent
|
|
@@ -3980,7 +4132,7 @@ const BreadcrumbItem = React.forwardRef((({children: children, href: href, acti
|
|
|
3980
4132
|
|
|
3981
4133
|
BreadcrumbItem.displayName = "BreadcrumbItem";
|
|
3982
4134
|
|
|
3983
|
-
const Breadcrumb = React.memo((({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style, children: children})
|
|
4135
|
+
const Breadcrumb = React.memo((function({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style, children: children}) {
|
|
3984
4136
|
const breadcrumbClasses = [ BREADCRUMB.CLASSES.BASE, className ].filter(Boolean).join(" ");
|
|
3985
4137
|
let content;
|
|
3986
4138
|
if (items && items.length > 0)
|
|
@@ -4002,12 +4154,12 @@ const Breadcrumb = React.memo((({items: items, divider: divider, className: cla
|
|
|
4002
4154
|
const childrenCount = React.Children.count(children);
|
|
4003
4155
|
content = React.Children.map(children, ((child, index) => {
|
|
4004
4156
|
if ( React.isValidElement(child)) {
|
|
4005
|
-
const isLast = index === childrenCount - 1, childProps = child.props
|
|
4157
|
+
const isLast = index === childrenCount - 1, childProps = child.props, {active: active, linkAs: linkAs, ...otherProps} = childProps, newProps = {
|
|
4158
|
+
active: active ?? (!!isLast || void 0),
|
|
4159
|
+
linkAs: linkAs ?? LinkComponent
|
|
4160
|
+
};
|
|
4006
4161
|
|
|
4007
|
-
return React.cloneElement(child,
|
|
4008
|
-
active: childProps.active ?? (!!isLast || void 0),
|
|
4009
|
-
linkAs: childProps.linkAs ?? LinkComponent
|
|
4010
|
-
});
|
|
4162
|
+
return React.cloneElement(child, newProps);
|
|
4011
4163
|
}
|
|
4012
4164
|
return child;
|
|
4013
4165
|
}));
|
|
@@ -4074,7 +4226,7 @@ const Spinner = React.memo((({size: size = "md", variant: variant = "primary",
|
|
|
4074
4226
|
const defaultGlassProps = {
|
|
4075
4227
|
displacementScale: 20,
|
|
4076
4228
|
blurAmount: 1,
|
|
4077
|
-
|
|
4229
|
+
borderRadius: 999,
|
|
4078
4230
|
mode: "shader"
|
|
4079
4231
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
4080
4232
|
...defaultGlassProps,
|
|
@@ -4238,6 +4390,7 @@ const Button = React__default.default.memo( React.forwardRef((({label: label, c
|
|
|
4238
4390
|
ref: ref,
|
|
4239
4391
|
// LinkComponent usually forwards ref to anchor
|
|
4240
4392
|
href: href,
|
|
4393
|
+
to: href,
|
|
4241
4394
|
target: target,
|
|
4242
4395
|
rel: "_blank" === target ? "noopener noreferrer" : void 0
|
|
4243
4396
|
};
|
|
@@ -4471,7 +4624,7 @@ const Callout = React.memo((({title: title, children: children, icon: icon, var
|
|
|
4471
4624
|
// Default glass settings for callouts
|
|
4472
4625
|
const defaultGlassProps = {
|
|
4473
4626
|
displacementScale: 30,
|
|
4474
|
-
|
|
4627
|
+
borderRadius: 8,
|
|
4475
4628
|
elasticity: 0
|
|
4476
4629
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
4477
4630
|
...defaultGlassProps,
|
|
@@ -4493,7 +4646,7 @@ const Callout = React.memo((({title: title, children: children, icon: icon, var
|
|
|
4493
4646
|
children: jsxRuntime.jsx("div", {
|
|
4494
4647
|
className: "c-callout__glass-content",
|
|
4495
4648
|
style: {
|
|
4496
|
-
borderRadius: glassProps.
|
|
4649
|
+
borderRadius: glassProps.borderRadius
|
|
4497
4650
|
},
|
|
4498
4651
|
children: calloutContent
|
|
4499
4652
|
})
|
|
@@ -4532,6 +4685,8 @@ active: active = !1, disabled: disabled = !1, loading: loading = !1, selected: s
|
|
|
4532
4685
|
header: header, image: image, imageAlt: imageAlt = "", title: title, text: text, actions: actions, icon: icon, footer: footer, children: children,
|
|
4533
4686
|
// Interaction
|
|
4534
4687
|
onClick: onClick, onHover: onHover, onFocus: onFocus, href: href, target: target,
|
|
4688
|
+
// Custom Link
|
|
4689
|
+
LinkComponent: LinkComponent,
|
|
4535
4690
|
// Glass
|
|
4536
4691
|
glass: glass,
|
|
4537
4692
|
// Accessibility
|
|
@@ -4615,7 +4770,19 @@ className: className = "", style: style, ...rest}, ref) => {
|
|
|
4615
4770
|
};
|
|
4616
4771
|
// Render as anchor if href is provided
|
|
4617
4772
|
if (href && !isDisabled) {
|
|
4618
|
-
|
|
4773
|
+
let anchorElement;
|
|
4774
|
+
if (LinkComponent) {
|
|
4775
|
+
const LinkComp = LinkComponent;
|
|
4776
|
+
anchorElement = jsxRuntime.jsx(LinkComp, {
|
|
4777
|
+
...commonProps,
|
|
4778
|
+
ref: ref,
|
|
4779
|
+
href: href,
|
|
4780
|
+
to: href,
|
|
4781
|
+
target: target,
|
|
4782
|
+
rel: "_blank" === target ? "noopener noreferrer" : void 0,
|
|
4783
|
+
children: cardContent
|
|
4784
|
+
});
|
|
4785
|
+
} else anchorElement = jsxRuntime.jsx("a", {
|
|
4619
4786
|
...commonProps,
|
|
4620
4787
|
ref: ref,
|
|
4621
4788
|
href: href,
|
|
@@ -5179,12 +5346,22 @@ function useChart(initialProps) {
|
|
|
5179
5346
|
left: 40
|
|
5180
5347
|
}, config) => {
|
|
5181
5348
|
if (!datasets || 0 === datasets.length) return null;
|
|
5182
|
-
//
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5349
|
+
// Calculate total points and min/max values efficiently avoiding spread operator
|
|
5350
|
+
let totalPoints = 0, minValue = 1 / 0, maxValue = -1 / 0, hasValidData = !1;
|
|
5351
|
+
for (const dataset of datasets) if (dataset.data) {
|
|
5352
|
+
totalPoints += dataset.data.length;
|
|
5353
|
+
const {min: min, max: max, hasValid: hasValid} = getDatasetBounds(dataset.data);
|
|
5354
|
+
hasValid && (min < minValue && (minValue = min), max > maxValue && (maxValue = max),
|
|
5355
|
+
hasValidData = !0);
|
|
5356
|
+
}
|
|
5357
|
+
if (0 === totalPoints) return null;
|
|
5358
|
+
// Handle case with no valid numeric data
|
|
5359
|
+
hasValidData || (minValue = 0, maxValue = 0);
|
|
5360
|
+
const valueRange = maxValue - minValue || 1, innerWidth = width - padding.left - padding.right, innerHeight = height - padding.top - padding.bottom;
|
|
5361
|
+
// Avoid division by zero
|
|
5362
|
+
// Apply padding
|
|
5363
|
+
return {
|
|
5364
|
+
xScale: (index, dataLength = totalPoints) => dataLength <= 1 ? padding.left + innerWidth / 2 : padding.left + index / (dataLength - 1) * innerWidth,
|
|
5188
5365
|
yScale: value => padding.top + innerHeight - (value - minValue) / valueRange * innerHeight,
|
|
5189
5366
|
minValue: minValue,
|
|
5190
5367
|
maxValue: maxValue,
|
|
@@ -5239,6 +5416,29 @@ function useChart(initialProps) {
|
|
|
5239
5416
|
|
|
5240
5417
|
/**
|
|
5241
5418
|
* Hook for chart data processing and transformation
|
|
5419
|
+
*/
|
|
5420
|
+
/**
|
|
5421
|
+
* Helper to calculate min/max values from a dataset efficiently
|
|
5422
|
+
* avoiding spread operator which can cause stack overflow on large arrays
|
|
5423
|
+
*/
|
|
5424
|
+
function getDatasetBounds(data) {
|
|
5425
|
+
let min = 1 / 0, max = -1 / 0, hasValid = !1;
|
|
5426
|
+
if (data && data.length > 0) for (let i = 0; i < data.length; i++) {
|
|
5427
|
+
const point = data[i];
|
|
5428
|
+
if (point && "number" == typeof point.value) {
|
|
5429
|
+
const val = point.value;
|
|
5430
|
+
val < min && (min = val), val > max && (max = val), hasValid = !0;
|
|
5431
|
+
}
|
|
5432
|
+
}
|
|
5433
|
+
return {
|
|
5434
|
+
min: min,
|
|
5435
|
+
max: max,
|
|
5436
|
+
hasValid: hasValid
|
|
5437
|
+
};
|
|
5438
|
+
}
|
|
5439
|
+
|
|
5440
|
+
/**
|
|
5441
|
+
* Hook for managing chart toolbar state and generating chart-specific configurations
|
|
5242
5442
|
*/ const ChartToolbar = React.memo( React.forwardRef((({chartType: chartType = "line", groups: groups = [], enableDefaults: enableDefaults = !0, defaults: defaults = {
|
|
5243
5443
|
refresh: !0,
|
|
5244
5444
|
export: !0,
|
|
@@ -5659,11 +5859,7 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
|
|
|
5659
5859
|
onZoomReset: handleZoomReset,
|
|
5660
5860
|
onPanToggle: handlePanToggle,
|
|
5661
5861
|
onReset: handleReset
|
|
5662
|
-
})), [ onRefresh, onExport, handleFullscreenChange, handleZoomIn, handleZoomOut, handleZoomReset, handlePanToggle, handleReset ]), {state: toolbarState, handlers: toolbarHandlers, toolbarGroups: toolbarGroups} =
|
|
5663
|
-
/**
|
|
5664
|
-
* Hook for managing chart toolbar state and generating chart-specific configurations
|
|
5665
|
-
*/
|
|
5666
|
-
function(chartType, config = {}, handlers = {}) {
|
|
5862
|
+
})), [ onRefresh, onExport, handleFullscreenChange, handleZoomIn, handleZoomOut, handleZoomReset, handlePanToggle, handleReset ]), {state: toolbarState, handlers: toolbarHandlers, toolbarGroups: toolbarGroups} = function(chartType, config = {}, handlers = {}) {
|
|
5667
5863
|
const [state, setState] = React.useState({
|
|
5668
5864
|
isFullscreen: !1,
|
|
5669
5865
|
isExporting: !1,
|
|
@@ -6048,16 +6244,16 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
|
|
|
6048
6244
|
aberrationIntensity: 1.5,
|
|
6049
6245
|
elasticity: 0,
|
|
6050
6246
|
// No elastic effect for charts
|
|
6051
|
-
|
|
6247
|
+
withLiquidBlur: !1,
|
|
6052
6248
|
// Keep it simple
|
|
6053
|
-
|
|
6249
|
+
withBorder: !0,
|
|
6054
6250
|
mode: "standard",
|
|
6055
6251
|
mouseContainer: chartContainerRef,
|
|
6056
6252
|
reducedMotion: !1
|
|
6057
6253
|
})), []), glassProps = React.useMemo((() => glass ? !0 === glass ? defaultChartGlassProps : {
|
|
6058
6254
|
...defaultChartGlassProps,
|
|
6059
6255
|
...glass
|
|
6060
|
-
} : null), [ glass, defaultChartGlassProps ]), chartBorderRadius = React.useMemo((() => glassProps?.
|
|
6256
|
+
} : null), [ glass, defaultChartGlassProps ]), chartBorderRadius = React.useMemo((() => glassProps?.borderRadius || void 0), [ glassProps?.borderRadius ]), chartContextValue = React.useMemo((() => ({
|
|
6061
6257
|
zoomLevel: zoomLevel,
|
|
6062
6258
|
panOffset: panOffset,
|
|
6063
6259
|
panEnabled: panEnabled,
|
|
@@ -6188,7 +6384,7 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
|
|
|
6188
6384
|
}) ]
|
|
6189
6385
|
}), wrappedChart = glassProps ? jsxRuntime.jsx(AtomixGlass, {
|
|
6190
6386
|
...glassProps,
|
|
6191
|
-
|
|
6387
|
+
borderRadius: chartBorderRadius,
|
|
6192
6388
|
style: {
|
|
6193
6389
|
width: "100%",
|
|
6194
6390
|
height: "100%",
|
|
@@ -6241,7 +6437,13 @@ const ChartRenderer = React.memo( React.forwardRef((({datasets: datasets = [],
|
|
|
6241
6437
|
// Get chart context (zoom/pan state from toolbar) - optional
|
|
6242
6438
|
// Always call useContext to maintain consistent hook order
|
|
6243
6439
|
const chartContext = React.useContext(ChartContext), {calculateScales: calculateScales, getChartColors: getChartColors} = useChart(), {processedData: processedData, isProcessing: isProcessing} = function(datasets, options) {
|
|
6244
|
-
const [processedData, setProcessedData] = React.useState(datasets), [isProcessing, setIsProcessing] = React.useState(!1), {enableDecimation: enableDecimation = !1, maxDataPoints: maxDataPoints = 1e3, enableRealTime: enableRealTime = !1, realTimeInterval: realTimeInterval = 1e3} = options || {},
|
|
6440
|
+
const [processedData, setProcessedData] = React.useState(datasets), [isProcessing, setIsProcessing] = React.useState(!1), {enableDecimation: enableDecimation = !1, maxDataPoints: maxDataPoints = 1e3, enableRealTime: enableRealTime = !1, realTimeInterval: realTimeInterval = 1e3} = options || {}, lastDataSignature = React.useRef(""), getDatasetSignature = React.useCallback((data => data.map((d => `${d.label}:${JSON.stringify(d.data)}`)).join("|")), []);
|
|
6441
|
+
// Update signature when processedData changes (e.g. via props)
|
|
6442
|
+
React.useEffect((() => {
|
|
6443
|
+
lastDataSignature.current = getDatasetSignature(processedData);
|
|
6444
|
+
}), [ processedData, getDatasetSignature ]);
|
|
6445
|
+
// Data decimation for performance
|
|
6446
|
+
const decimateData = React.useCallback(((data, maxPoints) => {
|
|
6245
6447
|
if (!enableDecimation || !data.length) return data;
|
|
6246
6448
|
const dataLength = data[0]?.data?.length || 0;
|
|
6247
6449
|
if (dataLength <= maxPoints) return data;
|
|
@@ -6261,10 +6463,17 @@ const ChartRenderer = React.memo( React.forwardRef((({datasets: datasets = [],
|
|
|
6261
6463
|
}), []), calculateTrendLine = React.useCallback((values => {
|
|
6262
6464
|
const n = values.length;
|
|
6263
6465
|
if (n < 2) return values.map((() => null));
|
|
6264
|
-
|
|
6466
|
+
let xSum = 0, ySum = 0, xySum = 0, x2Sum = 0;
|
|
6467
|
+
for (let i = 0; i < n; i++) {
|
|
6468
|
+
const val = values[i], safeVal = "number" == typeof val ? val : 0;
|
|
6469
|
+
// Treat null/undefined as 0 to match original reduce behavior
|
|
6470
|
+
xSum += i, ySum += safeVal, xySum += i * safeVal, x2Sum += i * i;
|
|
6471
|
+
}
|
|
6472
|
+
const slope = (n * xySum - xSum * ySum) / (n * x2Sum - xSum * xSum), intercept = (ySum - slope * xSum) / n;
|
|
6265
6473
|
return values.map(((_, i) => slope * i + intercept));
|
|
6266
6474
|
}), []);
|
|
6267
|
-
//
|
|
6475
|
+
// Moving average calculation
|
|
6476
|
+
// Process data when datasets change
|
|
6268
6477
|
return React.useEffect((() => {
|
|
6269
6478
|
setIsProcessing(!0), (async () => {
|
|
6270
6479
|
let processed = [ ...datasets ];
|
|
@@ -6276,11 +6485,12 @@ const ChartRenderer = React.memo( React.forwardRef((({datasets: datasets = [],
|
|
|
6276
6485
|
React.useEffect((() => {
|
|
6277
6486
|
if (!enableRealTime) return;
|
|
6278
6487
|
const interval = setInterval((() => {
|
|
6279
|
-
setProcessedData((prev =>
|
|
6280
|
-
|
|
6281
|
-
|
|
6488
|
+
setProcessedData((prev =>
|
|
6489
|
+
// Only trigger update if signature changed
|
|
6490
|
+
getDatasetSignature(prev) === lastDataSignature.current ? prev : [ ...prev ]));
|
|
6491
|
+
}), realTimeInterval);
|
|
6282
6492
|
return () => clearInterval(interval);
|
|
6283
|
-
}), [ enableRealTime, realTimeInterval ]), {
|
|
6493
|
+
}), [ enableRealTime, realTimeInterval, getDatasetSignature ]), {
|
|
6284
6494
|
processedData: processedData,
|
|
6285
6495
|
isProcessing: isProcessing,
|
|
6286
6496
|
decimateData: decimateData,
|
|
@@ -6301,12 +6511,12 @@ const ChartRenderer = React.memo( React.forwardRef((({datasets: datasets = [],
|
|
|
6301
6511
|
*/
|
|
6302
6512
|
function(datasets, options) {
|
|
6303
6513
|
const {enableVirtualization: enableVirtualization = !1, enableMemoization: enableMemoization = !0, debounceMs: debounceMs = 100} = options || {}, [isOptimizing, setIsOptimizing] = React.useState(!1), debounceRef = React.useRef(null), memoizedScales = React.useMemo((() => enableMemoization ? datasets.map((dataset => {
|
|
6304
|
-
const
|
|
6514
|
+
const {min: min, max: max, hasValid: hasValid} = getDatasetBounds(dataset.data);
|
|
6305
6515
|
return {
|
|
6306
6516
|
label: dataset.label,
|
|
6307
6517
|
dataLength: dataset.data?.length || 0,
|
|
6308
|
-
minValue:
|
|
6309
|
-
maxValue:
|
|
6518
|
+
minValue: hasValid ? min : 0,
|
|
6519
|
+
maxValue: hasValid ? max : 0
|
|
6310
6520
|
};
|
|
6311
6521
|
})) : null), [ datasets, enableMemoization ]), debouncedUpdate = React.useCallback((callback => {
|
|
6312
6522
|
debounceRef.current && clearTimeout(debounceRef.current), debounceRef.current = setTimeout((() => {
|
|
@@ -6405,8 +6615,8 @@ const ChartRenderer = React.memo( React.forwardRef((({datasets: datasets = [],
|
|
|
6405
6615
|
const getAccessibleDescription = React.useCallback((() => {
|
|
6406
6616
|
if (!datasets.length) return "Empty chart";
|
|
6407
6617
|
const datasetDescriptions = datasets.map(((dataset, i) => {
|
|
6408
|
-
const dataCount = dataset.data?.length || 0,
|
|
6409
|
-
return `Dataset ${i + 1}: ${dataset.label}, ${dataCount} points, range ${
|
|
6618
|
+
const dataCount = dataset.data?.length || 0, {min: min, max: max, hasValid: hasValid} = getDatasetBounds(dataset.data), minVal = hasValid ? min : 0, maxVal = hasValid ? max : 0;
|
|
6619
|
+
return `Dataset ${i + 1}: ${dataset.label}, ${dataCount} points, range ${minVal} to ${maxVal}`;
|
|
6410
6620
|
})).join(". ");
|
|
6411
6621
|
return `Chart with ${datasets.length} datasets. ${datasetDescriptions}`;
|
|
6412
6622
|
}), [ datasets ]);
|
|
@@ -8656,14 +8866,14 @@ const ScatterChart = React.memo( React.forwardRef((({datasets: datasets = [], c
|
|
|
8656
8866
|
|
|
8657
8867
|
ScatterChart.displayName = "ScatterChart";
|
|
8658
8868
|
|
|
8659
|
-
const
|
|
8869
|
+
const DEFAULT_COLOR_CONFIG = {
|
|
8660
8870
|
scheme: "category"
|
|
8661
|
-
},
|
|
8871
|
+
}, DEFAULT_LABEL_CONFIG = {
|
|
8662
8872
|
showLabels: !0,
|
|
8663
8873
|
minSize: 1e3,
|
|
8664
8874
|
fontSize: 12,
|
|
8665
8875
|
textColor: "white"
|
|
8666
|
-
}, onDataPointClick: onDataPointClick, config: config =
|
|
8876
|
+
}, DEFAULT_CONFIG = {}, TreemapChart = React.memo( React.forwardRef((({data: data = [], algorithm: algorithm = "squarified", colorConfig: colorConfig = DEFAULT_COLOR_CONFIG, labelConfig: labelConfig = DEFAULT_LABEL_CONFIG, onDataPointClick: onDataPointClick, config: config = DEFAULT_CONFIG, ...props}, ref) => {
|
|
8667
8877
|
const [hoveredNode, setHoveredNode] = React.useState(null), [selectedNode, setSelectedNode] = React.useState(null);
|
|
8668
8878
|
React.useState({
|
|
8669
8879
|
x: 0,
|
|
@@ -8775,87 +8985,87 @@ const TreemapChart = React.memo( React.forwardRef((({data: data = [], algorithm
|
|
|
8775
8985
|
remainingHeight -= rowHeight), currentRow = [];
|
|
8776
8986
|
}
|
|
8777
8987
|
}
|
|
8778
|
-
}), []),
|
|
8988
|
+
}), []), renderContent = React.useCallback((({scales: scales, colors: colors, datasets: renderedDatasets, handlers: handlers, hoveredPoint: hoveredPoint}) => {
|
|
8989
|
+
if (!data.length) return null;
|
|
8990
|
+
// Calculate available space with padding
|
|
8991
|
+
const availableWidth = scales.width - 40, availableHeight = scales.height - 40, leafNodes = data.filter((item => !item.children || 0 === item.children.length));
|
|
8992
|
+
if (!leafNodes.length) return null;
|
|
8993
|
+
const totalValue = _reduceInstanceProperty(leafNodes).call(leafNodes, ((sum, node) => sum + node.value), 0), treemapNodes = leafNodes.map(((item, index) => ({
|
|
8994
|
+
id: item.id,
|
|
8995
|
+
label: item.label,
|
|
8996
|
+
value: item.value,
|
|
8997
|
+
color: generateColor(item, 0, index) || "transparent",
|
|
8998
|
+
x: 0,
|
|
8999
|
+
// Will be calculated by squarify
|
|
9000
|
+
y: 0,
|
|
9001
|
+
// Will be calculated by squarify
|
|
9002
|
+
width: 0,
|
|
9003
|
+
// Will be calculated by squarify
|
|
9004
|
+
height: 0,
|
|
9005
|
+
// Will be calculated by squarify
|
|
9006
|
+
depth: 0,
|
|
9007
|
+
children: [],
|
|
9008
|
+
originalData: item
|
|
9009
|
+
})));
|
|
9010
|
+
// Create treemap nodes with proper dimensions
|
|
9011
|
+
// Apply squarified algorithm to layout nodes proportionally by value
|
|
9012
|
+
if ("squarified" === algorithm && totalValue > 0) squarify(treemapNodes, 20, 20, availableWidth, availableHeight); else {
|
|
9013
|
+
// Fallback: simple grid layout (equal sizes)
|
|
9014
|
+
const cols = Math.ceil(Math.sqrt(leafNodes.length)), rows = Math.ceil(leafNodes.length / cols), nodeWidth = availableWidth / cols, nodeHeight = availableHeight / rows;
|
|
9015
|
+
treemapNodes.forEach(((node, index) => {
|
|
9016
|
+
const col = index % cols, row = Math.floor(index / cols);
|
|
9017
|
+
node.x = 20 + col * nodeWidth, node.y = 20 + row * nodeHeight, node.width = nodeWidth,
|
|
9018
|
+
node.height = nodeHeight;
|
|
9019
|
+
}));
|
|
9020
|
+
}
|
|
9021
|
+
return jsxRuntime.jsx(jsxRuntime.Fragment, {
|
|
9022
|
+
children: treemapNodes.map((node => {
|
|
9023
|
+
const isHovered = hoveredNode === node, isSelected = selectedNode === node, area = node.width * node.height, showLabel = labelConfig.showLabels && area >= (labelConfig.minSize || 1e3);
|
|
9024
|
+
return jsxRuntime.jsxs("g", {
|
|
9025
|
+
children: [ jsxRuntime.jsx("rect", {
|
|
9026
|
+
x: node.x,
|
|
9027
|
+
y: node.y,
|
|
9028
|
+
width: node.width,
|
|
9029
|
+
height: node.height,
|
|
9030
|
+
fill: node.color,
|
|
9031
|
+
className: `c-chart__treemap-node ${isHovered ? "c-chart__treemap-node--hovered" : ""} ${isSelected ? "c-chart__treemap-node--selected" : ""}`,
|
|
9032
|
+
onClick: () => {
|
|
9033
|
+
setSelectedNode(node), handlers.onDataPointClick?.(node.originalData, 0, 0);
|
|
9034
|
+
},
|
|
9035
|
+
onMouseEnter: e => {
|
|
9036
|
+
setHoveredNode(node);
|
|
9037
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
9038
|
+
handlers.onPointHover(0, 0, node.x, node.y, rect.left + rect.width / 2, rect.top + rect.height / 2);
|
|
9039
|
+
},
|
|
9040
|
+
onMouseLeave: () => {
|
|
9041
|
+
setHoveredNode(null), handlers.onPointLeave();
|
|
9042
|
+
}
|
|
9043
|
+
}), showLabel && jsxRuntime.jsx("text", {
|
|
9044
|
+
x: node.x + node.width / 2,
|
|
9045
|
+
y: node.y + node.height / 2,
|
|
9046
|
+
textAnchor: "middle",
|
|
9047
|
+
dominantBaseline: "middle",
|
|
9048
|
+
className: "c-chart__treemap-label",
|
|
9049
|
+
style: {
|
|
9050
|
+
fontSize: labelConfig.fontSize,
|
|
9051
|
+
fill: labelConfig.textColor
|
|
9052
|
+
},
|
|
9053
|
+
children: node.label
|
|
9054
|
+
}) ]
|
|
9055
|
+
}, node.id);
|
|
9056
|
+
}))
|
|
9057
|
+
});
|
|
9058
|
+
}), [ data, algorithm, generateColor, squarify, labelConfig, hoveredNode, selectedNode ]), datasets = React.useMemo((() => [ {
|
|
8779
9059
|
label: "Treemap Data",
|
|
8780
9060
|
data: data
|
|
8781
|
-
} ];
|
|
9061
|
+
} ]), [ data ]);
|
|
8782
9062
|
// Squarified treemap algorithm
|
|
8783
9063
|
return jsxRuntime.jsx(BaseChart, {
|
|
8784
9064
|
ref: ref,
|
|
8785
9065
|
type: "treemap",
|
|
8786
9066
|
datasets: datasets,
|
|
8787
9067
|
config: config,
|
|
8788
|
-
renderContent:
|
|
8789
|
-
if (!data.length) return null;
|
|
8790
|
-
// Calculate available space with padding
|
|
8791
|
-
const availableWidth = scales.width - 40, availableHeight = scales.height - 40, leafNodes = data.filter((item => !item.children || 0 === item.children.length));
|
|
8792
|
-
if (!leafNodes.length) return null;
|
|
8793
|
-
const totalValue = _reduceInstanceProperty(leafNodes).call(leafNodes, ((sum, node) => sum + node.value), 0), treemapNodes = leafNodes.map(((item, index) => ({
|
|
8794
|
-
id: item.id,
|
|
8795
|
-
label: item.label,
|
|
8796
|
-
value: item.value,
|
|
8797
|
-
color: generateColor(item, 0, index) || "transparent",
|
|
8798
|
-
x: 0,
|
|
8799
|
-
// Will be calculated by squarify
|
|
8800
|
-
y: 0,
|
|
8801
|
-
// Will be calculated by squarify
|
|
8802
|
-
width: 0,
|
|
8803
|
-
// Will be calculated by squarify
|
|
8804
|
-
height: 0,
|
|
8805
|
-
// Will be calculated by squarify
|
|
8806
|
-
depth: 0,
|
|
8807
|
-
children: [],
|
|
8808
|
-
originalData: item
|
|
8809
|
-
})));
|
|
8810
|
-
// Create treemap nodes with proper dimensions
|
|
8811
|
-
// Apply squarified algorithm to layout nodes proportionally by value
|
|
8812
|
-
if ("squarified" === algorithm && totalValue > 0) squarify(treemapNodes, 20, 20, availableWidth, availableHeight); else {
|
|
8813
|
-
// Fallback: simple grid layout (equal sizes)
|
|
8814
|
-
const cols = Math.ceil(Math.sqrt(leafNodes.length)), rows = Math.ceil(leafNodes.length / cols), nodeWidth = availableWidth / cols, nodeHeight = availableHeight / rows;
|
|
8815
|
-
treemapNodes.forEach(((node, index) => {
|
|
8816
|
-
const col = index % cols, row = Math.floor(index / cols);
|
|
8817
|
-
node.x = 20 + col * nodeWidth, node.y = 20 + row * nodeHeight, node.width = nodeWidth,
|
|
8818
|
-
node.height = nodeHeight;
|
|
8819
|
-
}));
|
|
8820
|
-
}
|
|
8821
|
-
return jsxRuntime.jsx(jsxRuntime.Fragment, {
|
|
8822
|
-
children: treemapNodes.map((node => {
|
|
8823
|
-
const isHovered = hoveredNode === node, isSelected = selectedNode === node, area = node.width * node.height, showLabel = labelConfig.showLabels && area >= (labelConfig.minSize || 1e3);
|
|
8824
|
-
return jsxRuntime.jsxs("g", {
|
|
8825
|
-
children: [ jsxRuntime.jsx("rect", {
|
|
8826
|
-
x: node.x,
|
|
8827
|
-
y: node.y,
|
|
8828
|
-
width: node.width,
|
|
8829
|
-
height: node.height,
|
|
8830
|
-
fill: node.color,
|
|
8831
|
-
className: `c-chart__treemap-node ${isHovered ? "c-chart__treemap-node--hovered" : ""} ${isSelected ? "c-chart__treemap-node--selected" : ""}`,
|
|
8832
|
-
onClick: () => {
|
|
8833
|
-
setSelectedNode(node), handlers.onDataPointClick?.(node.originalData, 0, 0);
|
|
8834
|
-
},
|
|
8835
|
-
onMouseEnter: e => {
|
|
8836
|
-
setHoveredNode(node);
|
|
8837
|
-
const rect = e.currentTarget.getBoundingClientRect();
|
|
8838
|
-
handlers.onPointHover(0, 0, node.x, node.y, rect.left + rect.width / 2, rect.top + rect.height / 2);
|
|
8839
|
-
},
|
|
8840
|
-
onMouseLeave: () => {
|
|
8841
|
-
setHoveredNode(null), handlers.onPointLeave();
|
|
8842
|
-
}
|
|
8843
|
-
}), showLabel && jsxRuntime.jsx("text", {
|
|
8844
|
-
x: node.x + node.width / 2,
|
|
8845
|
-
y: node.y + node.height / 2,
|
|
8846
|
-
textAnchor: "middle",
|
|
8847
|
-
dominantBaseline: "middle",
|
|
8848
|
-
className: "c-chart__treemap-label",
|
|
8849
|
-
style: {
|
|
8850
|
-
fontSize: labelConfig.fontSize,
|
|
8851
|
-
fill: labelConfig.textColor
|
|
8852
|
-
},
|
|
8853
|
-
children: node.label
|
|
8854
|
-
}) ]
|
|
8855
|
-
}, node.id);
|
|
8856
|
-
}))
|
|
8857
|
-
});
|
|
8858
|
-
},
|
|
9068
|
+
renderContent: renderContent,
|
|
8859
9069
|
onDataPointClick: onDataPointClick,
|
|
8860
9070
|
interactive: !0,
|
|
8861
9071
|
...props
|
|
@@ -9543,7 +9753,7 @@ const range = (start, end) => {
|
|
|
9543
9753
|
blurAmount: 1,
|
|
9544
9754
|
saturation: 160,
|
|
9545
9755
|
aberrationIntensity: .5,
|
|
9546
|
-
|
|
9756
|
+
borderRadius: 8,
|
|
9547
9757
|
mode: "shader"
|
|
9548
9758
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
9549
9759
|
...defaultGlassProps,
|
|
@@ -9614,7 +9824,7 @@ const Checkbox = React__default.default.memo( React.forwardRef((({label: label,
|
|
|
9614
9824
|
blurAmount: 1,
|
|
9615
9825
|
saturation: 160,
|
|
9616
9826
|
aberrationIntensity: .3,
|
|
9617
|
-
|
|
9827
|
+
borderRadius: 6,
|
|
9618
9828
|
mode: "shader"
|
|
9619
9829
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
9620
9830
|
...defaultGlassProps,
|
|
@@ -9674,6 +9884,7 @@ const DropdownItem = React.memo((({children: children, href: href, active: acti
|
|
|
9674
9884
|
close());
|
|
9675
9885
|
}, itemClasses = [ "c-dropdown__menu-item", active ? "is-active" : "", disabled ? "is-disabled" : "", className ].filter(Boolean).join(" "), linkProps = {
|
|
9676
9886
|
href: href,
|
|
9887
|
+
to: href,
|
|
9677
9888
|
className: itemClasses,
|
|
9678
9889
|
onClick: handleClick,
|
|
9679
9890
|
role: "menuitem",
|
|
@@ -9712,13 +9923,32 @@ const DropdownItem = React.memo((({children: children, href: href, active: acti
|
|
|
9712
9923
|
}), children ]
|
|
9713
9924
|
})
|
|
9714
9925
|
});
|
|
9715
|
-
}))
|
|
9926
|
+
}));
|
|
9927
|
+
|
|
9928
|
+
DropdownItem.displayName = "DropdownItem";
|
|
9929
|
+
|
|
9930
|
+
/**
|
|
9931
|
+
* DropdownDivider component for separating groups of items
|
|
9932
|
+
*/
|
|
9933
|
+
const DropdownDivider = React.memo((({className: className = ""}) => jsxRuntime.jsx("li", {
|
|
9716
9934
|
className: `c-dropdown__divider ${className}`,
|
|
9717
9935
|
role: "separator"
|
|
9718
|
-
})))
|
|
9936
|
+
})));
|
|
9937
|
+
|
|
9938
|
+
DropdownDivider.displayName = "DropdownDivider";
|
|
9939
|
+
|
|
9940
|
+
/**
|
|
9941
|
+
* DropdownHeader component for section headers
|
|
9942
|
+
*/
|
|
9943
|
+
const DropdownHeader = React.memo((({children: children, className: className = ""}) => jsxRuntime.jsx("li", {
|
|
9719
9944
|
className: `c-dropdown__header ${className}`,
|
|
9720
9945
|
children: children
|
|
9721
|
-
})))
|
|
9946
|
+
})));
|
|
9947
|
+
|
|
9948
|
+
DropdownHeader.displayName = "DropdownHeader";
|
|
9949
|
+
|
|
9950
|
+
// Helper context to pass glass prop to DropdownMenu
|
|
9951
|
+
const DropdownStyleContext = React.createContext({}), Dropdown = React.memo((function({children: children, menu: menu, placement: placement = "bottom-start", trigger: trigger = "click", offset: offset = DROPDOWN.DEFAULTS.OFFSET, isOpen: controlledIsOpen, onOpenChange: onOpenChange, closeOnClickOutside: closeOnClickOutside = !0, closeOnEscape: closeOnEscape = !0, maxHeight: maxHeight, minWidth: minWidth = DROPDOWN.DEFAULTS.MIN_WIDTH, variant: variant, className: className = "", style: style, glass: glass, ...props}) {
|
|
9722
9952
|
// Set up controlled vs uncontrolled state
|
|
9723
9953
|
const [uncontrolledIsOpen, setUncontrolledIsOpen] = React.useState(!1), isControlled = void 0 !== controlledIsOpen, isOpen = isControlled ? controlledIsOpen : uncontrolledIsOpen, dropdownRef = React.useRef(null), toggleRef = React.useRef(null), menuRef = React.useRef(null), dropdownId = React.useRef(`dropdown-${Math.random().toString(36).substring(2, 9)}`).current, setIsOpen = React.useCallback((nextIsOpen => {
|
|
9724
9954
|
isControlled || setUncontrolledIsOpen(nextIsOpen), onOpenChange && onOpenChange(nextIsOpen);
|
|
@@ -9870,9 +10100,7 @@ const DropdownItem = React.memo((({children: children, href: href, active: acti
|
|
|
9870
10100
|
});
|
|
9871
10101
|
}));
|
|
9872
10102
|
|
|
9873
|
-
|
|
9874
|
-
* DropdownDivider component for separating groups of items
|
|
9875
|
-
*/ Dropdown.displayName = "Dropdown", Dropdown.Trigger = DropdownTrigger, Dropdown.Menu = DropdownMenu,
|
|
10103
|
+
Dropdown.displayName = "Dropdown", Dropdown.Trigger = DropdownTrigger, Dropdown.Menu = DropdownMenu,
|
|
9876
10104
|
Dropdown.Item = DropdownItem, Dropdown.Divider = DropdownDivider, Dropdown.Header = DropdownHeader;
|
|
9877
10105
|
|
|
9878
10106
|
/**
|
|
@@ -11296,7 +11524,7 @@ const Input = React.memo( React.forwardRef((({type: type = "text", value: value
|
|
|
11296
11524
|
blurAmount: 1,
|
|
11297
11525
|
saturation: 180,
|
|
11298
11526
|
aberrationIntensity: .2,
|
|
11299
|
-
|
|
11527
|
+
borderRadius: 12,
|
|
11300
11528
|
mode: "shader"
|
|
11301
11529
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
11302
11530
|
...defaultGlassProps,
|
|
@@ -11336,7 +11564,7 @@ function useHero(initialProps) {
|
|
|
11336
11564
|
* @returns Slider state and methods
|
|
11337
11565
|
*/
|
|
11338
11566
|
function(config) {
|
|
11339
|
-
const {slides: slides, autoplay: autoplay, loop: loop = !0, transition: transition = "fade", transitionDuration: transitionDuration = 1e3} = config, [currentIndex, setCurrentIndex] = React.useState(0), [isTransitioning, setIsTransitioning] = React.useState(!1), autoplayRef = React.useRef(null), isPausedRef = React.useRef(!1), slideRefs = React.useMemo((() => slides.map((() => React__default.default.createRef()))), [ slides.length ]), videoRefs = React.useMemo((() => slides.map((() => React__default.default.createRef()))), [ slides.length ]), handleSlideTransition = React.useCallback((nextIndex => {
|
|
11567
|
+
const {slides: slides, autoplay: autoplay, loop: loop = !0, transition: transition = "fade", transitionDuration: transitionDuration = 1e3} = config, [currentIndex, setCurrentIndex] = React.useState(0), [isTransitioning, setIsTransitioning] = React.useState(!1), autoplayRef = React.useRef(null), isPausedRef = React.useRef(!1), callbackRef = React.useRef(), slideRefs = React.useMemo((() => slides.map((() => React__default.default.createRef()))), [ slides.length ]), videoRefs = React.useMemo((() => slides.map((() => React__default.default.createRef()))), [ slides.length ]), handleSlideTransition = React.useCallback((nextIndex => {
|
|
11340
11568
|
if (nextIndex === currentIndex || isTransitioning) return;
|
|
11341
11569
|
if (nextIndex < 0 || nextIndex >= slides.length) return;
|
|
11342
11570
|
setIsTransitioning(!0),
|
|
@@ -11357,7 +11585,17 @@ function useHero(initialProps) {
|
|
|
11357
11585
|
let nextIndex;
|
|
11358
11586
|
nextIndex = loop ? (currentIndex + 1) % slides.length : Math.min(currentIndex + 1, slides.length - 1),
|
|
11359
11587
|
handleSlideTransition(nextIndex);
|
|
11360
|
-
}), [ currentIndex, slides.length, loop, handleSlideTransition ])
|
|
11588
|
+
}), [ currentIndex, slides.length, loop, handleSlideTransition ]);
|
|
11589
|
+
// Update callbackRef whenever nextSlide or isTransitioning changes
|
|
11590
|
+
React.useEffect((() => {
|
|
11591
|
+
callbackRef.current = () => {
|
|
11592
|
+
isPausedRef.current || isTransitioning || nextSlide();
|
|
11593
|
+
};
|
|
11594
|
+
}), [ nextSlide, isTransitioning ]);
|
|
11595
|
+
/**
|
|
11596
|
+
* Pause autoplay
|
|
11597
|
+
*/
|
|
11598
|
+
const pauseAutoplay = React.useCallback((() => {
|
|
11361
11599
|
isPausedRef.current = !0, autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
11362
11600
|
autoplayRef.current = null);
|
|
11363
11601
|
}), []), resumeAutoplay = React.useCallback((() => {
|
|
@@ -11366,24 +11604,26 @@ function useHero(initialProps) {
|
|
|
11366
11604
|
const delay = "object" == typeof autoplay ? autoplay.delay : 3e3;
|
|
11367
11605
|
// Restart autoplay
|
|
11368
11606
|
autoplayRef.current || (autoplayRef.current = setInterval((() => {
|
|
11369
|
-
|
|
11607
|
+
callbackRef.current && callbackRef.current();
|
|
11370
11608
|
}), delay));
|
|
11371
11609
|
}
|
|
11372
|
-
}), [ autoplay, slides.length
|
|
11610
|
+
}), [ autoplay, slides.length ]);
|
|
11611
|
+
/**
|
|
11612
|
+
* Resume autoplay
|
|
11613
|
+
*/
|
|
11373
11614
|
// Autoplay effect
|
|
11374
11615
|
return React.useEffect((() => {
|
|
11375
11616
|
if (!autoplay || slides.length <= 1) return;
|
|
11376
11617
|
const delay = "object" == typeof autoplay ? autoplay.delay : 3e3;
|
|
11377
|
-
return "object" == typeof autoplay && autoplay.pauseOnHover,
|
|
11378
11618
|
// Clear any existing interval
|
|
11379
|
-
|
|
11619
|
+
return autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null),
|
|
11380
11620
|
// Start autoplay if not paused
|
|
11381
11621
|
isPausedRef.current || (autoplayRef.current = setInterval((() => {
|
|
11382
|
-
|
|
11622
|
+
callbackRef.current && callbackRef.current();
|
|
11383
11623
|
}), delay)), () => {
|
|
11384
11624
|
autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null);
|
|
11385
11625
|
};
|
|
11386
|
-
}), [ autoplay, slides.length
|
|
11626
|
+
}), [ autoplay, slides.length ]),
|
|
11387
11627
|
// Initialize first video if needed
|
|
11388
11628
|
React.useEffect((() => {
|
|
11389
11629
|
if (slides.length > 0 && "video" === slides[currentIndex]?.type) {
|
|
@@ -12382,7 +12622,14 @@ const DEFAULT_ATOMIX_FONTS = [ {
|
|
|
12382
12622
|
}
|
|
12383
12623
|
|
|
12384
12624
|
function useSlider(options) {
|
|
12385
|
-
const {slides: slides, slidesToShow: slidesToShow = 1, spaceBetween: spaceBetween = 0, loop: loop = !1, initialSlide: initialSlide = 0, direction: direction = "horizontal", speed: speed = 300, allowTouchMove: allowTouchMove = !0, threshold: threshold = 50, autoplay: autoplay, onSlideChange: onSlideChange} = options, containerRef = React.useRef(null), wrapperRef = React.useRef(null), repositioningRef = React.useRef(!1), autoplayRef = React.useRef(null), [autoplayRunning, setAutoplayRunning] = React.useState(!1),
|
|
12625
|
+
const {slides: slides, slidesToShow: slidesToShow = 1, spaceBetween: spaceBetween = 0, loop: loop = !1, initialSlide: initialSlide = 0, direction: direction = "horizontal", speed: speed = 300, allowTouchMove: allowTouchMove = !0, threshold: threshold = 50, autoplay: autoplay, onSlideChange: onSlideChange} = options, containerRef = React.useRef(null), wrapperRef = React.useRef(null), repositioningRef = React.useRef(!1), autoplayRef = React.useRef(null), [autoplayRunning, setAutoplayRunning] = React.useState(!1), sliderStateRef = React.useRef({
|
|
12626
|
+
isTransitioning: !1,
|
|
12627
|
+
loop: loop,
|
|
12628
|
+
slides: slides,
|
|
12629
|
+
slidesToShow: slidesToShow,
|
|
12630
|
+
speed: speed,
|
|
12631
|
+
onSlideChange: onSlideChange
|
|
12632
|
+
}), [realIndex, setRealIndex] = React.useState(initialSlide), [internalIndex, setInternalIndex] = React.useState(0), [isTransitioning, setIsTransitioning] = React.useState(!1), [containerSize, setContainerSize] = React.useState(0), [touching, setTouching] = React.useState(!1), [touchStart, setTouchStart] = React.useState(0), [dragOffset, setDragOffset] = React.useState(0), slideWidth = React.useMemo((() => 0 === containerSize ? 0 : (containerSize - spaceBetween * (slidesToShow - 1)) / slidesToShow), [ containerSize, spaceBetween, slidesToShow ]), allSlides = React.useMemo((() => loop && 0 !== slides.length ? [ ...slides.map(((slide, i) => ({
|
|
12386
12633
|
...slide,
|
|
12387
12634
|
id: `set1-${slide.id || i}`
|
|
12388
12635
|
}))), ...slides.map(((slide, i) => ({
|
|
@@ -12392,6 +12639,17 @@ function useSlider(options) {
|
|
|
12392
12639
|
...slide,
|
|
12393
12640
|
id: `set3-${slide.id || i}`
|
|
12394
12641
|
}))) ] : slides), [ slides, loop ]), loopedSlides = slides.length, translateValue = React.useMemo((() => 0 === slideWidth ? 0 : -internalIndex * slideWidth + dragOffset), [ slideWidth, internalIndex, dragOffset ]);
|
|
12642
|
+
// Update the ref whenever the relevant state/props change
|
|
12643
|
+
React.useEffect((() => {
|
|
12644
|
+
sliderStateRef.current = {
|
|
12645
|
+
isTransitioning: isTransitioning,
|
|
12646
|
+
loop: loop,
|
|
12647
|
+
slides: slides,
|
|
12648
|
+
slidesToShow: slidesToShow,
|
|
12649
|
+
speed: speed,
|
|
12650
|
+
onSlideChange: onSlideChange
|
|
12651
|
+
};
|
|
12652
|
+
}), [ isTransitioning, loop, slides, slidesToShow, speed, onSlideChange ]),
|
|
12395
12653
|
// Autoplay effect
|
|
12396
12654
|
React.useEffect((() => {
|
|
12397
12655
|
if (!autoplay) return autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
@@ -12403,32 +12661,34 @@ function useSlider(options) {
|
|
|
12403
12661
|
autoplayRef.current && clearInterval(autoplayRef.current),
|
|
12404
12662
|
// Create new interval
|
|
12405
12663
|
autoplayRef.current = setInterval((() => {
|
|
12664
|
+
// Use ref to get the latest state without resetting the interval
|
|
12665
|
+
const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
|
|
12406
12666
|
// We need to use a functional update to get the latest values
|
|
12407
|
-
|
|
12408
|
-
if (
|
|
12667
|
+
setRealIndex((prevRealIndex => {
|
|
12668
|
+
if (currentIsTransitioning) return prevRealIndex;
|
|
12409
12669
|
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12410
12670
|
let nextIndex;
|
|
12411
12671
|
// Trigger the slide change
|
|
12412
12672
|
if (disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12413
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), nextIndex =
|
|
12673
|
+
autoplayRef.current = null, setAutoplayRunning(!1)), nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
|
|
12414
12674
|
reverseDirection) {
|
|
12415
12675
|
// For reverse direction, we would go to previous slide
|
|
12416
|
-
const prevIndex =
|
|
12417
|
-
return setInternalIndex(
|
|
12418
|
-
setDragOffset(0), setTimeout((() => {
|
|
12419
|
-
setIsTransitioning(!1),
|
|
12420
|
-
}),
|
|
12676
|
+
const prevIndex = currentLoop ? 0 === prevRealIndex ? currentSlides.length - 1 : prevRealIndex - 1 : Math.max(prevRealIndex - 1, 0);
|
|
12677
|
+
return setInternalIndex(currentLoop ? currentSlides.length + prevIndex : prevIndex),
|
|
12678
|
+
setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
|
|
12679
|
+
setIsTransitioning(!1), currentOnSlideChange?.(prevIndex);
|
|
12680
|
+
}), currentSpeed), prevIndex;
|
|
12421
12681
|
}
|
|
12422
12682
|
// Normal direction
|
|
12423
|
-
return setInternalIndex(
|
|
12424
|
-
setDragOffset(0), setTimeout((() => {
|
|
12425
|
-
setIsTransitioning(!1),
|
|
12683
|
+
return setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex),
|
|
12684
|
+
setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
|
|
12685
|
+
setIsTransitioning(!1), currentOnSlideChange?.(nextIndex),
|
|
12426
12686
|
// Reposition after transition ends for looped sliders
|
|
12427
|
-
|
|
12428
|
-
setTimeout((() => {
|
|
12687
|
+
currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
|
|
12688
|
+
setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
|
|
12429
12689
|
repositioningRef.current = !1;
|
|
12430
12690
|
}), 0));
|
|
12431
|
-
}),
|
|
12691
|
+
}), currentSpeed), nextIndex;
|
|
12432
12692
|
}));
|
|
12433
12693
|
}), delay), setAutoplayRunning(!0);
|
|
12434
12694
|
// Handle pause on mouse enter/leave if enabled
|
|
@@ -12439,17 +12699,18 @@ function useSlider(options) {
|
|
|
12439
12699
|
}, handleMouseLeave = () => {
|
|
12440
12700
|
// Restart autoplay
|
|
12441
12701
|
autoplayRef.current && clearInterval(autoplayRef.current), autoplayRef.current = setInterval((() => {
|
|
12702
|
+
const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
|
|
12442
12703
|
setRealIndex((prevRealIndex => {
|
|
12443
|
-
if (
|
|
12704
|
+
if (currentIsTransitioning) return prevRealIndex;
|
|
12444
12705
|
let nextIndex;
|
|
12445
|
-
return nextIndex =
|
|
12446
|
-
setInternalIndex(
|
|
12706
|
+
return nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
|
|
12707
|
+
setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex), setIsTransitioning(!0),
|
|
12447
12708
|
setDragOffset(0), setTimeout((() => {
|
|
12448
|
-
setIsTransitioning(!1),
|
|
12449
|
-
setInternalIndex(
|
|
12709
|
+
setIsTransitioning(!1), currentOnSlideChange?.(nextIndex), currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
|
|
12710
|
+
setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
|
|
12450
12711
|
repositioningRef.current = !1;
|
|
12451
12712
|
}), 0));
|
|
12452
|
-
}),
|
|
12713
|
+
}), currentSpeed), nextIndex;
|
|
12453
12714
|
}));
|
|
12454
12715
|
}), delay), setAutoplayRunning(!0);
|
|
12455
12716
|
};
|
|
@@ -12461,7 +12722,7 @@ function useSlider(options) {
|
|
|
12461
12722
|
containerElement && (containerElement.removeEventListener("mouseenter", handleMouseEnter),
|
|
12462
12723
|
containerElement.removeEventListener("mouseleave", handleMouseLeave)), setAutoplayRunning(!1);
|
|
12463
12724
|
};
|
|
12464
|
-
}), [ autoplay,
|
|
12725
|
+
}), [ autoplay, repositioningRef ]),
|
|
12465
12726
|
// Initialize
|
|
12466
12727
|
React.useEffect((() => {
|
|
12467
12728
|
setInternalIndex(loop ? slides.length + initialSlide : initialSlide);
|
|
@@ -12921,7 +13182,7 @@ const Select = React.memo((({options: options, value: value, onChange: onChange
|
|
|
12921
13182
|
blurAmount: 1,
|
|
12922
13183
|
saturation: 180,
|
|
12923
13184
|
aberrationIntensity: .2,
|
|
12924
|
-
|
|
13185
|
+
borderRadius: 12,
|
|
12925
13186
|
mode: "shader"
|
|
12926
13187
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
12927
13188
|
...defaultGlassProps,
|
|
@@ -12979,7 +13240,7 @@ const Radio = React.memo((({label: label, checked: checked = !1, onChange: onCh
|
|
|
12979
13240
|
blurAmount: 1,
|
|
12980
13241
|
saturation: 160,
|
|
12981
13242
|
aberrationIntensity: .3,
|
|
12982
|
-
|
|
13243
|
+
borderRadius: 6,
|
|
12983
13244
|
mode: "shader"
|
|
12984
13245
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
12985
13246
|
...defaultGlassProps,
|
|
@@ -13045,7 +13306,7 @@ const Textarea = React.memo( React.forwardRef((({value: value, defaultValue: de
|
|
|
13045
13306
|
blurAmount: 1,
|
|
13046
13307
|
saturation: 180,
|
|
13047
13308
|
aberrationIntensity: 1,
|
|
13048
|
-
|
|
13309
|
+
borderRadius: 8,
|
|
13049
13310
|
mode: "shader"
|
|
13050
13311
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
13051
13312
|
...defaultGlassProps,
|
|
@@ -13771,11 +14032,12 @@ const FooterLink = React.forwardRef((({href: href, icon: icon, external: extern
|
|
|
13771
14032
|
const Component = LinkComponent, componentProps = {
|
|
13772
14033
|
ref: ref,
|
|
13773
14034
|
...href && !disabled ? {
|
|
14035
|
+
href: href,
|
|
13774
14036
|
to: href
|
|
13775
14037
|
} : {},
|
|
13776
14038
|
...linkProps
|
|
13777
14039
|
};
|
|
13778
|
-
// Only pass href if the link is not disabled and href exists
|
|
14040
|
+
// Only pass href/to if the link is not disabled and href exists
|
|
13779
14041
|
return jsxRuntime.jsxs(Component, {
|
|
13780
14042
|
...componentProps,
|
|
13781
14043
|
children: [ icon && jsxRuntime.jsx("span", {
|
|
@@ -13886,7 +14148,7 @@ const Hero = ({title: title, subtitle: subtitle, text: text, imageSrc: imageSrc,
|
|
|
13886
14148
|
blurAmount: 3,
|
|
13887
14149
|
saturation: 180,
|
|
13888
14150
|
aberrationIntensity: 0,
|
|
13889
|
-
|
|
14151
|
+
borderRadius: 8,
|
|
13890
14152
|
overLight: !1,
|
|
13891
14153
|
mode: "standard",
|
|
13892
14154
|
children: jsxRuntime.jsxs("div", {
|
|
@@ -14094,7 +14356,7 @@ Hero.Title = ({children: children, className: className, level: level = "h1", ..
|
|
|
14094
14356
|
blurAmount: 3,
|
|
14095
14357
|
saturation: 180,
|
|
14096
14358
|
aberrationIntensity: 0,
|
|
14097
|
-
|
|
14359
|
+
borderRadius: 8,
|
|
14098
14360
|
overLight: !1,
|
|
14099
14361
|
mode: "standard"
|
|
14100
14362
|
} : glass;
|
|
@@ -14208,7 +14470,7 @@ const Messages = ({messages: messages = [], otherAvatar: otherAvatar, selfAvatar
|
|
|
14208
14470
|
onSendMessage: onSendMessage
|
|
14209
14471
|
}), messagesId = id || `messages-${Math.random().toString(36).substr(2, 9)}`, inputId = `${messagesId}-input`, defaultGlassProps = {
|
|
14210
14472
|
displacementScale: 150,
|
|
14211
|
-
|
|
14473
|
+
borderRadius: 12,
|
|
14212
14474
|
elasticity: 0,
|
|
14213
14475
|
aberrationIntensity: 2
|
|
14214
14476
|
}, messagesClasses = `${MESSAGES.CLASSES.BASE} ${glass ? "c-messages--glass" : ""} ${disabled ? "is-disabled" : ""} ${className}`, messagesContent = jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
@@ -14354,7 +14616,7 @@ const Messages = ({messages: messages = [], otherAvatar: otherAvatar, selfAvatar
|
|
|
14354
14616
|
children: jsxRuntime.jsx("div", {
|
|
14355
14617
|
className: "c-messages__glass-content",
|
|
14356
14618
|
style: {
|
|
14357
|
-
borderRadius: glassProps.
|
|
14619
|
+
borderRadius: glassProps.borderRadius
|
|
14358
14620
|
},
|
|
14359
14621
|
children: messagesContent
|
|
14360
14622
|
})
|
|
@@ -14582,7 +14844,7 @@ const Modal = ModalWithSubcomponents, Nav = React.forwardRef((({children: child
|
|
|
14582
14844
|
const defaultGlassProps = {
|
|
14583
14845
|
displacementScale: 60,
|
|
14584
14846
|
blurAmount: 1.5,
|
|
14585
|
-
|
|
14847
|
+
borderRadius: 8,
|
|
14586
14848
|
mode: "shader"
|
|
14587
14849
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
14588
14850
|
...defaultGlassProps,
|
|
@@ -14610,7 +14872,24 @@ const Modal = ModalWithSubcomponents, Nav = React.forwardRef((({children: child
|
|
|
14610
14872
|
* </NavDropdown>
|
|
14611
14873
|
* </Nav>
|
|
14612
14874
|
* ```
|
|
14613
|
-
*/
|
|
14875
|
+
*/
|
|
14876
|
+
/**
|
|
14877
|
+
* Utility to merge multiple React refs into one
|
|
14878
|
+
*/
|
|
14879
|
+
function setRef(ref, value) {
|
|
14880
|
+
"function" == typeof ref ? ref(value) : ref && (
|
|
14881
|
+
// This is safe because we're checking that ref exists first
|
|
14882
|
+
ref.current = value);
|
|
14883
|
+
}
|
|
14884
|
+
|
|
14885
|
+
/**
|
|
14886
|
+
* Combines two React refs into a single ref function
|
|
14887
|
+
* This is used when you need to use and forward a ref at the same time
|
|
14888
|
+
*/ function useForkRef(refA, refB) {
|
|
14889
|
+
return React__default.default.useMemo((() => null == refA && null == refB ? null : refValue => {
|
|
14890
|
+
setRef(refA, refValue), setRef(refB, refValue);
|
|
14891
|
+
}), [ refA, refB ]);
|
|
14892
|
+
}
|
|
14614
14893
|
|
|
14615
14894
|
/**
|
|
14616
14895
|
* NavItem component represents a single navigation item that can be a link, dropdown trigger, or mega menu trigger.
|
|
@@ -14639,14 +14918,15 @@ const Modal = ModalWithSubcomponents, Nav = React.forwardRef((({children: child
|
|
|
14639
14918
|
* </MegaMenu>
|
|
14640
14919
|
* </NavItem>
|
|
14641
14920
|
* ```
|
|
14642
|
-
*/
|
|
14921
|
+
*/ Nav.displayName = "Nav";
|
|
14922
|
+
|
|
14643
14923
|
const NavItem = React.forwardRef((({children: children, dropdown: dropdown = !1, megaMenu: megaMenu = !1, active: active = !1, href: href, onClick: onClick, className: className = "", disabled: disabled = !1, "aria-expanded": ariaExpanded, LinkComponent: LinkComponent}, ref) => {
|
|
14644
14924
|
const {generateNavItemClass: generateNavItemClass, generateNavLinkClass: generateNavLinkClass, handleClick: handleClick} = useNavItem({
|
|
14645
14925
|
dropdown: dropdown,
|
|
14646
14926
|
megaMenu: megaMenu,
|
|
14647
14927
|
active: active,
|
|
14648
14928
|
disabled: disabled
|
|
14649
|
-
}), [isActive, setIsActive] = React.useState(!1), itemRef = React.useRef(null);
|
|
14929
|
+
}), [isActive, setIsActive] = React.useState(!1), itemRef = React.useRef(null), combinedRef = useForkRef(ref, itemRef);
|
|
14650
14930
|
// State for tracking dropdown open state
|
|
14651
14931
|
// Close dropdown on outside click (desktop only)
|
|
14652
14932
|
React.useEffect((() => {
|
|
@@ -14677,8 +14957,9 @@ const NavItem = React.forwardRef((({children: children, dropdown: dropdown = !1
|
|
|
14677
14957
|
disabled: disabled,
|
|
14678
14958
|
className: className
|
|
14679
14959
|
}) + (isActive ? " is-active" : ""), navLinkClass = generateNavLinkClass(active, disabled, dropdown || megaMenu ? "c-nav__dropdown-toggle" : ""), childContent = React__default.default.Children.toArray(children), expanded = void 0 !== ariaExpanded ? ariaExpanded : isActive, linkProps = {
|
|
14680
|
-
ref:
|
|
14960
|
+
ref: combinedRef,
|
|
14681
14961
|
href: href || "#",
|
|
14962
|
+
to: href || "#",
|
|
14682
14963
|
className: navLinkClass,
|
|
14683
14964
|
onClick: dropdown || megaMenu ? e => {
|
|
14684
14965
|
(dropdown || megaMenu) && (e.preventDefault(), setIsActive(!isActive));
|
|
@@ -14688,7 +14969,6 @@ const NavItem = React.forwardRef((({children: children, dropdown: dropdown = !1
|
|
|
14688
14969
|
"aria-current": !active || dropdown || megaMenu ? void 0 : "page"
|
|
14689
14970
|
};
|
|
14690
14971
|
return jsxRuntime.jsxs("li", {
|
|
14691
|
-
ref: ref,
|
|
14692
14972
|
className: navItemClass,
|
|
14693
14973
|
role: "menuitem",
|
|
14694
14974
|
"aria-haspopup": dropdown || megaMenu,
|
|
@@ -14794,7 +15074,7 @@ const Navbar = React.forwardRef((({brand: brand, children: children, variant: v
|
|
|
14794
15074
|
const defaultGlassProps = {
|
|
14795
15075
|
displacementScale: 30,
|
|
14796
15076
|
blurAmount: 2,
|
|
14797
|
-
|
|
15077
|
+
borderRadius: 0,
|
|
14798
15078
|
elasticity: 0,
|
|
14799
15079
|
mode: "shader",
|
|
14800
15080
|
shaderVariant: "premiumGlass"
|
|
@@ -14833,23 +15113,7 @@ const Navbar = React.forwardRef((({brand: brand, children: children, variant: v
|
|
|
14833
15113
|
});
|
|
14834
15114
|
}));
|
|
14835
15115
|
|
|
14836
|
-
|
|
14837
|
-
* Utility to merge multiple React refs into one
|
|
14838
|
-
*/
|
|
14839
|
-
function setRef(ref, value) {
|
|
14840
|
-
"function" == typeof ref ? ref(value) : ref && (
|
|
14841
|
-
// This is safe because we're checking that ref exists first
|
|
14842
|
-
ref.current = value);
|
|
14843
|
-
}
|
|
14844
|
-
|
|
14845
|
-
/**
|
|
14846
|
-
* Combines two React refs into a single ref function
|
|
14847
|
-
* This is used when you need to use and forward a ref at the same time
|
|
14848
|
-
*/ function useForkRef(refA, refB) {
|
|
14849
|
-
return React__default.default.useMemo((() => null == refA && null == refB ? null : refValue => {
|
|
14850
|
-
setRef(refA, refValue), setRef(refB, refValue);
|
|
14851
|
-
}), [ refA, refB ]);
|
|
14852
|
-
}
|
|
15116
|
+
Navbar.displayName = "Navbar";
|
|
14853
15117
|
|
|
14854
15118
|
/**
|
|
14855
15119
|
* SideMenuList component provides a container for side menu items.
|
|
@@ -14862,8 +15126,7 @@ function setRef(ref, value) {
|
|
|
14862
15126
|
* <SideMenuItem href="/contact">Contact</SideMenuItem>
|
|
14863
15127
|
* </SideMenuList>
|
|
14864
15128
|
* ```
|
|
14865
|
-
*/
|
|
14866
|
-
|
|
15129
|
+
*/
|
|
14867
15130
|
const SideMenuList = React.forwardRef((({children: children, className: className = ""}, ref) => {
|
|
14868
15131
|
const listClass = `c-side-menu__list ${className}`.trim();
|
|
14869
15132
|
return jsxRuntime.jsx("ul", {
|
|
@@ -15175,7 +15438,7 @@ const SideMenu = React.forwardRef((({title: title, children: children, menuItem
|
|
|
15175
15438
|
const defaultGlassProps = {
|
|
15176
15439
|
displacementScale: 70,
|
|
15177
15440
|
blurAmount: 2,
|
|
15178
|
-
|
|
15441
|
+
borderRadius: 12,
|
|
15179
15442
|
mode: "shader"
|
|
15180
15443
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
15181
15444
|
...defaultGlassProps,
|
|
@@ -16754,7 +17017,7 @@ const PopoverContext = React.createContext({
|
|
|
16754
17017
|
blurAmount: 1,
|
|
16755
17018
|
saturation: 160,
|
|
16756
17019
|
aberrationIntensity: .5,
|
|
16757
|
-
|
|
17020
|
+
borderRadius: 8,
|
|
16758
17021
|
mode: "shader"
|
|
16759
17022
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
16760
17023
|
...defaultGlassProps,
|
|
@@ -16805,7 +17068,14 @@ const PopoverContext = React.createContext({
|
|
|
16805
17068
|
/**
|
|
16806
17069
|
* Hook for managing rating component state and interactions
|
|
16807
17070
|
*/
|
|
16808
|
-
const
|
|
17071
|
+
const calculateStarValue = (e, starValue, allowHalf) => {
|
|
17072
|
+
if (!allowHalf) return starValue;
|
|
17073
|
+
// Get the star element's bounding rectangle
|
|
17074
|
+
const starRect = e.currentTarget.getBoundingClientRect(), starCenterX = starRect.left + starRect.width / 2, adjustedValue = e.clientX < starCenterX ? starValue - .5 : starValue;
|
|
17075
|
+
// Calculate the x position within the star
|
|
17076
|
+
return Math.max(.5, adjustedValue);
|
|
17077
|
+
// Ensure minimum of 0.5
|
|
17078
|
+
}, Rating = React.forwardRef((({value: valueProp = 0, defaultValue: defaultValue, maxValue: maxValue = 5, allowHalf: allowHalf = !1, readOnly: readOnly = !1, size: size = "md", variant: variant, onChange: onChange, className: className = "", style: style, label: label, id: id, useVanillaJS: useVanillaJS = !1, glass: glass, ...restProps}, ref) => {
|
|
16809
17079
|
const internalRef = React.useRef(null), ratingInstance = React.useRef(null), {currentValue: currentValue, hoverValue: hoverValue, focusedIndex: focusedIndex, setHoverValue: setHoverValue, setFocused: setFocused, handleKeyDown: handleKeyDown} = (({value: value = 0, maxValue: maxValue = 5, allowHalf: allowHalf = !1, readOnly: readOnly = !1, onChange: onChange}) => {
|
|
16810
17080
|
// Determine if component is in controlled mode
|
|
16811
17081
|
const isControlled = void 0 !== onChange, [internalValue, setInternalValue] = React.useState(value), [hoverValue, setHoverValue] = React.useState(null), [focusedIndex, setFocusedIndex] = React.useState(null), currentValue = isControlled ? value : internalValue, handleMouseEnter = React.useCallback((starValue => {
|
|
@@ -16867,30 +17137,14 @@ const Rating = React.forwardRef((({value: valueProp = 0, defaultValue: defaultV
|
|
|
16867
17137
|
readOnly: readOnly,
|
|
16868
17138
|
onChange: onChange
|
|
16869
17139
|
}), forkedRef = useForkRef(internalRef, ref), handleMouseEnter = React.useCallback(((e, starValue) => {
|
|
16870
|
-
|
|
16871
|
-
// Get the star element's bounding rectangle
|
|
16872
|
-
const starRect = e.currentTarget.getBoundingClientRect(), starCenterX = starRect.left + starRect.width / 2, adjustedValue = e.clientX < starCenterX ? starValue - .5 : starValue;
|
|
16873
|
-
// Calculate the x position within the star
|
|
16874
|
-
setHoverValue(Math.max(.5, adjustedValue));
|
|
16875
|
-
} else setHoverValue(starValue);
|
|
17140
|
+
readOnly || setHoverValue(calculateStarValue(e, starValue, !!allowHalf));
|
|
16876
17141
|
}), [ readOnly, allowHalf, setHoverValue ]), handleMouseMove = React.useCallback(((e, starValue) => {
|
|
16877
|
-
|
|
16878
|
-
|
|
16879
|
-
const starRect = e.currentTarget.getBoundingClientRect(), starCenterX = starRect.left + starRect.width / 2, adjustedValue = e.clientX < starCenterX ? starValue - .5 : starValue;
|
|
16880
|
-
// Calculate the x position within the star
|
|
16881
|
-
setHoverValue(Math.max(.5, adjustedValue));
|
|
16882
|
-
} // Ensure minimum of 0.5
|
|
16883
|
-
), [ readOnly, allowHalf, setHoverValue ]), handleMouseLeave = React.useCallback((() => {
|
|
17142
|
+
!readOnly && allowHalf && setHoverValue(calculateStarValue(e, starValue, !!allowHalf));
|
|
17143
|
+
}), [ readOnly, allowHalf, setHoverValue ]), handleMouseLeave = React.useCallback((() => {
|
|
16884
17144
|
readOnly || setHoverValue(null);
|
|
16885
17145
|
}), [ readOnly, setHoverValue ]), handleClick = React.useCallback(((e, starValue) => {
|
|
16886
17146
|
if (readOnly) return;
|
|
16887
|
-
|
|
16888
|
-
if (allowHalf) {
|
|
16889
|
-
// Get the star element's bounding rectangle
|
|
16890
|
-
const starRect = e.currentTarget.getBoundingClientRect(), starCenterX = starRect.left + starRect.width / 2;
|
|
16891
|
-
// Calculate the x position within the star
|
|
16892
|
-
newValue = e.clientX < starCenterX ? starValue - .5 : starValue, newValue = Math.max(.5, newValue);
|
|
16893
|
-
}
|
|
17147
|
+
const newValue = calculateStarValue(e, starValue, !!allowHalf);
|
|
16894
17148
|
onChange?.(newValue);
|
|
16895
17149
|
}), [ readOnly, onChange, allowHalf ]);
|
|
16896
17150
|
// Use vanilla JS implementation if specified
|
|
@@ -16995,7 +17249,7 @@ const Rating = React.forwardRef((({value: valueProp = 0, defaultValue: defaultV
|
|
|
16995
17249
|
blurAmount: 1,
|
|
16996
17250
|
saturation: 160,
|
|
16997
17251
|
aberrationIntensity: .5,
|
|
16998
|
-
|
|
17252
|
+
borderRadius: 8,
|
|
16999
17253
|
mode: "shader"
|
|
17000
17254
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
17001
17255
|
...defaultGlassProps,
|
|
@@ -17009,21 +17263,8 @@ const Rating = React.forwardRef((({value: valueProp = 0, defaultValue: defaultV
|
|
|
17009
17263
|
return ratingContent;
|
|
17010
17264
|
}));
|
|
17011
17265
|
|
|
17012
|
-
|
|
17013
|
-
|
|
17014
|
-
*
|
|
17015
|
-
* @example
|
|
17016
|
-
* // Basic usage
|
|
17017
|
-
* <Rating value={3} onChange={handleRatingChange} />
|
|
17018
|
-
*
|
|
17019
|
-
* @example
|
|
17020
|
-
* // Read-only with custom variant
|
|
17021
|
-
* <Rating value={4.5} readOnly variant="warning" />
|
|
17022
|
-
*
|
|
17023
|
-
* @example
|
|
17024
|
-
* // With half-star support
|
|
17025
|
-
* <Rating value={3.5} allowHalf maxValue={5} />
|
|
17026
|
-
*/ Rating.displayName = "Rating";
|
|
17266
|
+
// Helper function to calculate star value based on mouse position
|
|
17267
|
+
Rating.displayName = "Rating";
|
|
17027
17268
|
|
|
17028
17269
|
/**
|
|
17029
17270
|
* ProductReview component for collecting user ratings and feedback
|
|
@@ -17168,7 +17409,7 @@ const Progress = React.memo( React.forwardRef((({value: value, variant: variant
|
|
|
17168
17409
|
const defaultGlassProps = {
|
|
17169
17410
|
displacementScale: 30,
|
|
17170
17411
|
blurAmount: .5,
|
|
17171
|
-
|
|
17412
|
+
borderRadius: 8,
|
|
17172
17413
|
mode: "shader"
|
|
17173
17414
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
17174
17415
|
...defaultGlassProps,
|
|
@@ -17572,7 +17813,7 @@ const Steps = ({items: items, activeIndex: activeIndex = 0, vertical: vertical =
|
|
|
17572
17813
|
blurAmount: 1,
|
|
17573
17814
|
saturation: 160,
|
|
17574
17815
|
aberrationIntensity: .5,
|
|
17575
|
-
|
|
17816
|
+
borderRadius: 8,
|
|
17576
17817
|
mode: "shader"
|
|
17577
17818
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
17578
17819
|
...defaultGlassProps,
|
|
@@ -17730,7 +17971,7 @@ const Tabs = React.memo((({items: items, activeIndex: activeIndex = TAB.DEFAULT
|
|
|
17730
17971
|
blurAmount: 1,
|
|
17731
17972
|
saturation: 160,
|
|
17732
17973
|
aberrationIntensity: .5,
|
|
17733
|
-
|
|
17974
|
+
borderRadius: 8,
|
|
17734
17975
|
mode: "shader"
|
|
17735
17976
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
17736
17977
|
...defaultGlassProps,
|
|
@@ -17973,7 +18214,7 @@ const Toggle = ({checked: controlledChecked, defaultChecked: defaultChecked = !1
|
|
|
17973
18214
|
blurAmount: 1,
|
|
17974
18215
|
saturation: 160,
|
|
17975
18216
|
aberrationIntensity: .5,
|
|
17976
|
-
|
|
18217
|
+
borderRadius: 8,
|
|
17977
18218
|
mode: "shader"
|
|
17978
18219
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
17979
18220
|
...defaultGlassProps,
|