@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.esm.js
CHANGED
|
@@ -1949,7 +1949,7 @@ function useAccordion(initialProps) {
|
|
|
1949
1949
|
};
|
|
1950
1950
|
}
|
|
1951
1951
|
|
|
1952
|
-
const {CONSTANTS: CONSTANTS$
|
|
1952
|
+
const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
|
|
1953
1953
|
if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
|
|
1954
1954
|
const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
|
|
1955
1955
|
return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
@@ -1962,36 +1962,36 @@ const {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
|
|
|
1962
1962
|
}, calculateMouseInfluence = mouseOffset => {
|
|
1963
1963
|
if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
|
|
1964
1964
|
// Bounded calculation — keeps the glass effect subtle and stable
|
|
1965
|
-
const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$
|
|
1965
|
+
const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$2.MOUSE_INFLUENCE_DIVISOR;
|
|
1966
1966
|
return Math.min(.8, influence);
|
|
1967
1967
|
// Tighter cap to prevent blur/filter blow-out
|
|
1968
|
-
}, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$
|
|
1968
|
+
}, 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 => {
|
|
1969
1969
|
if ("number" == typeof value) return Math.max(0, value);
|
|
1970
|
-
if ("string" != typeof value || !value.trim()) return CONSTANTS$
|
|
1970
|
+
if ("string" != typeof value || !value.trim()) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
1971
1971
|
const trimmedValue = value.trim();
|
|
1972
1972
|
// Handle px values
|
|
1973
1973
|
if (trimmedValue.endsWith("px")) {
|
|
1974
1974
|
const parsed = parseFloat(trimmedValue);
|
|
1975
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
1975
|
+
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
|
|
1976
1976
|
}
|
|
1977
1977
|
// Handle rem values (assume 16px = 1rem)
|
|
1978
1978
|
if (trimmedValue.endsWith("rem")) {
|
|
1979
1979
|
const parsed = parseFloat(trimmedValue);
|
|
1980
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
1980
|
+
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
1981
1981
|
}
|
|
1982
1982
|
// Handle em values (assume 16px = 1em for simplicity)
|
|
1983
1983
|
if (trimmedValue.endsWith("em")) {
|
|
1984
1984
|
const parsed = parseFloat(trimmedValue);
|
|
1985
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
1985
|
+
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
1986
1986
|
}
|
|
1987
1987
|
// Handle percentage (convert to approximate px value, assuming 200px container)
|
|
1988
1988
|
if (trimmedValue.endsWith("%")) {
|
|
1989
1989
|
const parsed = parseFloat(trimmedValue);
|
|
1990
|
-
return isNaN(parsed) ? CONSTANTS$
|
|
1990
|
+
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
|
|
1991
1991
|
}
|
|
1992
1992
|
// Handle unitless numbers
|
|
1993
1993
|
const numValue = parseFloat(trimmedValue);
|
|
1994
|
-
return isNaN(numValue) ? CONSTANTS$
|
|
1994
|
+
return isNaN(numValue) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
|
|
1995
1995
|
}, extractBorderRadiusFromElement = element => {
|
|
1996
1996
|
if (!element || !element.props) return null;
|
|
1997
1997
|
// Check inline styles first (highest priority)
|
|
@@ -2007,11 +2007,11 @@ const {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
|
|
|
2007
2007
|
// If element has children, recursively check them
|
|
2008
2008
|
if (element.props.children) {
|
|
2009
2009
|
const childRadius = extractBorderRadiusFromChildren(element.props.children);
|
|
2010
|
-
if (childRadius > 0 && childRadius !== CONSTANTS$
|
|
2010
|
+
if (childRadius > 0 && childRadius !== CONSTANTS$2.DEFAULT_CORNER_RADIUS) return childRadius;
|
|
2011
2011
|
}
|
|
2012
2012
|
return null;
|
|
2013
2013
|
}, extractBorderRadiusFromChildren = children => {
|
|
2014
|
-
if (!children) return CONSTANTS$
|
|
2014
|
+
if (!children) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
2015
2015
|
try {
|
|
2016
2016
|
const childArray = React.Children.toArray(children);
|
|
2017
2017
|
for (let i = 0; i < childArray.length; i++) {
|
|
@@ -2024,7 +2024,7 @@ const {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
|
|
|
2024
2024
|
} catch (error) {
|
|
2025
2025
|
// Silently handle errors
|
|
2026
2026
|
}
|
|
2027
|
-
return CONSTANTS$
|
|
2027
|
+
return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
2028
2028
|
}, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
|
|
2029
2029
|
switch (mode) {
|
|
2030
2030
|
case "standard":
|
|
@@ -2195,10 +2195,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2195
2195
|
}, globalMousePosition: globalMousePosition = {
|
|
2196
2196
|
x: 0,
|
|
2197
2197
|
y: 0
|
|
2198
|
-
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isHovered: isHovered = !1, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {},
|
|
2198
|
+
}, 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 = {
|
|
2199
2199
|
width: 0,
|
|
2200
2200
|
height: 0
|
|
2201
|
-
}, onClick: onClick, mode: mode = "standard",
|
|
2201
|
+
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
|
|
2202
2202
|
// Generate a stable, deterministic ID for SSR compatibility
|
|
2203
2203
|
// Use a module-level counter that's consistent across server and client
|
|
2204
2204
|
const filterId = useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null);
|
|
@@ -2308,7 +2308,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2308
2308
|
flowBlur: 1.2 * blurAmount
|
|
2309
2309
|
};
|
|
2310
2310
|
// Enhanced validation for liquid blur
|
|
2311
|
-
if (!
|
|
2311
|
+
if (!withLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
|
|
2312
2312
|
try {
|
|
2313
2313
|
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);
|
|
2314
2314
|
// NOTE: hover/active multipliers intentionally omitted here —
|
|
@@ -2323,14 +2323,14 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2323
2323
|
return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
|
|
2324
2324
|
defaultBlur;
|
|
2325
2325
|
}
|
|
2326
|
-
}), [
|
|
2326
|
+
}), [ withLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
|
|
2327
2327
|
try {
|
|
2328
2328
|
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;
|
|
2329
2329
|
// Validate blur values before using them
|
|
2330
|
-
return !
|
|
2330
|
+
return !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? {
|
|
2331
2331
|
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})`
|
|
2332
2332
|
} : {
|
|
2333
|
-
backdropFilter: `blur(${clampBlur(.4 * validatedBaseBlur + .25 * validatedEdgeBlur + .15 * validatedCenterBlur + .2 * validatedFlowBlur)}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1
|
|
2333
|
+
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})`
|
|
2334
2334
|
};
|
|
2335
2335
|
// Single-pass fallback: stronger radius to match perceived blur of multi-pass
|
|
2336
2336
|
} catch (error) {
|
|
@@ -2339,7 +2339,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2339
2339
|
backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
|
|
2340
2340
|
};
|
|
2341
2341
|
}
|
|
2342
|
-
}), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion,
|
|
2342
|
+
}), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur ]), containerVars = useMemo((() => {
|
|
2343
2343
|
try {
|
|
2344
2344
|
// Safe extraction of mouse offset values
|
|
2345
2345
|
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;
|
|
@@ -2347,10 +2347,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2347
2347
|
"--atomix-glass-container-width": `${glassSize?.width}`,
|
|
2348
2348
|
"--atomix-glass-container-height": `${glassSize?.height}`,
|
|
2349
2349
|
"--atomix-glass-container-padding": padding || "0 0",
|
|
2350
|
-
"--atomix-glass-container-radius": `${"number" != typeof
|
|
2350
|
+
"--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`,
|
|
2351
2351
|
"--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
|
|
2352
2352
|
"--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",
|
|
2353
|
-
"--atomix-glass-container-shadow-opacity":
|
|
2353
|
+
"--atomix-glass-container-shadow-opacity": effectiveWithoutEffects ? 0 : 1,
|
|
2354
2354
|
// Background and shadow values use design token-aligned RGB values
|
|
2355
2355
|
"--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",
|
|
2356
2356
|
"--atomix-glass-container-text-shadow": overLight ? "0px 2px 12px rgba(0, 0, 0, 0)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
|
|
@@ -2368,14 +2368,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2368
2368
|
"--atomix-glass-container-text-shadow": "none"
|
|
2369
2369
|
};
|
|
2370
2370
|
}
|
|
2371
|
-
}), [ glassSize, padding,
|
|
2372
|
-
el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
|
|
2373
|
-
el.style.setProperty("transition-delay", "0s", "important"));
|
|
2374
|
-
};
|
|
2371
|
+
}), [ glassSize, padding, borderRadius, backdropStyle, mouseOffset, overLight, effectiveWithoutEffects ]);
|
|
2375
2372
|
return jsx("div", {
|
|
2376
2373
|
ref: el => {
|
|
2377
2374
|
// Apply force no-transition
|
|
2378
|
-
setForceNoTransition(el),
|
|
2379
2375
|
// Handle forwarded ref
|
|
2380
2376
|
"function" == typeof ref ? ref(el) : ref && (ref.current = el);
|
|
2381
2377
|
},
|
|
@@ -2410,7 +2406,10 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2410
2406
|
aberrationIntensity: "number" != typeof aberrationIntensity || isNaN(aberrationIntensity) ? 0 : aberrationIntensity,
|
|
2411
2407
|
shaderMapUrl: shaderMapUrl
|
|
2412
2408
|
}), jsx("div", {
|
|
2413
|
-
ref:
|
|
2409
|
+
ref: el => {
|
|
2410
|
+
el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
|
|
2411
|
+
el.style.setProperty("transition-delay", "0s", "important"));
|
|
2412
|
+
},
|
|
2414
2413
|
className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
|
|
2415
2414
|
style: {
|
|
2416
2415
|
filter: `url(#${filterId})`,
|
|
@@ -2527,7 +2526,128 @@ class {
|
|
|
2527
2526
|
*/ getSubscriberCount() {
|
|
2528
2527
|
return this.listeners.size;
|
|
2529
2528
|
}
|
|
2530
|
-
},
|
|
2529
|
+
}, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
|
|
2530
|
+
if (!wrapperElement && !containerElement) return;
|
|
2531
|
+
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 = {
|
|
2532
|
+
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
2533
|
+
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
2534
|
+
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
2535
|
+
shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
|
|
2536
|
+
borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
|
|
2537
|
+
saturationBoost: baseOverLightConfig.saturationBoost
|
|
2538
|
+
};
|
|
2539
|
+
// Calculate mouse influence
|
|
2540
|
+
// Calculate elastic translation
|
|
2541
|
+
let elasticTranslation = {
|
|
2542
|
+
x: 0,
|
|
2543
|
+
y: 0
|
|
2544
|
+
};
|
|
2545
|
+
if (!effectiveWithoutEffects && wrapperElement) {
|
|
2546
|
+
const rect = wrapperElement.getBoundingClientRect(), center = calculateElementCenter(rect);
|
|
2547
|
+
// Calculate fade in factor
|
|
2548
|
+
let fadeInFactor = 0;
|
|
2549
|
+
if (globalMousePosition.x && globalMousePosition.y && validateGlassSize(glassSize)) {
|
|
2550
|
+
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({
|
|
2551
|
+
x: edgeDistanceX,
|
|
2552
|
+
y: edgeDistanceY
|
|
2553
|
+
}, {
|
|
2554
|
+
x: 0,
|
|
2555
|
+
y: 0
|
|
2556
|
+
});
|
|
2557
|
+
fadeInFactor = edgeDistance > ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE;
|
|
2558
|
+
}
|
|
2559
|
+
elasticTranslation = {
|
|
2560
|
+
x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
|
|
2561
|
+
y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
|
|
2562
|
+
};
|
|
2563
|
+
}
|
|
2564
|
+
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}`;
|
|
2565
|
+
// Update Wrapper Styles (glassVars)
|
|
2566
|
+
if (wrapperElement) {
|
|
2567
|
+
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 = {
|
|
2568
|
+
hover1: {
|
|
2569
|
+
x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
|
|
2570
|
+
y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
|
|
2571
|
+
},
|
|
2572
|
+
hover2: {
|
|
2573
|
+
x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_2,
|
|
2574
|
+
y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_2
|
|
2575
|
+
},
|
|
2576
|
+
hover3: {
|
|
2577
|
+
x: GRADIENT.CENTER_POSITION + mx * GRADIENT.HOVER_POSITION.MULTIPLIER_3,
|
|
2578
|
+
y: GRADIENT.CENTER_POSITION + my * GRADIENT.HOVER_POSITION.MULTIPLIER_3
|
|
2579
|
+
}
|
|
2580
|
+
}, basePosition = {
|
|
2581
|
+
x: GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER,
|
|
2582
|
+
y: GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER
|
|
2583
|
+
}, opacityValues = {
|
|
2584
|
+
hover1: isHovered || isActive ? .5 : 0,
|
|
2585
|
+
hover2: isActive ? .5 : 0,
|
|
2586
|
+
hover3: isHovered ? .4 : isActive ? .8 : 0,
|
|
2587
|
+
base: isOverLight ? overLightConfig.opacity : 0,
|
|
2588
|
+
over: isOverLight ? 1.1 * overLightConfig.opacity : 0
|
|
2589
|
+
}, style = wrapperElement.style;
|
|
2590
|
+
style.setProperty("--atomix-glass-transform", transformStyle || "none"),
|
|
2591
|
+
// Gradients
|
|
2592
|
+
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%)`),
|
|
2593
|
+
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%)`),
|
|
2594
|
+
// Hover gradients
|
|
2595
|
+
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}%)`),
|
|
2596
|
+
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}%)`),
|
|
2597
|
+
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}%)`),
|
|
2598
|
+
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})`),
|
|
2599
|
+
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})`),
|
|
2600
|
+
// Opacities
|
|
2601
|
+
style.setProperty("--atomix-glass-hover-1-opacity", opacityValues.hover1.toString()),
|
|
2602
|
+
style.setProperty("--atomix-glass-hover-2-opacity", opacityValues.hover2.toString()),
|
|
2603
|
+
style.setProperty("--atomix-glass-hover-3-opacity", opacityValues.hover3.toString()),
|
|
2604
|
+
style.setProperty("--atomix-glass-base-opacity", opacityValues.base.toString()),
|
|
2605
|
+
style.setProperty("--atomix-glass-overlay-opacity", opacityValues.over.toString()),
|
|
2606
|
+
style.setProperty("--atomix-glass-overlay-highlight-opacity", (opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER).toString()),
|
|
2607
|
+
// Other
|
|
2608
|
+
style.setProperty("--atomix-glass-blend-mode", isOverLight ? "multiply" : "overlay"),
|
|
2609
|
+
style.setProperty("--atomix-glass-radius", `${effectiveBorderRadius}px`);
|
|
2610
|
+
}
|
|
2611
|
+
// Update Container Styles (containerVars)
|
|
2612
|
+
if (containerElement) {
|
|
2613
|
+
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();
|
|
2614
|
+
let liquidBlur = {
|
|
2615
|
+
baseBlur: blurAmount,
|
|
2616
|
+
edgeBlur: blurAmount * EDGE_BLUR_MULTIPLIER,
|
|
2617
|
+
centerBlur: blurAmount * CENTER_BLUR_MULTIPLIER,
|
|
2618
|
+
flowBlur: blurAmount * FLOW_BLUR_MULTIPLIER
|
|
2619
|
+
};
|
|
2620
|
+
if (withLiquidBlur && rect) {
|
|
2621
|
+
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);
|
|
2622
|
+
liquidBlur = {
|
|
2623
|
+
baseBlur: clampBlur(baseBlur),
|
|
2624
|
+
edgeBlur: clampBlur(edgeBlur),
|
|
2625
|
+
centerBlur: clampBlur(centerBlur),
|
|
2626
|
+
flowBlur: clampBlur(flowBlur)
|
|
2627
|
+
};
|
|
2628
|
+
}
|
|
2629
|
+
// Backdrop filter
|
|
2630
|
+
let backdropFilterString = `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`;
|
|
2631
|
+
const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), area = rect ? rect.width * rect.height : 0;
|
|
2632
|
+
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})`;
|
|
2633
|
+
// Container variables
|
|
2634
|
+
const style = containerElement.style;
|
|
2635
|
+
style.setProperty("--atomix-glass-container-width", `${glassSize.width}`), style.setProperty("--atomix-glass-container-height", `${glassSize.height}`),
|
|
2636
|
+
style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
|
|
2637
|
+
style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
|
|
2638
|
+
// Shadows
|
|
2639
|
+
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"),
|
|
2640
|
+
style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
|
|
2641
|
+
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"),
|
|
2642
|
+
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)"),
|
|
2643
|
+
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)");
|
|
2644
|
+
}
|
|
2645
|
+
}, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
|
|
2646
|
+
|
|
2647
|
+
/**
|
|
2648
|
+
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
2649
|
+
* to avoid React re-renders on mouse movement.
|
|
2650
|
+
*/ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
|
|
2531
2651
|
parentElement && backgroundDetectionCache.set(parentElement, {
|
|
2532
2652
|
result: result,
|
|
2533
2653
|
timestamp: Date.now(),
|
|
@@ -2540,18 +2660,74 @@ class {
|
|
|
2540
2660
|
* Composable hook for AtomixGlass component logic
|
|
2541
2661
|
* Manages all state, calculations, and event handlers
|
|
2542
2662
|
*/
|
|
2543
|
-
function useAtomixGlass({glassRef: glassRef, contentRef: contentRef,
|
|
2663
|
+
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}) {
|
|
2544
2664
|
// State
|
|
2545
|
-
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1),
|
|
2546
|
-
width: 270,
|
|
2547
|
-
height: 69
|
|
2548
|
-
}), [internalGlobalMousePosition, setInternalGlobalMousePosition] = useState({
|
|
2665
|
+
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), cachedRectRef = useRef(null), internalGlobalMousePositionRef = useRef({
|
|
2549
2666
|
x: 0,
|
|
2550
2667
|
y: 0
|
|
2551
|
-
}),
|
|
2668
|
+
}), internalMouseOffsetRef = useRef({
|
|
2552
2669
|
x: 0,
|
|
2553
2670
|
y: 0
|
|
2554
|
-
}), [
|
|
2671
|
+
}), [dynamicBorderRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), effectiveBorderRadius = useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
|
|
2672
|
+
const [glassSize, setGlassSize] = useState({
|
|
2673
|
+
width: 270,
|
|
2674
|
+
height: 69
|
|
2675
|
+
});
|
|
2676
|
+
return useEffect((() => {
|
|
2677
|
+
const isValidElement = element => null !== element && element instanceof HTMLElement && element.isConnected;
|
|
2678
|
+
let rafId = null, lastSize = {
|
|
2679
|
+
width: 0,
|
|
2680
|
+
height: 0
|
|
2681
|
+
}, lastCornerRadius = effectiveBorderRadius;
|
|
2682
|
+
const updateGlassSize = (forceUpdate = !1) => {
|
|
2683
|
+
null !== rafId && cancelAnimationFrame(rafId), rafId = requestAnimationFrame((() => {
|
|
2684
|
+
if (!isValidElement(glassRef.current)) return void (rafId = null);
|
|
2685
|
+
const rect = glassRef.current.getBoundingClientRect();
|
|
2686
|
+
if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
|
|
2687
|
+
// Measure actual rendered size without artificial offsets to avoid feedback loops
|
|
2688
|
+
const newSize = {
|
|
2689
|
+
width: Math.round(rect.width),
|
|
2690
|
+
height: Math.round(rect.height)
|
|
2691
|
+
}, cornerRadiusChanged = lastCornerRadius !== effectiveBorderRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
|
|
2692
|
+
var size;
|
|
2693
|
+
(forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS$1.MAX_SIZE && size.height <= CONSTANTS$1.MAX_SIZE && (lastSize = newSize,
|
|
2694
|
+
lastCornerRadius = effectiveBorderRadius, setGlassSize(newSize)), rafId = null;
|
|
2695
|
+
}));
|
|
2696
|
+
};
|
|
2697
|
+
let resizeTimeoutId = null;
|
|
2698
|
+
const debouncedResizeHandler = () => {
|
|
2699
|
+
resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
|
|
2700
|
+
}, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
|
|
2701
|
+
let resizeObserver = null, resizeDebounceTimeout = null;
|
|
2702
|
+
// ResizeObserver has 98%+ browser support, no need for fallback
|
|
2703
|
+
if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
|
|
2704
|
+
resizeObserver = new ResizeObserver((entries => {
|
|
2705
|
+
for (const entry of entries) if (entry.target === glassRef.current) {
|
|
2706
|
+
// Update cached rect when size changes
|
|
2707
|
+
glassRef.current && cachedRectRef && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
|
|
2708
|
+
// Debounce resize updates to match RAF timing (16ms)
|
|
2709
|
+
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
|
|
2710
|
+
break;
|
|
2711
|
+
}
|
|
2712
|
+
})), resizeObserver.observe(glassRef.current);
|
|
2713
|
+
} catch (error) {
|
|
2714
|
+
console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
|
|
2715
|
+
}
|
|
2716
|
+
return window.addEventListener("resize", debouncedResizeHandler, {
|
|
2717
|
+
passive: !0
|
|
2718
|
+
}), () => {
|
|
2719
|
+
clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
|
|
2720
|
+
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
|
|
2721
|
+
resizeObserver?.disconnect();
|
|
2722
|
+
};
|
|
2723
|
+
}), [ effectiveBorderRadius, glassRef, cachedRectRef ]), {
|
|
2724
|
+
glassSize: glassSize
|
|
2725
|
+
};
|
|
2726
|
+
}({
|
|
2727
|
+
glassRef: glassRef,
|
|
2728
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
2729
|
+
cachedRectRef: cachedRectRef
|
|
2730
|
+
}), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveHighContrast = useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveWithoutEffects = useMemo((() => withoutEffects || effectiveReducedMotion), [ withoutEffects, effectiveReducedMotion ]), globalMousePosition = externalGlobalMousePosition || internalGlobalMousePositionRef.current, mouseOffset = externalMouseOffset || internalMouseOffsetRef.current;
|
|
2555
2731
|
// Extract border-radius from children
|
|
2556
2732
|
useEffect((() => {
|
|
2557
2733
|
const extractRadius = () => {
|
|
@@ -2582,13 +2758,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
2582
2758
|
}
|
|
2583
2759
|
null !== extractedRadius && extractedRadius > 0 && setDynamicCornerRadius(extractedRadius);
|
|
2584
2760
|
} catch (error) {
|
|
2585
|
-
"undefined" != typeof process && "production" === process.env?.NODE_ENV || !
|
|
2761
|
+
"undefined" != typeof process && "production" === process.env?.NODE_ENV || !debugBorderRadius || console.error("[AtomixGlass] Error extracting corner radius:", error);
|
|
2586
2762
|
}
|
|
2587
2763
|
};
|
|
2588
2764
|
extractRadius();
|
|
2589
2765
|
const timeoutId = setTimeout(extractRadius, 100);
|
|
2590
2766
|
return () => clearTimeout(timeoutId);
|
|
2591
|
-
}), [ children,
|
|
2767
|
+
}), [ children, debugBorderRadius, contentRef ]),
|
|
2592
2768
|
// Media query handlers and background detection
|
|
2593
2769
|
useEffect((() => {
|
|
2594
2770
|
if (("auto" === overLight || "object" == typeof overLight && null !== overLight) && glassRef.current) {
|
|
@@ -2644,72 +2820,52 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
2644
2820
|
const rgb = bgColor.match(/\d+/g);
|
|
2645
2821
|
if (rgb && rgb.length >= 3) {
|
|
2646
2822
|
const r = Number(rgb[0]), g = Number(rgb[1]), b = Number(rgb[2]);
|
|
2647
|
-
|
|
2648
|
-
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)) {
|
|
2823
|
+
if (!isNaN(r) && !isNaN(g) && !isNaN(b) && (r > 10 || g > 10 || b > 10)) {
|
|
2649
2824
|
const luminance = (.299 * r + .587 * g + .114 * b) / 255;
|
|
2650
2825
|
!isNaN(luminance) && isFinite(luminance) && (totalLuminance += luminance, validSamples++,
|
|
2651
2826
|
hasValidBackground = !0);
|
|
2652
2827
|
}
|
|
2653
2828
|
}
|
|
2654
2829
|
}
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
// For image backgrounds, assume medium luminance
|
|
2658
|
-
totalLuminance += .5, validSamples++, hasValidBackground = !0);
|
|
2830
|
+
bgImage && "none" !== bgImage && "initial" !== bgImage && (totalLuminance += .5,
|
|
2831
|
+
validSamples++, hasValidBackground = !0);
|
|
2659
2832
|
} catch (styleError) {
|
|
2660
|
-
|
|
2833
|
+
// Silently continue
|
|
2661
2834
|
}
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
// Exit loop if currentElement becomes null
|
|
2665
|
-
currentElement = currentElement.parentElement, depth++;
|
|
2835
|
+
if (!currentElement) break;
|
|
2836
|
+
currentElement = currentElement.parentElement, depth++;
|
|
2666
2837
|
}
|
|
2667
|
-
|
|
2668
|
-
if (hasValidBackground && validSamples > 0) {
|
|
2838
|
+
if (hasValidBackground && validSamples > 0) {
|
|
2669
2839
|
const avgLuminance = totalLuminance / validSamples;
|
|
2670
2840
|
if (!isNaN(avgLuminance) && isFinite(avgLuminance)) {
|
|
2671
2841
|
let threshold = .7;
|
|
2672
|
-
|
|
2673
|
-
// If overLight is an object, use its threshold property with validation
|
|
2674
|
-
if ("object" == typeof overLight && null !== overLight) {
|
|
2842
|
+
if ("object" == typeof overLight && null !== overLight) {
|
|
2675
2843
|
const objConfig = overLight;
|
|
2676
2844
|
if (void 0 !== objConfig.threshold) {
|
|
2677
|
-
const configThreshold = "number"
|
|
2845
|
+
const configThreshold = "number" != typeof objConfig.threshold || isNaN(objConfig.threshold) ? .7 : objConfig.threshold;
|
|
2678
2846
|
threshold = Math.min(.9, Math.max(.1, configThreshold));
|
|
2679
2847
|
}
|
|
2680
2848
|
}
|
|
2681
2849
|
const isOverLightDetected = avgLuminance > threshold;
|
|
2682
|
-
|
|
2683
|
-
setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
|
|
2850
|
+
setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
|
|
2684
2851
|
setDetectedOverLight(isOverLightDetected);
|
|
2685
2852
|
} else {
|
|
2686
|
-
// Invalid luminance calculation, default to false
|
|
2687
2853
|
const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
|
|
2688
2854
|
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
|
|
2689
2855
|
setDetectedOverLight(result);
|
|
2690
2856
|
}
|
|
2691
2857
|
} else {
|
|
2692
|
-
// Default to false if no valid background found
|
|
2693
2858
|
const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
|
|
2694
2859
|
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
|
|
2695
2860
|
setDetectedOverLight(result);
|
|
2696
2861
|
}
|
|
2697
2862
|
} catch (error) {
|
|
2698
|
-
|
|
2699
|
-
"undefined" != typeof process && "development" !== process.env?.NODE_ENV || console.warn("AtomixGlass: Error detecting background brightness:", error);
|
|
2700
|
-
const result = !1;
|
|
2701
|
-
if (element && element.parentElement) {
|
|
2702
|
-
const threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
|
|
2703
|
-
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold);
|
|
2704
|
-
}
|
|
2705
|
-
setDetectedOverLight(result);
|
|
2863
|
+
setDetectedOverLight(!1);
|
|
2706
2864
|
}
|
|
2707
2865
|
}), 150);
|
|
2708
2866
|
return () => clearTimeout(timeoutId);
|
|
2709
2867
|
}
|
|
2710
|
-
if ("boolean" == typeof overLight &&
|
|
2711
|
-
// For boolean values, disable auto-detection
|
|
2712
|
-
setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
|
|
2868
|
+
if ("boolean" == typeof overLight && setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
|
|
2713
2869
|
const mediaQueryReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"), mediaQueryHighContrast = window.matchMedia("(prefers-contrast: high)");
|
|
2714
2870
|
setUserPrefersReducedMotion(mediaQueryReducedMotion.matches), setUserPrefersHighContrast(mediaQueryHighContrast.matches);
|
|
2715
2871
|
const handleReducedMotionChange = e => {
|
|
@@ -2720,64 +2876,54 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
2720
2876
|
return mediaQueryReducedMotion.addEventListener ? (mediaQueryReducedMotion.addEventListener("change", handleReducedMotionChange),
|
|
2721
2877
|
mediaQueryHighContrast.addEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.addListener && (mediaQueryReducedMotion.addListener(handleReducedMotionChange),
|
|
2722
2878
|
mediaQueryHighContrast.addListener(handleHighContrastChange)), () => {
|
|
2723
|
-
|
|
2724
|
-
mediaQueryReducedMotion.removeEventListener ? (mediaQueryReducedMotion.removeEventListener("change", handleReducedMotionChange),
|
|
2725
|
-
mediaQueryHighContrast.removeEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.removeListener && (mediaQueryReducedMotion.removeListener(handleReducedMotionChange),
|
|
2726
|
-
mediaQueryHighContrast.removeListener(handleHighContrastChange));
|
|
2727
|
-
} catch (cleanupError) {
|
|
2728
|
-
console.error("AtomixGlass: Error cleaning up media query listeners:", cleanupError);
|
|
2729
|
-
}
|
|
2879
|
+
// ignore
|
|
2730
2880
|
};
|
|
2731
2881
|
} catch (error) {
|
|
2732
|
-
return
|
|
2882
|
+
return;
|
|
2733
2883
|
}
|
|
2734
2884
|
}), [ overLight, glassRef, debugOverLight ]);
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
y: (globalPos.y - center.y) / rect.height * 100
|
|
2885
|
+
/**
|
|
2886
|
+
* Get effective overLight value based on configuration
|
|
2887
|
+
*/
|
|
2888
|
+
const getEffectiveOverLight = useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []), baseOverLightConfig = useMemo((() => {
|
|
2889
|
+
const isOverLight = getEffectiveOverLight(), baseConfig = {
|
|
2890
|
+
isOverLight: isOverLight,
|
|
2891
|
+
threshold: .7,
|
|
2892
|
+
opacity: isOverLight ? Math.min(.6, Math.max(.2, .5)) : 0,
|
|
2893
|
+
contrast: 1,
|
|
2894
|
+
// Base contrast
|
|
2895
|
+
brightness: 1,
|
|
2896
|
+
// Base brightness
|
|
2897
|
+
saturationBoost: 1.3,
|
|
2898
|
+
shadowIntensity: .9,
|
|
2899
|
+
borderOpacity: .7
|
|
2751
2900
|
};
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
return;
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
|
|
2901
|
+
if ("object" == typeof overLight && null !== overLight) {
|
|
2902
|
+
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);
|
|
2903
|
+
return {
|
|
2904
|
+
...baseConfig,
|
|
2905
|
+
threshold: validatedThreshold,
|
|
2906
|
+
opacity: validatedOpacity,
|
|
2907
|
+
contrast: validatedContrast,
|
|
2908
|
+
brightness: validatedBrightness,
|
|
2909
|
+
saturationBoost: validatedSaturationBoost
|
|
2910
|
+
};
|
|
2911
|
+
}
|
|
2912
|
+
return baseConfig;
|
|
2913
|
+
}), [ overLight, getEffectiveOverLight, validateConfigValue ]), overLightConfig = useMemo((() => {
|
|
2914
|
+
const mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1;
|
|
2915
|
+
return {
|
|
2916
|
+
isOverLight: baseOverLightConfig.isOverLight,
|
|
2917
|
+
threshold: baseOverLightConfig.threshold,
|
|
2918
|
+
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
2919
|
+
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
2920
|
+
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
2921
|
+
saturationBoost: baseOverLightConfig.saturationBoost,
|
|
2922
|
+
shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
|
|
2923
|
+
borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence))
|
|
2776
2924
|
};
|
|
2777
|
-
}), [
|
|
2778
|
-
|
|
2779
|
-
const calculateDirectionalScale = useCallback((() => {
|
|
2780
|
-
if (!0 === overLight || "auto" === overLight && detectedOverLight || "object" == typeof overLight && null !== overLight && detectedOverLight) return "scale(1)";
|
|
2925
|
+
}), [ baseOverLightConfig, mouseOffset, isHovered, isActive ]), updateRectRef = useRef(null), calculateDirectionalScale = useCallback((() => {
|
|
2926
|
+
if (baseOverLightConfig.isOverLight) return "scale(1)";
|
|
2781
2927
|
if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return "scale(1)";
|
|
2782
2928
|
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({
|
|
2783
2929
|
x: edgeDistanceX,
|
|
@@ -2791,7 +2937,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
2791
2937
|
if (0 === centerDistance) return "scale(1)";
|
|
2792
2938
|
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;
|
|
2793
2939
|
return `scaleX(${Math.max(.8, scaleX)}) scaleY(${Math.max(.8, scaleY)})`;
|
|
2794
|
-
}), [ globalMousePosition, elasticity, glassSize, glassRef,
|
|
2940
|
+
}), [ globalMousePosition, elasticity, glassSize, glassRef, baseOverLightConfig ]), calculateFadeInFactor = useCallback((() => {
|
|
2795
2941
|
if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return 0;
|
|
2796
2942
|
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({
|
|
2797
2943
|
x: edgeDistanceX,
|
|
@@ -2811,122 +2957,110 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
2811
2957
|
x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
|
|
2812
2958
|
y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
|
|
2813
2959
|
};
|
|
2814
|
-
}), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() =>
|
|
2960
|
+
}), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() => effectiveWithoutEffects ? {
|
|
2815
2961
|
x: 0,
|
|
2816
2962
|
y: 0
|
|
2817
|
-
} : calculateElasticTranslation()), [ calculateElasticTranslation,
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
const
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
|
|
2830
|
-
// Measure actual rendered size without artificial offsets to avoid feedback loops
|
|
2831
|
-
const newSize = {
|
|
2832
|
-
width: Math.round(rect.width),
|
|
2833
|
-
height: Math.round(rect.height)
|
|
2834
|
-
}, cornerRadiusChanged = lastCornerRadius !== effectiveCornerRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
|
|
2835
|
-
var size;
|
|
2836
|
-
(forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS.MAX_SIZE && size.height <= CONSTANTS.MAX_SIZE && (lastSize = newSize,
|
|
2837
|
-
lastCornerRadius = effectiveCornerRadius, setGlassSize(newSize)), rafId = null;
|
|
2838
|
-
}));
|
|
2839
|
-
};
|
|
2840
|
-
let resizeTimeoutId = null;
|
|
2841
|
-
const debouncedResizeHandler = () => {
|
|
2842
|
-
resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
|
|
2843
|
-
}, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
|
|
2844
|
-
let resizeObserver = null, resizeDebounceTimeout = null;
|
|
2845
|
-
// ResizeObserver has 98%+ browser support, no need for fallback
|
|
2846
|
-
if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
|
|
2847
|
-
resizeObserver = new ResizeObserver((entries => {
|
|
2848
|
-
for (const entry of entries) if (entry.target === glassRef.current) {
|
|
2849
|
-
// Update cached rect when size changes
|
|
2850
|
-
glassRef.current && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
|
|
2851
|
-
// Debounce resize updates to match RAF timing (16ms)
|
|
2852
|
-
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
|
|
2853
|
-
break;
|
|
2854
|
-
}
|
|
2855
|
-
})), resizeObserver.observe(glassRef.current);
|
|
2856
|
-
} catch (error) {
|
|
2857
|
-
console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
|
|
2858
|
-
}
|
|
2859
|
-
return window.addEventListener("resize", debouncedResizeHandler, {
|
|
2860
|
-
passive: !0
|
|
2861
|
-
}), () => {
|
|
2862
|
-
clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
|
|
2863
|
-
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
|
|
2864
|
-
resizeObserver?.disconnect();
|
|
2963
|
+
} : calculateElasticTranslation()), [ calculateElasticTranslation, effectiveWithoutEffects ]), directionalScale = useMemo((() => effectiveWithoutEffects ? "scale(1)" : calculateDirectionalScale()), [ calculateDirectionalScale, effectiveWithoutEffects ]), transformStyle = 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 = useCallback((globalPos => {
|
|
2964
|
+
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
2965
|
+
if (effectiveWithoutEffects) return;
|
|
2966
|
+
const container = mouseContainer?.current || glassRef.current;
|
|
2967
|
+
if (!container) return;
|
|
2968
|
+
// Use cached rect if available, otherwise get new one
|
|
2969
|
+
let rect = cachedRectRef.current;
|
|
2970
|
+
if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
|
|
2971
|
+
cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
|
|
2972
|
+
const center = calculateElementCenter(rect), newOffset = {
|
|
2973
|
+
x: (globalPos.x - center.x) / rect.width * 100,
|
|
2974
|
+
y: (globalPos.y - center.y) / rect.height * 100
|
|
2865
2975
|
};
|
|
2866
|
-
|
|
2867
|
-
|
|
2976
|
+
// Calculate offset relative to this container
|
|
2977
|
+
// Store in refs instead of state
|
|
2978
|
+
internalMouseOffsetRef.current = newOffset, internalGlobalMousePositionRef.current = globalPos,
|
|
2979
|
+
// Imperative style update
|
|
2980
|
+
updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
|
|
2981
|
+
mouseOffset: newOffset,
|
|
2982
|
+
globalMousePosition: globalPos,
|
|
2983
|
+
glassSize: glassSize,
|
|
2984
|
+
isHovered: isHovered,
|
|
2985
|
+
isActive: isActive,
|
|
2986
|
+
isOverLight: baseOverLightConfig.isOverLight,
|
|
2987
|
+
baseOverLightConfig: baseOverLightConfig,
|
|
2988
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
2989
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
2990
|
+
effectiveReducedMotion: effectiveReducedMotion,
|
|
2991
|
+
elasticity: elasticity,
|
|
2992
|
+
directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
|
|
2993
|
+
// Simplified directional scale for fast path
|
|
2994
|
+
onClick: onClick,
|
|
2995
|
+
withLiquidBlur: withLiquidBlur,
|
|
2996
|
+
blurAmount: blurAmount,
|
|
2997
|
+
saturation: saturation,
|
|
2998
|
+
padding: padding
|
|
2999
|
+
});
|
|
3000
|
+
}), [ mouseContainer, glassRef, wrapperRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects, glassSize, isHovered, isActive, baseOverLightConfig, effectiveBorderRadius, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding ]);
|
|
2868
3001
|
/**
|
|
2869
|
-
*
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
const
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
3002
|
+
* Validate and clamp a numeric config value
|
|
3003
|
+
*/
|
|
3004
|
+
// Subscribe to shared mouse tracker
|
|
3005
|
+
useEffect((() => {
|
|
3006
|
+
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
3007
|
+
if (effectiveWithoutEffects) return;
|
|
3008
|
+
const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
|
|
3009
|
+
let resizeObserver = null;
|
|
3010
|
+
return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
|
|
3011
|
+
null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
|
|
3012
|
+
const container = mouseContainer?.current || glassRef.current;
|
|
3013
|
+
container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
|
|
3014
|
+
}));
|
|
3015
|
+
})), resizeObserver.observe(container)), () => {
|
|
3016
|
+
unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
|
|
3017
|
+
updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
|
|
2885
3018
|
};
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
3019
|
+
}), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]),
|
|
3020
|
+
// Also call updateStyles on other state changes (hover, active, etc)
|
|
3021
|
+
useEffect((() => {
|
|
3022
|
+
updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
|
|
3023
|
+
mouseOffset: externalMouseOffset || internalMouseOffsetRef.current,
|
|
3024
|
+
globalMousePosition: externalGlobalMousePosition || internalGlobalMousePositionRef.current,
|
|
3025
|
+
glassSize: glassSize,
|
|
3026
|
+
isHovered: isHovered,
|
|
3027
|
+
isActive: isActive,
|
|
3028
|
+
isOverLight: baseOverLightConfig.isOverLight,
|
|
3029
|
+
baseOverLightConfig: baseOverLightConfig,
|
|
3030
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
3031
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
3032
|
+
effectiveReducedMotion: effectiveReducedMotion,
|
|
3033
|
+
elasticity: elasticity,
|
|
3034
|
+
directionalScale: directionalScale,
|
|
3035
|
+
onClick: onClick,
|
|
3036
|
+
withLiquidBlur: withLiquidBlur,
|
|
3037
|
+
blurAmount: blurAmount,
|
|
3038
|
+
saturation: saturation,
|
|
3039
|
+
padding: padding
|
|
3040
|
+
});
|
|
3041
|
+
}), [ isHovered, isActive, glassSize, baseOverLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, directionalScale, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, padding, onClick ]);
|
|
3042
|
+
// Event handlers
|
|
3043
|
+
const handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleMouseMove = useCallback((_e => {}), []), handleKeyDown = useCallback((e => {
|
|
2901
3044
|
!onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
|
|
2902
|
-
}), [ onClick ])
|
|
2903
|
-
|
|
2904
|
-
* Validate and clamp a numeric config value
|
|
2905
|
-
* @param value - The value to validate
|
|
2906
|
-
* @param min - Minimum allowed value
|
|
2907
|
-
* @param max - Maximum allowed value
|
|
2908
|
-
* @param defaultValue - Default value if validation fails
|
|
2909
|
-
* @returns Validated and clamped value
|
|
2910
|
-
*/ return {
|
|
2911
|
-
// State
|
|
3045
|
+
}), [ onClick ]);
|
|
3046
|
+
return {
|
|
2912
3047
|
isHovered: isHovered,
|
|
2913
3048
|
isActive: isActive,
|
|
2914
3049
|
glassSize: glassSize,
|
|
2915
|
-
|
|
2916
|
-
|
|
3050
|
+
dynamicBorderRadius: dynamicBorderRadius,
|
|
3051
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
2917
3052
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
2918
3053
|
effectiveHighContrast: effectiveHighContrast,
|
|
2919
|
-
|
|
3054
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
2920
3055
|
detectedOverLight: detectedOverLight,
|
|
2921
3056
|
globalMousePosition: globalMousePosition,
|
|
3057
|
+
// This is now static (refs or props) unless prop changes
|
|
2922
3058
|
mouseOffset: mouseOffset,
|
|
2923
|
-
//
|
|
3059
|
+
// This is now static (refs or props) unless prop changes
|
|
2924
3060
|
overLightConfig: overLightConfig,
|
|
2925
|
-
// Transform calculations
|
|
2926
3061
|
elasticTranslation: elasticTranslation,
|
|
2927
3062
|
directionalScale: directionalScale,
|
|
2928
3063
|
transformStyle: transformStyle,
|
|
2929
|
-
// Event handlers
|
|
2930
3064
|
handleMouseEnter: handleMouseEnter,
|
|
2931
3065
|
handleMouseLeave: handleMouseLeave,
|
|
2932
3066
|
handleMouseDown: handleMouseDown,
|
|
@@ -2965,7 +3099,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
2965
3099
|
*
|
|
2966
3100
|
* @example
|
|
2967
3101
|
* // Manual border-radius override
|
|
2968
|
-
* <AtomixGlass
|
|
3102
|
+
* <AtomixGlass borderRadius={20}>
|
|
2969
3103
|
* <div>Content with 20px glass radius</div>
|
|
2970
3104
|
* </AtomixGlass>
|
|
2971
3105
|
*
|
|
@@ -3006,37 +3140,48 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
3006
3140
|
* <AtomixGlass overLight="auto" debugOverLight={true}>
|
|
3007
3141
|
* <div>Content with debug logging enabled</div>
|
|
3008
3142
|
* </AtomixGlass>
|
|
3009
|
-
*/ 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,
|
|
3010
|
-
const glassRef = useRef(null), contentRef = useRef(null), {isHovered: isHovered, isActive: isActive, glassSize: glassSize,
|
|
3143
|
+
*/ 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}) {
|
|
3144
|
+
const glassRef = useRef(null), contentRef = 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({
|
|
3011
3145
|
glassRef: glassRef,
|
|
3012
3146
|
contentRef: contentRef,
|
|
3013
|
-
|
|
3147
|
+
borderRadius: borderRadius,
|
|
3014
3148
|
globalMousePosition: externalGlobalMousePosition,
|
|
3015
3149
|
mouseOffset: externalMouseOffset,
|
|
3016
3150
|
mouseContainer: mouseContainer,
|
|
3017
3151
|
overLight: overLight,
|
|
3018
3152
|
reducedMotion: reducedMotion,
|
|
3019
3153
|
highContrast: highContrast,
|
|
3020
|
-
|
|
3154
|
+
withoutEffects: withoutEffects,
|
|
3021
3155
|
elasticity: elasticity,
|
|
3022
3156
|
onClick: onClick,
|
|
3023
|
-
|
|
3157
|
+
debugBorderRadius: debugBorderRadius,
|
|
3024
3158
|
debugOverLight: debugOverLight,
|
|
3025
|
-
|
|
3026
|
-
children: children
|
|
3027
|
-
|
|
3159
|
+
debugPerformance: debugPerformance,
|
|
3160
|
+
children: children,
|
|
3161
|
+
blurAmount: blurAmount,
|
|
3162
|
+
saturation: saturation,
|
|
3163
|
+
withLiquidBlur: withLiquidBlur,
|
|
3164
|
+
padding: padding,
|
|
3165
|
+
style: style
|
|
3166
|
+
}), isOverLight = useMemo((() => overLightConfig?.isOverLight), [ overLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, baseStyle = {
|
|
3028
3167
|
...style,
|
|
3029
|
-
...!
|
|
3168
|
+
...!effectiveWithoutEffects && {
|
|
3030
3169
|
transform: transformStyle
|
|
3031
3170
|
}
|
|
3032
|
-
}, componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`,
|
|
3171
|
+
}, 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 = useMemo((() => ({
|
|
3033
3172
|
position: style.position || "absolute",
|
|
3034
3173
|
top: style.top || 0,
|
|
3035
3174
|
left: style.left || 0
|
|
3036
|
-
})), [ style.position, style.top, style.left ]), adjustedSize = useMemo((() =>
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3175
|
+
})), [ style.position, style.top, style.left ]), adjustedSize = useMemo((() => {
|
|
3176
|
+
const resolveSize = (propValue, styleValue, measuredSize) => {
|
|
3177
|
+
const explicitSize = propValue ?? styleValue;
|
|
3178
|
+
return void 0 !== explicitSize ? "number" == typeof explicitSize ? `${explicitSize}px` : explicitSize : "fixed" === positionStyles.position ? `${Math.max(measuredSize, 0)}px` : "100%";
|
|
3179
|
+
};
|
|
3180
|
+
return {
|
|
3181
|
+
width: resolveSize(width, style.width, glassSize.width),
|
|
3182
|
+
height: resolveSize(height, style.height, glassSize.height)
|
|
3183
|
+
};
|
|
3184
|
+
}), [ width, height, style.width, style.height, positionStyles.position, glassSize.width, glassSize.height ]), gradientValues = useMemo((() => {
|
|
3040
3185
|
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
|
|
3041
3186
|
return {
|
|
3042
3187
|
borderGradientAngle: GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER,
|
|
@@ -3078,13 +3223,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
3078
3223
|
}), [ isHovered, isActive, isOverLight, overLightConfig.opacity ]), glassVars = useMemo((() => {
|
|
3079
3224
|
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;
|
|
3080
3225
|
return {
|
|
3081
|
-
"--atomix-glass-radius": `${
|
|
3226
|
+
"--atomix-glass-radius": `${effectiveBorderRadius}px`,
|
|
3082
3227
|
"--atomix-glass-transform": transformStyle || "none",
|
|
3083
3228
|
"--atomix-glass-position": positionStyles.position,
|
|
3084
3229
|
"--atomix-glass-top": "fixed" !== positionStyles.top ? `${positionStyles.top}px` : "0",
|
|
3085
3230
|
"--atomix-glass-left": "fixed" !== positionStyles.left ? `${positionStyles.left}px` : "0",
|
|
3086
|
-
"--atomix-glass-width":
|
|
3087
|
-
"--atomix-glass-height":
|
|
3231
|
+
"--atomix-glass-width": adjustedSize.width,
|
|
3232
|
+
"--atomix-glass-height": adjustedSize.height,
|
|
3088
3233
|
"--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.09375rem)",
|
|
3089
3234
|
"--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay",
|
|
3090
3235
|
"--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%)`,
|
|
@@ -3100,24 +3245,25 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
3100
3245
|
"--atomix-glass-overlay-opacity": opacityValues.over,
|
|
3101
3246
|
"--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})`
|
|
3102
3247
|
};
|
|
3103
|
-
}), [ gradientValues, opacityValues,
|
|
3248
|
+
}), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, positionStyles, adjustedSize, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsx("div", {
|
|
3104
3249
|
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(" "),
|
|
3105
3250
|
style: {
|
|
3106
3251
|
...positionStyles,
|
|
3107
3252
|
height: adjustedSize.height,
|
|
3108
3253
|
width: adjustedSize.width,
|
|
3109
|
-
borderRadius: `${
|
|
3254
|
+
borderRadius: `${effectiveBorderRadius}px`,
|
|
3110
3255
|
transform: baseStyle.transform
|
|
3111
3256
|
}
|
|
3112
3257
|
});
|
|
3113
3258
|
return jsxs("div", {
|
|
3259
|
+
...rest,
|
|
3114
3260
|
className: componentClassName,
|
|
3115
3261
|
style: glassVars,
|
|
3116
3262
|
role: role || (onClick ? "button" : void 0),
|
|
3117
3263
|
tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
|
|
3118
3264
|
"aria-label": ariaLabel,
|
|
3119
3265
|
"aria-describedby": ariaDescribedBy,
|
|
3120
|
-
"aria-disabled": !(!onClick || !
|
|
3266
|
+
"aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
|
|
3121
3267
|
"aria-pressed": !(!onClick || !isActive) || !onClick && void 0,
|
|
3122
3268
|
onKeyDown: onClick ? handleKeyDown : void 0,
|
|
3123
3269
|
children: [ jsx(AtomixGlassContainer, {
|
|
@@ -3125,18 +3271,18 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
3125
3271
|
contentRef: contentRef,
|
|
3126
3272
|
className: className,
|
|
3127
3273
|
style: baseStyle,
|
|
3128
|
-
|
|
3129
|
-
displacementScale:
|
|
3130
|
-
blurAmount:
|
|
3274
|
+
borderRadius: effectiveBorderRadius,
|
|
3275
|
+
displacementScale: effectiveWithoutEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
|
|
3276
|
+
blurAmount: effectiveWithoutEffects ? 0 : blurAmount,
|
|
3131
3277
|
saturation: effectiveHighContrast ? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST : isOverLight ? saturation * overLightConfig.saturationBoost : saturation,
|
|
3132
|
-
aberrationIntensity:
|
|
3278
|
+
aberrationIntensity: effectiveWithoutEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
|
|
3133
3279
|
glassSize: glassSize,
|
|
3134
3280
|
padding: padding,
|
|
3135
|
-
mouseOffset:
|
|
3281
|
+
mouseOffset: effectiveWithoutEffects ? {
|
|
3136
3282
|
x: 0,
|
|
3137
3283
|
y: 0
|
|
3138
3284
|
} : mouseOffset,
|
|
3139
|
-
globalMousePosition:
|
|
3285
|
+
globalMousePosition: effectiveWithoutEffects ? {
|
|
3140
3286
|
x: 0,
|
|
3141
3287
|
y: 0
|
|
3142
3288
|
} : globalMousePosition,
|
|
@@ -3156,11 +3302,11 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
3156
3302
|
onClick: onClick,
|
|
3157
3303
|
mode: mode,
|
|
3158
3304
|
transform: baseStyle.transform,
|
|
3159
|
-
|
|
3305
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
3160
3306
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
3161
3307
|
shaderVariant: shaderVariant,
|
|
3162
3308
|
elasticity: elasticity,
|
|
3163
|
-
|
|
3309
|
+
withLiquidBlur: withLiquidBlur,
|
|
3164
3310
|
children: children
|
|
3165
3311
|
}), Boolean(onClick) && jsxs(Fragment, {
|
|
3166
3312
|
children: [ jsx("div", {
|
|
@@ -3182,11 +3328,19 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
|
|
|
3182
3328
|
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}%)`
|
|
3183
3329
|
}
|
|
3184
3330
|
}) ]
|
|
3185
|
-
}),
|
|
3331
|
+
}), withBorder && jsxs(Fragment, {
|
|
3186
3332
|
children: [ jsx("span", {
|
|
3187
|
-
className: ATOMIX_GLASS.BORDER_1_CLASS
|
|
3333
|
+
className: ATOMIX_GLASS.BORDER_1_CLASS,
|
|
3334
|
+
style: {
|
|
3335
|
+
width: glassSize.width,
|
|
3336
|
+
height: glassSize.height
|
|
3337
|
+
}
|
|
3188
3338
|
}), jsx("span", {
|
|
3189
|
-
className: ATOMIX_GLASS.BORDER_2_CLASS
|
|
3339
|
+
className: ATOMIX_GLASS.BORDER_2_CLASS,
|
|
3340
|
+
style: {
|
|
3341
|
+
width: glassSize.width,
|
|
3342
|
+
height: glassSize.height
|
|
3343
|
+
}
|
|
3190
3344
|
}) ]
|
|
3191
3345
|
}) ]
|
|
3192
3346
|
});
|
|
@@ -3788,7 +3942,7 @@ const Badge = memo((({label: label, variant: variant = "primary", size: size =
|
|
|
3788
3942
|
// Default glass settings for badges
|
|
3789
3943
|
const defaultGlassProps = {
|
|
3790
3944
|
displacementScale: 20,
|
|
3791
|
-
|
|
3945
|
+
borderRadius: ref.current?.getBoundingClientRect().width ? ref.current?.getBoundingClientRect().width / 2 : 16,
|
|
3792
3946
|
className: "c-badge--glass",
|
|
3793
3947
|
elasticity: 0
|
|
3794
3948
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
@@ -3909,7 +4063,7 @@ const useBlock = () => ({
|
|
|
3909
4063
|
* ```
|
|
3910
4064
|
*/ Block.displayName = "Block";
|
|
3911
4065
|
|
|
3912
|
-
const BreadcrumbItem = forwardRef((({children: children, href: href, active: active, icon: icon, onClick: onClick, className: className = "", style: style, linkAs:
|
|
4066
|
+
const BreadcrumbItem = forwardRef((({children: children, href: href, active: active, icon: icon, onClick: onClick, className: className = "", style: style, linkAs: linkAs, linkProps: linkProps = {}, ...props}, ref) => {
|
|
3913
4067
|
const itemClasses = [ BREADCRUMB.CLASSES.ITEM, active ? BREADCRUMB.CLASSES.ACTIVE : "", className ].filter(Boolean).join(" "), linkContent = jsxs(Fragment, {
|
|
3914
4068
|
children: [ icon && jsx("span", {
|
|
3915
4069
|
className: "c-breadcrumb__icon",
|
|
@@ -3927,7 +4081,12 @@ const BreadcrumbItem = forwardRef((({children: children, href: href, active: ac
|
|
|
3927
4081
|
className: itemClasses,
|
|
3928
4082
|
style: style,
|
|
3929
4083
|
...props,
|
|
3930
|
-
children: href && !active ? jsx(
|
|
4084
|
+
children: href && !active ? linkAs && linkAs ? jsx(linkAs, {
|
|
4085
|
+
href: href,
|
|
4086
|
+
to: href,
|
|
4087
|
+
...commonLinkProps,
|
|
4088
|
+
children: linkContent
|
|
4089
|
+
}) : jsx("a", {
|
|
3931
4090
|
href: href,
|
|
3932
4091
|
...commonLinkProps,
|
|
3933
4092
|
children: linkContent
|
|
@@ -3940,7 +4099,7 @@ const BreadcrumbItem = forwardRef((({children: children, href: href, active: ac
|
|
|
3940
4099
|
|
|
3941
4100
|
BreadcrumbItem.displayName = "BreadcrumbItem";
|
|
3942
4101
|
|
|
3943
|
-
const Breadcrumb = memo((({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style, children: children})
|
|
4102
|
+
const Breadcrumb = memo((function({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style, children: children}) {
|
|
3944
4103
|
const breadcrumbClasses = [ BREADCRUMB.CLASSES.BASE, className ].filter(Boolean).join(" ");
|
|
3945
4104
|
let content;
|
|
3946
4105
|
if (items && items.length > 0)
|
|
@@ -3962,11 +4121,11 @@ const Breadcrumb = memo((({items: items, divider: divider, className: className
|
|
|
3962
4121
|
const childrenCount = Children.count(children);
|
|
3963
4122
|
content = Children.map(children, ((child, index) => {
|
|
3964
4123
|
if ( isValidElement(child)) {
|
|
3965
|
-
const isLast = index === childrenCount - 1, childProps = child.props;
|
|
4124
|
+
const isLast = index === childrenCount - 1, childProps = child.props, {active: active, linkAs: linkAs, ...otherProps} = childProps;
|
|
3966
4125
|
|
|
3967
4126
|
return cloneElement(child, {
|
|
3968
|
-
active:
|
|
3969
|
-
linkAs:
|
|
4127
|
+
active: active ?? (!!isLast || void 0),
|
|
4128
|
+
linkAs: linkAs ?? LinkComponent
|
|
3970
4129
|
});
|
|
3971
4130
|
}
|
|
3972
4131
|
return child;
|
|
@@ -4034,7 +4193,7 @@ const Spinner = memo((({size: size = "md", variant: variant = "primary", fullsc
|
|
|
4034
4193
|
const defaultGlassProps = {
|
|
4035
4194
|
displacementScale: 20,
|
|
4036
4195
|
blurAmount: 1,
|
|
4037
|
-
|
|
4196
|
+
borderRadius: 999,
|
|
4038
4197
|
mode: "shader"
|
|
4039
4198
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
4040
4199
|
...defaultGlassProps,
|
|
@@ -4198,6 +4357,7 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
|
|
|
4198
4357
|
ref: ref,
|
|
4199
4358
|
// LinkComponent usually forwards ref to anchor
|
|
4200
4359
|
href: href,
|
|
4360
|
+
to: href,
|
|
4201
4361
|
target: target,
|
|
4202
4362
|
rel: "_blank" === target ? "noopener noreferrer" : void 0
|
|
4203
4363
|
};
|
|
@@ -4431,7 +4591,7 @@ const Callout = memo((({title: title, children: children, icon: icon, variant:
|
|
|
4431
4591
|
// Default glass settings for callouts
|
|
4432
4592
|
const defaultGlassProps = {
|
|
4433
4593
|
displacementScale: 30,
|
|
4434
|
-
|
|
4594
|
+
borderRadius: 8,
|
|
4435
4595
|
elasticity: 0
|
|
4436
4596
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
4437
4597
|
...defaultGlassProps,
|
|
@@ -4453,7 +4613,7 @@ const Callout = memo((({title: title, children: children, icon: icon, variant:
|
|
|
4453
4613
|
children: jsx("div", {
|
|
4454
4614
|
className: "c-callout__glass-content",
|
|
4455
4615
|
style: {
|
|
4456
|
-
borderRadius: glassProps.
|
|
4616
|
+
borderRadius: glassProps.borderRadius
|
|
4457
4617
|
},
|
|
4458
4618
|
children: calloutContent
|
|
4459
4619
|
})
|
|
@@ -4492,6 +4652,8 @@ active: active = !1, disabled: disabled = !1, loading: loading = !1, selected: s
|
|
|
4492
4652
|
header: header, image: image, imageAlt: imageAlt = "", title: title, text: text, actions: actions, icon: icon, footer: footer, children: children,
|
|
4493
4653
|
// Interaction
|
|
4494
4654
|
onClick: onClick, onHover: onHover, onFocus: onFocus, href: href, target: target,
|
|
4655
|
+
// Custom Link
|
|
4656
|
+
LinkComponent: LinkComponent,
|
|
4495
4657
|
// Glass
|
|
4496
4658
|
glass: glass,
|
|
4497
4659
|
// Accessibility
|
|
@@ -4575,15 +4737,23 @@ className: className = "", style: style, ...rest}, ref) => {
|
|
|
4575
4737
|
};
|
|
4576
4738
|
// Render as anchor if href is provided
|
|
4577
4739
|
if (href && !isDisabled) {
|
|
4578
|
-
|
|
4740
|
+
let anchorElement;
|
|
4741
|
+
return anchorElement = LinkComponent ? jsx(LinkComponent, {
|
|
4579
4742
|
...commonProps,
|
|
4580
4743
|
ref: ref,
|
|
4581
4744
|
href: href,
|
|
4745
|
+
to: href,
|
|
4582
4746
|
target: target,
|
|
4583
4747
|
rel: "_blank" === target ? "noopener noreferrer" : void 0,
|
|
4584
4748
|
children: cardContent
|
|
4585
|
-
})
|
|
4586
|
-
|
|
4749
|
+
}) : jsx("a", {
|
|
4750
|
+
...commonProps,
|
|
4751
|
+
ref: ref,
|
|
4752
|
+
href: href,
|
|
4753
|
+
target: target,
|
|
4754
|
+
rel: "_blank" === target ? "noopener noreferrer" : void 0,
|
|
4755
|
+
children: cardContent
|
|
4756
|
+
}), glass ? jsx(AtomixGlass, {
|
|
4587
4757
|
...!0 === glass ? {} : glass,
|
|
4588
4758
|
elasticity: 0,
|
|
4589
4759
|
children: anchorElement
|
|
@@ -5132,12 +5302,22 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
5132
5302
|
left: 40
|
|
5133
5303
|
}, config) => {
|
|
5134
5304
|
if (!datasets || 0 === datasets.length) return null;
|
|
5135
|
-
//
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5305
|
+
// Calculate total points and min/max values efficiently avoiding spread operator
|
|
5306
|
+
let totalPoints = 0, minValue = 1 / 0, maxValue = -1 / 0, hasValidData = !1;
|
|
5307
|
+
for (const dataset of datasets) if (dataset.data) {
|
|
5308
|
+
totalPoints += dataset.data.length;
|
|
5309
|
+
const {min: min, max: max, hasValid: hasValid} = getDatasetBounds(dataset.data);
|
|
5310
|
+
hasValid && (min < minValue && (minValue = min), max > maxValue && (maxValue = max),
|
|
5311
|
+
hasValidData = !0);
|
|
5312
|
+
}
|
|
5313
|
+
if (0 === totalPoints) return null;
|
|
5314
|
+
// Handle case with no valid numeric data
|
|
5315
|
+
hasValidData || (minValue = 0, maxValue = 0);
|
|
5316
|
+
const valueRange = maxValue - minValue || 1, innerWidth = width - padding.left - padding.right, innerHeight = height - padding.top - padding.bottom;
|
|
5317
|
+
// Avoid division by zero
|
|
5318
|
+
// Apply padding
|
|
5319
|
+
return {
|
|
5320
|
+
xScale: (index, dataLength = totalPoints) => dataLength <= 1 ? padding.left + innerWidth / 2 : padding.left + index / (dataLength - 1) * innerWidth,
|
|
5141
5321
|
yScale: value => padding.top + innerHeight - (value - minValue) / valueRange * innerHeight,
|
|
5142
5322
|
minValue: minValue,
|
|
5143
5323
|
maxValue: maxValue,
|
|
@@ -5192,6 +5372,29 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
5192
5372
|
|
|
5193
5373
|
/**
|
|
5194
5374
|
* Hook for chart data processing and transformation
|
|
5375
|
+
*/
|
|
5376
|
+
/**
|
|
5377
|
+
* Helper to calculate min/max values from a dataset efficiently
|
|
5378
|
+
* avoiding spread operator which can cause stack overflow on large arrays
|
|
5379
|
+
*/
|
|
5380
|
+
function getDatasetBounds(data) {
|
|
5381
|
+
let min = 1 / 0, max = -1 / 0, hasValid = !1;
|
|
5382
|
+
if (data && data.length > 0) for (let i = 0; i < data.length; i++) {
|
|
5383
|
+
const point = data[i];
|
|
5384
|
+
if (point && "number" == typeof point.value) {
|
|
5385
|
+
const val = point.value;
|
|
5386
|
+
val < min && (min = val), val > max && (max = val), hasValid = !0;
|
|
5387
|
+
}
|
|
5388
|
+
}
|
|
5389
|
+
return {
|
|
5390
|
+
min: min,
|
|
5391
|
+
max: max,
|
|
5392
|
+
hasValid: hasValid
|
|
5393
|
+
};
|
|
5394
|
+
}
|
|
5395
|
+
|
|
5396
|
+
/**
|
|
5397
|
+
* Hook for managing chart toolbar state and generating chart-specific configurations
|
|
5195
5398
|
*/ const ChartToolbar = memo( forwardRef((({chartType: chartType = "line", groups: groups = [], enableDefaults: enableDefaults = !0, defaults: defaults = {
|
|
5196
5399
|
refresh: !0,
|
|
5197
5400
|
export: !0,
|
|
@@ -5612,11 +5815,7 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
|
|
|
5612
5815
|
onZoomReset: handleZoomReset,
|
|
5613
5816
|
onPanToggle: handlePanToggle,
|
|
5614
5817
|
onReset: handleReset
|
|
5615
|
-
})), [ onRefresh, onExport, handleFullscreenChange, handleZoomIn, handleZoomOut, handleZoomReset, handlePanToggle, handleReset ]), {state: toolbarState, handlers: toolbarHandlers, toolbarGroups: toolbarGroups} =
|
|
5616
|
-
/**
|
|
5617
|
-
* Hook for managing chart toolbar state and generating chart-specific configurations
|
|
5618
|
-
*/
|
|
5619
|
-
function(chartType, config = {}, handlers = {}) {
|
|
5818
|
+
})), [ onRefresh, onExport, handleFullscreenChange, handleZoomIn, handleZoomOut, handleZoomReset, handlePanToggle, handleReset ]), {state: toolbarState, handlers: toolbarHandlers, toolbarGroups: toolbarGroups} = function(chartType, config = {}, handlers = {}) {
|
|
5620
5819
|
const [state, setState] = useState({
|
|
5621
5820
|
isFullscreen: !1,
|
|
5622
5821
|
isExporting: !1,
|
|
@@ -6001,16 +6200,16 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
|
|
|
6001
6200
|
aberrationIntensity: 1.5,
|
|
6002
6201
|
elasticity: 0,
|
|
6003
6202
|
// No elastic effect for charts
|
|
6004
|
-
|
|
6203
|
+
withLiquidBlur: !1,
|
|
6005
6204
|
// Keep it simple
|
|
6006
|
-
|
|
6205
|
+
withBorder: !0,
|
|
6007
6206
|
mode: "standard",
|
|
6008
6207
|
mouseContainer: chartContainerRef,
|
|
6009
6208
|
reducedMotion: !1
|
|
6010
6209
|
})), []), glassProps = useMemo((() => glass ? !0 === glass ? defaultChartGlassProps : {
|
|
6011
6210
|
...defaultChartGlassProps,
|
|
6012
6211
|
...glass
|
|
6013
|
-
} : null), [ glass, defaultChartGlassProps ]), chartBorderRadius = useMemo((() => glassProps?.
|
|
6212
|
+
} : null), [ glass, defaultChartGlassProps ]), chartBorderRadius = useMemo((() => glassProps?.borderRadius || void 0), [ glassProps?.borderRadius ]), chartContextValue = useMemo((() => ({
|
|
6014
6213
|
zoomLevel: zoomLevel,
|
|
6015
6214
|
panOffset: panOffset,
|
|
6016
6215
|
panEnabled: panEnabled,
|
|
@@ -6141,7 +6340,7 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
|
|
|
6141
6340
|
}) ]
|
|
6142
6341
|
}), wrappedChart = glassProps ? jsx(AtomixGlass, {
|
|
6143
6342
|
...glassProps,
|
|
6144
|
-
|
|
6343
|
+
borderRadius: chartBorderRadius,
|
|
6145
6344
|
style: {
|
|
6146
6345
|
width: "100%",
|
|
6147
6346
|
height: "100%",
|
|
@@ -6194,7 +6393,13 @@ const ChartRenderer = memo( forwardRef((({datasets: datasets = [], config: conf
|
|
|
6194
6393
|
// Get chart context (zoom/pan state from toolbar) - optional
|
|
6195
6394
|
// Always call useContext to maintain consistent hook order
|
|
6196
6395
|
const chartContext = useContext(ChartContext), {calculateScales: calculateScales, getChartColors: getChartColors} = useChart(), {processedData: processedData, isProcessing: isProcessing} = function(datasets, options) {
|
|
6197
|
-
const [processedData, setProcessedData] = useState(datasets), [isProcessing, setIsProcessing] = useState(!1), {enableDecimation: enableDecimation = !1, maxDataPoints: maxDataPoints = 1e3, enableRealTime: enableRealTime = !1, realTimeInterval: realTimeInterval = 1e3} = options || {},
|
|
6396
|
+
const [processedData, setProcessedData] = useState(datasets), [isProcessing, setIsProcessing] = useState(!1), {enableDecimation: enableDecimation = !1, maxDataPoints: maxDataPoints = 1e3, enableRealTime: enableRealTime = !1, realTimeInterval: realTimeInterval = 1e3} = options || {}, lastDataSignature = useRef(""), getDatasetSignature = useCallback((data => data.map((d => `${d.label}:${JSON.stringify(d.data)}`)).join("|")), []);
|
|
6397
|
+
// Update signature when processedData changes (e.g. via props)
|
|
6398
|
+
useEffect((() => {
|
|
6399
|
+
lastDataSignature.current = getDatasetSignature(processedData);
|
|
6400
|
+
}), [ processedData, getDatasetSignature ]);
|
|
6401
|
+
// Data decimation for performance
|
|
6402
|
+
const decimateData = useCallback(((data, maxPoints) => {
|
|
6198
6403
|
if (!enableDecimation || !data.length) return data;
|
|
6199
6404
|
const dataLength = data[0]?.data?.length || 0;
|
|
6200
6405
|
if (dataLength <= maxPoints) return data;
|
|
@@ -6214,10 +6419,17 @@ const ChartRenderer = memo( forwardRef((({datasets: datasets = [], config: conf
|
|
|
6214
6419
|
}), []), calculateTrendLine = useCallback((values => {
|
|
6215
6420
|
const n = values.length;
|
|
6216
6421
|
if (n < 2) return values.map((() => null));
|
|
6217
|
-
|
|
6422
|
+
let xSum = 0, ySum = 0, xySum = 0, x2Sum = 0;
|
|
6423
|
+
for (let i = 0; i < n; i++) {
|
|
6424
|
+
const val = values[i], safeVal = "number" == typeof val ? val : 0;
|
|
6425
|
+
// Treat null/undefined as 0 to match original reduce behavior
|
|
6426
|
+
xSum += i, ySum += safeVal, xySum += i * safeVal, x2Sum += i * i;
|
|
6427
|
+
}
|
|
6428
|
+
const slope = (n * xySum - xSum * ySum) / (n * x2Sum - xSum * xSum), intercept = (ySum - slope * xSum) / n;
|
|
6218
6429
|
return values.map(((_, i) => slope * i + intercept));
|
|
6219
6430
|
}), []);
|
|
6220
|
-
//
|
|
6431
|
+
// Moving average calculation
|
|
6432
|
+
// Process data when datasets change
|
|
6221
6433
|
return useEffect((() => {
|
|
6222
6434
|
setIsProcessing(!0), (async () => {
|
|
6223
6435
|
let processed = [ ...datasets ];
|
|
@@ -6229,11 +6441,12 @@ const ChartRenderer = memo( forwardRef((({datasets: datasets = [], config: conf
|
|
|
6229
6441
|
useEffect((() => {
|
|
6230
6442
|
if (!enableRealTime) return;
|
|
6231
6443
|
const interval = setInterval((() => {
|
|
6232
|
-
setProcessedData((prev =>
|
|
6233
|
-
|
|
6234
|
-
|
|
6444
|
+
setProcessedData((prev =>
|
|
6445
|
+
// Only trigger update if signature changed
|
|
6446
|
+
getDatasetSignature(prev) === lastDataSignature.current ? prev : [ ...prev ]));
|
|
6447
|
+
}), realTimeInterval);
|
|
6235
6448
|
return () => clearInterval(interval);
|
|
6236
|
-
}), [ enableRealTime, realTimeInterval ]), {
|
|
6449
|
+
}), [ enableRealTime, realTimeInterval, getDatasetSignature ]), {
|
|
6237
6450
|
processedData: processedData,
|
|
6238
6451
|
isProcessing: isProcessing,
|
|
6239
6452
|
decimateData: decimateData,
|
|
@@ -6254,12 +6467,12 @@ const ChartRenderer = memo( forwardRef((({datasets: datasets = [], config: conf
|
|
|
6254
6467
|
*/
|
|
6255
6468
|
function(datasets, options) {
|
|
6256
6469
|
const {enableVirtualization: enableVirtualization = !1, enableMemoization: enableMemoization = !0, debounceMs: debounceMs = 100} = options || {}, [isOptimizing, setIsOptimizing] = useState(!1), debounceRef = useRef(null), memoizedScales = useMemo((() => enableMemoization ? datasets.map((dataset => {
|
|
6257
|
-
const
|
|
6470
|
+
const {min: min, max: max, hasValid: hasValid} = getDatasetBounds(dataset.data);
|
|
6258
6471
|
return {
|
|
6259
6472
|
label: dataset.label,
|
|
6260
6473
|
dataLength: dataset.data?.length || 0,
|
|
6261
|
-
minValue:
|
|
6262
|
-
maxValue:
|
|
6474
|
+
minValue: hasValid ? min : 0,
|
|
6475
|
+
maxValue: hasValid ? max : 0
|
|
6263
6476
|
};
|
|
6264
6477
|
})) : null), [ datasets, enableMemoization ]), debouncedUpdate = useCallback((callback => {
|
|
6265
6478
|
debounceRef.current && clearTimeout(debounceRef.current), debounceRef.current = setTimeout((() => {
|
|
@@ -6358,8 +6571,8 @@ const ChartRenderer = memo( forwardRef((({datasets: datasets = [], config: conf
|
|
|
6358
6571
|
const getAccessibleDescription = useCallback((() => {
|
|
6359
6572
|
if (!datasets.length) return "Empty chart";
|
|
6360
6573
|
const datasetDescriptions = datasets.map(((dataset, i) => {
|
|
6361
|
-
const dataCount = dataset.data?.length || 0,
|
|
6362
|
-
return `Dataset ${i + 1}: ${dataset.label}, ${dataCount} points, range ${
|
|
6574
|
+
const dataCount = dataset.data?.length || 0, {min: min, max: max, hasValid: hasValid} = getDatasetBounds(dataset.data), minVal = hasValid ? min : 0, maxVal = hasValid ? max : 0;
|
|
6575
|
+
return `Dataset ${i + 1}: ${dataset.label}, ${dataCount} points, range ${minVal} to ${maxVal}`;
|
|
6363
6576
|
})).join(". ");
|
|
6364
6577
|
return `Chart with ${datasets.length} datasets. ${datasetDescriptions}`;
|
|
6365
6578
|
}), [ datasets ]);
|
|
@@ -8605,14 +8818,14 @@ const ScatterChart = memo( forwardRef((({datasets: datasets = [], config: confi
|
|
|
8605
8818
|
|
|
8606
8819
|
ScatterChart.displayName = "ScatterChart";
|
|
8607
8820
|
|
|
8608
|
-
const
|
|
8821
|
+
const DEFAULT_COLOR_CONFIG = {
|
|
8609
8822
|
scheme: "category"
|
|
8610
|
-
},
|
|
8823
|
+
}, DEFAULT_LABEL_CONFIG = {
|
|
8611
8824
|
showLabels: !0,
|
|
8612
8825
|
minSize: 1e3,
|
|
8613
8826
|
fontSize: 12,
|
|
8614
8827
|
textColor: "white"
|
|
8615
|
-
}, onDataPointClick: onDataPointClick, config: config =
|
|
8828
|
+
}, DEFAULT_CONFIG = {}, TreemapChart = memo( forwardRef((({data: data = [], algorithm: algorithm = "squarified", colorConfig: colorConfig = DEFAULT_COLOR_CONFIG, labelConfig: labelConfig = DEFAULT_LABEL_CONFIG, onDataPointClick: onDataPointClick, config: config = DEFAULT_CONFIG, ...props}, ref) => {
|
|
8616
8829
|
const [hoveredNode, setHoveredNode] = useState(null), [selectedNode, setSelectedNode] = useState(null);
|
|
8617
8830
|
useState({
|
|
8618
8831
|
x: 0,
|
|
@@ -8724,87 +8937,87 @@ const TreemapChart = memo( forwardRef((({data: data = [], algorithm: algorithm
|
|
|
8724
8937
|
remainingHeight -= rowHeight), currentRow = [];
|
|
8725
8938
|
}
|
|
8726
8939
|
}
|
|
8727
|
-
}), [])
|
|
8940
|
+
}), []), renderContent = useCallback((({scales: scales, colors: colors, datasets: renderedDatasets, handlers: handlers, hoveredPoint: hoveredPoint}) => {
|
|
8941
|
+
if (!data.length) return null;
|
|
8942
|
+
// Calculate available space with padding
|
|
8943
|
+
const availableWidth = scales.width - 40, availableHeight = scales.height - 40, leafNodes = data.filter((item => !item.children || 0 === item.children.length));
|
|
8944
|
+
if (!leafNodes.length) return null;
|
|
8945
|
+
const totalValue = _reduceInstanceProperty(leafNodes).call(leafNodes, ((sum, node) => sum + node.value), 0), treemapNodes = leafNodes.map(((item, index) => ({
|
|
8946
|
+
id: item.id,
|
|
8947
|
+
label: item.label,
|
|
8948
|
+
value: item.value,
|
|
8949
|
+
color: generateColor(item, 0, index) || "transparent",
|
|
8950
|
+
x: 0,
|
|
8951
|
+
// Will be calculated by squarify
|
|
8952
|
+
y: 0,
|
|
8953
|
+
// Will be calculated by squarify
|
|
8954
|
+
width: 0,
|
|
8955
|
+
// Will be calculated by squarify
|
|
8956
|
+
height: 0,
|
|
8957
|
+
// Will be calculated by squarify
|
|
8958
|
+
depth: 0,
|
|
8959
|
+
children: [],
|
|
8960
|
+
originalData: item
|
|
8961
|
+
})));
|
|
8962
|
+
// Create treemap nodes with proper dimensions
|
|
8963
|
+
// Apply squarified algorithm to layout nodes proportionally by value
|
|
8964
|
+
if ("squarified" === algorithm && totalValue > 0) squarify(treemapNodes, 20, 20, availableWidth, availableHeight); else {
|
|
8965
|
+
// Fallback: simple grid layout (equal sizes)
|
|
8966
|
+
const cols = Math.ceil(Math.sqrt(leafNodes.length)), rows = Math.ceil(leafNodes.length / cols), nodeWidth = availableWidth / cols, nodeHeight = availableHeight / rows;
|
|
8967
|
+
treemapNodes.forEach(((node, index) => {
|
|
8968
|
+
const col = index % cols, row = Math.floor(index / cols);
|
|
8969
|
+
node.x = 20 + col * nodeWidth, node.y = 20 + row * nodeHeight, node.width = nodeWidth,
|
|
8970
|
+
node.height = nodeHeight;
|
|
8971
|
+
}));
|
|
8972
|
+
}
|
|
8973
|
+
return jsx(Fragment, {
|
|
8974
|
+
children: treemapNodes.map((node => {
|
|
8975
|
+
const isHovered = hoveredNode === node, isSelected = selectedNode === node, area = node.width * node.height, showLabel = labelConfig.showLabels && area >= (labelConfig.minSize || 1e3);
|
|
8976
|
+
return jsxs("g", {
|
|
8977
|
+
children: [ jsx("rect", {
|
|
8978
|
+
x: node.x,
|
|
8979
|
+
y: node.y,
|
|
8980
|
+
width: node.width,
|
|
8981
|
+
height: node.height,
|
|
8982
|
+
fill: node.color,
|
|
8983
|
+
className: `c-chart__treemap-node ${isHovered ? "c-chart__treemap-node--hovered" : ""} ${isSelected ? "c-chart__treemap-node--selected" : ""}`,
|
|
8984
|
+
onClick: () => {
|
|
8985
|
+
setSelectedNode(node), handlers.onDataPointClick?.(node.originalData, 0, 0);
|
|
8986
|
+
},
|
|
8987
|
+
onMouseEnter: e => {
|
|
8988
|
+
setHoveredNode(node);
|
|
8989
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
8990
|
+
handlers.onPointHover(0, 0, node.x, node.y, rect.left + rect.width / 2, rect.top + rect.height / 2);
|
|
8991
|
+
},
|
|
8992
|
+
onMouseLeave: () => {
|
|
8993
|
+
setHoveredNode(null), handlers.onPointLeave();
|
|
8994
|
+
}
|
|
8995
|
+
}), showLabel && jsx("text", {
|
|
8996
|
+
x: node.x + node.width / 2,
|
|
8997
|
+
y: node.y + node.height / 2,
|
|
8998
|
+
textAnchor: "middle",
|
|
8999
|
+
dominantBaseline: "middle",
|
|
9000
|
+
className: "c-chart__treemap-label",
|
|
9001
|
+
style: {
|
|
9002
|
+
fontSize: labelConfig.fontSize,
|
|
9003
|
+
fill: labelConfig.textColor
|
|
9004
|
+
},
|
|
9005
|
+
children: node.label
|
|
9006
|
+
}) ]
|
|
9007
|
+
}, node.id);
|
|
9008
|
+
}))
|
|
9009
|
+
});
|
|
9010
|
+
}), [ data, algorithm, generateColor, squarify, labelConfig, hoveredNode, selectedNode ]), datasets = useMemo((() => [ {
|
|
9011
|
+
label: "Treemap Data",
|
|
9012
|
+
data: data
|
|
9013
|
+
} ]), [ data ]);
|
|
8728
9014
|
// Squarified treemap algorithm
|
|
8729
9015
|
return jsx(BaseChart, {
|
|
8730
9016
|
ref: ref,
|
|
8731
9017
|
type: "treemap",
|
|
8732
|
-
datasets:
|
|
8733
|
-
label: "Treemap Data",
|
|
8734
|
-
data: data
|
|
8735
|
-
} ],
|
|
9018
|
+
datasets: datasets,
|
|
8736
9019
|
config: config,
|
|
8737
|
-
renderContent:
|
|
8738
|
-
if (!data.length) return null;
|
|
8739
|
-
// Calculate available space with padding
|
|
8740
|
-
const availableWidth = scales.width - 40, availableHeight = scales.height - 40, leafNodes = data.filter((item => !item.children || 0 === item.children.length));
|
|
8741
|
-
if (!leafNodes.length) return null;
|
|
8742
|
-
const totalValue = _reduceInstanceProperty(leafNodes).call(leafNodes, ((sum, node) => sum + node.value), 0), treemapNodes = leafNodes.map(((item, index) => ({
|
|
8743
|
-
id: item.id,
|
|
8744
|
-
label: item.label,
|
|
8745
|
-
value: item.value,
|
|
8746
|
-
color: generateColor(item, 0, index) || "transparent",
|
|
8747
|
-
x: 0,
|
|
8748
|
-
// Will be calculated by squarify
|
|
8749
|
-
y: 0,
|
|
8750
|
-
// Will be calculated by squarify
|
|
8751
|
-
width: 0,
|
|
8752
|
-
// Will be calculated by squarify
|
|
8753
|
-
height: 0,
|
|
8754
|
-
// Will be calculated by squarify
|
|
8755
|
-
depth: 0,
|
|
8756
|
-
children: [],
|
|
8757
|
-
originalData: item
|
|
8758
|
-
})));
|
|
8759
|
-
// Create treemap nodes with proper dimensions
|
|
8760
|
-
// Apply squarified algorithm to layout nodes proportionally by value
|
|
8761
|
-
if ("squarified" === algorithm && totalValue > 0) squarify(treemapNodes, 20, 20, availableWidth, availableHeight); else {
|
|
8762
|
-
// Fallback: simple grid layout (equal sizes)
|
|
8763
|
-
const cols = Math.ceil(Math.sqrt(leafNodes.length)), rows = Math.ceil(leafNodes.length / cols), nodeWidth = availableWidth / cols, nodeHeight = availableHeight / rows;
|
|
8764
|
-
treemapNodes.forEach(((node, index) => {
|
|
8765
|
-
const col = index % cols, row = Math.floor(index / cols);
|
|
8766
|
-
node.x = 20 + col * nodeWidth, node.y = 20 + row * nodeHeight, node.width = nodeWidth,
|
|
8767
|
-
node.height = nodeHeight;
|
|
8768
|
-
}));
|
|
8769
|
-
}
|
|
8770
|
-
return jsx(Fragment, {
|
|
8771
|
-
children: treemapNodes.map((node => {
|
|
8772
|
-
const isHovered = hoveredNode === node, isSelected = selectedNode === node, area = node.width * node.height, showLabel = labelConfig.showLabels && area >= (labelConfig.minSize || 1e3);
|
|
8773
|
-
return jsxs("g", {
|
|
8774
|
-
children: [ jsx("rect", {
|
|
8775
|
-
x: node.x,
|
|
8776
|
-
y: node.y,
|
|
8777
|
-
width: node.width,
|
|
8778
|
-
height: node.height,
|
|
8779
|
-
fill: node.color,
|
|
8780
|
-
className: `c-chart__treemap-node ${isHovered ? "c-chart__treemap-node--hovered" : ""} ${isSelected ? "c-chart__treemap-node--selected" : ""}`,
|
|
8781
|
-
onClick: () => {
|
|
8782
|
-
setSelectedNode(node), handlers.onDataPointClick?.(node.originalData, 0, 0);
|
|
8783
|
-
},
|
|
8784
|
-
onMouseEnter: e => {
|
|
8785
|
-
setHoveredNode(node);
|
|
8786
|
-
const rect = e.currentTarget.getBoundingClientRect();
|
|
8787
|
-
handlers.onPointHover(0, 0, node.x, node.y, rect.left + rect.width / 2, rect.top + rect.height / 2);
|
|
8788
|
-
},
|
|
8789
|
-
onMouseLeave: () => {
|
|
8790
|
-
setHoveredNode(null), handlers.onPointLeave();
|
|
8791
|
-
}
|
|
8792
|
-
}), showLabel && jsx("text", {
|
|
8793
|
-
x: node.x + node.width / 2,
|
|
8794
|
-
y: node.y + node.height / 2,
|
|
8795
|
-
textAnchor: "middle",
|
|
8796
|
-
dominantBaseline: "middle",
|
|
8797
|
-
className: "c-chart__treemap-label",
|
|
8798
|
-
style: {
|
|
8799
|
-
fontSize: labelConfig.fontSize,
|
|
8800
|
-
fill: labelConfig.textColor
|
|
8801
|
-
},
|
|
8802
|
-
children: node.label
|
|
8803
|
-
}) ]
|
|
8804
|
-
}, node.id);
|
|
8805
|
-
}))
|
|
8806
|
-
});
|
|
8807
|
-
},
|
|
9020
|
+
renderContent: renderContent,
|
|
8808
9021
|
onDataPointClick: onDataPointClick,
|
|
8809
9022
|
interactive: !0,
|
|
8810
9023
|
...props
|
|
@@ -9492,7 +9705,7 @@ const DOTS = "...", range = (start, end) => {
|
|
|
9492
9705
|
blurAmount: 1,
|
|
9493
9706
|
saturation: 160,
|
|
9494
9707
|
aberrationIntensity: .5,
|
|
9495
|
-
|
|
9708
|
+
borderRadius: 8,
|
|
9496
9709
|
mode: "shader"
|
|
9497
9710
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
9498
9711
|
...defaultGlassProps,
|
|
@@ -9563,7 +9776,7 @@ const Checkbox = React.memo( forwardRef((({label: label, checked: checked, onCh
|
|
|
9563
9776
|
blurAmount: 1,
|
|
9564
9777
|
saturation: 160,
|
|
9565
9778
|
aberrationIntensity: .3,
|
|
9566
|
-
|
|
9779
|
+
borderRadius: 6,
|
|
9567
9780
|
mode: "shader"
|
|
9568
9781
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
9569
9782
|
...defaultGlassProps,
|
|
@@ -9623,6 +9836,7 @@ const DropdownItem = memo((({children: children, href: href, active: active = !
|
|
|
9623
9836
|
close());
|
|
9624
9837
|
}, itemClasses = [ "c-dropdown__menu-item", active ? "is-active" : "", disabled ? "is-disabled" : "", className ].filter(Boolean).join(" "), linkProps = {
|
|
9625
9838
|
href: href,
|
|
9839
|
+
to: href,
|
|
9626
9840
|
className: itemClasses,
|
|
9627
9841
|
onClick: handleClick,
|
|
9628
9842
|
role: "menuitem",
|
|
@@ -9652,13 +9866,32 @@ const DropdownItem = memo((({children: children, href: href, active: active = !
|
|
|
9652
9866
|
}), children ]
|
|
9653
9867
|
})
|
|
9654
9868
|
});
|
|
9655
|
-
}))
|
|
9869
|
+
}));
|
|
9870
|
+
|
|
9871
|
+
DropdownItem.displayName = "DropdownItem";
|
|
9872
|
+
|
|
9873
|
+
/**
|
|
9874
|
+
* DropdownDivider component for separating groups of items
|
|
9875
|
+
*/
|
|
9876
|
+
const DropdownDivider = memo((({className: className = ""}) => jsx("li", {
|
|
9656
9877
|
className: `c-dropdown__divider ${className}`,
|
|
9657
9878
|
role: "separator"
|
|
9658
|
-
})))
|
|
9879
|
+
})));
|
|
9880
|
+
|
|
9881
|
+
DropdownDivider.displayName = "DropdownDivider";
|
|
9882
|
+
|
|
9883
|
+
/**
|
|
9884
|
+
* DropdownHeader component for section headers
|
|
9885
|
+
*/
|
|
9886
|
+
const DropdownHeader = memo((({children: children, className: className = ""}) => jsx("li", {
|
|
9659
9887
|
className: `c-dropdown__header ${className}`,
|
|
9660
9888
|
children: children
|
|
9661
|
-
})))
|
|
9889
|
+
})));
|
|
9890
|
+
|
|
9891
|
+
DropdownHeader.displayName = "DropdownHeader";
|
|
9892
|
+
|
|
9893
|
+
// Helper context to pass glass prop to DropdownMenu
|
|
9894
|
+
const DropdownStyleContext = createContext({}), Dropdown = 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}) {
|
|
9662
9895
|
// Set up controlled vs uncontrolled state
|
|
9663
9896
|
const [uncontrolledIsOpen, setUncontrolledIsOpen] = useState(!1), isControlled = void 0 !== controlledIsOpen, isOpen = isControlled ? controlledIsOpen : uncontrolledIsOpen, dropdownRef = useRef(null), toggleRef = useRef(null), menuRef = useRef(null), dropdownId = useRef(`dropdown-${Math.random().toString(36).substring(2, 9)}`).current, setIsOpen = useCallback((nextIsOpen => {
|
|
9664
9897
|
isControlled || setUncontrolledIsOpen(nextIsOpen), onOpenChange && onOpenChange(nextIsOpen);
|
|
@@ -9810,9 +10043,7 @@ const DropdownItem = memo((({children: children, href: href, active: active = !
|
|
|
9810
10043
|
});
|
|
9811
10044
|
}));
|
|
9812
10045
|
|
|
9813
|
-
|
|
9814
|
-
* DropdownDivider component for separating groups of items
|
|
9815
|
-
*/ Dropdown.displayName = "Dropdown", Dropdown.Trigger = DropdownTrigger, Dropdown.Menu = DropdownMenu,
|
|
10046
|
+
Dropdown.displayName = "Dropdown", Dropdown.Trigger = DropdownTrigger, Dropdown.Menu = DropdownMenu,
|
|
9816
10047
|
Dropdown.Item = DropdownItem, Dropdown.Divider = DropdownDivider, Dropdown.Header = DropdownHeader;
|
|
9817
10048
|
|
|
9818
10049
|
/**
|
|
@@ -11236,7 +11467,7 @@ const Input = memo( forwardRef((({type: type = "text", value: value, defaultVal
|
|
|
11236
11467
|
blurAmount: 1,
|
|
11237
11468
|
saturation: 180,
|
|
11238
11469
|
aberrationIntensity: .2,
|
|
11239
|
-
|
|
11470
|
+
borderRadius: 12,
|
|
11240
11471
|
mode: "shader"
|
|
11241
11472
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
11242
11473
|
...defaultGlassProps,
|
|
@@ -11276,7 +11507,7 @@ function useHero(initialProps) {
|
|
|
11276
11507
|
* @returns Slider state and methods
|
|
11277
11508
|
*/
|
|
11278
11509
|
function(config) {
|
|
11279
|
-
const {slides: slides, autoplay: autoplay, loop: loop = !0, transition: transition = "fade", transitionDuration: transitionDuration = 1e3} = config, [currentIndex, setCurrentIndex] = useState(0), [isTransitioning, setIsTransitioning] = useState(!1), autoplayRef = useRef(null), isPausedRef = useRef(!1), slideRefs = useMemo((() => slides.map((() => React.createRef()))), [ slides.length ]), videoRefs = useMemo((() => slides.map((() => React.createRef()))), [ slides.length ]), handleSlideTransition = useCallback((nextIndex => {
|
|
11510
|
+
const {slides: slides, autoplay: autoplay, loop: loop = !0, transition: transition = "fade", transitionDuration: transitionDuration = 1e3} = config, [currentIndex, setCurrentIndex] = useState(0), [isTransitioning, setIsTransitioning] = useState(!1), autoplayRef = useRef(null), isPausedRef = useRef(!1), callbackRef = useRef(), slideRefs = useMemo((() => slides.map((() => React.createRef()))), [ slides.length ]), videoRefs = useMemo((() => slides.map((() => React.createRef()))), [ slides.length ]), handleSlideTransition = useCallback((nextIndex => {
|
|
11280
11511
|
if (nextIndex === currentIndex || isTransitioning) return;
|
|
11281
11512
|
if (nextIndex < 0 || nextIndex >= slides.length) return;
|
|
11282
11513
|
setIsTransitioning(!0),
|
|
@@ -11297,7 +11528,17 @@ function useHero(initialProps) {
|
|
|
11297
11528
|
let nextIndex;
|
|
11298
11529
|
nextIndex = loop ? (currentIndex + 1) % slides.length : Math.min(currentIndex + 1, slides.length - 1),
|
|
11299
11530
|
handleSlideTransition(nextIndex);
|
|
11300
|
-
}), [ currentIndex, slides.length, loop, handleSlideTransition ])
|
|
11531
|
+
}), [ currentIndex, slides.length, loop, handleSlideTransition ]);
|
|
11532
|
+
// Update callbackRef whenever nextSlide or isTransitioning changes
|
|
11533
|
+
useEffect((() => {
|
|
11534
|
+
callbackRef.current = () => {
|
|
11535
|
+
isPausedRef.current || isTransitioning || nextSlide();
|
|
11536
|
+
};
|
|
11537
|
+
}), [ nextSlide, isTransitioning ]);
|
|
11538
|
+
/**
|
|
11539
|
+
* Pause autoplay
|
|
11540
|
+
*/
|
|
11541
|
+
const pauseAutoplay = useCallback((() => {
|
|
11301
11542
|
isPausedRef.current = !0, autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
11302
11543
|
autoplayRef.current = null);
|
|
11303
11544
|
}), []), resumeAutoplay = useCallback((() => {
|
|
@@ -11306,24 +11547,26 @@ function useHero(initialProps) {
|
|
|
11306
11547
|
const delay = "object" == typeof autoplay ? autoplay.delay : 3e3;
|
|
11307
11548
|
// Restart autoplay
|
|
11308
11549
|
autoplayRef.current || (autoplayRef.current = setInterval((() => {
|
|
11309
|
-
|
|
11550
|
+
callbackRef.current && callbackRef.current();
|
|
11310
11551
|
}), delay));
|
|
11311
11552
|
}
|
|
11312
|
-
}), [ autoplay, slides.length
|
|
11553
|
+
}), [ autoplay, slides.length ]);
|
|
11554
|
+
/**
|
|
11555
|
+
* Resume autoplay
|
|
11556
|
+
*/
|
|
11313
11557
|
// Autoplay effect
|
|
11314
11558
|
return useEffect((() => {
|
|
11315
11559
|
if (!autoplay || slides.length <= 1) return;
|
|
11316
11560
|
const delay = "object" == typeof autoplay ? autoplay.delay : 3e3;
|
|
11317
|
-
return "object" == typeof autoplay && autoplay.pauseOnHover,
|
|
11318
11561
|
// Clear any existing interval
|
|
11319
|
-
|
|
11562
|
+
return autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null),
|
|
11320
11563
|
// Start autoplay if not paused
|
|
11321
11564
|
isPausedRef.current || (autoplayRef.current = setInterval((() => {
|
|
11322
|
-
|
|
11565
|
+
callbackRef.current && callbackRef.current();
|
|
11323
11566
|
}), delay)), () => {
|
|
11324
11567
|
autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null);
|
|
11325
11568
|
};
|
|
11326
|
-
}), [ autoplay, slides.length
|
|
11569
|
+
}), [ autoplay, slides.length ]),
|
|
11327
11570
|
// Initialize first video if needed
|
|
11328
11571
|
useEffect((() => {
|
|
11329
11572
|
if (slides.length > 0 && "video" === slides[currentIndex]?.type) {
|
|
@@ -12324,7 +12567,14 @@ function useTodo(initialProps) {
|
|
|
12324
12567
|
}
|
|
12325
12568
|
|
|
12326
12569
|
function useSlider(options) {
|
|
12327
|
-
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 = useRef(null), wrapperRef = useRef(null), repositioningRef = useRef(!1), autoplayRef = useRef(null), [autoplayRunning, setAutoplayRunning] = useState(!1),
|
|
12570
|
+
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 = useRef(null), wrapperRef = useRef(null), repositioningRef = useRef(!1), autoplayRef = useRef(null), [autoplayRunning, setAutoplayRunning] = useState(!1), sliderStateRef = useRef({
|
|
12571
|
+
isTransitioning: !1,
|
|
12572
|
+
loop: loop,
|
|
12573
|
+
slides: slides,
|
|
12574
|
+
slidesToShow: slidesToShow,
|
|
12575
|
+
speed: speed,
|
|
12576
|
+
onSlideChange: onSlideChange
|
|
12577
|
+
}), [realIndex, setRealIndex] = useState(initialSlide), [internalIndex, setInternalIndex] = useState(0), [isTransitioning, setIsTransitioning] = useState(!1), [containerSize, setContainerSize] = useState(0), [touching, setTouching] = useState(!1), [touchStart, setTouchStart] = useState(0), [dragOffset, setDragOffset] = useState(0), slideWidth = useMemo((() => 0 === containerSize ? 0 : (containerSize - spaceBetween * (slidesToShow - 1)) / slidesToShow), [ containerSize, spaceBetween, slidesToShow ]), allSlides = useMemo((() => loop && 0 !== slides.length ? [ ...slides.map(((slide, i) => ({
|
|
12328
12578
|
...slide,
|
|
12329
12579
|
id: `set1-${slide.id || i}`
|
|
12330
12580
|
}))), ...slides.map(((slide, i) => ({
|
|
@@ -12334,6 +12584,17 @@ function useSlider(options) {
|
|
|
12334
12584
|
...slide,
|
|
12335
12585
|
id: `set3-${slide.id || i}`
|
|
12336
12586
|
}))) ] : slides), [ slides, loop ]), loopedSlides = slides.length, translateValue = useMemo((() => 0 === slideWidth ? 0 : -internalIndex * slideWidth + dragOffset), [ slideWidth, internalIndex, dragOffset ]);
|
|
12587
|
+
// Update the ref whenever the relevant state/props change
|
|
12588
|
+
useEffect((() => {
|
|
12589
|
+
sliderStateRef.current = {
|
|
12590
|
+
isTransitioning: isTransitioning,
|
|
12591
|
+
loop: loop,
|
|
12592
|
+
slides: slides,
|
|
12593
|
+
slidesToShow: slidesToShow,
|
|
12594
|
+
speed: speed,
|
|
12595
|
+
onSlideChange: onSlideChange
|
|
12596
|
+
};
|
|
12597
|
+
}), [ isTransitioning, loop, slides, slidesToShow, speed, onSlideChange ]),
|
|
12337
12598
|
// Autoplay effect
|
|
12338
12599
|
useEffect((() => {
|
|
12339
12600
|
if (!autoplay) return autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
@@ -12345,32 +12606,34 @@ function useSlider(options) {
|
|
|
12345
12606
|
autoplayRef.current && clearInterval(autoplayRef.current),
|
|
12346
12607
|
// Create new interval
|
|
12347
12608
|
autoplayRef.current = setInterval((() => {
|
|
12609
|
+
// Use ref to get the latest state without resetting the interval
|
|
12610
|
+
const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
|
|
12348
12611
|
// We need to use a functional update to get the latest values
|
|
12349
|
-
|
|
12350
|
-
if (
|
|
12612
|
+
setRealIndex((prevRealIndex => {
|
|
12613
|
+
if (currentIsTransitioning) return prevRealIndex;
|
|
12351
12614
|
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12352
12615
|
let nextIndex;
|
|
12353
12616
|
// Trigger the slide change
|
|
12354
12617
|
if (disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12355
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), nextIndex =
|
|
12618
|
+
autoplayRef.current = null, setAutoplayRunning(!1)), nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
|
|
12356
12619
|
reverseDirection) {
|
|
12357
12620
|
// For reverse direction, we would go to previous slide
|
|
12358
|
-
const prevIndex =
|
|
12359
|
-
return setInternalIndex(
|
|
12360
|
-
setDragOffset(0), setTimeout((() => {
|
|
12361
|
-
setIsTransitioning(!1),
|
|
12362
|
-
}),
|
|
12621
|
+
const prevIndex = currentLoop ? 0 === prevRealIndex ? currentSlides.length - 1 : prevRealIndex - 1 : Math.max(prevRealIndex - 1, 0);
|
|
12622
|
+
return setInternalIndex(currentLoop ? currentSlides.length + prevIndex : prevIndex),
|
|
12623
|
+
setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
|
|
12624
|
+
setIsTransitioning(!1), currentOnSlideChange?.(prevIndex);
|
|
12625
|
+
}), currentSpeed), prevIndex;
|
|
12363
12626
|
}
|
|
12364
12627
|
// Normal direction
|
|
12365
|
-
return setInternalIndex(
|
|
12366
|
-
setDragOffset(0), setTimeout((() => {
|
|
12367
|
-
setIsTransitioning(!1),
|
|
12628
|
+
return setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex),
|
|
12629
|
+
setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
|
|
12630
|
+
setIsTransitioning(!1), currentOnSlideChange?.(nextIndex),
|
|
12368
12631
|
// Reposition after transition ends for looped sliders
|
|
12369
|
-
|
|
12370
|
-
setTimeout((() => {
|
|
12632
|
+
currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
|
|
12633
|
+
setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
|
|
12371
12634
|
repositioningRef.current = !1;
|
|
12372
12635
|
}), 0));
|
|
12373
|
-
}),
|
|
12636
|
+
}), currentSpeed), nextIndex;
|
|
12374
12637
|
}));
|
|
12375
12638
|
}), delay), setAutoplayRunning(!0);
|
|
12376
12639
|
// Handle pause on mouse enter/leave if enabled
|
|
@@ -12381,17 +12644,18 @@ function useSlider(options) {
|
|
|
12381
12644
|
}, handleMouseLeave = () => {
|
|
12382
12645
|
// Restart autoplay
|
|
12383
12646
|
autoplayRef.current && clearInterval(autoplayRef.current), autoplayRef.current = setInterval((() => {
|
|
12647
|
+
const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
|
|
12384
12648
|
setRealIndex((prevRealIndex => {
|
|
12385
|
-
if (
|
|
12649
|
+
if (currentIsTransitioning) return prevRealIndex;
|
|
12386
12650
|
let nextIndex;
|
|
12387
|
-
return nextIndex =
|
|
12388
|
-
setInternalIndex(
|
|
12651
|
+
return nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
|
|
12652
|
+
setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex), setIsTransitioning(!0),
|
|
12389
12653
|
setDragOffset(0), setTimeout((() => {
|
|
12390
|
-
setIsTransitioning(!1),
|
|
12391
|
-
setInternalIndex(
|
|
12654
|
+
setIsTransitioning(!1), currentOnSlideChange?.(nextIndex), currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
|
|
12655
|
+
setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
|
|
12392
12656
|
repositioningRef.current = !1;
|
|
12393
12657
|
}), 0));
|
|
12394
|
-
}),
|
|
12658
|
+
}), currentSpeed), nextIndex;
|
|
12395
12659
|
}));
|
|
12396
12660
|
}), delay), setAutoplayRunning(!0);
|
|
12397
12661
|
};
|
|
@@ -12403,7 +12667,7 @@ function useSlider(options) {
|
|
|
12403
12667
|
containerElement && (containerElement.removeEventListener("mouseenter", handleMouseEnter),
|
|
12404
12668
|
containerElement.removeEventListener("mouseleave", handleMouseLeave)), setAutoplayRunning(!1);
|
|
12405
12669
|
};
|
|
12406
|
-
}), [ autoplay,
|
|
12670
|
+
}), [ autoplay, repositioningRef ]),
|
|
12407
12671
|
// Initialize
|
|
12408
12672
|
useEffect((() => {
|
|
12409
12673
|
setInternalIndex(loop ? slides.length + initialSlide : initialSlide);
|
|
@@ -12863,7 +13127,7 @@ const Select = memo((({options: options, value: value, onChange: onChange, onBl
|
|
|
12863
13127
|
blurAmount: 1,
|
|
12864
13128
|
saturation: 180,
|
|
12865
13129
|
aberrationIntensity: .2,
|
|
12866
|
-
|
|
13130
|
+
borderRadius: 12,
|
|
12867
13131
|
mode: "shader"
|
|
12868
13132
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
12869
13133
|
...defaultGlassProps,
|
|
@@ -12921,7 +13185,7 @@ const Radio = memo((({label: label, checked: checked = !1, onChange: onChange,
|
|
|
12921
13185
|
blurAmount: 1,
|
|
12922
13186
|
saturation: 160,
|
|
12923
13187
|
aberrationIntensity: .3,
|
|
12924
|
-
|
|
13188
|
+
borderRadius: 6,
|
|
12925
13189
|
mode: "shader"
|
|
12926
13190
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
12927
13191
|
...defaultGlassProps,
|
|
@@ -12987,7 +13251,7 @@ const Textarea = memo( forwardRef((({value: value, defaultValue: defaultValue,
|
|
|
12987
13251
|
blurAmount: 1,
|
|
12988
13252
|
saturation: 180,
|
|
12989
13253
|
aberrationIntensity: 1,
|
|
12990
|
-
|
|
13254
|
+
borderRadius: 8,
|
|
12991
13255
|
mode: "shader"
|
|
12992
13256
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
12993
13257
|
...defaultGlassProps,
|
|
@@ -13713,11 +13977,12 @@ const FooterLink = forwardRef((({href: href, icon: icon, external: external = !
|
|
|
13713
13977
|
const Component = LinkComponent, componentProps = {
|
|
13714
13978
|
ref: ref,
|
|
13715
13979
|
...href && !disabled ? {
|
|
13980
|
+
href: href,
|
|
13716
13981
|
to: href
|
|
13717
13982
|
} : {},
|
|
13718
13983
|
...linkProps
|
|
13719
13984
|
};
|
|
13720
|
-
// Only pass href if the link is not disabled and href exists
|
|
13985
|
+
// Only pass href/to if the link is not disabled and href exists
|
|
13721
13986
|
return jsxs(Component, {
|
|
13722
13987
|
...componentProps,
|
|
13723
13988
|
children: [ icon && jsx("span", {
|
|
@@ -13828,7 +14093,7 @@ const Hero = ({title: title, subtitle: subtitle, text: text, imageSrc: imageSrc,
|
|
|
13828
14093
|
blurAmount: 3,
|
|
13829
14094
|
saturation: 180,
|
|
13830
14095
|
aberrationIntensity: 0,
|
|
13831
|
-
|
|
14096
|
+
borderRadius: 8,
|
|
13832
14097
|
overLight: !1,
|
|
13833
14098
|
mode: "standard",
|
|
13834
14099
|
children: jsxs("div", {
|
|
@@ -14033,7 +14298,7 @@ Hero.Title = ({children: children, className: className, level: level = "h1", ..
|
|
|
14033
14298
|
blurAmount: 3,
|
|
14034
14299
|
saturation: 180,
|
|
14035
14300
|
aberrationIntensity: 0,
|
|
14036
|
-
|
|
14301
|
+
borderRadius: 8,
|
|
14037
14302
|
overLight: !1,
|
|
14038
14303
|
mode: "standard"
|
|
14039
14304
|
} : glass;
|
|
@@ -14147,7 +14412,7 @@ const Messages = ({messages: messages = [], otherAvatar: otherAvatar, selfAvatar
|
|
|
14147
14412
|
onSendMessage: onSendMessage
|
|
14148
14413
|
}), messagesId = id || `messages-${Math.random().toString(36).substr(2, 9)}`, inputId = `${messagesId}-input`, defaultGlassProps = {
|
|
14149
14414
|
displacementScale: 150,
|
|
14150
|
-
|
|
14415
|
+
borderRadius: 12,
|
|
14151
14416
|
elasticity: 0,
|
|
14152
14417
|
aberrationIntensity: 2
|
|
14153
14418
|
}, messagesClasses = `${MESSAGES.CLASSES.BASE} ${glass ? "c-messages--glass" : ""} ${disabled ? "is-disabled" : ""} ${className}`, messagesContent = jsxs(Fragment, {
|
|
@@ -14293,7 +14558,7 @@ const Messages = ({messages: messages = [], otherAvatar: otherAvatar, selfAvatar
|
|
|
14293
14558
|
children: jsx("div", {
|
|
14294
14559
|
className: "c-messages__glass-content",
|
|
14295
14560
|
style: {
|
|
14296
|
-
borderRadius: glassProps.
|
|
14561
|
+
borderRadius: glassProps.borderRadius
|
|
14297
14562
|
},
|
|
14298
14563
|
children: messagesContent
|
|
14299
14564
|
})
|
|
@@ -14521,7 +14786,7 @@ const Modal = ModalWithSubcomponents, Nav = forwardRef((({children: children, a
|
|
|
14521
14786
|
const defaultGlassProps = {
|
|
14522
14787
|
displacementScale: 60,
|
|
14523
14788
|
blurAmount: 1.5,
|
|
14524
|
-
|
|
14789
|
+
borderRadius: 8,
|
|
14525
14790
|
mode: "shader"
|
|
14526
14791
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
14527
14792
|
...defaultGlassProps,
|
|
@@ -14549,7 +14814,24 @@ const Modal = ModalWithSubcomponents, Nav = forwardRef((({children: children, a
|
|
|
14549
14814
|
* </NavDropdown>
|
|
14550
14815
|
* </Nav>
|
|
14551
14816
|
* ```
|
|
14552
|
-
*/
|
|
14817
|
+
*/
|
|
14818
|
+
/**
|
|
14819
|
+
* Utility to merge multiple React refs into one
|
|
14820
|
+
*/
|
|
14821
|
+
function setRef(ref, value) {
|
|
14822
|
+
"function" == typeof ref ? ref(value) : ref && (
|
|
14823
|
+
// This is safe because we're checking that ref exists first
|
|
14824
|
+
ref.current = value);
|
|
14825
|
+
}
|
|
14826
|
+
|
|
14827
|
+
/**
|
|
14828
|
+
* Combines two React refs into a single ref function
|
|
14829
|
+
* This is used when you need to use and forward a ref at the same time
|
|
14830
|
+
*/ function useForkRef(refA, refB) {
|
|
14831
|
+
return React.useMemo((() => null == refA && null == refB ? null : refValue => {
|
|
14832
|
+
setRef(refA, refValue), setRef(refB, refValue);
|
|
14833
|
+
}), [ refA, refB ]);
|
|
14834
|
+
}
|
|
14553
14835
|
|
|
14554
14836
|
/**
|
|
14555
14837
|
* NavItem component represents a single navigation item that can be a link, dropdown trigger, or mega menu trigger.
|
|
@@ -14578,14 +14860,15 @@ const Modal = ModalWithSubcomponents, Nav = forwardRef((({children: children, a
|
|
|
14578
14860
|
* </MegaMenu>
|
|
14579
14861
|
* </NavItem>
|
|
14580
14862
|
* ```
|
|
14581
|
-
*/
|
|
14863
|
+
*/ Nav.displayName = "Nav";
|
|
14864
|
+
|
|
14582
14865
|
const NavItem = 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) => {
|
|
14583
14866
|
const {generateNavItemClass: generateNavItemClass, generateNavLinkClass: generateNavLinkClass, handleClick: handleClick} = useNavItem({
|
|
14584
14867
|
dropdown: dropdown,
|
|
14585
14868
|
megaMenu: megaMenu,
|
|
14586
14869
|
active: active,
|
|
14587
14870
|
disabled: disabled
|
|
14588
|
-
}), [isActive, setIsActive] = useState(!1), itemRef = useRef(null);
|
|
14871
|
+
}), [isActive, setIsActive] = useState(!1), itemRef = useRef(null), combinedRef = useForkRef(ref, itemRef);
|
|
14589
14872
|
// State for tracking dropdown open state
|
|
14590
14873
|
// Close dropdown on outside click (desktop only)
|
|
14591
14874
|
useEffect((() => {
|
|
@@ -14616,8 +14899,9 @@ const NavItem = forwardRef((({children: children, dropdown: dropdown = !1, mega
|
|
|
14616
14899
|
disabled: disabled,
|
|
14617
14900
|
className: className
|
|
14618
14901
|
}) + (isActive ? " is-active" : ""), navLinkClass = generateNavLinkClass(active, disabled, dropdown || megaMenu ? "c-nav__dropdown-toggle" : ""), childContent = React.Children.toArray(children), expanded = void 0 !== ariaExpanded ? ariaExpanded : isActive, linkProps = {
|
|
14619
|
-
ref:
|
|
14902
|
+
ref: combinedRef,
|
|
14620
14903
|
href: href || "#",
|
|
14904
|
+
to: href || "#",
|
|
14621
14905
|
className: navLinkClass,
|
|
14622
14906
|
onClick: dropdown || megaMenu ? e => {
|
|
14623
14907
|
(dropdown || megaMenu) && (e.preventDefault(), setIsActive(!isActive));
|
|
@@ -14627,7 +14911,6 @@ const NavItem = forwardRef((({children: children, dropdown: dropdown = !1, mega
|
|
|
14627
14911
|
"aria-current": !active || dropdown || megaMenu ? void 0 : "page"
|
|
14628
14912
|
};
|
|
14629
14913
|
return jsxs("li", {
|
|
14630
|
-
ref: ref,
|
|
14631
14914
|
className: navItemClass,
|
|
14632
14915
|
role: "menuitem",
|
|
14633
14916
|
"aria-haspopup": dropdown || megaMenu,
|
|
@@ -14727,7 +15010,7 @@ const Navbar = forwardRef((({brand: brand, children: children, variant: variant
|
|
|
14727
15010
|
const defaultGlassProps = {
|
|
14728
15011
|
displacementScale: 30,
|
|
14729
15012
|
blurAmount: 2,
|
|
14730
|
-
|
|
15013
|
+
borderRadius: 0,
|
|
14731
15014
|
elasticity: 0,
|
|
14732
15015
|
mode: "shader",
|
|
14733
15016
|
shaderVariant: "premiumGlass"
|
|
@@ -14766,23 +15049,7 @@ const Navbar = forwardRef((({brand: brand, children: children, variant: variant
|
|
|
14766
15049
|
});
|
|
14767
15050
|
}));
|
|
14768
15051
|
|
|
14769
|
-
|
|
14770
|
-
* Utility to merge multiple React refs into one
|
|
14771
|
-
*/
|
|
14772
|
-
function setRef(ref, value) {
|
|
14773
|
-
"function" == typeof ref ? ref(value) : ref && (
|
|
14774
|
-
// This is safe because we're checking that ref exists first
|
|
14775
|
-
ref.current = value);
|
|
14776
|
-
}
|
|
14777
|
-
|
|
14778
|
-
/**
|
|
14779
|
-
* Combines two React refs into a single ref function
|
|
14780
|
-
* This is used when you need to use and forward a ref at the same time
|
|
14781
|
-
*/ function useForkRef(refA, refB) {
|
|
14782
|
-
return React.useMemo((() => null == refA && null == refB ? null : refValue => {
|
|
14783
|
-
setRef(refA, refValue), setRef(refB, refValue);
|
|
14784
|
-
}), [ refA, refB ]);
|
|
14785
|
-
}
|
|
15052
|
+
Navbar.displayName = "Navbar";
|
|
14786
15053
|
|
|
14787
15054
|
/**
|
|
14788
15055
|
* SideMenuList component provides a container for side menu items.
|
|
@@ -14795,8 +15062,7 @@ function setRef(ref, value) {
|
|
|
14795
15062
|
* <SideMenuItem href="/contact">Contact</SideMenuItem>
|
|
14796
15063
|
* </SideMenuList>
|
|
14797
15064
|
* ```
|
|
14798
|
-
*/
|
|
14799
|
-
|
|
15065
|
+
*/
|
|
14800
15066
|
const SideMenuList = forwardRef((({children: children, className: className = ""}, ref) => {
|
|
14801
15067
|
const listClass = `c-side-menu__list ${className}`.trim();
|
|
14802
15068
|
return jsx("ul", {
|
|
@@ -15108,7 +15374,7 @@ const SideMenu = forwardRef((({title: title, children: children, menuItems: men
|
|
|
15108
15374
|
const defaultGlassProps = {
|
|
15109
15375
|
displacementScale: 70,
|
|
15110
15376
|
blurAmount: 2,
|
|
15111
|
-
|
|
15377
|
+
borderRadius: 12,
|
|
15112
15378
|
mode: "shader"
|
|
15113
15379
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
15114
15380
|
...defaultGlassProps,
|
|
@@ -16681,7 +16947,7 @@ const PopoverContext = createContext({
|
|
|
16681
16947
|
blurAmount: 1,
|
|
16682
16948
|
saturation: 160,
|
|
16683
16949
|
aberrationIntensity: .5,
|
|
16684
|
-
|
|
16950
|
+
borderRadius: 8,
|
|
16685
16951
|
mode: "shader"
|
|
16686
16952
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
16687
16953
|
...defaultGlassProps,
|
|
@@ -16732,7 +16998,14 @@ const PopoverContext = createContext({
|
|
|
16732
16998
|
/**
|
|
16733
16999
|
* Hook for managing rating component state and interactions
|
|
16734
17000
|
*/
|
|
16735
|
-
const
|
|
17001
|
+
const calculateStarValue = (e, starValue, allowHalf) => {
|
|
17002
|
+
if (!allowHalf) return starValue;
|
|
17003
|
+
// Get the star element's bounding rectangle
|
|
17004
|
+
const starRect = e.currentTarget.getBoundingClientRect(), starCenterX = starRect.left + starRect.width / 2, adjustedValue = e.clientX < starCenterX ? starValue - .5 : starValue;
|
|
17005
|
+
// Calculate the x position within the star
|
|
17006
|
+
return Math.max(.5, adjustedValue);
|
|
17007
|
+
// Ensure minimum of 0.5
|
|
17008
|
+
}, Rating = 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) => {
|
|
16736
17009
|
const internalRef = useRef(null), ratingInstance = 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}) => {
|
|
16737
17010
|
// Determine if component is in controlled mode
|
|
16738
17011
|
const isControlled = void 0 !== onChange, [internalValue, setInternalValue] = useState(value), [hoverValue, setHoverValue] = useState(null), [focusedIndex, setFocusedIndex] = useState(null), currentValue = isControlled ? value : internalValue, handleMouseEnter = useCallback((starValue => {
|
|
@@ -16794,30 +17067,14 @@ const Rating = forwardRef((({value: valueProp = 0, defaultValue: defaultValue,
|
|
|
16794
17067
|
readOnly: readOnly,
|
|
16795
17068
|
onChange: onChange
|
|
16796
17069
|
}), forkedRef = useForkRef(internalRef, ref), handleMouseEnter = useCallback(((e, starValue) => {
|
|
16797
|
-
|
|
16798
|
-
// Get the star element's bounding rectangle
|
|
16799
|
-
const starRect = e.currentTarget.getBoundingClientRect(), starCenterX = starRect.left + starRect.width / 2, adjustedValue = e.clientX < starCenterX ? starValue - .5 : starValue;
|
|
16800
|
-
// Calculate the x position within the star
|
|
16801
|
-
setHoverValue(Math.max(.5, adjustedValue));
|
|
16802
|
-
} else setHoverValue(starValue);
|
|
17070
|
+
readOnly || setHoverValue(calculateStarValue(e, starValue, !!allowHalf));
|
|
16803
17071
|
}), [ readOnly, allowHalf, setHoverValue ]), handleMouseMove = useCallback(((e, starValue) => {
|
|
16804
|
-
|
|
16805
|
-
|
|
16806
|
-
const starRect = e.currentTarget.getBoundingClientRect(), starCenterX = starRect.left + starRect.width / 2, adjustedValue = e.clientX < starCenterX ? starValue - .5 : starValue;
|
|
16807
|
-
// Calculate the x position within the star
|
|
16808
|
-
setHoverValue(Math.max(.5, adjustedValue));
|
|
16809
|
-
} // Ensure minimum of 0.5
|
|
16810
|
-
), [ readOnly, allowHalf, setHoverValue ]), handleMouseLeave = useCallback((() => {
|
|
17072
|
+
!readOnly && allowHalf && setHoverValue(calculateStarValue(e, starValue, !!allowHalf));
|
|
17073
|
+
}), [ readOnly, allowHalf, setHoverValue ]), handleMouseLeave = useCallback((() => {
|
|
16811
17074
|
readOnly || setHoverValue(null);
|
|
16812
17075
|
}), [ readOnly, setHoverValue ]), handleClick = useCallback(((e, starValue) => {
|
|
16813
17076
|
if (readOnly) return;
|
|
16814
|
-
|
|
16815
|
-
if (allowHalf) {
|
|
16816
|
-
// Get the star element's bounding rectangle
|
|
16817
|
-
const starRect = e.currentTarget.getBoundingClientRect(), starCenterX = starRect.left + starRect.width / 2;
|
|
16818
|
-
// Calculate the x position within the star
|
|
16819
|
-
newValue = e.clientX < starCenterX ? starValue - .5 : starValue, newValue = Math.max(.5, newValue);
|
|
16820
|
-
}
|
|
17077
|
+
const newValue = calculateStarValue(e, starValue, !!allowHalf);
|
|
16821
17078
|
onChange?.(newValue);
|
|
16822
17079
|
}), [ readOnly, onChange, allowHalf ]);
|
|
16823
17080
|
// Use vanilla JS implementation if specified
|
|
@@ -16922,7 +17179,7 @@ const Rating = forwardRef((({value: valueProp = 0, defaultValue: defaultValue,
|
|
|
16922
17179
|
blurAmount: 1,
|
|
16923
17180
|
saturation: 160,
|
|
16924
17181
|
aberrationIntensity: .5,
|
|
16925
|
-
|
|
17182
|
+
borderRadius: 8,
|
|
16926
17183
|
mode: "shader"
|
|
16927
17184
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
16928
17185
|
...defaultGlassProps,
|
|
@@ -16936,21 +17193,8 @@ const Rating = forwardRef((({value: valueProp = 0, defaultValue: defaultValue,
|
|
|
16936
17193
|
return ratingContent;
|
|
16937
17194
|
}));
|
|
16938
17195
|
|
|
16939
|
-
|
|
16940
|
-
|
|
16941
|
-
*
|
|
16942
|
-
* @example
|
|
16943
|
-
* // Basic usage
|
|
16944
|
-
* <Rating value={3} onChange={handleRatingChange} />
|
|
16945
|
-
*
|
|
16946
|
-
* @example
|
|
16947
|
-
* // Read-only with custom variant
|
|
16948
|
-
* <Rating value={4.5} readOnly variant="warning" />
|
|
16949
|
-
*
|
|
16950
|
-
* @example
|
|
16951
|
-
* // With half-star support
|
|
16952
|
-
* <Rating value={3.5} allowHalf maxValue={5} />
|
|
16953
|
-
*/ Rating.displayName = "Rating";
|
|
17196
|
+
// Helper function to calculate star value based on mouse position
|
|
17197
|
+
Rating.displayName = "Rating";
|
|
16954
17198
|
|
|
16955
17199
|
/**
|
|
16956
17200
|
* ProductReview component for collecting user ratings and feedback
|
|
@@ -17095,7 +17339,7 @@ const Progress = memo( forwardRef((({value: value, variant: variant = "primary"
|
|
|
17095
17339
|
const defaultGlassProps = {
|
|
17096
17340
|
displacementScale: 30,
|
|
17097
17341
|
blurAmount: .5,
|
|
17098
|
-
|
|
17342
|
+
borderRadius: 8,
|
|
17099
17343
|
mode: "shader"
|
|
17100
17344
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
17101
17345
|
...defaultGlassProps,
|
|
@@ -17499,7 +17743,7 @@ const Steps = ({items: items, activeIndex: activeIndex = 0, vertical: vertical =
|
|
|
17499
17743
|
blurAmount: 1,
|
|
17500
17744
|
saturation: 160,
|
|
17501
17745
|
aberrationIntensity: .5,
|
|
17502
|
-
|
|
17746
|
+
borderRadius: 8,
|
|
17503
17747
|
mode: "shader"
|
|
17504
17748
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
17505
17749
|
...defaultGlassProps,
|
|
@@ -17657,7 +17901,7 @@ const Tabs = memo((({items: items, activeIndex: activeIndex = TAB.DEFAULTS.ACTI
|
|
|
17657
17901
|
blurAmount: 1,
|
|
17658
17902
|
saturation: 160,
|
|
17659
17903
|
aberrationIntensity: .5,
|
|
17660
|
-
|
|
17904
|
+
borderRadius: 8,
|
|
17661
17905
|
mode: "shader"
|
|
17662
17906
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
17663
17907
|
...defaultGlassProps,
|
|
@@ -17900,7 +18144,7 @@ const Toggle = ({checked: controlledChecked, defaultChecked: defaultChecked = !1
|
|
|
17900
18144
|
blurAmount: 1,
|
|
17901
18145
|
saturation: 160,
|
|
17902
18146
|
aberrationIntensity: .5,
|
|
17903
|
-
|
|
18147
|
+
borderRadius: 8,
|
|
17904
18148
|
mode: "shader"
|
|
17905
18149
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
17906
18150
|
...defaultGlassProps,
|