@shohojdhara/atomix 0.4.7 → 0.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/atomix.config.ts +58 -1
- package/dist/atomix.css +172 -157
- 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 +33 -0
- package/dist/charts.js +1274 -164
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +33 -10
- package/dist/core.js +1099 -83
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +33 -0
- package/dist/forms.js +2106 -1050
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +42 -1
- package/dist/heavy.js +1663 -638
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +442 -270
- package/dist/index.esm.js +1947 -680
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1982 -712
- 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 +6 -3
- package/scripts/atomix-cli.js +136 -1827
- package/scripts/cli/__tests__/basic.test.js +3 -2
- package/scripts/cli/__tests__/clean.test.js +278 -0
- package/scripts/cli/__tests__/component-validator.test.js +433 -0
- package/scripts/cli/__tests__/generator.test.js +613 -0
- package/scripts/cli/__tests__/glass-motion.test.js +256 -0
- package/scripts/cli/__tests__/integration.test.js +719 -108
- package/scripts/cli/__tests__/migrate.test.js +74 -0
- package/scripts/cli/__tests__/security.test.js +206 -0
- package/scripts/cli/__tests__/test-setup.js +3 -1
- package/scripts/cli/__tests__/theme-bridge.test.js +507 -0
- package/scripts/cli/__tests__/token-provider.test.js +361 -0
- package/scripts/cli/__tests__/utils.test.js +5 -5
- package/scripts/cli/commands/benchmark.js +105 -0
- package/scripts/cli/commands/build-theme.js +115 -0
- package/scripts/cli/commands/clean.js +109 -0
- package/scripts/cli/commands/doctor.js +88 -0
- package/scripts/cli/commands/generate.js +218 -0
- package/scripts/cli/commands/init.js +73 -0
- package/scripts/cli/commands/migrate.js +106 -0
- package/scripts/cli/commands/sync-tokens.js +206 -0
- package/scripts/cli/commands/theme-bridge.js +248 -0
- package/scripts/cli/commands/tokens.js +157 -0
- package/scripts/cli/commands/validate.js +194 -0
- package/scripts/cli/internal/ai-engine.js +156 -0
- package/scripts/cli/internal/compiler.js +114 -0
- package/scripts/cli/internal/component-validator.js +443 -0
- package/scripts/cli/internal/config-loader.js +162 -0
- package/scripts/cli/internal/filesystem.js +158 -0
- package/scripts/cli/internal/generator.js +430 -0
- package/scripts/cli/internal/glass-generator.js +398 -0
- package/scripts/cli/internal/hook-generator.js +369 -0
- package/scripts/cli/internal/hooks.js +61 -0
- package/scripts/cli/internal/itcss-generator.js +565 -0
- package/scripts/cli/internal/motion-generator.js +679 -0
- package/scripts/cli/internal/template-engine.js +301 -0
- package/scripts/cli/internal/theme-bridge.js +664 -0
- package/scripts/cli/internal/tokens/engine.js +122 -0
- package/scripts/cli/internal/tokens/provider.js +34 -0
- package/scripts/cli/internal/tokens/providers/figma.js +50 -0
- package/scripts/cli/internal/tokens/providers/style-dictionary.js +48 -0
- package/scripts/cli/internal/tokens/providers/w3c.js +48 -0
- package/scripts/cli/internal/tokens/token-provider.js +443 -0
- package/scripts/cli/internal/tokens/token-validator.js +513 -0
- package/scripts/cli/internal/validator.js +276 -0
- package/scripts/cli/internal/wizard.js +115 -0
- package/scripts/cli/mappings.js +23 -0
- package/scripts/cli/migration-tools.js +164 -94
- package/scripts/cli/plugins/style-dictionary.js +46 -0
- package/scripts/cli/templates/README.md +525 -95
- package/scripts/cli/templates/common-templates.js +40 -14
- package/scripts/cli/templates/components/react-component.ts +282 -0
- package/scripts/cli/templates/config/project-config.ts +112 -0
- package/scripts/cli/templates/hooks/use-component.ts +477 -0
- package/scripts/cli/templates/index.js +19 -4
- package/scripts/cli/templates/index.ts +171 -0
- package/scripts/cli/templates/next-templates.js +72 -0
- package/scripts/cli/templates/react-templates.js +70 -126
- package/scripts/cli/templates/scss-templates.js +35 -35
- package/scripts/cli/templates/stories/storybook-story.ts +241 -0
- package/scripts/cli/templates/styles/scss-component.ts +255 -0
- package/scripts/cli/templates/tests/vitest-test.ts +229 -0
- package/scripts/cli/templates/token-templates.js +337 -1
- package/scripts/cli/templates/tokens/token-generators.ts +1088 -0
- package/scripts/cli/templates/types/component-types.ts +145 -0
- package/scripts/cli/templates/utils/testing-utils.ts +144 -0
- package/scripts/cli/templates/vanilla-templates.js +39 -0
- package/scripts/cli/token-manager.js +8 -2
- package/scripts/cli/utils/cache-manager.js +240 -0
- package/scripts/cli/utils/detector.js +46 -0
- package/scripts/cli/utils/diagnostics.js +289 -0
- package/scripts/cli/utils/error.js +89 -0
- package/scripts/cli/utils/helpers.js +67 -0
- package/scripts/cli/utils/logger.js +75 -0
- package/scripts/cli/utils/security.js +302 -0
- package/scripts/cli/utils/telemetry.js +115 -0
- package/scripts/cli/utils/validation.js +37 -0
- package/scripts/cli/utils.js +28 -341
- package/src/components/Accordion/Accordion.stories.tsx +0 -18
- package/src/components/Accordion/Accordion.test.tsx +0 -17
- package/src/components/Accordion/Accordion.tsx +0 -4
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +37 -3
- package/src/components/AtomixGlass/AtomixGlass.tsx +143 -31
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +129 -31
- package/src/components/AtomixGlass/PerformanceDashboard.tsx +219 -0
- package/src/components/AtomixGlass/README.md +25 -10
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +216 -0
- package/src/components/AtomixGlass/animation-system.ts +578 -0
- package/src/components/AtomixGlass/shader-utils.ts +4 -1
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +157 -6
- package/src/components/AtomixGlass/stories/Phase1-Animation.stories.tsx +653 -0
- package/src/components/AtomixGlass/stories/Phase1-Test.stories.tsx +95 -0
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +51 -51
- package/src/components/AtomixGlass/stories/shared-components.tsx +6 -0
- package/src/components/Avatar/Avatar.tsx +1 -1
- package/src/components/Button/Button.stories.disabled-link.tsx +10 -0
- package/src/components/Button/Button.stories.tsx +10 -0
- package/src/components/Button/Button.test.tsx +16 -11
- package/src/components/Button/Button.tsx +4 -4
- package/src/components/Card/Card.tsx +1 -1
- package/src/components/Dropdown/Dropdown.tsx +12 -12
- package/src/components/Form/Select.tsx +62 -3
- package/src/components/Modal/Modal.tsx +14 -3
- package/src/components/Navigation/Navbar/Navbar.tsx +44 -0
- package/src/components/Slider/Slider.stories.tsx +3 -3
- package/src/components/Slider/Slider.tsx +38 -0
- package/src/components/Steps/Steps.tsx +3 -3
- package/src/components/Tabs/Tabs.tsx +77 -8
- package/src/components/Testimonial/Testimonial.tsx +1 -1
- package/src/components/TypedButton/TypedButton.stories.tsx +59 -0
- package/src/components/TypedButton/TypedButton.tsx +39 -0
- package/src/components/TypedButton/index.ts +2 -0
- package/src/components/VideoPlayer/VideoPlayer.tsx +11 -4
- package/src/lib/composables/index.ts +4 -7
- package/src/lib/composables/types.ts +45 -0
- package/src/lib/composables/useAccordion.ts +0 -7
- package/src/lib/composables/useAtomixGlass.ts +148 -6
- package/src/lib/composables/useAtomixGlassStyles.ts +9 -7
- package/src/lib/composables/useChartExport.ts +3 -13
- package/src/lib/composables/useDropdown.ts +66 -0
- package/src/lib/composables/useFocusTrap.ts +80 -0
- package/src/lib/composables/usePerformanceMonitor.ts +448 -0
- package/src/lib/composables/useResponsiveGlass.presets.ts +192 -0
- package/src/lib/composables/useResponsiveGlass.ts +441 -0
- package/src/lib/composables/useTooltip.ts +16 -0
- package/src/lib/composables/useTypedButton.ts +66 -0
- package/src/lib/config/index.ts +62 -5
- package/src/lib/constants/components.ts +62 -7
- package/src/lib/theme/devtools/__tests__/useHistory.test.tsx +150 -0
- package/src/lib/theme/tokens/centralized-tokens.ts +120 -0
- package/src/lib/theme/utils/__tests__/domUtils.test.ts +101 -0
- package/src/lib/types/components.ts +37 -11
- package/src/lib/types/glass.ts +35 -0
- package/src/lib/types/index.ts +1 -0
- package/src/lib/utils/displacement-generator.ts +1 -1
- package/src/styles/01-settings/_settings.testtypecheck.scss +53 -0
- package/src/styles/01-settings/_settings.typedbutton.scss +53 -0
- package/src/styles/06-components/_components.atomix-glass.scss +17 -21
- package/src/styles/06-components/_components.edge-panel.scss +1 -5
- package/src/styles/06-components/_components.modal.scss +1 -4
- package/src/styles/06-components/_components.navbar.scss +1 -1
- package/src/styles/06-components/_components.testbutton.scss +212 -0
- package/src/styles/06-components/_components.testtypecheck.scss +212 -0
- package/src/styles/06-components/_components.tooltip.scss +9 -5
- package/src/styles/06-components/_components.typedbutton.scss +212 -0
- package/src/styles/99-utilities/_index.scss +1 -0
- package/src/styles/99-utilities/_utilities.text.scss +1 -1
- package/src/styles/99-utilities/_utilities.touch-target.scss +36 -0
- package/scripts/cli/component-generator.js +0 -564
- package/scripts/cli/interactive-init.js +0 -357
- package/src/styles/06-components/old.chart.styles.scss +0 -2788
package/dist/index.js
CHANGED
|
@@ -413,6 +413,14 @@ const THEME_COLORS = [ "primary", "secondary", "success", "info", "warning", "er
|
|
|
413
413
|
ICON_ELEMENT: "icon",
|
|
414
414
|
LABEL_ELEMENT: "label",
|
|
415
415
|
SPINNER_ELEMENT: "spinner"
|
|
416
|
+
}, TYPEDBUTTON = {
|
|
417
|
+
BASE_CLASS: "c-typedbutton",
|
|
418
|
+
VARIANT_PREFIX: "c-typedbutton--",
|
|
419
|
+
CLASSES: {
|
|
420
|
+
BASE: "c-typedbutton",
|
|
421
|
+
DISABLED: "c-typedbutton--disabled",
|
|
422
|
+
GLASS: "c-typedbutton--glass"
|
|
423
|
+
}
|
|
416
424
|
}, BUTTON = {
|
|
417
425
|
BASE_CLASS: "c-btn",
|
|
418
426
|
ICON_CLASS: "c-btn__icon",
|
|
@@ -1740,20 +1748,29 @@ const THEME_COLORS = [ "primary", "secondary", "success", "info", "warning", "er
|
|
|
1740
1748
|
SHADER: "c-atomix-glass--shader"
|
|
1741
1749
|
},
|
|
1742
1750
|
DEFAULTS: {
|
|
1743
|
-
DISPLACEMENT_SCALE:
|
|
1744
|
-
BLUR_AMOUNT:
|
|
1751
|
+
DISPLACEMENT_SCALE: 70,
|
|
1752
|
+
BLUR_AMOUNT: 0,
|
|
1745
1753
|
SATURATION: 140,
|
|
1746
|
-
ABERRATION_INTENSITY: 2
|
|
1747
|
-
ELASTICITY: .
|
|
1748
|
-
CORNER_RADIUS:
|
|
1754
|
+
ABERRATION_INTENSITY: 2,
|
|
1755
|
+
ELASTICITY: .15,
|
|
1756
|
+
CORNER_RADIUS: 20,
|
|
1749
1757
|
// Default border-radius matching design system
|
|
1750
|
-
PADDING: "0
|
|
1758
|
+
PADDING: "0",
|
|
1751
1759
|
MODE: "standard",
|
|
1752
1760
|
OVER_LIGHT: !1,
|
|
1753
|
-
ENABLE_OVER_LIGHT_LAYERS: !0
|
|
1761
|
+
ENABLE_OVER_LIGHT_LAYERS: !0,
|
|
1762
|
+
// Phase 1: Time-Based Animation System defaults
|
|
1763
|
+
WITH_TIME_ANIMATION: !0,
|
|
1764
|
+
ANIMATION_SPEED: 1,
|
|
1765
|
+
// Phase 1: Multi-Layer Distortion System defaults
|
|
1766
|
+
WITH_MULTI_LAYER_DISTORTION: !1,
|
|
1767
|
+
DISTORTION_OCTAVES: 5,
|
|
1768
|
+
DISTORTION_LACUNARITY: 2,
|
|
1769
|
+
DISTORTION_GAIN: .5,
|
|
1770
|
+
DISTORTION_QUALITY: "high"
|
|
1754
1771
|
},
|
|
1755
1772
|
CONSTANTS: {
|
|
1756
|
-
ACTIVATION_ZONE:
|
|
1773
|
+
ACTIVATION_ZONE: 200,
|
|
1757
1774
|
LERP_FACTOR: .08,
|
|
1758
1775
|
SMOOTHSTEP_POWER: 2.5,
|
|
1759
1776
|
MIN_BLUR: .1,
|
|
@@ -1913,6 +1930,44 @@ const THEME_COLORS = [ "primary", "secondary", "success", "info", "warning", "er
|
|
|
1913
1930
|
// Saturation constants
|
|
1914
1931
|
SATURATION: {
|
|
1915
1932
|
HIGH_CONTRAST: 200
|
|
1933
|
+
},
|
|
1934
|
+
// Phase 1: Animation System Constants
|
|
1935
|
+
ANIMATION: {
|
|
1936
|
+
// Breathing effect timing (in milliseconds)
|
|
1937
|
+
BREATHING_CYCLE: 2e3,
|
|
1938
|
+
// 2-second breathing cycle
|
|
1939
|
+
// Flow animation speed
|
|
1940
|
+
FLOW_SPEED_X: .1,
|
|
1941
|
+
// Horizontal flow speed
|
|
1942
|
+
FLOW_SPEED_Y: .15,
|
|
1943
|
+
// Vertical flow speed
|
|
1944
|
+
// Wave propagation
|
|
1945
|
+
WAVE_SPEED: .05,
|
|
1946
|
+
// Radial wave speed
|
|
1947
|
+
WAVE_AMPLITUDE: .02
|
|
1948
|
+
},
|
|
1949
|
+
// Phase 1: Multi-Layer Distortion Quality Presets
|
|
1950
|
+
DISTORTION_QUALITY_PRESETS: {
|
|
1951
|
+
low: {
|
|
1952
|
+
octaves: 2,
|
|
1953
|
+
lacunarity: 2,
|
|
1954
|
+
gain: .5
|
|
1955
|
+
},
|
|
1956
|
+
medium: {
|
|
1957
|
+
octaves: 4,
|
|
1958
|
+
lacunarity: 2,
|
|
1959
|
+
gain: .5
|
|
1960
|
+
},
|
|
1961
|
+
high: {
|
|
1962
|
+
octaves: 5,
|
|
1963
|
+
lacunarity: 2,
|
|
1964
|
+
gain: .5
|
|
1965
|
+
},
|
|
1966
|
+
ultra: {
|
|
1967
|
+
octaves: 7,
|
|
1968
|
+
lacunarity: 2,
|
|
1969
|
+
gain: .5
|
|
1970
|
+
}
|
|
1916
1971
|
}
|
|
1917
1972
|
}
|
|
1918
1973
|
};
|
|
@@ -1961,9 +2016,7 @@ function useAccordion(initialProps) {
|
|
|
1961
2016
|
toggle: () => {
|
|
1962
2017
|
if (!defaultProps.disabled) {
|
|
1963
2018
|
const nextOpen = !isOpen;
|
|
1964
|
-
isControlled || setInternalOpen(nextOpen), defaultProps.onOpenChange?.(nextOpen)
|
|
1965
|
-
// Call legacy handlers
|
|
1966
|
-
nextOpen ? defaultProps.onOpen?.() : defaultProps.onClose?.();
|
|
2019
|
+
isControlled || setInternalOpen(nextOpen), defaultProps.onOpenChange?.(nextOpen);
|
|
1967
2020
|
}
|
|
1968
2021
|
},
|
|
1969
2022
|
updatePanelHeight: updatePanelHeight,
|
|
@@ -2050,7 +2103,7 @@ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
|
|
|
2050
2103
|
// Silently handle errors
|
|
2051
2104
|
}
|
|
2052
2105
|
return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
2053
|
-
}, lerp = (a, b, t) => a + (b - a) * t, softClamp = (value, max) => max <= 0 ? 0 : max * (1 - Math.exp(-value / max)), getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
|
|
2106
|
+
}, lerp$1 = (a, b, t) => a + (b - a) * t, softClamp = (value, max) => max <= 0 ? 0 : max * (1 - Math.exp(-value / max)), getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
|
|
2054
2107
|
switch (mode) {
|
|
2055
2108
|
case "standard":
|
|
2056
2109
|
return displacementMap;
|
|
@@ -2217,20 +2270,19 @@ let idCounter = 0;
|
|
|
2217
2270
|
const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({children: children, className: className = "", style: style, displacementScale: displacementScale = 25, blurAmount: blurAmount = .0625, saturation: saturation = 180, aberrationIntensity: aberrationIntensity = 2, mouseOffset: mouseOffset = {
|
|
2218
2271
|
x: 0,
|
|
2219
2272
|
y: 0
|
|
2220
|
-
},
|
|
2221
|
-
x: 0,
|
|
2222
|
-
y: 0
|
|
2223
|
-
}, 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 = {
|
|
2273
|
+
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0, padding: padding = "0 0", glassSize: glassSize = {
|
|
2224
2274
|
width: 0,
|
|
2225
2275
|
height: 0
|
|
2226
|
-
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1,
|
|
2276
|
+
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1,
|
|
2277
|
+
// Phase 1: Animation System props
|
|
2278
|
+
shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", contentRef: contentRef}, ref) => {
|
|
2227
2279
|
// Generate a stable, deterministic ID for SSR compatibility
|
|
2228
2280
|
// Use a module-level counter that's consistent across server and client
|
|
2229
|
-
const filterId = React.useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = React.useState(""), shaderGeneratorRef = React.useRef(null), shaderUtilsRef = React.useRef(null), shaderDebounceTimeoutRef = React.useRef(null);
|
|
2281
|
+
const filterId = React.useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = React.useState(""), shaderGeneratorRef = React.useRef(null), shaderUtilsRef = React.useRef(null), shaderDebounceTimeoutRef = React.useRef(null), shaderUpdateTimeoutRef = React.useRef(null), animationFrameRef = React.useRef(null);
|
|
2230
2282
|
// Lazy load shader utilities only when shader mode is needed
|
|
2231
2283
|
React.useEffect((() => {
|
|
2232
2284
|
"shader" === mode ?
|
|
2233
|
-
// Dynamic import shader utilities
|
|
2285
|
+
// Dynamic import shader utilities with animation support
|
|
2234
2286
|
Promise.resolve().then((function() {
|
|
2235
2287
|
return shaderUtils;
|
|
2236
2288
|
})).then((shaderUtils => {
|
|
@@ -2247,7 +2299,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2247
2299
|
// Generate shader map with debouncing and caching
|
|
2248
2300
|
React.useEffect((() => {
|
|
2249
2301
|
// Enhanced validation for shader mode
|
|
2250
|
-
if ("shader" === mode && glassSize && validateGlassSize(glassSize)
|
|
2302
|
+
if ("shader" === mode && glassSize && validateGlassSize(glassSize)) {
|
|
2251
2303
|
// Create cache key from size and variant
|
|
2252
2304
|
const cacheKey = `${glassSize.width}x${glassSize.height}-${shaderVariant}`, cachedUrl = (key => {
|
|
2253
2305
|
const entry = sharedShaderCache.get(key);
|
|
@@ -2269,11 +2321,9 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2269
2321
|
width: glassSize.width,
|
|
2270
2322
|
height: glassSize.height,
|
|
2271
2323
|
fragment: selectedShader
|
|
2272
|
-
}),
|
|
2273
|
-
// Defer shader generation with longer delay to avoid blocking
|
|
2274
|
-
setTimeout((() => {
|
|
2324
|
+
}), shaderUpdateTimeoutRef.current = setTimeout((() => {
|
|
2275
2325
|
const url = shaderGeneratorRef.current?.updateShader() || "";
|
|
2276
|
-
((key, url) => {
|
|
2326
|
+
url && ((key, url) => {
|
|
2277
2327
|
// Evict oldest entries if at capacity
|
|
2278
2328
|
if (sharedShaderCache.size >= 15) {
|
|
2279
2329
|
const entries = Array.from(sharedShaderCache.entries());
|
|
@@ -2305,7 +2355,8 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2305
2355
|
// Cleanup function with error handling
|
|
2306
2356
|
return () => {
|
|
2307
2357
|
shaderDebounceTimeoutRef.current && (clearTimeout(shaderDebounceTimeoutRef.current),
|
|
2308
|
-
shaderDebounceTimeoutRef.current = null)
|
|
2358
|
+
shaderDebounceTimeoutRef.current = null), shaderUpdateTimeoutRef.current && (clearTimeout(shaderUpdateTimeoutRef.current),
|
|
2359
|
+
shaderUpdateTimeoutRef.current = null);
|
|
2309
2360
|
try {
|
|
2310
2361
|
shaderGeneratorRef.current?.destroy();
|
|
2311
2362
|
} catch (error) {
|
|
@@ -2314,7 +2365,37 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2314
2365
|
shaderGeneratorRef.current = null;
|
|
2315
2366
|
}
|
|
2316
2367
|
};
|
|
2317
|
-
}), [ mode, glassSize, shaderVariant ])
|
|
2368
|
+
}), [ mode, glassSize, shaderVariant ]),
|
|
2369
|
+
// Phase 1: Time-Based Animation Loop - Continuous shader regeneration
|
|
2370
|
+
React.useEffect((() => {
|
|
2371
|
+
// Only run animations in shader mode with time animation enabled
|
|
2372
|
+
if ("shader" !== mode || !withTimeAnimation || effectiveReducedMotion || effectiveWithoutEffects)
|
|
2373
|
+
// Cancel any existing animation frame
|
|
2374
|
+
return void (null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
|
|
2375
|
+
animationFrameRef.current = null));
|
|
2376
|
+
const baseFps = "ultra" === distortionQuality ? 60 : "high" === distortionQuality ? 30 : "medium" === distortionQuality ? 24 : 20, effectiveSpeed = Math.max(.5, Math.min(2, animationSpeed || 1)), complexity = withMultiLayerDistortion ? Math.max(1, (distortionOctaves || 3) / 3 + .25 * Math.max(0, (distortionLacunarity || 2) - 2) + Math.max(0, (distortionGain || .5) - .5)) : 1, frameInterval = 1e3 / Math.max(12, Math.min(60, Math.round(baseFps * effectiveSpeed / complexity)));
|
|
2377
|
+
let lastUpdate = 0, isCancelled = !1;
|
|
2378
|
+
const animate = currentTime => {
|
|
2379
|
+
if (!isCancelled) {
|
|
2380
|
+
if (currentTime - lastUpdate >= frameInterval && shaderGeneratorRef.current) {
|
|
2381
|
+
lastUpdate = currentTime;
|
|
2382
|
+
try {
|
|
2383
|
+
const animatedShaderUrl = shaderGeneratorRef.current.updateShader();
|
|
2384
|
+
animatedShaderUrl && setShaderMapUrl(animatedShaderUrl);
|
|
2385
|
+
} catch (error) {
|
|
2386
|
+
console.warn("AtomixGlassContainer: Error in animation loop", error);
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
animationFrameRef.current = requestAnimationFrame(animate);
|
|
2390
|
+
}
|
|
2391
|
+
};
|
|
2392
|
+
// Start animation loop
|
|
2393
|
+
// Cleanup animation on unmount or dependency change
|
|
2394
|
+
return animationFrameRef.current = requestAnimationFrame(animate), () => {
|
|
2395
|
+
isCancelled = !0, null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
|
|
2396
|
+
animationFrameRef.current = null);
|
|
2397
|
+
};
|
|
2398
|
+
}), [ mode, withTimeAnimation, animationSpeed, displacementScale, withMultiLayerDistortion, distortionOctaves, distortionLacunarity, distortionGain, distortionQuality, effectiveReducedMotion, effectiveWithoutEffects, glassSize ]);
|
|
2318
2399
|
// Removed forced reflow to avoid layout thrash and potential feedback sizing loops
|
|
2319
2400
|
const [rectCache, setRectCache] = React.useState(null);
|
|
2320
2401
|
React.useEffect((() => {
|
|
@@ -2366,21 +2447,18 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2366
2447
|
backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
|
|
2367
2448
|
};
|
|
2368
2449
|
}
|
|
2369
|
-
}), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur ]), containerVars = React.useMemo((() => {
|
|
2450
|
+
}), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur, overLightConfig ]), containerVars = React.useMemo((() => {
|
|
2370
2451
|
try {
|
|
2371
2452
|
// Safe extraction of mouse offset values
|
|
2372
2453
|
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;
|
|
2373
2454
|
return {
|
|
2374
|
-
"--atomix-glass-container-width": `${glassSize?.width}`,
|
|
2375
|
-
"--atomix-glass-container-height": `${glassSize?.height}`,
|
|
2376
|
-
"--atomix-glass-container-padding": padding || "0 0",
|
|
2377
2455
|
"--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`,
|
|
2378
2456
|
"--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
|
|
2379
2457
|
"--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",
|
|
2380
2458
|
"--atomix-glass-container-shadow-opacity": effectiveWithoutEffects ? 0 : 1,
|
|
2381
2459
|
// Background and shadow values use design token-aligned RGB values
|
|
2382
2460
|
"--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",
|
|
2383
|
-
"--atomix-glass-container-text-shadow": overLight ? "0px 2px
|
|
2461
|
+
"--atomix-glass-container-text-shadow": overLight ? "0px 1px 2px rgba(255, 255, 255, 0.15)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
|
|
2384
2462
|
"--atomix-glass-container-box-shadow": overLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0px 12px 40px rgba(0, 0, 0, 0.25)"
|
|
2385
2463
|
};
|
|
2386
2464
|
} catch (error) {
|
|
@@ -2395,7 +2473,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2395
2473
|
"--atomix-glass-container-text-shadow": "none"
|
|
2396
2474
|
};
|
|
2397
2475
|
}
|
|
2398
|
-
}), [
|
|
2476
|
+
}), [ borderRadius, backdropStyle, mouseOffset, overLight, effectiveWithoutEffects, overLightConfig ]);
|
|
2399
2477
|
return jsxRuntime.jsx("div", {
|
|
2400
2478
|
ref: el => {
|
|
2401
2479
|
// Apply force no-transition
|
|
@@ -2424,10 +2502,6 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2424
2502
|
aberrationIntensity: "number" != typeof aberrationIntensity || isNaN(aberrationIntensity) ? 0 : aberrationIntensity,
|
|
2425
2503
|
shaderMapUrl: shaderMapUrl
|
|
2426
2504
|
}), jsxRuntime.jsx("div", {
|
|
2427
|
-
ref: el => {
|
|
2428
|
-
el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
|
|
2429
|
-
el.style.setProperty("transition-delay", "0s", "important"));
|
|
2430
|
-
},
|
|
2431
2505
|
className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
|
|
2432
2506
|
style: {
|
|
2433
2507
|
filter: `url(#${filterId})`
|
|
@@ -2532,7 +2606,7 @@ class {
|
|
|
2532
2606
|
}
|
|
2533
2607
|
}, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
|
|
2534
2608
|
if (!wrapperElement && !containerElement) return;
|
|
2535
|
-
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 = {
|
|
2609
|
+
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, isFixedOrSticky: isFixedOrSticky = !1} = params, mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, overLightConfig = {
|
|
2536
2610
|
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
2537
2611
|
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
2538
2612
|
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
@@ -2622,7 +2696,7 @@ class {
|
|
|
2622
2696
|
}
|
|
2623
2697
|
// Update Container Styles (containerVars)
|
|
2624
2698
|
if (containerElement) {
|
|
2625
|
-
const mx = mouseOffset.x, my = mouseOffset.y, EDGE_BLUR_MULTIPLIER =
|
|
2699
|
+
const mx = mouseOffset.x, my = mouseOffset.y, EDGE_BLUR_MULTIPLIER = .5, CENTER_BLUR_MULTIPLIER = .2, FLOW_BLUR_MULTIPLIER = .3, MOUSE_INFLUENCE_BLUR_FACTOR = .4, EDGE_INTENSITY_MOUSE_FACTOR = .15, CENTER_INTENSITY_MOUSE_FACTOR = .1, MAX_BLUR_RELATIVE = 2, rect = containerElement.getBoundingClientRect();
|
|
2626
2700
|
let liquidBlur = {
|
|
2627
2701
|
baseBlur: blurAmount,
|
|
2628
2702
|
edgeBlur: blurAmount * EDGE_BLUR_MULTIPLIER,
|
|
@@ -2644,22 +2718,155 @@ class {
|
|
|
2644
2718
|
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})`;
|
|
2645
2719
|
// Container variables
|
|
2646
2720
|
const style = containerElement.style;
|
|
2647
|
-
style.setProperty("--atomix-glass-container-width", `${glassSize.width}`
|
|
2721
|
+
style.setProperty("--atomix-glass-container-width", isFixedOrSticky ? `${glassSize.width}` : "100%"),
|
|
2722
|
+
style.setProperty("--atomix-glass-container-height", isFixedOrSticky ? `${glassSize.height}` : "100%"),
|
|
2648
2723
|
style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
|
|
2649
2724
|
style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
|
|
2650
2725
|
// Shadows
|
|
2651
2726
|
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"),
|
|
2652
2727
|
style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
|
|
2653
2728
|
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"),
|
|
2654
|
-
style.setProperty("--atomix-glass-container-text-shadow", isOverLight ? "0px 2px
|
|
2729
|
+
style.setProperty("--atomix-glass-container-text-shadow", isOverLight ? "0px 1px 2px rgba(255, 255, 255, 0.15)" : "0px 2px 12px rgba(0, 0, 0, 0.4)"),
|
|
2655
2730
|
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)");
|
|
2656
2731
|
}
|
|
2657
|
-
}
|
|
2732
|
+
};
|
|
2658
2733
|
|
|
2659
2734
|
/**
|
|
2660
2735
|
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
2661
2736
|
* to avoid React re-renders on mouse movement.
|
|
2662
|
-
*/
|
|
2737
|
+
*/
|
|
2738
|
+
/**
|
|
2739
|
+
* Animation System for AtomixGlass Component
|
|
2740
|
+
*
|
|
2741
|
+
* Implements Phase 1 features from the AtomixGlass Feature Implementation Roadmap:
|
|
2742
|
+
* - Feature 1.1: Time-Based Animation System
|
|
2743
|
+
* - Feature 1.2: Multi-Layer Distortion System (FBM)
|
|
2744
|
+
*
|
|
2745
|
+
* @packageDocumentation
|
|
2746
|
+
*/
|
|
2747
|
+
// ============================================================================
|
|
2748
|
+
// Noise Functions for FBM (Feature 1.2)
|
|
2749
|
+
// ============================================================================
|
|
2750
|
+
/**
|
|
2751
|
+
* Perlin noise implementation for smooth gradient noise
|
|
2752
|
+
*
|
|
2753
|
+
* @param x - X coordinate
|
|
2754
|
+
* @param y - Y coordinate
|
|
2755
|
+
* @returns Noise value in range [0, 1]
|
|
2756
|
+
*/
|
|
2757
|
+
function perlinNoise(x, y) {
|
|
2758
|
+
// Simplified Perlin noise using pseudo-random gradients
|
|
2759
|
+
const X = 255 & Math.floor(x), Y = 255 & Math.floor(y), xf = x - Math.floor(x), yf = y - Math.floor(y), u = fade(xf), v = fade(yf), A = p[X] + Y & 255, B = p[X + 1] + Y & 255, ga = grad(p[A], xf, yf), gb = grad(p[B], xf - 1, yf), gc = grad(p[A + 1 & 255], xf, yf - 1), gd = grad(p[B + 1 & 255], xf - 1, yf - 1), lerpX1 = lerp(ga, gb, u), lerpX2 = lerp(gc, gd, u);
|
|
2760
|
+
// Scale to [0, 1] range
|
|
2761
|
+
return (lerp(lerpX1, lerpX2, v) + 1) / 2;
|
|
2762
|
+
}
|
|
2763
|
+
|
|
2764
|
+
// ============================================================================
|
|
2765
|
+
// Fractal Brownian Motion (FBM) Engine (Feature 1.2)
|
|
2766
|
+
// ============================================================================
|
|
2767
|
+
/**
|
|
2768
|
+
* Creates an FBM engine with configurable parameters
|
|
2769
|
+
*
|
|
2770
|
+
* @param config - FBM configuration (octaves, lacunarity, gain)
|
|
2771
|
+
* @returns Object with fbm function
|
|
2772
|
+
*
|
|
2773
|
+
* @example
|
|
2774
|
+
* ```typescript
|
|
2775
|
+
* const fbmEngine = createFBMEngine({ octaves: 5, lacunarity: 2, gain: 0.5 });
|
|
2776
|
+
*
|
|
2777
|
+
* // Generate noise at position (0.5, 0.5) with time animation
|
|
2778
|
+
* const noiseValue = fbmEngine.fbm(0.5, 0.5, Date.now());
|
|
2779
|
+
* ```
|
|
2780
|
+
*/ function createFBMEngine(config) {
|
|
2781
|
+
/**
|
|
2782
|
+
* Fractal Brownian Motion function
|
|
2783
|
+
* Combines multiple octaves of noise for complex, natural patterns
|
|
2784
|
+
*
|
|
2785
|
+
* @param x - X coordinate
|
|
2786
|
+
* @param y - Y coordinate
|
|
2787
|
+
* @param time - Optional time value for animation
|
|
2788
|
+
* @returns FBM noise value in range [0, 1]
|
|
2789
|
+
*/
|
|
2790
|
+
const fbm = (x, y, time = 0) => {
|
|
2791
|
+
let value = 0, amplitude = .5, frequency = 1, phase = .001 * time;
|
|
2792
|
+
// Convert to seconds for reasonable animation speed
|
|
2793
|
+
for (let i = 0; i < config.octaves; i++)
|
|
2794
|
+
// Apply time-based phase shift to all octaves
|
|
2795
|
+
value += perlinNoise(x * frequency + phase, y * frequency + phase) * amplitude,
|
|
2796
|
+
frequency *= config.lacunarity, // Increase frequency
|
|
2797
|
+
amplitude *= config.gain;
|
|
2798
|
+
return value;
|
|
2799
|
+
};
|
|
2800
|
+
/**
|
|
2801
|
+
* Get FBM with simple time factor
|
|
2802
|
+
*/ return {
|
|
2803
|
+
fbm: fbm,
|
|
2804
|
+
fbmWithTime: (x, y, time) => fbm(x, y, time)
|
|
2805
|
+
};
|
|
2806
|
+
}
|
|
2807
|
+
|
|
2808
|
+
/**
|
|
2809
|
+
* Gets optimal FBM config based on quality preset
|
|
2810
|
+
*
|
|
2811
|
+
* @param quality - Quality preset level
|
|
2812
|
+
* @returns FBM configuration for the quality level
|
|
2813
|
+
*/ const fbmEngineCache = new Map;
|
|
2814
|
+
|
|
2815
|
+
// ============================================================================
|
|
2816
|
+
// Shader Utility Functions for Time-Based Effects
|
|
2817
|
+
// ============================================================================
|
|
2818
|
+
/**
|
|
2819
|
+
* Liquid glass distortion with time-based animation
|
|
2820
|
+
* Uses FBM to create organic, flowing liquid effects
|
|
2821
|
+
*
|
|
2822
|
+
* @param uv - UV coordinates (normalized 0-1)
|
|
2823
|
+
* @param time - Elapsed time in milliseconds
|
|
2824
|
+
* @param config - FBM configuration
|
|
2825
|
+
* @returns Distorted UV coordinates
|
|
2826
|
+
*/ function liquidGlassWithTime(uv, time, config) {
|
|
2827
|
+
const configKey = `${config.octaves}-${config.lacunarity}-${config.gain}`;
|
|
2828
|
+
let fbmEngine = fbmEngineCache.get(configKey);
|
|
2829
|
+
fbmEngine || (fbmEngine = createFBMEngine(config), fbmEngineCache.set(configKey, fbmEngine));
|
|
2830
|
+
// Animate noise with time
|
|
2831
|
+
const animatedNoise = fbmEngine.fbmWithTime(2 * uv.x + 1e-4 * time, 2 * uv.y + 15e-5 * time, time);
|
|
2832
|
+
return {
|
|
2833
|
+
x: uv.x + .04 * (animatedNoise - .5),
|
|
2834
|
+
y: uv.y + .04 * (animatedNoise - .5)
|
|
2835
|
+
};
|
|
2836
|
+
}
|
|
2837
|
+
|
|
2838
|
+
// ============================================================================
|
|
2839
|
+
// Helper Functions
|
|
2840
|
+
// ============================================================================
|
|
2841
|
+
/**
|
|
2842
|
+
* Fade curve for smooth interpolation (Perlin's fade function)
|
|
2843
|
+
*/ function fade(t) {
|
|
2844
|
+
return t * t * t * (t * (6 * t - 15) + 10);
|
|
2845
|
+
}
|
|
2846
|
+
|
|
2847
|
+
/**
|
|
2848
|
+
* Linear interpolation
|
|
2849
|
+
*/ function lerp(a, b, t) {
|
|
2850
|
+
return a + t * (b - a);
|
|
2851
|
+
}
|
|
2852
|
+
|
|
2853
|
+
/**
|
|
2854
|
+
* Gradient calculation for Perlin noise
|
|
2855
|
+
*/ function grad(hash, x, y) {
|
|
2856
|
+
const h = 15 & hash, u = h < 8 ? x : y, v = h < 4 ? y : 12 === h || 14 === h ? x : 0;
|
|
2857
|
+
return (1 & h ? -u : u) + (2 & h ? -v : v);
|
|
2858
|
+
}
|
|
2859
|
+
|
|
2860
|
+
/**
|
|
2861
|
+
* Permutation table for Perlin noise
|
|
2862
|
+
*/ const p = (() => {
|
|
2863
|
+
const permutation = [];
|
|
2864
|
+
for (let i = 0; i < 256; i++) permutation[i] = Math.floor(256 * Math.random());
|
|
2865
|
+
// Duplicate for overflow handling
|
|
2866
|
+
return [ ...permutation, ...permutation ];
|
|
2867
|
+
})(), {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
|
|
2868
|
+
|
|
2869
|
+
const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
|
|
2663
2870
|
parentElement && backgroundDetectionCache.set(parentElement, {
|
|
2664
2871
|
result: result,
|
|
2665
2872
|
timestamp: Date.now(),
|
|
@@ -2672,7 +2879,9 @@ class {
|
|
|
2672
2879
|
* Composable hook for AtomixGlass component logic
|
|
2673
2880
|
* Manages all state, calculations, and event handlers
|
|
2674
2881
|
*/
|
|
2675
|
-
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,
|
|
2882
|
+
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, children: children, blurAmount: blurAmount, saturation: saturation, padding: padding, withLiquidBlur: withLiquidBlur, isFixedOrSticky: isFixedOrSticky = !1, withTimeAnimation:
|
|
2883
|
+
// Phase 1: Animation System Props
|
|
2884
|
+
withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: animationSpeed = ATOMIX_GLASS.DEFAULTS.ANIMATION_SPEED, withMultiLayerDistortion: withMultiLayerDistortion = ATOMIX_GLASS.DEFAULTS.WITH_MULTI_LAYER_DISTORTION, distortionOctaves: distortionOctaves = ATOMIX_GLASS.DEFAULTS.DISTORTION_OCTAVES, distortionLacunarity: distortionLacunarity = ATOMIX_GLASS.DEFAULTS.DISTORTION_LACUNARITY, distortionGain: distortionGain = ATOMIX_GLASS.DEFAULTS.DISTORTION_GAIN, distortionQuality: distortionQuality = ATOMIX_GLASS.DEFAULTS.DISTORTION_QUALITY}) {
|
|
2676
2885
|
// State
|
|
2677
2886
|
const [isHovered, setIsHovered] = React.useState(!1), [isActive, setIsActive] = React.useState(!1), cachedRectRef = React.useRef(null), internalGlobalMousePositionRef = React.useRef({
|
|
2678
2887
|
x: 0,
|
|
@@ -2686,7 +2895,47 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2686
2895
|
}), targetGlobalMousePositionRef = React.useRef({
|
|
2687
2896
|
x: 0,
|
|
2688
2897
|
y: 0
|
|
2689
|
-
}), lerpRafRef = React.useRef(null), lerpActiveRef = React.useRef(!1), [dynamicBorderRadius, setDynamicCornerRadius] = React.useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = React.useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = React.useState(!1), [detectedOverLight, setDetectedOverLight] = React.useState(!1),
|
|
2898
|
+
}), lerpRafRef = React.useRef(null), lerpActiveRef = React.useRef(!1), [dynamicBorderRadius, setDynamicCornerRadius] = React.useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = React.useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = React.useState(!1), [detectedOverLight, setDetectedOverLight] = React.useState(!1), animationFrameIdRef = React.useRef(null), animationStartTimeRef = React.useRef(0), elapsedTimeRef = React.useRef(0), shaderTimeRef = React.useRef(0), fbmConfig = React.useMemo((() => {
|
|
2899
|
+
// If quality preset is provided, use it as base
|
|
2900
|
+
const preset = (quality = distortionQuality, ATOMIX_GLASS.CONSTANTS.DISTORTION_QUALITY_PRESETS[quality]);
|
|
2901
|
+
// Override with custom values if provided
|
|
2902
|
+
var quality;
|
|
2903
|
+
return {
|
|
2904
|
+
octaves: distortionOctaves ?? preset.octaves,
|
|
2905
|
+
lacunarity: distortionLacunarity ?? preset.lacunarity,
|
|
2906
|
+
gain: distortionGain ?? preset.gain
|
|
2907
|
+
};
|
|
2908
|
+
}), [ distortionQuality, distortionOctaves, distortionLacunarity, distortionGain ]), fbmEngine = React.useMemo((() => withMultiLayerDistortion ? createFBMEngine(fbmConfig) : null), [ withMultiLayerDistortion, fbmConfig ]), effectiveReducedMotion = React.useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveWithTimeAnimation = React.useMemo((() => withTimeAnimation && !effectiveReducedMotion), [ withTimeAnimation, effectiveReducedMotion ]);
|
|
2909
|
+
/**
|
|
2910
|
+
* Animation loop for time-based effects
|
|
2911
|
+
*/
|
|
2912
|
+
React.useEffect((() => {
|
|
2913
|
+
if (!effectiveWithTimeAnimation || "undefined" == typeof window) return;
|
|
2914
|
+
let lastFrameTime = performance.now();
|
|
2915
|
+
/**
|
|
2916
|
+
* Animation frame handler
|
|
2917
|
+
*/ const animate = currentTime => {
|
|
2918
|
+
// Calculate delta time
|
|
2919
|
+
const deltaTime = currentTime - lastFrameTime;
|
|
2920
|
+
lastFrameTime = currentTime;
|
|
2921
|
+
// Apply animation speed multiplier
|
|
2922
|
+
const scaledDelta = deltaTime * animationSpeed;
|
|
2923
|
+
elapsedTimeRef.current += scaledDelta, shaderTimeRef.current = elapsedTimeRef.current,
|
|
2924
|
+
// Continue animation loop
|
|
2925
|
+
animationFrameIdRef.current = requestAnimationFrame(animate);
|
|
2926
|
+
};
|
|
2927
|
+
// Start animation
|
|
2928
|
+
// Cleanup
|
|
2929
|
+
return animationStartTimeRef.current = performance.now(), animationFrameIdRef.current = requestAnimationFrame(animate),
|
|
2930
|
+
() => {
|
|
2931
|
+
null !== animationFrameIdRef.current && (cancelAnimationFrame(animationFrameIdRef.current),
|
|
2932
|
+
animationFrameIdRef.current = null);
|
|
2933
|
+
};
|
|
2934
|
+
}), [ effectiveWithTimeAnimation, animationSpeed ]);
|
|
2935
|
+
/**
|
|
2936
|
+
* Get current shader time for animations
|
|
2937
|
+
*/
|
|
2938
|
+
const getShaderTime = React.useCallback((() => shaderTimeRef.current), []), applyTimeBasedDistortion = React.useCallback((uv => effectiveWithTimeAnimation && fbmEngine ? liquidGlassWithTime(uv, shaderTimeRef.current, fbmConfig) : uv), [ effectiveWithTimeAnimation, fbmEngine, fbmConfig ]), effectiveBorderRadius = React.useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
|
|
2690
2939
|
const [glassSize, setGlassSize] = React.useState({
|
|
2691
2940
|
width: 270,
|
|
2692
2941
|
height: 69
|
|
@@ -2745,7 +2994,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2745
2994
|
glassRef: glassRef,
|
|
2746
2995
|
effectiveBorderRadius: effectiveBorderRadius,
|
|
2747
2996
|
cachedRectRef: cachedRectRef
|
|
2748
|
-
}),
|
|
2997
|
+
}), effectiveHighContrast = React.useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveWithoutEffects = React.useMemo((() => withoutEffects || effectiveReducedMotion), [ withoutEffects, effectiveReducedMotion ]), globalMousePosition = externalGlobalMousePosition || internalGlobalMousePositionRef.current, mouseOffset = externalMouseOffset || internalMouseOffsetRef.current;
|
|
2998
|
+
/**
|
|
2999
|
+
* Apply time-based distortion to UV coordinates
|
|
3000
|
+
*/
|
|
2749
3001
|
// Extract border-radius from children
|
|
2750
3002
|
React.useEffect((() => {
|
|
2751
3003
|
const extractRadius = () => {
|
|
@@ -2948,6 +3200,8 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2948
3200
|
lerpActiveRef.current = !0;
|
|
2949
3201
|
const LERP_T = CONSTANTS.LERP_FACTOR, tick = () => {
|
|
2950
3202
|
if (!lerpActiveRef.current) return;
|
|
3203
|
+
// Add ref validity check to prevent memory leaks
|
|
3204
|
+
if (!glassRef.current || !wrapperRef?.current) return void (lerpActiveRef.current = !1);
|
|
2951
3205
|
const cur = internalMouseOffsetRef.current, tgt = targetMouseOffsetRef.current, dx = tgt.x - cur.x, dy = tgt.y - cur.y;
|
|
2952
3206
|
// If we're close enough, snap and park
|
|
2953
3207
|
if (Math.abs(dx) < .05 && Math.abs(dy) < .05) internalMouseOffsetRef.current = {
|
|
@@ -2956,17 +3210,17 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2956
3210
|
...targetGlobalMousePositionRef.current
|
|
2957
3211
|
}; else {
|
|
2958
3212
|
internalMouseOffsetRef.current = {
|
|
2959
|
-
x: lerp(cur.x, tgt.x, LERP_T),
|
|
2960
|
-
y: lerp(cur.y, tgt.y, LERP_T)
|
|
3213
|
+
x: lerp$1(cur.x, tgt.x, LERP_T),
|
|
3214
|
+
y: lerp$1(cur.y, tgt.y, LERP_T)
|
|
2961
3215
|
};
|
|
2962
3216
|
const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
|
|
2963
3217
|
internalGlobalMousePositionRef.current = {
|
|
2964
|
-
x: lerp(curG.x, tgtG.x, LERP_T),
|
|
2965
|
-
y: lerp(curG.y, tgtG.y, LERP_T)
|
|
3218
|
+
x: lerp$1(curG.x, tgtG.x, LERP_T),
|
|
3219
|
+
y: lerp$1(curG.y, tgtG.y, LERP_T)
|
|
2966
3220
|
};
|
|
2967
3221
|
}
|
|
2968
3222
|
// Imperative style update with the smoothed values
|
|
2969
|
-
updateAtomixGlassStyles(wrapperRef
|
|
3223
|
+
updateAtomixGlassStyles(wrapperRef.current, glassRef.current, {
|
|
2970
3224
|
mouseOffset: internalMouseOffsetRef.current,
|
|
2971
3225
|
globalMousePosition: internalGlobalMousePositionRef.current,
|
|
2972
3226
|
glassSize: glassSize,
|
|
@@ -2983,12 +3237,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2983
3237
|
withLiquidBlur: withLiquidBlur,
|
|
2984
3238
|
blurAmount: blurAmount,
|
|
2985
3239
|
saturation: saturation,
|
|
2986
|
-
padding: padding
|
|
3240
|
+
padding: padding,
|
|
3241
|
+
isFixedOrSticky: isFixedOrSticky
|
|
2987
3242
|
}), lerpRafRef.current = requestAnimationFrame(tick);
|
|
2988
3243
|
};
|
|
2989
3244
|
// 0.08 – lower = more viscous
|
|
2990
3245
|
lerpRafRef.current = requestAnimationFrame(tick);
|
|
2991
|
-
}), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding ]), stopLerpLoop = React.useCallback((() => {
|
|
3246
|
+
}), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding, isFixedOrSticky ]), stopLerpLoop = React.useCallback((() => {
|
|
2992
3247
|
lerpActiveRef.current = !1, null !== lerpRafRef.current && (cancelAnimationFrame(lerpRafRef.current),
|
|
2993
3248
|
lerpRafRef.current = null);
|
|
2994
3249
|
}), []);
|
|
@@ -3056,6 +3311,8 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3056
3311
|
// This is now static (refs or props) unless prop changes
|
|
3057
3312
|
overLightConfig: overLightConfig,
|
|
3058
3313
|
transformStyle: transformStyle,
|
|
3314
|
+
getShaderTime: getShaderTime,
|
|
3315
|
+
applyTimeBasedDistortion: applyTimeBasedDistortion,
|
|
3059
3316
|
handleMouseEnter: handleMouseEnter,
|
|
3060
3317
|
handleMouseLeave: handleMouseLeave,
|
|
3061
3318
|
handleMouseDown: handleMouseDown,
|
|
@@ -3064,6 +3321,800 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3064
3321
|
};
|
|
3065
3322
|
}
|
|
3066
3323
|
|
|
3324
|
+
/**
|
|
3325
|
+
* Default responsive breakpoints configuration
|
|
3326
|
+
*
|
|
3327
|
+
* These breakpoints are optimized for glass effect performance across device classes:
|
|
3328
|
+
* - Mobile: Reduced complexity for 60 FPS target
|
|
3329
|
+
* - Tablet: Balanced quality and performance
|
|
3330
|
+
* - Desktop: Full fidelity effects
|
|
3331
|
+
*/ const DEFAULT_BREAKPOINTS = {
|
|
3332
|
+
mobile: {
|
|
3333
|
+
maxWidth: 640,
|
|
3334
|
+
params: {
|
|
3335
|
+
distortionOctaves: 3,
|
|
3336
|
+
displacementScale: .7,
|
|
3337
|
+
blurAmount: .8,
|
|
3338
|
+
animationSpeed: .8,
|
|
3339
|
+
chromaticIntensity: .5
|
|
3340
|
+
}
|
|
3341
|
+
},
|
|
3342
|
+
tablet: {
|
|
3343
|
+
minWidth: 641,
|
|
3344
|
+
maxWidth: 1024,
|
|
3345
|
+
params: {
|
|
3346
|
+
distortionOctaves: 4,
|
|
3347
|
+
displacementScale: .85,
|
|
3348
|
+
blurAmount: .9,
|
|
3349
|
+
animationSpeed: .9,
|
|
3350
|
+
chromaticIntensity: .75
|
|
3351
|
+
}
|
|
3352
|
+
},
|
|
3353
|
+
desktop: {
|
|
3354
|
+
minWidth: 1025,
|
|
3355
|
+
params: {
|
|
3356
|
+
distortionOctaves: 5,
|
|
3357
|
+
displacementScale: 1,
|
|
3358
|
+
blurAmount: 1,
|
|
3359
|
+
animationSpeed: 1,
|
|
3360
|
+
chromaticIntensity: 1
|
|
3361
|
+
}
|
|
3362
|
+
}
|
|
3363
|
+
};
|
|
3364
|
+
|
|
3365
|
+
/**
|
|
3366
|
+
* Device performance tier detection
|
|
3367
|
+
*
|
|
3368
|
+
* Uses Device Memory API and Hardware Concurrency API to classify devices
|
|
3369
|
+
* into performance tiers for automatic quality adjustment.
|
|
3370
|
+
*
|
|
3371
|
+
* @returns Performance tier classification
|
|
3372
|
+
*/
|
|
3373
|
+
/**
|
|
3374
|
+
* Responsive Glass Parameters Hook
|
|
3375
|
+
*
|
|
3376
|
+
* Automatically adjusts glass effect parameters based on:
|
|
3377
|
+
* 1. Screen size (mobile/tablet/desktop breakpoints)
|
|
3378
|
+
* 2. Device performance (RAM and CPU detection)
|
|
3379
|
+
* 3. Custom breakpoint configuration
|
|
3380
|
+
*
|
|
3381
|
+
* Features:
|
|
3382
|
+
* - Debounced resize handling
|
|
3383
|
+
* - Performance-based quality adjustment
|
|
3384
|
+
* - Smooth parameter transitions
|
|
3385
|
+
* - Debug mode for development
|
|
3386
|
+
*
|
|
3387
|
+
* @example
|
|
3388
|
+
* ```typescript
|
|
3389
|
+
* const { responsiveParams, currentBreakpoint } = useResponsiveGlass({
|
|
3390
|
+
* baseParams: {
|
|
3391
|
+
* distortionOctaves: 5,
|
|
3392
|
+
* displacementScale: 20,
|
|
3393
|
+
* blurAmount: 10,
|
|
3394
|
+
* },
|
|
3395
|
+
* debug: true,
|
|
3396
|
+
* });
|
|
3397
|
+
* ```
|
|
3398
|
+
*
|
|
3399
|
+
* @param options Hook configuration options
|
|
3400
|
+
* @returns Responsive parameters and metadata
|
|
3401
|
+
*/
|
|
3402
|
+
function useResponsiveGlass({baseParams: baseParams, breakpoints: breakpoints = DEFAULT_BREAKPOINTS, enabled: enabled = !0, enablePerformanceAdjustment: enablePerformanceAdjustment = !0, debug: debug = !1}) {
|
|
3403
|
+
const [responsiveParams, setResponsiveParams] = React.useState(baseParams), [currentBreakpoint, setCurrentBreakpoint] = React.useState("desktop"), [performanceTier, setPerformanceTier] = React.useState("high"), [isActive, setIsActive] = React.useState(enabled), baseParamsRef = React.useRef(baseParams), breakpointsRef = React.useRef(breakpoints);
|
|
3404
|
+
// Update refs when props change
|
|
3405
|
+
baseParamsRef.current = baseParams, breakpointsRef.current = breakpoints;
|
|
3406
|
+
/**
|
|
3407
|
+
* Calculate and apply responsive parameters
|
|
3408
|
+
*/
|
|
3409
|
+
const calculateParams = React.useCallback((() => {
|
|
3410
|
+
if (!enabled || "undefined" == typeof window) return setIsActive(!1), setResponsiveParams(baseParamsRef.current),
|
|
3411
|
+
void setCurrentBreakpoint("disabled");
|
|
3412
|
+
setIsActive(!0);
|
|
3413
|
+
// Get current screen width
|
|
3414
|
+
const width = window.innerWidth, {name: name, params: breakpointParams} = ((width, breakpoints) => {
|
|
3415
|
+
// Convert breakpoints to array and sort by minWidth descending
|
|
3416
|
+
const sortedBreakpoints = Object.entries(breakpoints).filter((([_, bp]) => void 0 !== bp.minWidth)).sort(((a, b) => (b[1].minWidth || 0) - (a[1].minWidth || 0)));
|
|
3417
|
+
// Find first breakpoint where width >= minWidth
|
|
3418
|
+
for (const [name, bp] of sortedBreakpoints) if (width >= (bp.minWidth || 0)) return {
|
|
3419
|
+
name: name,
|
|
3420
|
+
params: bp.params
|
|
3421
|
+
};
|
|
3422
|
+
// If no minWidth matched, check maxWidth breakpoints
|
|
3423
|
+
const maxWidthBreakpoints = Object.entries(breakpoints).filter((([_, bp]) => void 0 !== bp.maxWidth)).sort(((a, b) => (a[1].maxWidth || 1 / 0) - (b[1].maxWidth || 1 / 0)));
|
|
3424
|
+
for (const [name, bp] of maxWidthBreakpoints) if (width <= (bp.maxWidth || 1 / 0)) return {
|
|
3425
|
+
name: name,
|
|
3426
|
+
params: bp.params
|
|
3427
|
+
};
|
|
3428
|
+
// Fallback to first available breakpoint
|
|
3429
|
+
const entries = Object.entries(breakpoints);
|
|
3430
|
+
if (0 === entries.length)
|
|
3431
|
+
// Ultimate fallback - return sensible defaults
|
|
3432
|
+
return {
|
|
3433
|
+
name: "desktop",
|
|
3434
|
+
params: {
|
|
3435
|
+
distortionOctaves: 5,
|
|
3436
|
+
displacementScale: 1,
|
|
3437
|
+
blurAmount: 1
|
|
3438
|
+
}
|
|
3439
|
+
};
|
|
3440
|
+
const firstEntry = entries[0];
|
|
3441
|
+
if (!firstEntry) return {
|
|
3442
|
+
name: "desktop",
|
|
3443
|
+
params: {
|
|
3444
|
+
distortionOctaves: 5,
|
|
3445
|
+
displacementScale: 1,
|
|
3446
|
+
blurAmount: 1
|
|
3447
|
+
}
|
|
3448
|
+
};
|
|
3449
|
+
const [fallbackName, fallbackBreakpoint] = firstEntry;
|
|
3450
|
+
return {
|
|
3451
|
+
name: fallbackName,
|
|
3452
|
+
params: fallbackBreakpoint.params
|
|
3453
|
+
};
|
|
3454
|
+
})(width, breakpointsRef.current);
|
|
3455
|
+
// Determine current breakpoint
|
|
3456
|
+
setCurrentBreakpoint(name);
|
|
3457
|
+
// Merge base params with breakpoint params
|
|
3458
|
+
let mergedParams = ((baseParams, breakpointParams) => {
|
|
3459
|
+
const result = {
|
|
3460
|
+
...baseParams
|
|
3461
|
+
}, scaleProperties = [ "displacementScale", "blurAmount", "saturation", "aberrationIntensity", "animationSpeed", "chromaticIntensity" ];
|
|
3462
|
+
// Apply scaling for specific properties
|
|
3463
|
+
for (const prop of scaleProperties) void 0 !== breakpointParams[prop] && void 0 !== baseParams[prop] && (result[prop] = baseParams[prop] * breakpointParams[prop]);
|
|
3464
|
+
// Override properties that should be set directly (not scaled)
|
|
3465
|
+
const overrideProperties = [ "distortionOctaves", "distortionLacunarity", "distortionGain" ];
|
|
3466
|
+
for (const prop of overrideProperties) void 0 !== breakpointParams[prop] && (result[prop] = breakpointParams[prop]);
|
|
3467
|
+
return result;
|
|
3468
|
+
})(baseParamsRef.current, breakpointParams);
|
|
3469
|
+
// Apply performance adjustments if enabled
|
|
3470
|
+
if (enablePerformanceAdjustment) {
|
|
3471
|
+
const tier = (() => {
|
|
3472
|
+
// Check if we're in a browser environment
|
|
3473
|
+
if ("undefined" == typeof window || "undefined" == typeof navigator) return "high"; // Default to high for SSR
|
|
3474
|
+
// Device Memory API (Chrome, Edge, Opera)
|
|
3475
|
+
// Returns RAM in GB: 0.25, 0.5, 1, 2, 4, 8
|
|
3476
|
+
const deviceMemory = navigator.deviceMemory || 4, hardwareConcurrency = navigator.hardwareConcurrency || 4;
|
|
3477
|
+
// Hardware Concurrency API (logical CPU cores)
|
|
3478
|
+
// Low-end: ≤2GB RAM OR ≤2 CPU cores
|
|
3479
|
+
return deviceMemory <= 2 || hardwareConcurrency <= 2 ? "low" :
|
|
3480
|
+
// High-end: ≥4GB RAM AND ≥4 CPU cores
|
|
3481
|
+
deviceMemory >= 4 && hardwareConcurrency >= 4 ? "high" : "medium";
|
|
3482
|
+
})();
|
|
3483
|
+
setPerformanceTier(tier), mergedParams = ((baseParams, performanceTier) => {
|
|
3484
|
+
if ("high" === performanceTier) return baseParams;
|
|
3485
|
+
// No adjustment needed
|
|
3486
|
+
const multiplier = "low" === performanceTier ? .7 : .85;
|
|
3487
|
+
return {
|
|
3488
|
+
...baseParams,
|
|
3489
|
+
distortionOctaves: Math.max(2, Math.round((baseParams.distortionOctaves || 5) * multiplier)),
|
|
3490
|
+
displacementScale: (baseParams.displacementScale || 1) * multiplier,
|
|
3491
|
+
blurAmount: (baseParams.blurAmount || 1) * multiplier,
|
|
3492
|
+
animationSpeed: (baseParams.animationSpeed || 1) * multiplier,
|
|
3493
|
+
chromaticIntensity: (baseParams.chromaticIntensity || 1) * multiplier
|
|
3494
|
+
};
|
|
3495
|
+
})(mergedParams, tier);
|
|
3496
|
+
}
|
|
3497
|
+
setResponsiveParams(mergedParams);
|
|
3498
|
+
}), [ enabled, enablePerformanceAdjustment, debug ]), debouncedCalculate = (func => {
|
|
3499
|
+
const timeoutRef = React.useRef(null);
|
|
3500
|
+
return React.useEffect((() => () => {
|
|
3501
|
+
timeoutRef.current && clearTimeout(timeoutRef.current);
|
|
3502
|
+
}), []), React.useCallback(((...args) => {
|
|
3503
|
+
timeoutRef.current && clearTimeout(timeoutRef.current), timeoutRef.current = setTimeout((() => {
|
|
3504
|
+
func(...args);
|
|
3505
|
+
}), 200);
|
|
3506
|
+
}), [ func, 200 ]);
|
|
3507
|
+
})(calculateParams);
|
|
3508
|
+
/**
|
|
3509
|
+
* Debounced parameter calculation for resize events
|
|
3510
|
+
*/
|
|
3511
|
+
/**
|
|
3512
|
+
* Handle window resize
|
|
3513
|
+
*/
|
|
3514
|
+
return React.useEffect((() => {
|
|
3515
|
+
if (enabled)
|
|
3516
|
+
// Cleanup
|
|
3517
|
+
// Initial calculation
|
|
3518
|
+
return calculateParams(),
|
|
3519
|
+
// Listen for resize events
|
|
3520
|
+
window.addEventListener("resize", debouncedCalculate), () => {
|
|
3521
|
+
window.removeEventListener("resize", debouncedCalculate);
|
|
3522
|
+
};
|
|
3523
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3524
|
+
}), [ enabled ]), {
|
|
3525
|
+
responsiveParams: responsiveParams,
|
|
3526
|
+
currentBreakpoint: currentBreakpoint,
|
|
3527
|
+
performanceTier: performanceTier,
|
|
3528
|
+
isActive: isActive,
|
|
3529
|
+
recalculate: React.useCallback((() => {
|
|
3530
|
+
calculateParams();
|
|
3531
|
+
}), [ calculateParams ])
|
|
3532
|
+
};
|
|
3533
|
+
}
|
|
3534
|
+
|
|
3535
|
+
/**
|
|
3536
|
+
* Utility function to get default breakpoints
|
|
3537
|
+
* Useful for documentation and debugging
|
|
3538
|
+
*/ function getDefaultBreakpoints() {
|
|
3539
|
+
return {
|
|
3540
|
+
...DEFAULT_BREAKPOINTS
|
|
3541
|
+
};
|
|
3542
|
+
}
|
|
3543
|
+
|
|
3544
|
+
/**
|
|
3545
|
+
* Utility function to create custom breakpoints
|
|
3546
|
+
*
|
|
3547
|
+
* @param customBreakpoints Partial breakpoint overrides
|
|
3548
|
+
* @returns Complete breakpoint configuration
|
|
3549
|
+
*/ function createBreakpoints$1(customBreakpoints) {
|
|
3550
|
+
return {
|
|
3551
|
+
...DEFAULT_BREAKPOINTS,
|
|
3552
|
+
...customBreakpoints
|
|
3553
|
+
};
|
|
3554
|
+
}
|
|
3555
|
+
|
|
3556
|
+
/**
|
|
3557
|
+
* Get GPU memory info if available (Chrome DevTools only)
|
|
3558
|
+
*/
|
|
3559
|
+
/**
|
|
3560
|
+
* Performance Monitor Hook
|
|
3561
|
+
*
|
|
3562
|
+
* Real-time performance tracking with automatic quality scaling.
|
|
3563
|
+
* Monitors FPS, frame time, and GPU memory to optimize glass effects.
|
|
3564
|
+
*
|
|
3565
|
+
* Features:
|
|
3566
|
+
* - Real-time FPS measurement
|
|
3567
|
+
* - Frame timing analysis
|
|
3568
|
+
* - Automatic quality scaling
|
|
3569
|
+
* - Debug overlay option
|
|
3570
|
+
* - Manual override capability
|
|
3571
|
+
*
|
|
3572
|
+
* @example
|
|
3573
|
+
* ```typescript
|
|
3574
|
+
* const { metrics, recommendedQuality, setQualityLevel } = usePerformanceMonitor({
|
|
3575
|
+
* targetFps: 60,
|
|
3576
|
+
* minFps: 45,
|
|
3577
|
+
* debug: true,
|
|
3578
|
+
* });
|
|
3579
|
+
* ```
|
|
3580
|
+
*
|
|
3581
|
+
* @param config Monitor configuration
|
|
3582
|
+
* @returns Performance metrics and controls
|
|
3583
|
+
*/
|
|
3584
|
+
function usePerformanceMonitor(config = {}) {
|
|
3585
|
+
const {enabled: enabled = !0, targetFps: targetFps = 60, minFps: minFps = 45, scaleUpThreshold: scaleUpThreshold = 58, lowFpsFrames: lowFpsFrames = 3, highFpsFrames: highFpsFrames = 10, debug: debug = !1, showOverlay: showOverlay = !1} = config, [metrics, setMetrics] = React.useState({
|
|
3586
|
+
fps: 0,
|
|
3587
|
+
frameTime: 0,
|
|
3588
|
+
gpuMemory: null,
|
|
3589
|
+
qualityLevel: "medium",
|
|
3590
|
+
timestamp: 0,
|
|
3591
|
+
isAutoScaling: !0,
|
|
3592
|
+
lowFpsCount: 0
|
|
3593
|
+
}), [manualOverride, setManualOverride] = React.useState(!1), [isEnabled, setIsEnabled] = React.useState(enabled), frameCountRef = React.useRef(0), lastFpsUpdateRef = React.useRef(0), lastFrameTimeRef = React.useRef(0), animationFrameRef = React.useRef(null), lowFpsCountRef = React.useRef(0), highFpsCountRef = React.useRef(0), qualityLevelRef = React.useRef("medium"), updateMetrics = React.useCallback((newMetrics => {
|
|
3594
|
+
setMetrics((prev => ({
|
|
3595
|
+
...prev,
|
|
3596
|
+
...newMetrics,
|
|
3597
|
+
timestamp: performance.now()
|
|
3598
|
+
})));
|
|
3599
|
+
}), []), applyAutoScaling = React.useCallback((currentFps => {
|
|
3600
|
+
if (manualOverride) return;
|
|
3601
|
+
const currentQuality = qualityLevelRef.current;
|
|
3602
|
+
// Check for low FPS
|
|
3603
|
+
if (currentFps < minFps) lowFpsCountRef.current++, highFpsCountRef.current = 0,
|
|
3604
|
+
// Scale down after N consecutive low-FPS frames
|
|
3605
|
+
lowFpsCountRef.current >= lowFpsFrames && "low" !== currentQuality && (qualityLevelRef.current = "low",
|
|
3606
|
+
updateMetrics({
|
|
3607
|
+
qualityLevel: "low",
|
|
3608
|
+
lowFpsCount: lowFpsCountRef.current
|
|
3609
|
+
})); else if (currentFps >= scaleUpThreshold) {
|
|
3610
|
+
// Scale up after N consecutive high-FPS frames
|
|
3611
|
+
if (highFpsCountRef.current++, lowFpsCountRef.current = 0, highFpsCountRef.current >= highFpsFrames) {
|
|
3612
|
+
const newQuality = "low" === currentQuality ? "medium" : "high";
|
|
3613
|
+
qualityLevelRef.current = newQuality, updateMetrics({
|
|
3614
|
+
qualityLevel: newQuality,
|
|
3615
|
+
lowFpsCount: 0
|
|
3616
|
+
}), highFpsCountRef.current = 0;
|
|
3617
|
+
}
|
|
3618
|
+
} else
|
|
3619
|
+
// FPS in normal range, reset counters
|
|
3620
|
+
lowFpsCountRef.current = 0, highFpsCountRef.current = 0;
|
|
3621
|
+
}), [ manualOverride, minFps, scaleUpThreshold, lowFpsFrames, highFpsFrames, debug, updateMetrics ]), measureFrame = React.useCallback((currentTime => {
|
|
3622
|
+
if (!isEnabled) return;
|
|
3623
|
+
frameCountRef.current++;
|
|
3624
|
+
// Calculate frame time
|
|
3625
|
+
const frameTime = currentTime - lastFrameTimeRef.current;
|
|
3626
|
+
// Update FPS every 100ms for responsiveness
|
|
3627
|
+
if (lastFrameTimeRef.current = currentTime, currentTime - lastFpsUpdateRef.current >= 100) {
|
|
3628
|
+
const elapsed = currentTime - lastFpsUpdateRef.current, fps = Math.round(1e3 * frameCountRef.current / elapsed);
|
|
3629
|
+
// Apply auto-scaling
|
|
3630
|
+
applyAutoScaling(fps), updateMetrics({
|
|
3631
|
+
fps: fps,
|
|
3632
|
+
frameTime: frameTime,
|
|
3633
|
+
qualityLevel: qualityLevelRef.current,
|
|
3634
|
+
lowFpsCount: lowFpsCountRef.current
|
|
3635
|
+
}),
|
|
3636
|
+
// Reset for next measurement period
|
|
3637
|
+
frameCountRef.current = 0, lastFpsUpdateRef.current = currentTime;
|
|
3638
|
+
}
|
|
3639
|
+
// Continue measurement loop
|
|
3640
|
+
animationFrameRef.current = requestAnimationFrame(measureFrame);
|
|
3641
|
+
}), [ isEnabled, applyAutoScaling, updateMetrics ]);
|
|
3642
|
+
/**
|
|
3643
|
+
* Initialize GPU memory tracking
|
|
3644
|
+
*/
|
|
3645
|
+
React.useEffect((() => {
|
|
3646
|
+
if (!isEnabled || "undefined" == typeof window) return;
|
|
3647
|
+
let mounted = !0;
|
|
3648
|
+
return (async () => {
|
|
3649
|
+
const memory = await new Promise((resolve => {
|
|
3650
|
+
// Check for WebGL debug renderer info
|
|
3651
|
+
if ("undefined" != typeof window && "undefined" != typeof document) try {
|
|
3652
|
+
const canvas = document.createElement("canvas"), gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
|
|
3653
|
+
if (gl) {
|
|
3654
|
+
const debugInfo = gl.getExtension("WEBGL_debug_renderer_info");
|
|
3655
|
+
if (debugInfo) {
|
|
3656
|
+
var _context, _context2, _context3;
|
|
3657
|
+
// Note: Actual memory info is not directly available via WebGL
|
|
3658
|
+
// We estimate based on renderer
|
|
3659
|
+
const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
|
|
3660
|
+
// Rough estimation based on renderer type
|
|
3661
|
+
return void ((null == (_context = renderer) ? void 0 : Function.call.bind(_includesInstanceProperty(_context), _context))?.("Integrated") ? resolve(256) : (null == (_context2 = renderer) ? void 0 : Function.call.bind(_includesInstanceProperty(_context2), _context2))?.("AMD") || (null == (_context3 = renderer) ? void 0 : Function.call.bind(_includesInstanceProperty(_context3), _context3))?.("NVIDIA") ? resolve(512) : resolve(null));
|
|
3662
|
+
}
|
|
3663
|
+
}
|
|
3664
|
+
} catch (e) {
|
|
3665
|
+
// WebGL not available or error occurred
|
|
3666
|
+
}
|
|
3667
|
+
resolve(null);
|
|
3668
|
+
}));
|
|
3669
|
+
mounted && updateMetrics({
|
|
3670
|
+
gpuMemory: memory
|
|
3671
|
+
});
|
|
3672
|
+
})(), () => {
|
|
3673
|
+
mounted = !1;
|
|
3674
|
+
};
|
|
3675
|
+
}), [ isEnabled, updateMetrics ]),
|
|
3676
|
+
/**
|
|
3677
|
+
* Start/stop monitoring based on enabled state
|
|
3678
|
+
*/
|
|
3679
|
+
React.useEffect((() => {
|
|
3680
|
+
if (isEnabled)
|
|
3681
|
+
// Cleanup
|
|
3682
|
+
// Initialize
|
|
3683
|
+
return lastFpsUpdateRef.current = performance.now(), lastFrameTimeRef.current = performance.now(),
|
|
3684
|
+
animationFrameRef.current = requestAnimationFrame(measureFrame), () => {
|
|
3685
|
+
null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
|
|
3686
|
+
animationFrameRef.current = null);
|
|
3687
|
+
};
|
|
3688
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3689
|
+
null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
|
|
3690
|
+
animationFrameRef.current = null);
|
|
3691
|
+
}), [ isEnabled ]);
|
|
3692
|
+
// measureFrame is stable via useCallback, avoid re-creating RAF loop
|
|
3693
|
+
/**
|
|
3694
|
+
* Manually set quality level (disables auto-scaling)
|
|
3695
|
+
*/
|
|
3696
|
+
const setQualityLevel = React.useCallback((level => {
|
|
3697
|
+
setManualOverride(!0), qualityLevelRef.current = level, updateMetrics({
|
|
3698
|
+
qualityLevel: level,
|
|
3699
|
+
isAutoScaling: !1
|
|
3700
|
+
});
|
|
3701
|
+
}), [ updateMetrics, debug ]), resetAutoScaling = React.useCallback((() => {
|
|
3702
|
+
setManualOverride(!1), lowFpsCountRef.current = 0, highFpsCountRef.current = 0,
|
|
3703
|
+
updateMetrics({
|
|
3704
|
+
isAutoScaling: !0,
|
|
3705
|
+
lowFpsCount: 0
|
|
3706
|
+
});
|
|
3707
|
+
}), [ updateMetrics, debug ]), toggleMonitoring = React.useCallback((() => {
|
|
3708
|
+
setIsEnabled((prev => !prev));
|
|
3709
|
+
}), []);
|
|
3710
|
+
/**
|
|
3711
|
+
* Reset to auto-scaling mode
|
|
3712
|
+
*/ var fps, currentQuality;
|
|
3713
|
+
return {
|
|
3714
|
+
metrics: metrics,
|
|
3715
|
+
recommendedQuality: (fps = metrics.fps, currentQuality = metrics.qualityLevel, fps >= 58 ? "high" : fps >= 45 ? "high" === currentQuality ? "high" : "medium" : "low"),
|
|
3716
|
+
isUnderperforming: metrics.fps < minFps,
|
|
3717
|
+
setQualityLevel: setQualityLevel,
|
|
3718
|
+
resetAutoScaling: resetAutoScaling,
|
|
3719
|
+
toggleMonitoring: toggleMonitoring
|
|
3720
|
+
};
|
|
3721
|
+
}
|
|
3722
|
+
|
|
3723
|
+
/**
|
|
3724
|
+
* Debug Overlay Component (Optional)
|
|
3725
|
+
*
|
|
3726
|
+
* Shows real-time performance metrics on screen.
|
|
3727
|
+
* Only rendered when showOverlay is enabled.
|
|
3728
|
+
*/ function PerformanceOverlay({metrics: metrics}) {
|
|
3729
|
+
return null;
|
|
3730
|
+
// Performance overlay removed - will be implemented as separate component
|
|
3731
|
+
}
|
|
3732
|
+
|
|
3733
|
+
/**
|
|
3734
|
+
* Utility to get quality multipliers for glass parameters
|
|
3735
|
+
*/ function getQualityMultipliers(quality) {
|
|
3736
|
+
switch (quality) {
|
|
3737
|
+
case "low":
|
|
3738
|
+
return {
|
|
3739
|
+
distortionOctaves: 2,
|
|
3740
|
+
displacementScale: .6,
|
|
3741
|
+
blurAmount: .7,
|
|
3742
|
+
animationSpeed: .8,
|
|
3743
|
+
chromaticIntensity: .5
|
|
3744
|
+
};
|
|
3745
|
+
|
|
3746
|
+
case "medium":
|
|
3747
|
+
return {
|
|
3748
|
+
distortionOctaves: 4,
|
|
3749
|
+
displacementScale: .85,
|
|
3750
|
+
blurAmount: .9,
|
|
3751
|
+
animationSpeed: .95,
|
|
3752
|
+
chromaticIntensity: .75
|
|
3753
|
+
};
|
|
3754
|
+
|
|
3755
|
+
case "high":
|
|
3756
|
+
return {
|
|
3757
|
+
distortionOctaves: 5,
|
|
3758
|
+
displacementScale: 1,
|
|
3759
|
+
blurAmount: 1,
|
|
3760
|
+
animationSpeed: 1,
|
|
3761
|
+
chromaticIntensity: 1
|
|
3762
|
+
};
|
|
3763
|
+
}
|
|
3764
|
+
}
|
|
3765
|
+
|
|
3766
|
+
/**
|
|
3767
|
+
* PerformanceDashboard - Real-time performance monitoring overlay
|
|
3768
|
+
*
|
|
3769
|
+
* Displays:
|
|
3770
|
+
* - Current FPS with color coding
|
|
3771
|
+
* - Frame time statistics
|
|
3772
|
+
* - Quality level indicator
|
|
3773
|
+
* - GPU memory usage (if available)
|
|
3774
|
+
* - Auto-scaling status
|
|
3775
|
+
*/ const PerformanceDashboard = ({metrics: metrics, isVisible: isVisible = !0, onClose: onClose}) => {
|
|
3776
|
+
// Get color for FPS display
|
|
3777
|
+
const getFpsColor = fps => fps >= 58 ? "#4ade80" : // Green - good
|
|
3778
|
+
fps >= 45 ? "#fbbf24" : "#ef4444" // Red - critical
|
|
3779
|
+
, dashboardStyle = React.useMemo((() => ({
|
|
3780
|
+
position: "fixed",
|
|
3781
|
+
top: "16px",
|
|
3782
|
+
right: "16px",
|
|
3783
|
+
padding: "12px 16px",
|
|
3784
|
+
backgroundColor: "rgba(17, 24, 39, 0.95)",
|
|
3785
|
+
borderRadius: "8px",
|
|
3786
|
+
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
|
|
3787
|
+
fontFamily: "monospace",
|
|
3788
|
+
fontSize: "12px",
|
|
3789
|
+
color: "#fff",
|
|
3790
|
+
zIndex: 9999,
|
|
3791
|
+
minWidth: "200px",
|
|
3792
|
+
backdropFilter: "blur(8px)",
|
|
3793
|
+
border: "1px solid rgba(255, 255, 255, 0.1)",
|
|
3794
|
+
transition: "opacity 0.3s ease",
|
|
3795
|
+
opacity: isVisible ? 1 : 0,
|
|
3796
|
+
pointerEvents: isVisible ? "auto" : "none"
|
|
3797
|
+
})), [ isVisible ]), headerStyle = React.useMemo((() => ({
|
|
3798
|
+
display: "flex",
|
|
3799
|
+
justifyContent: "space-between",
|
|
3800
|
+
alignItems: "center",
|
|
3801
|
+
marginBottom: "8px",
|
|
3802
|
+
paddingBottom: "8px",
|
|
3803
|
+
borderBottom: "1px solid rgba(255, 255, 255, 0.1)"
|
|
3804
|
+
})), []), titleStyle = React.useMemo((() => ({
|
|
3805
|
+
fontWeight: "bold",
|
|
3806
|
+
fontSize: "13px",
|
|
3807
|
+
color: "#fff"
|
|
3808
|
+
})), []), closeButtonStyle = React.useMemo((() => ({
|
|
3809
|
+
background: "transparent",
|
|
3810
|
+
border: "none",
|
|
3811
|
+
color: "#9ca3af",
|
|
3812
|
+
cursor: "pointer",
|
|
3813
|
+
fontSize: "16px",
|
|
3814
|
+
padding: "0",
|
|
3815
|
+
lineHeight: "1"
|
|
3816
|
+
})), []), metricRowStyle = React.useMemo((() => ({
|
|
3817
|
+
display: "flex",
|
|
3818
|
+
justifyContent: "space-between",
|
|
3819
|
+
alignItems: "center",
|
|
3820
|
+
marginBottom: "6px"
|
|
3821
|
+
})), []), labelStyle = React.useMemo((() => ({
|
|
3822
|
+
color: "#9ca3af",
|
|
3823
|
+
marginRight: "12px"
|
|
3824
|
+
})), []), valueStyle = React.useMemo((() => ({
|
|
3825
|
+
fontWeight: "bold"
|
|
3826
|
+
})), []);
|
|
3827
|
+
// Get quality level badge color
|
|
3828
|
+
return isVisible ? jsxRuntime.jsxs("div", {
|
|
3829
|
+
style: dashboardStyle,
|
|
3830
|
+
children: [ jsxRuntime.jsxs("div", {
|
|
3831
|
+
style: headerStyle,
|
|
3832
|
+
children: [ jsxRuntime.jsx("span", {
|
|
3833
|
+
style: titleStyle,
|
|
3834
|
+
children: "Performance Monitor"
|
|
3835
|
+
}), onClose && jsxRuntime.jsx("button", {
|
|
3836
|
+
style: closeButtonStyle,
|
|
3837
|
+
onClick: onClose,
|
|
3838
|
+
"aria-label": "Close performance dashboard",
|
|
3839
|
+
children: "×"
|
|
3840
|
+
}) ]
|
|
3841
|
+
}), jsxRuntime.jsxs("div", {
|
|
3842
|
+
style: metricRowStyle,
|
|
3843
|
+
children: [ jsxRuntime.jsx("span", {
|
|
3844
|
+
style: labelStyle,
|
|
3845
|
+
children: "FPS"
|
|
3846
|
+
}), jsxRuntime.jsx("span", {
|
|
3847
|
+
style: {
|
|
3848
|
+
...valueStyle,
|
|
3849
|
+
color: getFpsColor(metrics.fps)
|
|
3850
|
+
},
|
|
3851
|
+
children: Math.round(metrics.fps)
|
|
3852
|
+
}) ]
|
|
3853
|
+
}), jsxRuntime.jsxs("div", {
|
|
3854
|
+
style: metricRowStyle,
|
|
3855
|
+
children: [ jsxRuntime.jsx("span", {
|
|
3856
|
+
style: labelStyle,
|
|
3857
|
+
children: "Frame Time"
|
|
3858
|
+
}), jsxRuntime.jsxs("span", {
|
|
3859
|
+
style: valueStyle,
|
|
3860
|
+
children: [ metrics.frameTime.toFixed(2), "ms" ]
|
|
3861
|
+
}) ]
|
|
3862
|
+
}), jsxRuntime.jsxs("div", {
|
|
3863
|
+
style: metricRowStyle,
|
|
3864
|
+
children: [ jsxRuntime.jsx("span", {
|
|
3865
|
+
style: labelStyle,
|
|
3866
|
+
children: "Quality"
|
|
3867
|
+
}), jsxRuntime.jsx("span", {
|
|
3868
|
+
style: {
|
|
3869
|
+
...valueStyle,
|
|
3870
|
+
color: (quality => {
|
|
3871
|
+
switch (quality) {
|
|
3872
|
+
case "high":
|
|
3873
|
+
return "#4ade80";
|
|
3874
|
+
|
|
3875
|
+
case "medium":
|
|
3876
|
+
return "#fbbf24";
|
|
3877
|
+
|
|
3878
|
+
case "low":
|
|
3879
|
+
return "#ef4444";
|
|
3880
|
+
|
|
3881
|
+
default:
|
|
3882
|
+
return "#9ca3af";
|
|
3883
|
+
}
|
|
3884
|
+
})(metrics.qualityLevel),
|
|
3885
|
+
textTransform: "uppercase",
|
|
3886
|
+
fontSize: "11px"
|
|
3887
|
+
},
|
|
3888
|
+
children: metrics.qualityLevel
|
|
3889
|
+
}) ]
|
|
3890
|
+
}), metrics.gpuMemory && jsxRuntime.jsxs("div", {
|
|
3891
|
+
style: metricRowStyle,
|
|
3892
|
+
children: [ jsxRuntime.jsx("span", {
|
|
3893
|
+
style: labelStyle,
|
|
3894
|
+
children: "GPU Memory"
|
|
3895
|
+
}), jsxRuntime.jsxs("span", {
|
|
3896
|
+
style: valueStyle,
|
|
3897
|
+
children: [ "~", Math.round(metrics.gpuMemory / 1024), "MB" ]
|
|
3898
|
+
}) ]
|
|
3899
|
+
}), metrics.isAutoScaling && jsxRuntime.jsx("div", {
|
|
3900
|
+
style: {
|
|
3901
|
+
marginTop: "8px",
|
|
3902
|
+
paddingTop: "8px",
|
|
3903
|
+
borderTop: "1px solid rgba(255, 255, 255, 0.1)",
|
|
3904
|
+
fontSize: "10px",
|
|
3905
|
+
color: "#6b7280",
|
|
3906
|
+
textAlign: "center"
|
|
3907
|
+
},
|
|
3908
|
+
children: "Auto-scaling active"
|
|
3909
|
+
}), jsxRuntime.jsxs("div", {
|
|
3910
|
+
style: {
|
|
3911
|
+
marginTop: "8px",
|
|
3912
|
+
paddingTop: "8px",
|
|
3913
|
+
borderTop: "1px solid rgba(255, 255, 255, 0.1)",
|
|
3914
|
+
display: "flex",
|
|
3915
|
+
alignItems: "center",
|
|
3916
|
+
gap: "6px"
|
|
3917
|
+
},
|
|
3918
|
+
children: [ jsxRuntime.jsx("div", {
|
|
3919
|
+
style: {
|
|
3920
|
+
width: "8px",
|
|
3921
|
+
height: "8px",
|
|
3922
|
+
borderRadius: "50%",
|
|
3923
|
+
backgroundColor: getFpsColor(metrics.fps),
|
|
3924
|
+
animation: metrics.fps < 45 ? "pulse 1s infinite" : "none"
|
|
3925
|
+
}
|
|
3926
|
+
}), jsxRuntime.jsx("span", {
|
|
3927
|
+
style: {
|
|
3928
|
+
fontSize: "10px",
|
|
3929
|
+
color: metrics.fps >= 58 ? "#4ade80" : metrics.fps >= 45 ? "#fbbf24" : "#ef4444"
|
|
3930
|
+
},
|
|
3931
|
+
children: metrics.fps >= 58 ? "Optimal" : metrics.fps >= 45 ? "Warning" : "Critical"
|
|
3932
|
+
}) ]
|
|
3933
|
+
}) ]
|
|
3934
|
+
}) : null;
|
|
3935
|
+
};
|
|
3936
|
+
|
|
3937
|
+
// Add pulse animation for critical FPS
|
|
3938
|
+
if ("undefined" != typeof document) {
|
|
3939
|
+
const styleSheet = document.createElement("style");
|
|
3940
|
+
styleSheet.textContent = "\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n ",
|
|
3941
|
+
document.head.appendChild(styleSheet);
|
|
3942
|
+
}
|
|
3943
|
+
|
|
3944
|
+
/**
|
|
3945
|
+
* Mobile optimization presets
|
|
3946
|
+
*
|
|
3947
|
+
* These presets adjust glass effect parameters based on device performance tier
|
|
3948
|
+
* to ensure smooth animations and responsive interactions.
|
|
3949
|
+
*/
|
|
3950
|
+
/**
|
|
3951
|
+
* Performance preset - Maximum FPS, reduced quality
|
|
3952
|
+
* Best for low-end devices or when battery saving is priority
|
|
3953
|
+
*/ const PERFORMANCE_PRESET = {
|
|
3954
|
+
distortionOctaves: 2,
|
|
3955
|
+
// Minimal FBM layers
|
|
3956
|
+
displacementScale: 50,
|
|
3957
|
+
// Subtle displacement
|
|
3958
|
+
blurAmount: 5,
|
|
3959
|
+
// Light blur
|
|
3960
|
+
saturation: 80,
|
|
3961
|
+
// Reduced saturation
|
|
3962
|
+
aberrationIntensity: .3,
|
|
3963
|
+
// Minimal chromatic aberration
|
|
3964
|
+
animationSpeed: .8,
|
|
3965
|
+
// Slightly slower for performance
|
|
3966
|
+
chromaticIntensity: .3,
|
|
3967
|
+
// Low chromatic effect
|
|
3968
|
+
distortionLacunarity: 1.5,
|
|
3969
|
+
// Simpler noise pattern
|
|
3970
|
+
distortionGain: .3
|
|
3971
|
+
}, BALANCED_PRESET = {
|
|
3972
|
+
distortionOctaves: 3,
|
|
3973
|
+
// Moderate FBM layers
|
|
3974
|
+
displacementScale: 75,
|
|
3975
|
+
// Medium displacement
|
|
3976
|
+
blurAmount: 8,
|
|
3977
|
+
// Moderate blur
|
|
3978
|
+
saturation: 90,
|
|
3979
|
+
// Near-full saturation
|
|
3980
|
+
aberrationIntensity: .5,
|
|
3981
|
+
// Moderate chromatic aberration
|
|
3982
|
+
animationSpeed: 1,
|
|
3983
|
+
// Normal speed
|
|
3984
|
+
chromaticIntensity: .5,
|
|
3985
|
+
// Moderate chromatic effect
|
|
3986
|
+
distortionLacunarity: 2,
|
|
3987
|
+
// Standard noise pattern
|
|
3988
|
+
distortionGain: .4
|
|
3989
|
+
}, QUALITY_PRESET = {
|
|
3990
|
+
distortionOctaves: 4,
|
|
3991
|
+
// More FBM layers for detail
|
|
3992
|
+
displacementScale: 100,
|
|
3993
|
+
// Stronger displacement
|
|
3994
|
+
blurAmount: 12,
|
|
3995
|
+
// Smoother blur
|
|
3996
|
+
saturation: 100,
|
|
3997
|
+
// Full saturation
|
|
3998
|
+
aberrationIntensity: .7,
|
|
3999
|
+
// Pronounced chromatic aberration
|
|
4000
|
+
animationSpeed: 1.2,
|
|
4001
|
+
// Slightly faster for drama
|
|
4002
|
+
chromaticIntensity: .7,
|
|
4003
|
+
// Strong chromatic effect
|
|
4004
|
+
distortionLacunarity: 2.2,
|
|
4005
|
+
// Richer noise pattern
|
|
4006
|
+
distortionGain: .5
|
|
4007
|
+
};
|
|
4008
|
+
|
|
4009
|
+
/**
|
|
4010
|
+
* Balanced preset - Good quality with reasonable performance
|
|
4011
|
+
* Default preset for most mobile devices
|
|
4012
|
+
*/
|
|
4013
|
+
/**
|
|
4014
|
+
* Get preset by name
|
|
4015
|
+
*/
|
|
4016
|
+
function getDevicePreset(presetName) {
|
|
4017
|
+
switch (presetName) {
|
|
4018
|
+
case "performance":
|
|
4019
|
+
return PERFORMANCE_PRESET;
|
|
4020
|
+
|
|
4021
|
+
case "balanced":
|
|
4022
|
+
default:
|
|
4023
|
+
return BALANCED_PRESET;
|
|
4024
|
+
|
|
4025
|
+
case "quality":
|
|
4026
|
+
return QUALITY_PRESET;
|
|
4027
|
+
}
|
|
4028
|
+
}
|
|
4029
|
+
|
|
4030
|
+
/**
|
|
4031
|
+
* Mobile-optimized responsive breakpoints
|
|
4032
|
+
* Automatically applies appropriate presets based on viewport size
|
|
4033
|
+
*/ const MOBILE_OPTIMIZED_BREAKPOINTS = {
|
|
4034
|
+
/** Desktop - Full quality */
|
|
4035
|
+
desktop: {
|
|
4036
|
+
minWidth: 1024,
|
|
4037
|
+
params: {
|
|
4038
|
+
distortionOctaves: 6,
|
|
4039
|
+
displacementScale: 150,
|
|
4040
|
+
blurAmount: 15,
|
|
4041
|
+
saturation: 100,
|
|
4042
|
+
aberrationIntensity: 1,
|
|
4043
|
+
animationSpeed: 1,
|
|
4044
|
+
chromaticIntensity: 1,
|
|
4045
|
+
distortionLacunarity: 2.5,
|
|
4046
|
+
distortionGain: .6
|
|
4047
|
+
}
|
|
4048
|
+
},
|
|
4049
|
+
/** Laptop - High quality */
|
|
4050
|
+
laptop: {
|
|
4051
|
+
minWidth: 768,
|
|
4052
|
+
params: {
|
|
4053
|
+
...QUALITY_PRESET,
|
|
4054
|
+
distortionOctaves: 5,
|
|
4055
|
+
displacementScale: 120
|
|
4056
|
+
}
|
|
4057
|
+
},
|
|
4058
|
+
/** Tablet - Balanced quality */
|
|
4059
|
+
tablet: {
|
|
4060
|
+
minWidth: 640,
|
|
4061
|
+
params: {
|
|
4062
|
+
...BALANCED_PRESET,
|
|
4063
|
+
distortionOctaves: 4,
|
|
4064
|
+
displacementScale: 90
|
|
4065
|
+
}
|
|
4066
|
+
},
|
|
4067
|
+
/** Mobile - Performance optimized */
|
|
4068
|
+
mobile: {
|
|
4069
|
+
maxWidth: 639,
|
|
4070
|
+
params: {
|
|
4071
|
+
...PERFORMANCE_PRESET,
|
|
4072
|
+
distortionOctaves: 3,
|
|
4073
|
+
displacementScale: 75,
|
|
4074
|
+
blurAmount: 6
|
|
4075
|
+
}
|
|
4076
|
+
},
|
|
4077
|
+
/** Small mobile - Maximum performance */
|
|
4078
|
+
mobileSmall: {
|
|
4079
|
+
maxWidth: 375,
|
|
4080
|
+
params: {
|
|
4081
|
+
...PERFORMANCE_PRESET,
|
|
4082
|
+
distortionOctaves: 2,
|
|
4083
|
+
displacementScale: 50,
|
|
4084
|
+
blurAmount: 4,
|
|
4085
|
+
saturation: 70
|
|
4086
|
+
}
|
|
4087
|
+
}
|
|
4088
|
+
};
|
|
4089
|
+
|
|
4090
|
+
/**
|
|
4091
|
+
* Get mobile-optimized parameters for current viewport
|
|
4092
|
+
* Can be used standalone or with useResponsiveGlass hook
|
|
4093
|
+
*/ function getMobileOptimizedParams(viewportWidth) {
|
|
4094
|
+
return viewportWidth >= 1024 ? MOBILE_OPTIMIZED_BREAKPOINTS.desktop?.params || BALANCED_PRESET : viewportWidth >= 768 ? MOBILE_OPTIMIZED_BREAKPOINTS.laptop?.params || BALANCED_PRESET : viewportWidth >= 640 ? MOBILE_OPTIMIZED_BREAKPOINTS.tablet?.params || BALANCED_PRESET : viewportWidth >= 375 ? MOBILE_OPTIMIZED_BREAKPOINTS.mobile?.params || PERFORMANCE_PRESET : MOBILE_OPTIMIZED_BREAKPOINTS.mobileSmall?.params || PERFORMANCE_PRESET;
|
|
4095
|
+
}
|
|
4096
|
+
|
|
4097
|
+
/**
|
|
4098
|
+
* Device detection utilities
|
|
4099
|
+
*/ const DeviceDetector = {
|
|
4100
|
+
/** Check if device is mobile */
|
|
4101
|
+
isMobile: () => "undefined" != typeof window && /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
|
|
4102
|
+
/** Check if device is tablet */
|
|
4103
|
+
isTablet() {
|
|
4104
|
+
if ("undefined" == typeof window) return !1;
|
|
4105
|
+
const width = window.innerWidth;
|
|
4106
|
+
return width >= 640 && width < 1024 && this.isMobile();
|
|
4107
|
+
},
|
|
4108
|
+
/** Get recommended preset based on device type */
|
|
4109
|
+
getRecommendedPreset() {
|
|
4110
|
+
return this.isMobile() ? this.isTablet() ? "balanced" : "performance" : "quality";
|
|
4111
|
+
},
|
|
4112
|
+
/** Get device pixel ratio */
|
|
4113
|
+
getPixelRatio: () => "undefined" == typeof window ? 1 : window.devicePixelRatio || 1,
|
|
4114
|
+
/** Check if device has touch support */
|
|
4115
|
+
hasTouchSupport: () => "undefined" != typeof window && ("ontouchstart" in window || navigator.maxTouchPoints > 0)
|
|
4116
|
+
};
|
|
4117
|
+
|
|
3067
4118
|
/**
|
|
3068
4119
|
* AtomixGlass - A high-performance glass morphism component with liquid distortion effects
|
|
3069
4120
|
*
|
|
@@ -3078,6 +4129,8 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3078
4129
|
* - Focus ring support for keyboard navigation
|
|
3079
4130
|
* - Responsive breakpoints for mobile optimization
|
|
3080
4131
|
* - Enhanced ARIA attributes for screen readers
|
|
4132
|
+
* - Time-based animation system with FBM distortion
|
|
4133
|
+
* - Device preset optimization for performance/quality balance
|
|
3081
4134
|
*
|
|
3082
4135
|
* Design System Compliance:
|
|
3083
4136
|
* - Uses design tokens for opacity, spacing, and colors
|
|
@@ -3134,8 +4187,14 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3134
4187
|
* <AtomixGlass overLight="auto" debugOverLight={true}>
|
|
3135
4188
|
* <div>Content with debug logging enabled</div>
|
|
3136
4189
|
* </AtomixGlass>
|
|
3137
|
-
|
|
3138
|
-
|
|
4190
|
+
*
|
|
4191
|
+
* @example
|
|
4192
|
+
* // Performance-optimized for mobile devices
|
|
4193
|
+
* <AtomixGlass devicePreset="performance" disableResponsiveBreakpoints={false}>
|
|
4194
|
+
* <div>Mobile-optimized glass effect</div>
|
|
4195
|
+
* </AtomixGlass>
|
|
4196
|
+
*/ 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, debugOverLight: debugOverLight = !1, height: height, width: width, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", devicePreset: devicePreset = "balanced", disableResponsiveBreakpoints: disableResponsiveBreakpoints = !1, ...rest}) {
|
|
4197
|
+
const glassRef = React.useRef(null), contentRef = React.useRef(null), {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = "fixed" === restStyle.position || "sticky" === restStyle.position, {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, getShaderTime: getShaderTime, applyTimeBasedDistortion: applyTimeBasedDistortion, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
|
|
3139
4198
|
glassRef: glassRef,
|
|
3140
4199
|
contentRef: contentRef,
|
|
3141
4200
|
borderRadius: borderRadius,
|
|
@@ -3148,7 +4207,6 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3148
4207
|
withoutEffects: withoutEffects,
|
|
3149
4208
|
elasticity: elasticity,
|
|
3150
4209
|
onClick: onClick,
|
|
3151
|
-
debugBorderRadius: debugBorderRadius,
|
|
3152
4210
|
debugOverLight: debugOverLight,
|
|
3153
4211
|
debugPerformance: debugPerformance,
|
|
3154
4212
|
children: children,
|
|
@@ -3156,8 +4214,49 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3156
4214
|
saturation: saturation,
|
|
3157
4215
|
withLiquidBlur: withLiquidBlur,
|
|
3158
4216
|
padding: padding,
|
|
3159
|
-
style: style
|
|
3160
|
-
|
|
4217
|
+
style: style,
|
|
4218
|
+
isFixedOrSticky: isFixedOrSticky,
|
|
4219
|
+
// Phase 1: Animation System props
|
|
4220
|
+
withTimeAnimation: withTimeAnimation,
|
|
4221
|
+
animationSpeed: animationSpeed,
|
|
4222
|
+
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
4223
|
+
distortionOctaves: distortionOctaves,
|
|
4224
|
+
distortionLacunarity: distortionLacunarity,
|
|
4225
|
+
distortionGain: distortionGain,
|
|
4226
|
+
distortionQuality: distortionQuality
|
|
4227
|
+
});
|
|
4228
|
+
// Re-calculate only when devicePreset changes
|
|
4229
|
+
// Responsive breakpoint system - automatically adjusts parameters based on viewport
|
|
4230
|
+
useResponsiveGlass({
|
|
4231
|
+
baseParams: {
|
|
4232
|
+
...React.useMemo((() => getDevicePreset(devicePreset)), [ devicePreset ]),
|
|
4233
|
+
distortionOctaves: Math.round((displacementScale || ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE) / 25),
|
|
4234
|
+
displacementScale: displacementScale || ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE,
|
|
4235
|
+
blurAmount: blurAmount || ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT,
|
|
4236
|
+
saturation: saturation || ATOMIX_GLASS.DEFAULTS.SATURATION,
|
|
4237
|
+
aberrationIntensity: aberrationIntensity || ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY,
|
|
4238
|
+
animationSpeed: 1,
|
|
4239
|
+
chromaticIntensity: aberrationIntensity || ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY
|
|
4240
|
+
},
|
|
4241
|
+
breakpoints: MOBILE_OPTIMIZED_BREAKPOINTS,
|
|
4242
|
+
enabled: !disableResponsiveBreakpoints && "undefined" != typeof window,
|
|
4243
|
+
// Enable unless disabled
|
|
4244
|
+
debug: !1
|
|
4245
|
+
});
|
|
4246
|
+
// Performance monitoring - tracks FPS, frame time, memory usage
|
|
4247
|
+
const {metrics: performanceMetrics, recommendedQuality: recommendedQuality, isUnderperforming: isUnderperforming, setQualityLevel: setQualityLevel, toggleMonitoring: toggleMonitoring} = usePerformanceMonitor({
|
|
4248
|
+
enabled: !1,
|
|
4249
|
+
// We'll toggle manually based on prop
|
|
4250
|
+
debug: !1,
|
|
4251
|
+
showOverlay: !1
|
|
4252
|
+
});
|
|
4253
|
+
// Auto-start performance monitoring if enabled (only in development)
|
|
4254
|
+
React__default.default.useEffect((() => {
|
|
4255
|
+
"development" === process.env.NODE_ENV && window?.enablePerformanceMonitoring && toggleMonitoring();
|
|
4256
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
4257
|
+
}), []);
|
|
4258
|
+
// Only run once on mount
|
|
4259
|
+
const isOverLight = React.useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, rootLayoutStyle = React.useMemo((() => {
|
|
3161
4260
|
if (!isFixedOrSticky) return {};
|
|
3162
4261
|
const {position: p, top: t, left: l, right: r, bottom: b} = restStyle;
|
|
3163
4262
|
return {
|
|
@@ -3177,7 +4276,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3177
4276
|
bottom: b
|
|
3178
4277
|
}
|
|
3179
4278
|
};
|
|
3180
|
-
}), [ isFixedOrSticky, restStyle ])
|
|
4279
|
+
}), [ isFixedOrSticky, restStyle ]);
|
|
4280
|
+
// Calculate base style with transforms
|
|
4281
|
+
// When layout is hoisted to the root, strip those props from the container
|
|
4282
|
+
React.useMemo((() => {
|
|
3181
4283
|
if (isFixedOrSticky) {
|
|
3182
4284
|
const {position: _p, top: _t, left: _l, right: _r, bottom: _b, ...visualStyle} = restStyle;
|
|
3183
4285
|
return {
|
|
@@ -3193,18 +4295,20 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3193
4295
|
transform: transformStyle
|
|
3194
4296
|
}
|
|
3195
4297
|
};
|
|
3196
|
-
}), [ isFixedOrSticky, restStyle, effectiveWithoutEffects, transformStyle ])
|
|
4298
|
+
}), [ isFixedOrSticky, restStyle, effectiveWithoutEffects, transformStyle ]);
|
|
4299
|
+
// Build className with state modifiers
|
|
4300
|
+
const componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveWithoutEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className ].filter(Boolean).join(" "), positionStyles = React.useMemo((() => ({
|
|
3197
4301
|
position: isFixedOrSticky ? "absolute" : restStyle.position || "absolute",
|
|
3198
4302
|
top: isFixedOrSticky ? 0 : restStyle.top || 0,
|
|
3199
4303
|
left: isFixedOrSticky ? 0 : restStyle.left || 0
|
|
3200
4304
|
})), [ isFixedOrSticky, restStyle.position, restStyle.top, restStyle.left ]), adjustedSize = React.useMemo((() => {
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
};
|
|
4305
|
+
// Keep a reference to positionStyles to avoid unused-variable lint,
|
|
4306
|
+
// but sizing is driven by explicit width/height or measured size.
|
|
4307
|
+
positionStyles.position;
|
|
4308
|
+
const resolveLength = (value, measured) => void 0 !== value ? "number" == typeof value ? `${value}px` : value : measured > 0 ? `${measured}px` : "100%", effectiveWidth = width ?? restStyle.width, effectiveHeight = height ?? restStyle.height;
|
|
3205
4309
|
return {
|
|
3206
|
-
width:
|
|
3207
|
-
height:
|
|
4310
|
+
width: resolveLength(effectiveWidth, glassSize.width),
|
|
4311
|
+
height: resolveLength(effectiveHeight, glassSize.height)
|
|
3208
4312
|
};
|
|
3209
4313
|
}), [ width, height, restStyle.width, restStyle.height, positionStyles.position, glassSize.width, glassSize.height ]), gradientValues = React.useMemo((() => {
|
|
3210
4314
|
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
|
|
@@ -3253,9 +4357,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3253
4357
|
},
|
|
3254
4358
|
"--atomix-glass-radius": `${effectiveBorderRadius}px`,
|
|
3255
4359
|
"--atomix-glass-transform": transformStyle || "none",
|
|
3256
|
-
|
|
3257
|
-
"--atomix-glass-
|
|
3258
|
-
"--atomix-glass-
|
|
4360
|
+
// Internal decorative layers are positioned relative to the root;
|
|
4361
|
+
"--atomix-glass-position": rootLayoutStyle.position,
|
|
4362
|
+
"--atomix-glass-top": `${isFixedOrSticky ? rootLayoutStyle.top : 0}px`,
|
|
4363
|
+
"--atomix-glass-left": `${isFixedOrSticky ? rootLayoutStyle.left : 0}px`,
|
|
3259
4364
|
"--atomix-glass-width": adjustedSize.width,
|
|
3260
4365
|
"--atomix-glass-height": adjustedSize.height,
|
|
3261
4366
|
"--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.09375rem)",
|
|
@@ -3275,10 +4380,12 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3275
4380
|
"--atomix-glass-overlay-highlight-opacity": opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
|
|
3276
4381
|
"--atomix-glass-overlay-highlight-bg": `radial-gradient(circle at ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_X}% ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_Y}%, rgba(255, 255, 255, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.WHITE_OPACITY}) 0%, transparent ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.STOP}%)`
|
|
3277
4382
|
};
|
|
3278
|
-
}), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle,
|
|
4383
|
+
}), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, adjustedSize, isOverLight, overLightConfig.borderOpacity, customZIndex, rootLayoutStyle, isFixedOrSticky ]), renderBackgroundLayer = layerType => jsxRuntime.jsx("div", {
|
|
3279
4384
|
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(" ")
|
|
3280
4385
|
});
|
|
3281
|
-
|
|
4386
|
+
// Calculate position and size styles for internal layers
|
|
4387
|
+
// When root is fixed/sticky, internal layers use absolute (relative to root)
|
|
4388
|
+
return jsxRuntime.jsxs("div", {
|
|
3282
4389
|
...rest,
|
|
3283
4390
|
className: componentClassName,
|
|
3284
4391
|
style: {
|
|
@@ -3295,7 +4402,12 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3295
4402
|
ref: glassRef,
|
|
3296
4403
|
contentRef: contentRef,
|
|
3297
4404
|
className: className,
|
|
3298
|
-
style:
|
|
4405
|
+
style: {
|
|
4406
|
+
...restStyle,
|
|
4407
|
+
...!isFixedOrSticky && {
|
|
4408
|
+
position: "relative"
|
|
4409
|
+
}
|
|
4410
|
+
},
|
|
3299
4411
|
borderRadius: effectiveBorderRadius,
|
|
3300
4412
|
displacementScale: effectiveWithoutEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
|
|
3301
4413
|
blurAmount: effectiveWithoutEffects ? 0 : blurAmount,
|
|
@@ -3326,11 +4438,19 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3326
4438
|
},
|
|
3327
4439
|
onClick: onClick,
|
|
3328
4440
|
mode: mode,
|
|
3329
|
-
transform: baseStyle.transform,
|
|
3330
4441
|
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
3331
4442
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
3332
4443
|
shaderVariant: shaderVariant,
|
|
3333
4444
|
withLiquidBlur: withLiquidBlur,
|
|
4445
|
+
// Phase 1: Animation System props
|
|
4446
|
+
shaderTime: getShaderTime(),
|
|
4447
|
+
withTimeAnimation: withTimeAnimation,
|
|
4448
|
+
animationSpeed: animationSpeed,
|
|
4449
|
+
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
4450
|
+
distortionOctaves: distortionOctaves,
|
|
4451
|
+
distortionLacunarity: distortionLacunarity,
|
|
4452
|
+
distortionGain: distortionGain,
|
|
4453
|
+
distortionQuality: distortionQuality,
|
|
3334
4454
|
children: children
|
|
3335
4455
|
}), Boolean(onClick) && jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
3336
4456
|
children: [ jsxRuntime.jsx("div", {
|
|
@@ -3354,6 +4474,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3354
4474
|
}), jsxRuntime.jsx("span", {
|
|
3355
4475
|
className: ATOMIX_GLASS.BORDER_2_CLASS
|
|
3356
4476
|
}) ]
|
|
4477
|
+
}), debugPerformance && performanceMetrics && jsxRuntime.jsx(PerformanceDashboard, {
|
|
4478
|
+
metrics: performanceMetrics,
|
|
4479
|
+
isVisible: !0,
|
|
4480
|
+
onClose: () => {}
|
|
3357
4481
|
}) ]
|
|
3358
4482
|
});
|
|
3359
4483
|
}
|
|
@@ -3420,16 +4544,14 @@ const AccordionBody = React.forwardRef((({children: children, className: classN
|
|
|
3420
4544
|
|
|
3421
4545
|
AccordionBody.displayName = "AccordionBody";
|
|
3422
4546
|
|
|
3423
|
-
const AccordionImpl = React.memo((({title: title, children: children, defaultOpen: defaultOpen = !1, isOpen: controlledOpen, onOpenChange: onOpenChange,
|
|
4547
|
+
const AccordionImpl = React.memo((({title: title, children: children, defaultOpen: defaultOpen = !1, isOpen: controlledOpen, onOpenChange: onOpenChange, disabled: disabled = !1, iconPosition: iconPosition = "right", icon: icon, className: className = "", style: style, glass: glass}) => {
|
|
3424
4548
|
// Generate unique IDs for accessibility
|
|
3425
4549
|
const instanceId = React.useId(), buttonId = `accordion-header-${instanceId}`, panelId = `accordion-panel-${instanceId}`, {state: state, toggle: toggle, updatePanelHeight: updatePanelHeight, panelRef: panelRef, contentRef: contentRef, generateClassNames: generateClassNames, generateHeaderClassNames: generateHeaderClassNames} = useAccordion({
|
|
3426
4550
|
defaultOpen: defaultOpen,
|
|
3427
4551
|
disabled: disabled,
|
|
3428
4552
|
iconPosition: iconPosition,
|
|
3429
4553
|
isOpen: controlledOpen,
|
|
3430
|
-
onOpenChange: onOpenChange
|
|
3431
|
-
onOpen: onOpen,
|
|
3432
|
-
onClose: onClose
|
|
4554
|
+
onOpenChange: onOpenChange
|
|
3433
4555
|
}), headerClassNames = generateHeaderClassNames(), panelClassNames = ACCORDION.SELECTORS.PANEL.replace(".", ""), hasCompoundComponents = React__default.default.Children.toArray(children).some((child => {
|
|
3434
4556
|
var _context;
|
|
3435
4557
|
|
|
@@ -3812,7 +4934,9 @@ var shaderUtils = Object.freeze({
|
|
|
3812
4934
|
return this.canvasDPI;
|
|
3813
4935
|
}
|
|
3814
4936
|
},
|
|
3815
|
-
|
|
4937
|
+
createFBMEngine: createFBMEngine,
|
|
4938
|
+
fragmentShaders: fragmentShaders,
|
|
4939
|
+
liquidGlassWithTime: liquidGlassWithTime
|
|
3816
4940
|
});
|
|
3817
4941
|
|
|
3818
4942
|
// Map string sizes to pixel values
|
|
@@ -3847,7 +4971,7 @@ const sizeMap = {
|
|
|
3847
4971
|
* Icon component that displays a Phosphor icon
|
|
3848
4972
|
*/ Icon.displayName = "Icon";
|
|
3849
4973
|
|
|
3850
|
-
const Avatar = React.memo((({src: src, alt: alt = "
|
|
4974
|
+
const Avatar = React.memo((({src: src, alt: alt = "User avatar", initials: initials, icon: icon, size: size = "md", circle: circle = !1, className: className = "", disabled: disabled = !1, onClick: onClick, style: style, glass: glass}) => {
|
|
3851
4975
|
const [imageError, setImageError] = React.useState(!1), avatarClasses = [ AVATAR.CLASSES.BASE, "md" !== size && `c-avatar--${size}`, circle && AVATAR.CLASSES.CIRCLE, disabled && "is-disabled", className ].filter(Boolean).join(" ");
|
|
3852
4976
|
return jsxRuntime.jsx("div", {
|
|
3853
4977
|
className: avatarClasses,
|
|
@@ -4320,7 +5444,7 @@ class ThemeNaming {
|
|
|
4320
5444
|
ThemeNaming.prefix = "atomix";
|
|
4321
5445
|
|
|
4322
5446
|
const Button = React__default.default.memo( React.forwardRef((({label: label, children: children, onClick: onClick, variant: variant = "primary", size: size = "md", disabled: disabled = !1, loading: loading = !1, loadingText: loadingText, icon: icon, iconName: iconName, iconSize: iconSize = "sm", iconPosition: iconPosition = "start", iconOnly: iconOnly = !1, rounded: rounded = !1, fullWidth: fullWidth = !1, block: block = !1, active: active = !1, selected: selected = !1, type: type = "button", className: className = "", as: Component = "button", href: href, target: target, glass: glass, onHover: onHover, onFocus: onFocus, onBlur: onBlur, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, tabIndex: tabIndex, style: style, linkComponent: linkComponent, ...props}, ref) => {
|
|
4323
|
-
const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href
|
|
5447
|
+
const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href), iconElement = iconName ? jsxRuntime.jsx(Icon, {
|
|
4324
5448
|
name: iconName,
|
|
4325
5449
|
size: iconSize
|
|
4326
5450
|
}) : icon, buttonClass = [ BUTTON.BASE_CLASS, ThemeNaming.variantClass(THEME_NAMING.BUTTON_PREFIX, variant), "md" !== size ? ThemeNaming.sizeClass(THEME_NAMING.BUTTON_PREFIX, size) : "", iconOnly ? ThemeNaming.stateClass(THEME_NAMING.BUTTON_PREFIX, THEME_NAMING.ICON_ELEMENT) : "", rounded ? ThemeNaming.stateClass(THEME_NAMING.BUTTON_PREFIX, "rounded") : "", isDisabled ? ThemeNaming.stateClass(THEME_NAMING.BUTTON_PREFIX, "disabled") : "", glass ? ThemeNaming.stateClass(THEME_NAMING.BUTTON_PREFIX, "glass") : "", loading ? BUTTON.CLASSES.LOADING : "", fullWidth ? BUTTON.CLASSES.FULL_WIDTH : "", block ? BUTTON.CLASSES.BLOCK : "", active ? BUTTON.CLASSES.ACTIVE : "", selected ? BUTTON.CLASSES.SELECTED : "", className ].filter(Boolean).join(" "), handleClickEvent = React.useCallback((event => {
|
|
@@ -4376,8 +5500,8 @@ const Button = React__default.default.memo( React.forwardRef((({label: label, c
|
|
|
4376
5500
|
...buttonProps,
|
|
4377
5501
|
ref: ref,
|
|
4378
5502
|
// linkComponent usually forwards ref to anchor
|
|
4379
|
-
href: href,
|
|
4380
|
-
to: href,
|
|
5503
|
+
href: isDisabled ? void 0 : href,
|
|
5504
|
+
to: isDisabled ? void 0 : href,
|
|
4381
5505
|
target: target,
|
|
4382
5506
|
rel: "_blank" === target ? "noopener noreferrer" : void 0
|
|
4383
5507
|
};
|
|
@@ -4390,7 +5514,7 @@ const Button = React__default.default.memo( React.forwardRef((({label: label, c
|
|
|
4390
5514
|
content = jsxRuntime.jsx("a", {
|
|
4391
5515
|
...buttonProps,
|
|
4392
5516
|
ref: ref,
|
|
4393
|
-
href: href,
|
|
5517
|
+
href: isDisabled ? void 0 : href,
|
|
4394
5518
|
target: target,
|
|
4395
5519
|
rel: "_blank" === target ? "noopener noreferrer" : void 0,
|
|
4396
5520
|
children: buttonContent
|
|
@@ -4669,7 +5793,7 @@ row: row = !1, flat: flat = !1,
|
|
|
4669
5793
|
// States
|
|
4670
5794
|
active: active = !1, disabled: disabled = !1, loading: loading = !1, selected: selected = !1, interactive: interactive = !1,
|
|
4671
5795
|
// Content
|
|
4672
|
-
header: header, image: image, imageAlt: imageAlt = "", title: title, text: text, actions: actions, icon: icon, footer: footer, children: children,
|
|
5796
|
+
header: header, image: image, imageAlt: imageAlt = "Card image", title: title, text: text, actions: actions, icon: icon, footer: footer, children: children,
|
|
4673
5797
|
// Interaction
|
|
4674
5798
|
onClick: onClick, onHover: onHover, onFocus: onFocus, href: href, target: target,
|
|
4675
5799
|
// Custom Link
|
|
@@ -4872,50 +5996,50 @@ Card.Header = CardHeader, Card.Body = CardBody, Card.Footer = CardFooter;
|
|
|
4872
5996
|
* @param options - Configuration options for the card
|
|
4873
5997
|
* @returns Card state and handlers
|
|
4874
5998
|
*/
|
|
4875
|
-
const
|
|
4876
|
-
const {
|
|
4877
|
-
flipEffect
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
}
|
|
4918
|
-
|
|
5999
|
+
const ElevationCard = ({elevationClass: elevationClass = "is-elevated", className: className = "", style: style, children: children, onClick: onClick, ...props}) => {
|
|
6000
|
+
const {getCardProps: getCardProps} = ((options = {}) => {
|
|
6001
|
+
const {elevationEffect: elevationEffect = !1, elevationClass: elevationClass = CARD.CLASSES.ACTIVE, flipEffect: flipEffect = !1, flipTrigger: flipTrigger = "click", focusEffect: focusEffect = !1, clickable: clickable = !1, onClick: onClick} = options, cardRef = React.useRef(null), frontRef = React.useRef(null), backRef = React.useRef(null), [isFlipped, setIsFlipped] = React.useState(!1), [isElevated, setIsElevated] = React.useState(!1), [isFocused, setIsFocused] = React.useState(!1), [isHovered, setIsHovered] = React.useState(!1), handleClick = React.useCallback((event => {
|
|
6002
|
+
flipEffect && "click" === flipTrigger && setIsFlipped((prev => !prev)), onClick && onClick(event);
|
|
6003
|
+
}), [ flipEffect, flipTrigger, onClick ]), handleKeyDown = React.useCallback((event => {
|
|
6004
|
+
"Enter" !== event.key && " " !== event.key || (event.preventDefault(), flipEffect && "click" === flipTrigger && setIsFlipped((prev => !prev)),
|
|
6005
|
+
onClick && onClick(event));
|
|
6006
|
+
}), [ flipEffect, flipTrigger, onClick ]), handleMouseEnter = React.useCallback((() => {
|
|
6007
|
+
setIsHovered(!0), elevationEffect && setIsElevated(!0), flipEffect && "hover" === flipTrigger && setIsFlipped(!0);
|
|
6008
|
+
}), [ elevationEffect, flipEffect, flipTrigger ]), handleMouseLeave = React.useCallback((() => {
|
|
6009
|
+
setIsHovered(!1), elevationEffect && setIsElevated(!1), flipEffect && "hover" === flipTrigger && setIsFlipped(!1);
|
|
6010
|
+
}), [ elevationEffect, flipEffect, flipTrigger ]), handleFocus = React.useCallback((() => {
|
|
6011
|
+
setIsFocused(!0);
|
|
6012
|
+
}), []), handleBlur = React.useCallback((() => {
|
|
6013
|
+
setIsFocused(!1);
|
|
6014
|
+
}), []), getCardProps = React.useCallback((() => ({
|
|
6015
|
+
className: [ CARD.CLASSES.BASE, isElevated ? elevationClass : "", isFlipped ? CARD.CLASSES.FLIPPED : "", isFocused && focusEffect ? CARD.CLASSES.FOCUSED : "", clickable ? CARD.CLASSES.CLICKABLE : "" ].filter(Boolean).join(" "),
|
|
6016
|
+
ref: cardRef,
|
|
6017
|
+
tabxwIndex: clickable || flipEffect ? 0 : -1,
|
|
6018
|
+
role: clickable ? "button" : void 0,
|
|
6019
|
+
onMouseEnter: handleMouseEnter,
|
|
6020
|
+
onMouseLeave: handleMouseLeave,
|
|
6021
|
+
onFocus: handleFocus,
|
|
6022
|
+
onBlur: handleBlur,
|
|
6023
|
+
onClick: handleClick,
|
|
6024
|
+
onKeyDown: handleKeyDown
|
|
6025
|
+
})), [ isElevated, isFlipped, isFocused, elevationClass, focusEffect, clickable, handleMouseEnter, handleMouseLeave, handleFocus, handleBlur, handleClick, handleKeyDown, flipEffect ]);
|
|
6026
|
+
return {
|
|
6027
|
+
cardRef: cardRef,
|
|
6028
|
+
frontRef: frontRef,
|
|
6029
|
+
backRef: backRef,
|
|
6030
|
+
isFlipped: isFlipped,
|
|
6031
|
+
isElevated: isElevated,
|
|
6032
|
+
isFocused: isFocused,
|
|
6033
|
+
isHovered: isHovered,
|
|
6034
|
+
handleClick: handleClick,
|
|
6035
|
+
handleKeyDown: handleKeyDown,
|
|
6036
|
+
handleMouseEnter: handleMouseEnter,
|
|
6037
|
+
handleMouseLeave: handleMouseLeave,
|
|
6038
|
+
handleFocus: handleFocus,
|
|
6039
|
+
handleBlur: handleBlur,
|
|
6040
|
+
getCardProps: getCardProps
|
|
6041
|
+
};
|
|
6042
|
+
})({
|
|
4919
6043
|
elevationEffect: !0,
|
|
4920
6044
|
elevationClass: elevationClass,
|
|
4921
6045
|
clickable: Boolean(onClick),
|
|
@@ -9299,216 +10423,13 @@ function getRowId$1(row, rowKey) {
|
|
|
9299
10423
|
|
|
9300
10424
|
/**
|
|
9301
10425
|
* Hook for managing DataTable state and behavior
|
|
9302
|
-
*/
|
|
9303
|
-
// Sort state
|
|
9304
|
-
const [sortConfig, setSortConfig] = React.useState(initialSortConfig || null), [currentPage, setCurrentPage] = React.useState(1), [searchQuery, setSearchQuery] = React.useState(""), [internalSelectedRowIds, setInternalSelectedRowIds] = React.useState([]), selectedRowIds = controlledSelectedRowIds ?? internalSelectedRowIds, [columnOrder, setColumnOrder] = React.useState((() => columns.map((col => col.key)))), [columnVisibility, setColumnVisibility] = React.useState((() => {
|
|
9305
|
-
const visibility = {};
|
|
9306
|
-
return columns.forEach((col => {
|
|
9307
|
-
visibility[col.key] = !1 !== col.visible;
|
|
9308
|
-
})), visibility;
|
|
9309
|
-
})), [columnFilterValues, setColumnFilterValues] = React.useState({});
|
|
9310
|
-
// Pagination state
|
|
9311
|
-
// Update column order when columns prop changes
|
|
9312
|
-
React.useEffect((() => {
|
|
9313
|
-
const newOrder = columns.map((col => col.key)), currentOrderSet = new Set(columnOrder), newOrderSet = new Set(newOrder);
|
|
9314
|
-
// Only update if there are actual differences
|
|
9315
|
-
newOrder.length === columnOrder.length && newOrder.every((key => currentOrderSet.has(key))) && columnOrder.every((key => newOrderSet.has(key))) || setColumnOrder(newOrder);
|
|
9316
|
-
}), [ columns ]),
|
|
9317
|
-
// Update column visibility when columns prop changes
|
|
9318
|
-
React.useEffect((() => {
|
|
9319
|
-
setColumnVisibility((prev => {
|
|
9320
|
-
const updated = {
|
|
9321
|
-
...prev
|
|
9322
|
-
};
|
|
9323
|
-
return columns.forEach((col => {
|
|
9324
|
-
col.key in updated || (updated[col.key] = !1 !== col.visible);
|
|
9325
|
-
})), updated;
|
|
9326
|
-
}));
|
|
9327
|
-
}), [ columns ]);
|
|
9328
|
-
// Visible columns based on order and visibility
|
|
9329
|
-
const visibleColumns = React.useMemo((() => columnOrder.map((key => columns.find((col => col.key === key)))).filter((col => void 0 !== col && !1 !== columnVisibility[col.key]))), [ columns, columnOrder, columnVisibility ]), handleSort = React.useCallback((key => {
|
|
9330
|
-
if (!sortable) return;
|
|
9331
|
-
let direction = "asc";
|
|
9332
|
-
sortConfig && sortConfig.key === key && "asc" === sortConfig.direction && (direction = "desc");
|
|
9333
|
-
const newSortConfig = {
|
|
9334
|
-
key: key,
|
|
9335
|
-
direction: direction
|
|
9336
|
-
};
|
|
9337
|
-
setSortConfig(newSortConfig), onSort && onSort(newSortConfig);
|
|
9338
|
-
}), [ sortable, sortConfig, onSort ]), handlePageChange = React.useCallback((page => {
|
|
9339
|
-
page < 1 || setCurrentPage(page);
|
|
9340
|
-
}), []), handleSearch = React.useCallback((query => {
|
|
9341
|
-
setSearchQuery(query), setCurrentPage(1);
|
|
9342
|
-
} // Reset to first page when searching
|
|
9343
|
-
), []), handleColumnFilterChange = React.useCallback(((columnKey, value) => {
|
|
9344
|
-
setColumnFilterValues((prev => ({
|
|
9345
|
-
...prev,
|
|
9346
|
-
[columnKey]: value
|
|
9347
|
-
}))), setCurrentPage(1);
|
|
9348
|
-
} // Reset to first page when filtering
|
|
9349
|
-
), []), clearColumnFilters = React.useCallback((() => {
|
|
9350
|
-
setColumnFilterValues({}), setCurrentPage(1);
|
|
9351
|
-
}), []), activeColumnFilters = React.useMemo((() => columnFilters ? Object.entries(columnFilterValues).filter((([, value]) => null != value && "" !== value)).map((([columnKey, value]) => {
|
|
9352
|
-
const column = columns.find((col => col.key === columnKey));
|
|
9353
|
-
return column && column.filterable ? {
|
|
9354
|
-
key: columnKey,
|
|
9355
|
-
value: value,
|
|
9356
|
-
lowercaseValue: "string" == typeof value ? value.toLowerCase() : String(value).toLowerCase(),
|
|
9357
|
-
column: column
|
|
9358
|
-
} : null;
|
|
9359
|
-
})).filter((f => null !== f)) : []), [ columnFilters, columnFilterValues, columns ]), filteredData = React.useMemo((() => {
|
|
9360
|
-
if (!searchQuery && 0 === activeColumnFilters.length) return data;
|
|
9361
|
-
const lowercaseQuery = searchQuery ? searchQuery.toLowerCase() : "";
|
|
9362
|
-
return data.filter((row => {
|
|
9363
|
-
// Apply global search
|
|
9364
|
-
if (searchQuery && !visibleColumns.some((column => {
|
|
9365
|
-
var _context;
|
|
9366
|
-
const value = row[column.key];
|
|
9367
|
-
return null != value && _includesInstanceProperty(_context = String(value).toLowerCase()).call(_context, lowercaseQuery);
|
|
9368
|
-
}))) return !1;
|
|
9369
|
-
// Apply column-specific filters
|
|
9370
|
-
for (let i = 0; i < activeColumnFilters.length; i++) {
|
|
9371
|
-
const filter = activeColumnFilters[i];
|
|
9372
|
-
if (!filter) continue;
|
|
9373
|
-
const {key: key, value: value, lowercaseValue: lowercaseValue, column: column} = filter, cellValue = row[key];
|
|
9374
|
-
if (null == cellValue) return !1;
|
|
9375
|
-
// Use custom filter function if provided
|
|
9376
|
-
var _context2;
|
|
9377
|
-
// Default text filter
|
|
9378
|
-
if (column.filterFunction) {
|
|
9379
|
-
if (!column.filterFunction(cellValue, value)) return !1;
|
|
9380
|
-
} else if (!_includesInstanceProperty(_context2 = String(cellValue).toLowerCase()).call(_context2, lowercaseValue)) return !1;
|
|
9381
|
-
}
|
|
9382
|
-
return !0;
|
|
9383
|
-
}));
|
|
9384
|
-
}), [ data, visibleColumns, searchQuery, activeColumnFilters ]), sortedData = React.useMemo((() => sortConfig && sortable ? [ ...filteredData ].sort(((a, b) => {
|
|
9385
|
-
const aValue = a[sortConfig.key], bValue = b[sortConfig.key];
|
|
9386
|
-
return null == aValue ? "asc" === sortConfig.direction ? -1 : 1 : null == bValue ? "asc" === sortConfig.direction ? 1 : -1 : "string" == typeof aValue && "string" == typeof bValue ? "asc" === sortConfig.direction ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue) : "asc" === sortConfig.direction ? aValue > bValue ? 1 : -1 : aValue > bValue ? -1 : 1;
|
|
9387
|
-
})) : filteredData), [ filteredData, sortConfig, sortable ]), paginatedData = React.useMemo((() => {
|
|
9388
|
-
if (!paginated) return sortedData;
|
|
9389
|
-
const startIndex = (currentPage - 1) * pageSize;
|
|
9390
|
-
return sortedData.slice(startIndex, startIndex + pageSize);
|
|
9391
|
-
}), [ sortedData, paginated, currentPage, pageSize ]), totalPages = React.useMemo((() => paginated ? Math.max(1, Math.ceil(sortedData.length / pageSize)) : 1), [ sortedData.length, paginated, pageSize ]), selectedRows = React.useMemo((() => "none" === selectionMode || 0 === selectedRowIds.length ? [] : sortedData.filter((row => _includesInstanceProperty(selectedRowIds).call(selectedRowIds, getRowId$1(row, rowKey))))), [ sortedData, selectedRowIds, selectionMode, rowKey ]), handleRowSelect = React.useCallback(((rowId, selected) => {
|
|
9392
|
-
if ("none" === selectionMode) return;
|
|
9393
|
-
let newSelectedIds;
|
|
9394
|
-
if (newSelectedIds = "single" === selectionMode ? selected ? [ rowId ] : [] :
|
|
9395
|
-
// multiple
|
|
9396
|
-
selected ? [ ...selectedRowIds, rowId ] : selectedRowIds.filter((id => id !== rowId)),
|
|
9397
|
-
controlledSelectedRowIds || setInternalSelectedRowIds(newSelectedIds), onSelectionChange) {
|
|
9398
|
-
const selectedRowsData = sortedData.filter((row => _includesInstanceProperty(newSelectedIds).call(newSelectedIds, getRowId$1(row, rowKey))));
|
|
9399
|
-
onSelectionChange(selectedRowsData, newSelectedIds);
|
|
9400
|
-
}
|
|
9401
|
-
}), [ selectionMode, selectedRowIds, controlledSelectedRowIds, onSelectionChange, sortedData, rowKey ]), handleSelectAll = React.useCallback((selected => {
|
|
9402
|
-
if ("multiple" !== selectionMode) return;
|
|
9403
|
-
const newSelectedIds = selected ? paginatedData.map((row => getRowId$1(row, rowKey))) : [];
|
|
9404
|
-
if (controlledSelectedRowIds || setInternalSelectedRowIds(newSelectedIds), onSelectionChange) {
|
|
9405
|
-
const selectedRowsData = sortedData.filter((row => _includesInstanceProperty(newSelectedIds).call(newSelectedIds, getRowId$1(row, rowKey))));
|
|
9406
|
-
onSelectionChange(selectedRowsData, newSelectedIds);
|
|
9407
|
-
}
|
|
9408
|
-
}), [ selectionMode, paginatedData, sortedData, controlledSelectedRowIds, onSelectionChange, rowKey ]), isAllSelected = React.useMemo((() => "multiple" === selectionMode && 0 !== paginatedData.length && paginatedData.every((row => _includesInstanceProperty(selectedRowIds).call(selectedRowIds, getRowId$1(row, rowKey))))), [ selectionMode, paginatedData, selectedRowIds, rowKey ]), isIndeterminate = React.useMemo((() => {
|
|
9409
|
-
if ("multiple" !== selectionMode || 0 === paginatedData.length) return !1;
|
|
9410
|
-
const selectedCount = paginatedData.filter((row => _includesInstanceProperty(selectedRowIds).call(selectedRowIds, getRowId$1(row, rowKey)))).length;
|
|
9411
|
-
return selectedCount > 0 && selectedCount < paginatedData.length;
|
|
9412
|
-
}), [ selectionMode, paginatedData, selectedRowIds, rowKey ]), handleColumnVisibilityToggle = React.useCallback((columnKey => {
|
|
9413
|
-
setColumnVisibility((prev => {
|
|
9414
|
-
const updated = {
|
|
9415
|
-
...prev,
|
|
9416
|
-
[columnKey]: !prev[columnKey]
|
|
9417
|
-
};
|
|
9418
|
-
if (onColumnVisibilityChange) {
|
|
9419
|
-
const visibleKeys = Object.entries(updated).filter((([, visible]) => visible)).map((([key]) => key));
|
|
9420
|
-
onColumnVisibilityChange(visibleKeys);
|
|
9421
|
-
}
|
|
9422
|
-
return updated;
|
|
9423
|
-
}));
|
|
9424
|
-
}), [ onColumnVisibilityChange ]);
|
|
9425
|
-
// Handle sorting
|
|
9426
|
-
// Handle column reorder
|
|
9427
|
-
return React.useCallback(((fromIndex, toIndex) => {
|
|
9428
|
-
const newOrder = [ ...columnOrder ], [removed] = newOrder.splice(fromIndex, 1);
|
|
9429
|
-
removed && (newOrder.splice(toIndex, 0, removed), setColumnOrder(newOrder), onColumnReorder && onColumnReorder(newOrder));
|
|
9430
|
-
}), [ columnOrder, onColumnReorder ]),
|
|
9431
|
-
// Reset to first page when data changes
|
|
9432
|
-
React.useEffect((() => {
|
|
9433
|
-
setCurrentPage(1);
|
|
9434
|
-
}), [ data ]),
|
|
9435
|
-
// Reset current page if it's out of bounds
|
|
9436
|
-
React.useEffect((() => {
|
|
9437
|
-
currentPage > totalPages && totalPages > 0 && setCurrentPage(Math.max(1, totalPages));
|
|
9438
|
-
}), [ currentPage, totalPages ]), {
|
|
9439
|
-
displayData: paginatedData,
|
|
9440
|
-
sortConfig: sortConfig,
|
|
9441
|
-
currentPage: currentPage,
|
|
9442
|
-
totalPages: totalPages,
|
|
9443
|
-
handleSort: handleSort,
|
|
9444
|
-
handlePageChange: handlePageChange,
|
|
9445
|
-
handleSearch: handleSearch,
|
|
9446
|
-
selectedRowIds: selectedRowIds,
|
|
9447
|
-
selectedRows: selectedRows,
|
|
9448
|
-
handleRowSelect: handleRowSelect,
|
|
9449
|
-
handleSelectAll: handleSelectAll,
|
|
9450
|
-
isAllSelected: isAllSelected,
|
|
9451
|
-
isIndeterminate: isIndeterminate,
|
|
9452
|
-
columnOrder: columnOrder,
|
|
9453
|
-
visibleColumns: visibleColumns,
|
|
9454
|
-
columnVisibility: columnVisibility,
|
|
9455
|
-
handleColumnVisibilityToggle: handleColumnVisibilityToggle,
|
|
9456
|
-
columnFilterValues: columnFilterValues,
|
|
9457
|
-
handleColumnFilterChange: handleColumnFilterChange,
|
|
9458
|
-
clearColumnFilters: clearColumnFilters
|
|
9459
|
-
};
|
|
9460
|
-
}
|
|
9461
|
-
|
|
9462
|
-
Countdown.displayName = "Countdown";
|
|
10426
|
+
*/ Countdown.displayName = "Countdown";
|
|
9463
10427
|
|
|
9464
10428
|
const range = (start, end) => {
|
|
9465
10429
|
const length = end - start + 1;
|
|
9466
10430
|
return Array.from({
|
|
9467
10431
|
length: length
|
|
9468
10432
|
}, ((_, idx) => idx + start));
|
|
9469
|
-
}, usePagination = ({currentPage: currentPage, totalPages: totalPages, siblingCount: siblingCount = 1, onPageChange: onPageChange}) => {
|
|
9470
|
-
const paginationRange = React.useMemo((() => {
|
|
9471
|
-
// siblingCount + firstPage + lastPage + currentPage + 2*DOTS
|
|
9472
|
-
/*
|
|
9473
|
-
Case 1: If the number of pages is less than the page numbers we want to show in our
|
|
9474
|
-
paginationComponent, we return the range [1..totalPages]
|
|
9475
|
-
*/
|
|
9476
|
-
if (siblingCount + 5 >= totalPages) return range(1, totalPages);
|
|
9477
|
-
const leftSiblingIndex = Math.max(currentPage - siblingCount, 1), rightSiblingIndex = Math.min(currentPage + siblingCount, totalPages), shouldShowLeftDots = leftSiblingIndex > 2, shouldShowRightDots = rightSiblingIndex < totalPages - 2, lastPageIndex = totalPages;
|
|
9478
|
-
/*
|
|
9479
|
-
Case 2: No left dots to show, but rights dots to be shown
|
|
9480
|
-
*/
|
|
9481
|
-
return !shouldShowLeftDots && shouldShowRightDots ? [ ...range(1, 3 + 2 * siblingCount), "...", totalPages ] :
|
|
9482
|
-
/*
|
|
9483
|
-
Case 3: No right dots to show, but left dots to be shown
|
|
9484
|
-
*/
|
|
9485
|
-
shouldShowLeftDots && !shouldShowRightDots ? [ 1, "...", ...range(totalPages - (3 + 2 * siblingCount) + 1, totalPages) ] :
|
|
9486
|
-
/*
|
|
9487
|
-
Case 4: Both left and right dots to be shown
|
|
9488
|
-
*/
|
|
9489
|
-
shouldShowLeftDots && shouldShowRightDots ? [ 1, "...", ...range(leftSiblingIndex, rightSiblingIndex), "...", lastPageIndex ] : [];
|
|
9490
|
-
}), [ totalPages, siblingCount, currentPage ]), goToPage = page => {
|
|
9491
|
-
page >= 1 && page <= totalPages && page !== currentPage && onPageChange(page);
|
|
9492
|
-
};
|
|
9493
|
-
return {
|
|
9494
|
-
paginationRange: paginationRange,
|
|
9495
|
-
currentPage: currentPage,
|
|
9496
|
-
totalPages: totalPages,
|
|
9497
|
-
goToPage: goToPage,
|
|
9498
|
-
nextPage: () => {
|
|
9499
|
-
goToPage(currentPage + 1);
|
|
9500
|
-
},
|
|
9501
|
-
prevPage: () => {
|
|
9502
|
-
goToPage(currentPage - 1);
|
|
9503
|
-
},
|
|
9504
|
-
firstPage: () => {
|
|
9505
|
-
goToPage(1);
|
|
9506
|
-
},
|
|
9507
|
-
lastPage: () => {
|
|
9508
|
-
goToPage(totalPages);
|
|
9509
|
-
},
|
|
9510
|
-
DOTS: "..."
|
|
9511
|
-
};
|
|
9512
10433
|
}, PaginationNavButton = React.memo((({type: type, onClick: onClick, disabled: disabled, label: label, iconName: iconName}) => jsxRuntime.jsx("li", {
|
|
9513
10434
|
className: `c-pagination__item c-pagination__item--${type} ${disabled ? "is-disabled" : ""}`,
|
|
9514
10435
|
"aria-disabled": disabled,
|
|
@@ -9525,7 +10446,50 @@ const range = (start, end) => {
|
|
|
9525
10446
|
})
|
|
9526
10447
|
})
|
|
9527
10448
|
}))), Pagination = React.memo((({currentPage: currentPage = PAGINATION_DEFAULTS.currentPage, totalPages: totalPages = PAGINATION_DEFAULTS.totalPages, onPageChange: onPageChange, siblingCount: siblingCount = PAGINATION_DEFAULTS.siblingCount, showFirstLastButtons: showFirstLastButtons = PAGINATION_DEFAULTS.showFirstLastButtons, showPrevNextButtons: showPrevNextButtons = PAGINATION_DEFAULTS.showPrevNextButtons, showSearch: showSearch = !1, searchPlaceholder: searchPlaceholder = "Go to page", size: size = PAGINATION_DEFAULTS.size, className: className = "", style: style, "aria-label": ariaLabel = "Pagination", glass: glass}) => {
|
|
9528
|
-
const {paginationRange: paginationRange, goToPage: goToPage, nextPage: nextPage, prevPage: prevPage, firstPage: firstPage, lastPage: lastPage} =
|
|
10449
|
+
const {paginationRange: paginationRange, goToPage: goToPage, nextPage: nextPage, prevPage: prevPage, firstPage: firstPage, lastPage: lastPage} = (({currentPage: currentPage, totalPages: totalPages, siblingCount: siblingCount = 1, onPageChange: onPageChange}) => {
|
|
10450
|
+
const paginationRange = React.useMemo((() => {
|
|
10451
|
+
// siblingCount + firstPage + lastPage + currentPage + 2*DOTS
|
|
10452
|
+
/*
|
|
10453
|
+
Case 1: If the number of pages is less than the page numbers we want to show in our
|
|
10454
|
+
paginationComponent, we return the range [1..totalPages]
|
|
10455
|
+
*/
|
|
10456
|
+
if (siblingCount + 5 >= totalPages) return range(1, totalPages);
|
|
10457
|
+
const leftSiblingIndex = Math.max(currentPage - siblingCount, 1), rightSiblingIndex = Math.min(currentPage + siblingCount, totalPages), shouldShowLeftDots = leftSiblingIndex > 2, shouldShowRightDots = rightSiblingIndex < totalPages - 2, lastPageIndex = totalPages;
|
|
10458
|
+
/*
|
|
10459
|
+
Case 2: No left dots to show, but rights dots to be shown
|
|
10460
|
+
*/
|
|
10461
|
+
return !shouldShowLeftDots && shouldShowRightDots ? [ ...range(1, 3 + 2 * siblingCount), "...", totalPages ] :
|
|
10462
|
+
/*
|
|
10463
|
+
Case 3: No right dots to show, but left dots to be shown
|
|
10464
|
+
*/
|
|
10465
|
+
shouldShowLeftDots && !shouldShowRightDots ? [ 1, "...", ...range(totalPages - (3 + 2 * siblingCount) + 1, totalPages) ] :
|
|
10466
|
+
/*
|
|
10467
|
+
Case 4: Both left and right dots to be shown
|
|
10468
|
+
*/
|
|
10469
|
+
shouldShowLeftDots && shouldShowRightDots ? [ 1, "...", ...range(leftSiblingIndex, rightSiblingIndex), "...", lastPageIndex ] : [];
|
|
10470
|
+
}), [ totalPages, siblingCount, currentPage ]), goToPage = page => {
|
|
10471
|
+
page >= 1 && page <= totalPages && page !== currentPage && onPageChange(page);
|
|
10472
|
+
};
|
|
10473
|
+
return {
|
|
10474
|
+
paginationRange: paginationRange,
|
|
10475
|
+
currentPage: currentPage,
|
|
10476
|
+
totalPages: totalPages,
|
|
10477
|
+
goToPage: goToPage,
|
|
10478
|
+
nextPage: () => {
|
|
10479
|
+
goToPage(currentPage + 1);
|
|
10480
|
+
},
|
|
10481
|
+
prevPage: () => {
|
|
10482
|
+
goToPage(currentPage - 1);
|
|
10483
|
+
},
|
|
10484
|
+
firstPage: () => {
|
|
10485
|
+
goToPage(1);
|
|
10486
|
+
},
|
|
10487
|
+
lastPage: () => {
|
|
10488
|
+
goToPage(totalPages);
|
|
10489
|
+
},
|
|
10490
|
+
DOTS: "..."
|
|
10491
|
+
};
|
|
10492
|
+
})({
|
|
9529
10493
|
currentPage: currentPage,
|
|
9530
10494
|
totalPages: totalPages,
|
|
9531
10495
|
siblingCount: siblingCount,
|
|
@@ -9737,14 +10701,13 @@ const DropdownContext = React.createContext({
|
|
|
9737
10701
|
id: "",
|
|
9738
10702
|
trigger: "click"
|
|
9739
10703
|
}), DropdownMenu = React.forwardRef((({children: children, className: className = "", ...props}, ref) => {
|
|
9740
|
-
const {glass: glass} = React.useContext(DropdownStyleContext);
|
|
9741
|
-
|
|
9742
|
-
// Wait, the original code wrapped <ul> in Context Provider.
|
|
9743
|
-
// And applied glass wrapper around <ul>.
|
|
9744
|
-
// If we use Compound Component, DropdownMenu should be the list.
|
|
9745
|
-
return jsxRuntime.jsx("ul", {
|
|
10704
|
+
const {glass: glass} = React.useContext(DropdownStyleContext), {id: id} = React.useContext(DropdownContext);
|
|
10705
|
+
return jsxRuntime.jsx("ul", {
|
|
9746
10706
|
ref: ref,
|
|
10707
|
+
id: `${id}-menu`,
|
|
9747
10708
|
className: `c-dropdown__menu ${glass ? "c-dropdown__menu--glass" : ""} ${className}`.trim(),
|
|
10709
|
+
role: "menu",
|
|
10710
|
+
"aria-labelledby": `${id}-trigger`,
|
|
9748
10711
|
...props,
|
|
9749
10712
|
children: children
|
|
9750
10713
|
});
|
|
@@ -9753,14 +10716,23 @@ const DropdownContext = React.createContext({
|
|
|
9753
10716
|
// Compound Components
|
|
9754
10717
|
DropdownMenu.displayName = "DropdownMenu";
|
|
9755
10718
|
|
|
9756
|
-
const DropdownTrigger = React.forwardRef((({children: children, className: className = "", onClick: onClick, onKeyDown: onKeyDown, ...props}, ref) =>
|
|
9757
|
-
|
|
9758
|
-
|
|
9759
|
-
|
|
9760
|
-
|
|
9761
|
-
|
|
9762
|
-
|
|
9763
|
-
|
|
10719
|
+
const DropdownTrigger = React.forwardRef((({children: children, className: className = "", onClick: onClick, onKeyDown: onKeyDown, ...props}, ref) => {
|
|
10720
|
+
const {isOpen: isOpen, id: id} = React.useContext(DropdownContext);
|
|
10721
|
+
return jsxRuntime.jsx("div", {
|
|
10722
|
+
ref: ref,
|
|
10723
|
+
id: `${id}-trigger`,
|
|
10724
|
+
className: `c-dropdown__toggle ${className}`.trim(),
|
|
10725
|
+
onClick: onClick,
|
|
10726
|
+
onKeyDown: onKeyDown,
|
|
10727
|
+
"aria-haspopup": "true",
|
|
10728
|
+
"aria-expanded": isOpen,
|
|
10729
|
+
"aria-controls": `${id}-menu`,
|
|
10730
|
+
tabIndex: 0,
|
|
10731
|
+
role: "button",
|
|
10732
|
+
...props,
|
|
10733
|
+
children: children
|
|
10734
|
+
});
|
|
10735
|
+
}));
|
|
9764
10736
|
|
|
9765
10737
|
DropdownTrigger.displayName = "DropdownTrigger";
|
|
9766
10738
|
|
|
@@ -10009,7 +10981,165 @@ Dropdown.Item = DropdownItem, Dropdown.Divider = DropdownDivider, Dropdown.Heade
|
|
|
10009
10981
|
* ```
|
|
10010
10982
|
*/
|
|
10011
10983
|
const DataTable = React.memo((({data: data, columns: columns, className: className, style: style, sortable: sortable = !1, filterable: filterable = !1, paginated: paginated = !1, pageSize: pageSize = 10, striped: striped = !1, bordered: bordered = !1, dense: dense = !1, loading: loading = !1, emptyMessage: emptyMessage = "No data available", onRowClick: onRowClick, onSort: onSort, selectionMode: selectionMode = "none", selectedRowIds: controlledSelectedRowIds, onSelectionChange: onSelectionChange, rowKey: rowKey, resizable: resizable = !1, reorderable: reorderable = !1, onColumnReorder: onColumnReorder, showColumnVisibility: showColumnVisibility = !1, onColumnVisibilityChange: onColumnVisibilityChange, stickyHeader: stickyHeader = !1, stickyHeaderOffset: stickyHeaderOffset = "0px", virtualScrolling: virtualScrolling = !1, estimatedRowHeight: estimatedRowHeight = 50, overscan: overscan = 5, exportable: exportable = !1, exportFormats: exportFormats = [ "csv", "excel", "json" ], exportFilename: exportFilename = "data-table", onExport: onExport, columnFilters: columnFilters = !1, ...props}) => {
|
|
10012
|
-
const tableRef = React.useRef(null), headerRef = React.useRef(null), [resizingColumn, setResizingColumn] = React.useState(null), [columnWidths, setColumnWidths] = React.useState({}), [dragStartIndex, setDragStartIndex] = React.useState(null), [dragOverIndex, setDragOverIndex] = React.useState(null), {displayData: displayData, sortConfig: sortConfig, currentPage: currentPage, totalPages: totalPages, handleSort: handleSort, handlePageChange: handlePageChange, handleSearch: handleSearch, selectedRowIds: selectedRowIds, selectedRows: selectedRows, handleRowSelect: handleRowSelect, handleSelectAll: handleSelectAll, isAllSelected: isAllSelected, isIndeterminate: isIndeterminate, visibleColumns: visibleColumns, columnVisibility: columnVisibility, handleColumnVisibilityToggle: handleColumnVisibilityToggle, columnFilterValues: columnFilterValues, handleColumnFilterChange: handleColumnFilterChange, clearColumnFilters: clearColumnFilters} =
|
|
10984
|
+
const tableRef = React.useRef(null), headerRef = React.useRef(null), [resizingColumn, setResizingColumn] = React.useState(null), [columnWidths, setColumnWidths] = React.useState({}), [dragStartIndex, setDragStartIndex] = React.useState(null), [dragOverIndex, setDragOverIndex] = React.useState(null), {displayData: displayData, sortConfig: sortConfig, currentPage: currentPage, totalPages: totalPages, handleSort: handleSort, handlePageChange: handlePageChange, handleSearch: handleSearch, selectedRowIds: selectedRowIds, selectedRows: selectedRows, handleRowSelect: handleRowSelect, handleSelectAll: handleSelectAll, isAllSelected: isAllSelected, isIndeterminate: isIndeterminate, visibleColumns: visibleColumns, columnVisibility: columnVisibility, handleColumnVisibilityToggle: handleColumnVisibilityToggle, columnFilterValues: columnFilterValues, handleColumnFilterChange: handleColumnFilterChange, clearColumnFilters: clearColumnFilters} = function({data: data = [], columns: columns = [], sortable: sortable = !1, paginated: paginated = !1, pageSize: pageSize = 10, onSort: onSort, initialSortConfig: initialSortConfig, selectionMode: selectionMode = "none", selectedRowIds: controlledSelectedRowIds, onSelectionChange: onSelectionChange, rowKey: rowKey, columnFilters: columnFilters = !1, reorderable: reorderable = !1, onColumnReorder: onColumnReorder, onColumnVisibilityChange: onColumnVisibilityChange}) {
|
|
10985
|
+
// Sort state
|
|
10986
|
+
const [sortConfig, setSortConfig] = React.useState(initialSortConfig || null), [currentPage, setCurrentPage] = React.useState(1), [searchQuery, setSearchQuery] = React.useState(""), [internalSelectedRowIds, setInternalSelectedRowIds] = React.useState([]), selectedRowIds = controlledSelectedRowIds ?? internalSelectedRowIds, [columnOrder, setColumnOrder] = React.useState((() => columns.map((col => col.key)))), [columnVisibility, setColumnVisibility] = React.useState((() => {
|
|
10987
|
+
const visibility = {};
|
|
10988
|
+
return columns.forEach((col => {
|
|
10989
|
+
visibility[col.key] = !1 !== col.visible;
|
|
10990
|
+
})), visibility;
|
|
10991
|
+
})), [columnFilterValues, setColumnFilterValues] = React.useState({});
|
|
10992
|
+
// Pagination state
|
|
10993
|
+
// Update column order when columns prop changes
|
|
10994
|
+
React.useEffect((() => {
|
|
10995
|
+
const newOrder = columns.map((col => col.key)), currentOrderSet = new Set(columnOrder), newOrderSet = new Set(newOrder);
|
|
10996
|
+
// Only update if there are actual differences
|
|
10997
|
+
newOrder.length === columnOrder.length && newOrder.every((key => currentOrderSet.has(key))) && columnOrder.every((key => newOrderSet.has(key))) || setColumnOrder(newOrder);
|
|
10998
|
+
}), [ columns ]),
|
|
10999
|
+
// Update column visibility when columns prop changes
|
|
11000
|
+
React.useEffect((() => {
|
|
11001
|
+
setColumnVisibility((prev => {
|
|
11002
|
+
const updated = {
|
|
11003
|
+
...prev
|
|
11004
|
+
};
|
|
11005
|
+
return columns.forEach((col => {
|
|
11006
|
+
col.key in updated || (updated[col.key] = !1 !== col.visible);
|
|
11007
|
+
})), updated;
|
|
11008
|
+
}));
|
|
11009
|
+
}), [ columns ]);
|
|
11010
|
+
// Visible columns based on order and visibility
|
|
11011
|
+
const visibleColumns = React.useMemo((() => columnOrder.map((key => columns.find((col => col.key === key)))).filter((col => void 0 !== col && !1 !== columnVisibility[col.key]))), [ columns, columnOrder, columnVisibility ]), handleSort = React.useCallback((key => {
|
|
11012
|
+
if (!sortable) return;
|
|
11013
|
+
let direction = "asc";
|
|
11014
|
+
sortConfig && sortConfig.key === key && "asc" === sortConfig.direction && (direction = "desc");
|
|
11015
|
+
const newSortConfig = {
|
|
11016
|
+
key: key,
|
|
11017
|
+
direction: direction
|
|
11018
|
+
};
|
|
11019
|
+
setSortConfig(newSortConfig), onSort && onSort(newSortConfig);
|
|
11020
|
+
}), [ sortable, sortConfig, onSort ]), handlePageChange = React.useCallback((page => {
|
|
11021
|
+
page < 1 || setCurrentPage(page);
|
|
11022
|
+
}), []), handleSearch = React.useCallback((query => {
|
|
11023
|
+
setSearchQuery(query), setCurrentPage(1);
|
|
11024
|
+
} // Reset to first page when searching
|
|
11025
|
+
), []), handleColumnFilterChange = React.useCallback(((columnKey, value) => {
|
|
11026
|
+
setColumnFilterValues((prev => ({
|
|
11027
|
+
...prev,
|
|
11028
|
+
[columnKey]: value
|
|
11029
|
+
}))), setCurrentPage(1);
|
|
11030
|
+
} // Reset to first page when filtering
|
|
11031
|
+
), []), clearColumnFilters = React.useCallback((() => {
|
|
11032
|
+
setColumnFilterValues({}), setCurrentPage(1);
|
|
11033
|
+
}), []), activeColumnFilters = React.useMemo((() => columnFilters ? Object.entries(columnFilterValues).filter((([, value]) => null != value && "" !== value)).map((([columnKey, value]) => {
|
|
11034
|
+
const column = columns.find((col => col.key === columnKey));
|
|
11035
|
+
return column && column.filterable ? {
|
|
11036
|
+
key: columnKey,
|
|
11037
|
+
value: value,
|
|
11038
|
+
lowercaseValue: "string" == typeof value ? value.toLowerCase() : String(value).toLowerCase(),
|
|
11039
|
+
column: column
|
|
11040
|
+
} : null;
|
|
11041
|
+
})).filter((f => null !== f)) : []), [ columnFilters, columnFilterValues, columns ]), filteredData = React.useMemo((() => {
|
|
11042
|
+
if (!searchQuery && 0 === activeColumnFilters.length) return data;
|
|
11043
|
+
const lowercaseQuery = searchQuery ? searchQuery.toLowerCase() : "";
|
|
11044
|
+
return data.filter((row => {
|
|
11045
|
+
// Apply global search
|
|
11046
|
+
if (searchQuery && !visibleColumns.some((column => {
|
|
11047
|
+
var _context;
|
|
11048
|
+
const value = row[column.key];
|
|
11049
|
+
return null != value && _includesInstanceProperty(_context = String(value).toLowerCase()).call(_context, lowercaseQuery);
|
|
11050
|
+
}))) return !1;
|
|
11051
|
+
// Apply column-specific filters
|
|
11052
|
+
for (let i = 0; i < activeColumnFilters.length; i++) {
|
|
11053
|
+
const filter = activeColumnFilters[i];
|
|
11054
|
+
if (!filter) continue;
|
|
11055
|
+
const {key: key, value: value, lowercaseValue: lowercaseValue, column: column} = filter, cellValue = row[key];
|
|
11056
|
+
if (null == cellValue) return !1;
|
|
11057
|
+
// Use custom filter function if provided
|
|
11058
|
+
var _context2;
|
|
11059
|
+
// Default text filter
|
|
11060
|
+
if (column.filterFunction) {
|
|
11061
|
+
if (!column.filterFunction(cellValue, value)) return !1;
|
|
11062
|
+
} else if (!_includesInstanceProperty(_context2 = String(cellValue).toLowerCase()).call(_context2, lowercaseValue)) return !1;
|
|
11063
|
+
}
|
|
11064
|
+
return !0;
|
|
11065
|
+
}));
|
|
11066
|
+
}), [ data, visibleColumns, searchQuery, activeColumnFilters ]), sortedData = React.useMemo((() => sortConfig && sortable ? [ ...filteredData ].sort(((a, b) => {
|
|
11067
|
+
const aValue = a[sortConfig.key], bValue = b[sortConfig.key];
|
|
11068
|
+
return null == aValue ? "asc" === sortConfig.direction ? -1 : 1 : null == bValue ? "asc" === sortConfig.direction ? 1 : -1 : "string" == typeof aValue && "string" == typeof bValue ? "asc" === sortConfig.direction ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue) : "asc" === sortConfig.direction ? aValue > bValue ? 1 : -1 : aValue > bValue ? -1 : 1;
|
|
11069
|
+
})) : filteredData), [ filteredData, sortConfig, sortable ]), paginatedData = React.useMemo((() => {
|
|
11070
|
+
if (!paginated) return sortedData;
|
|
11071
|
+
const startIndex = (currentPage - 1) * pageSize;
|
|
11072
|
+
return sortedData.slice(startIndex, startIndex + pageSize);
|
|
11073
|
+
}), [ sortedData, paginated, currentPage, pageSize ]), totalPages = React.useMemo((() => paginated ? Math.max(1, Math.ceil(sortedData.length / pageSize)) : 1), [ sortedData.length, paginated, pageSize ]), selectedRows = React.useMemo((() => "none" === selectionMode || 0 === selectedRowIds.length ? [] : sortedData.filter((row => _includesInstanceProperty(selectedRowIds).call(selectedRowIds, getRowId$1(row, rowKey))))), [ sortedData, selectedRowIds, selectionMode, rowKey ]), handleRowSelect = React.useCallback(((rowId, selected) => {
|
|
11074
|
+
if ("none" === selectionMode) return;
|
|
11075
|
+
let newSelectedIds;
|
|
11076
|
+
if (newSelectedIds = "single" === selectionMode ? selected ? [ rowId ] : [] :
|
|
11077
|
+
// multiple
|
|
11078
|
+
selected ? [ ...selectedRowIds, rowId ] : selectedRowIds.filter((id => id !== rowId)),
|
|
11079
|
+
controlledSelectedRowIds || setInternalSelectedRowIds(newSelectedIds), onSelectionChange) {
|
|
11080
|
+
const selectedRowsData = sortedData.filter((row => _includesInstanceProperty(newSelectedIds).call(newSelectedIds, getRowId$1(row, rowKey))));
|
|
11081
|
+
onSelectionChange(selectedRowsData, newSelectedIds);
|
|
11082
|
+
}
|
|
11083
|
+
}), [ selectionMode, selectedRowIds, controlledSelectedRowIds, onSelectionChange, sortedData, rowKey ]), handleSelectAll = React.useCallback((selected => {
|
|
11084
|
+
if ("multiple" !== selectionMode) return;
|
|
11085
|
+
const newSelectedIds = selected ? paginatedData.map((row => getRowId$1(row, rowKey))) : [];
|
|
11086
|
+
if (controlledSelectedRowIds || setInternalSelectedRowIds(newSelectedIds), onSelectionChange) {
|
|
11087
|
+
const selectedRowsData = sortedData.filter((row => _includesInstanceProperty(newSelectedIds).call(newSelectedIds, getRowId$1(row, rowKey))));
|
|
11088
|
+
onSelectionChange(selectedRowsData, newSelectedIds);
|
|
11089
|
+
}
|
|
11090
|
+
}), [ selectionMode, paginatedData, sortedData, controlledSelectedRowIds, onSelectionChange, rowKey ]), isAllSelected = React.useMemo((() => "multiple" === selectionMode && 0 !== paginatedData.length && paginatedData.every((row => _includesInstanceProperty(selectedRowIds).call(selectedRowIds, getRowId$1(row, rowKey))))), [ selectionMode, paginatedData, selectedRowIds, rowKey ]), isIndeterminate = React.useMemo((() => {
|
|
11091
|
+
if ("multiple" !== selectionMode || 0 === paginatedData.length) return !1;
|
|
11092
|
+
const selectedCount = paginatedData.filter((row => _includesInstanceProperty(selectedRowIds).call(selectedRowIds, getRowId$1(row, rowKey)))).length;
|
|
11093
|
+
return selectedCount > 0 && selectedCount < paginatedData.length;
|
|
11094
|
+
}), [ selectionMode, paginatedData, selectedRowIds, rowKey ]), handleColumnVisibilityToggle = React.useCallback((columnKey => {
|
|
11095
|
+
setColumnVisibility((prev => {
|
|
11096
|
+
const updated = {
|
|
11097
|
+
...prev,
|
|
11098
|
+
[columnKey]: !prev[columnKey]
|
|
11099
|
+
};
|
|
11100
|
+
if (onColumnVisibilityChange) {
|
|
11101
|
+
const visibleKeys = Object.entries(updated).filter((([, visible]) => visible)).map((([key]) => key));
|
|
11102
|
+
onColumnVisibilityChange(visibleKeys);
|
|
11103
|
+
}
|
|
11104
|
+
return updated;
|
|
11105
|
+
}));
|
|
11106
|
+
}), [ onColumnVisibilityChange ]);
|
|
11107
|
+
// Handle sorting
|
|
11108
|
+
// Handle column reorder
|
|
11109
|
+
return React.useCallback(((fromIndex, toIndex) => {
|
|
11110
|
+
const newOrder = [ ...columnOrder ], [removed] = newOrder.splice(fromIndex, 1);
|
|
11111
|
+
removed && (newOrder.splice(toIndex, 0, removed), setColumnOrder(newOrder), onColumnReorder && onColumnReorder(newOrder));
|
|
11112
|
+
}), [ columnOrder, onColumnReorder ]),
|
|
11113
|
+
// Reset to first page when data changes
|
|
11114
|
+
React.useEffect((() => {
|
|
11115
|
+
setCurrentPage(1);
|
|
11116
|
+
}), [ data ]),
|
|
11117
|
+
// Reset current page if it's out of bounds
|
|
11118
|
+
React.useEffect((() => {
|
|
11119
|
+
currentPage > totalPages && totalPages > 0 && setCurrentPage(Math.max(1, totalPages));
|
|
11120
|
+
}), [ currentPage, totalPages ]), {
|
|
11121
|
+
displayData: paginatedData,
|
|
11122
|
+
sortConfig: sortConfig,
|
|
11123
|
+
currentPage: currentPage,
|
|
11124
|
+
totalPages: totalPages,
|
|
11125
|
+
handleSort: handleSort,
|
|
11126
|
+
handlePageChange: handlePageChange,
|
|
11127
|
+
handleSearch: handleSearch,
|
|
11128
|
+
selectedRowIds: selectedRowIds,
|
|
11129
|
+
selectedRows: selectedRows,
|
|
11130
|
+
handleRowSelect: handleRowSelect,
|
|
11131
|
+
handleSelectAll: handleSelectAll,
|
|
11132
|
+
isAllSelected: isAllSelected,
|
|
11133
|
+
isIndeterminate: isIndeterminate,
|
|
11134
|
+
columnOrder: columnOrder,
|
|
11135
|
+
visibleColumns: visibleColumns,
|
|
11136
|
+
columnVisibility: columnVisibility,
|
|
11137
|
+
handleColumnVisibilityToggle: handleColumnVisibilityToggle,
|
|
11138
|
+
columnFilterValues: columnFilterValues,
|
|
11139
|
+
handleColumnFilterChange: handleColumnFilterChange,
|
|
11140
|
+
clearColumnFilters: clearColumnFilters
|
|
11141
|
+
};
|
|
11142
|
+
}({
|
|
10013
11143
|
data: data,
|
|
10014
11144
|
columns: columns,
|
|
10015
11145
|
sortable: sortable,
|
|
@@ -12361,297 +13491,6 @@ const DEFAULT_ATOMIX_FONTS = [ {
|
|
|
12361
13491
|
};
|
|
12362
13492
|
}
|
|
12363
13493
|
|
|
12364
|
-
/**
|
|
12365
|
-
* Breadcrumb state and functionality
|
|
12366
|
-
* @param initialOptions - Initial breadcrumb options
|
|
12367
|
-
* @returns Breadcrumb state and methods
|
|
12368
|
-
*/ function useBreadcrumb(initialOptions) {
|
|
12369
|
-
return {
|
|
12370
|
-
defaultOptions: {
|
|
12371
|
-
items: [],
|
|
12372
|
-
divider: BREADCRUMB.DEFAULTS.DIVIDER,
|
|
12373
|
-
className: "",
|
|
12374
|
-
"aria-label": "Breadcrumb",
|
|
12375
|
-
...initialOptions
|
|
12376
|
-
},
|
|
12377
|
-
generateBreadcrumbClass: options => {
|
|
12378
|
-
const {className: className = ""} = options;
|
|
12379
|
-
return [ BREADCRUMB.CLASSES.BASE, className ].filter(Boolean).join(" ").trim();
|
|
12380
|
-
},
|
|
12381
|
-
generateItemClass: (item, isLast) => [ BREADCRUMB.CLASSES.ITEM, item.active || isLast ? BREADCRUMB.CLASSES.ACTIVE : "" ].filter(Boolean).join(" ").trim(),
|
|
12382
|
-
isItemLink: (item, isLast) => Boolean(item.href && !item.active && !isLast),
|
|
12383
|
-
parseItemsFromJson: jsonString => {
|
|
12384
|
-
try {
|
|
12385
|
-
return JSON.parse(jsonString);
|
|
12386
|
-
} catch (error) {
|
|
12387
|
-
return console.error("Error parsing breadcrumb items:", error), [];
|
|
12388
|
-
}
|
|
12389
|
-
}
|
|
12390
|
-
};
|
|
12391
|
-
}
|
|
12392
|
-
|
|
12393
|
-
/**
|
|
12394
|
-
* Hook for managing modal state
|
|
12395
|
-
*/ function useModal$1({isOpen: isOpenProp, onOpenChange: onOpenChange, onOpen: onOpen, onClose: onClose} = {}) {
|
|
12396
|
-
// For uncontrolled usage
|
|
12397
|
-
const [isOpenState, setIsOpenState] = React.useState(!1), isControlled = void 0 !== isOpenProp, isOpen = isControlled ? !!isOpenProp : isOpenState;
|
|
12398
|
-
// Determine if we're in controlled or uncontrolled mode
|
|
12399
|
-
// Update internal state when prop changes (for controlled mode)
|
|
12400
|
-
React.useEffect((() => {
|
|
12401
|
-
isControlled && setIsOpenState(!!isOpenProp);
|
|
12402
|
-
}), [ isOpenProp, isControlled ]);
|
|
12403
|
-
const updateOpen = React.useCallback((nextIsOpen => {
|
|
12404
|
-
// For uncontrolled mode, update internal state
|
|
12405
|
-
isControlled || setIsOpenState(nextIsOpen),
|
|
12406
|
-
// Call the change handler in either mode
|
|
12407
|
-
onOpenChange && onOpenChange(nextIsOpen),
|
|
12408
|
-
// Call the specific handler
|
|
12409
|
-
nextIsOpen && onOpen ? onOpen() : !nextIsOpen && onClose && onClose();
|
|
12410
|
-
}), [ isControlled, onOpenChange, onOpen, onClose ]), open = React.useCallback((() => {
|
|
12411
|
-
updateOpen(!0);
|
|
12412
|
-
}), [ updateOpen ]), close = React.useCallback((() => {
|
|
12413
|
-
updateOpen(!1);
|
|
12414
|
-
}), [ updateOpen ]), toggle = React.useCallback((() => {
|
|
12415
|
-
updateOpen(!isOpen);
|
|
12416
|
-
}), [ isOpen, updateOpen ]);
|
|
12417
|
-
return {
|
|
12418
|
-
isOpen: isOpen,
|
|
12419
|
-
open: open,
|
|
12420
|
-
close: close,
|
|
12421
|
-
toggle: toggle
|
|
12422
|
-
};
|
|
12423
|
-
}
|
|
12424
|
-
|
|
12425
|
-
function useSlider(options) {
|
|
12426
|
-
const {slides: rawSlides, 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, slides = Array.isArray(rawSlides) ? rawSlides : [], containerRef = React.useRef(null), wrapperRef = React.useRef(null), repositioningRef = React.useRef(!1), autoplayRef = React.useRef(null), [autoplayRunning, setAutoplayRunning] = React.useState(!1), sliderStateRef = React.useRef({
|
|
12427
|
-
isTransitioning: !1,
|
|
12428
|
-
loop: loop,
|
|
12429
|
-
slides: slides,
|
|
12430
|
-
slidesToShow: slidesToShow,
|
|
12431
|
-
speed: speed,
|
|
12432
|
-
onSlideChange: onSlideChange
|
|
12433
|
-
}), [realIndex, setRealIndex] = React.useState(initialSlide), [internalIndex, setInternalIndex] = React.useState(0), [isTransitioning, setIsTransitioning] = React.useState(!1), [containerSize, setContainerSize] = React.useState(0), [touching, setTouching] = React.useState(!1), [touchStart, setTouchStart] = React.useState(0), [dragOffset, setDragOffset] = React.useState(0), slideWidth = React.useMemo((() => 0 === containerSize ? 0 : (containerSize - spaceBetween * (slidesToShow - 1)) / slidesToShow), [ containerSize, spaceBetween, slidesToShow ]), allSlides = React.useMemo((() => loop && 0 !== slides.length ? [ ...slides.map(((slide, i) => ({
|
|
12434
|
-
...slide,
|
|
12435
|
-
id: `set1-${slide.id || i}`
|
|
12436
|
-
}))), ...slides.map(((slide, i) => ({
|
|
12437
|
-
...slide,
|
|
12438
|
-
id: `set2-${slide.id || i}`
|
|
12439
|
-
}))), ...slides.map(((slide, i) => ({
|
|
12440
|
-
...slide,
|
|
12441
|
-
id: `set3-${slide.id || i}`
|
|
12442
|
-
}))) ] : slides), [ slides, loop ]), loopedSlides = slides.length, translateValue = React.useMemo((() => 0 === slideWidth ? 0 : -internalIndex * slideWidth + dragOffset), [ slideWidth, internalIndex, dragOffset ]);
|
|
12443
|
-
// Update the ref whenever the relevant state/props change
|
|
12444
|
-
React.useEffect((() => {
|
|
12445
|
-
sliderStateRef.current = {
|
|
12446
|
-
isTransitioning: isTransitioning,
|
|
12447
|
-
loop: loop,
|
|
12448
|
-
slides: slides,
|
|
12449
|
-
slidesToShow: slidesToShow,
|
|
12450
|
-
speed: speed,
|
|
12451
|
-
onSlideChange: onSlideChange
|
|
12452
|
-
};
|
|
12453
|
-
}), [ isTransitioning, loop, slides, slidesToShow, speed, onSlideChange ]),
|
|
12454
|
-
// Autoplay effect
|
|
12455
|
-
React.useEffect((() => {
|
|
12456
|
-
if (!autoplay) return autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12457
|
-
autoplayRef.current = null), void setAutoplayRunning(!1);
|
|
12458
|
-
const autoplayParams = "boolean" == typeof autoplay ? {
|
|
12459
|
-
delay: 3e3
|
|
12460
|
-
} : autoplay, {delay: delay = 3e3, pauseOnMouseEnter: pauseOnMouseEnter = !1, disableOnInteraction: disableOnInteraction = !1, reverseDirection: reverseDirection = !1} = autoplayParams;
|
|
12461
|
-
// Clear any existing interval
|
|
12462
|
-
autoplayRef.current && clearInterval(autoplayRef.current),
|
|
12463
|
-
// Create new interval
|
|
12464
|
-
autoplayRef.current = setInterval((() => {
|
|
12465
|
-
// Use ref to get the latest state without resetting the interval
|
|
12466
|
-
const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
|
|
12467
|
-
// We need to use a functional update to get the latest values
|
|
12468
|
-
setRealIndex((prevRealIndex => {
|
|
12469
|
-
if (currentIsTransitioning) return prevRealIndex;
|
|
12470
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12471
|
-
let nextIndex;
|
|
12472
|
-
// Trigger the slide change
|
|
12473
|
-
if (disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12474
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
|
|
12475
|
-
reverseDirection) {
|
|
12476
|
-
// For reverse direction, we would go to previous slide
|
|
12477
|
-
const prevIndex = currentLoop ? 0 === prevRealIndex ? currentSlides.length - 1 : prevRealIndex - 1 : Math.max(prevRealIndex - 1, 0);
|
|
12478
|
-
return setInternalIndex(currentLoop ? currentSlides.length + prevIndex : prevIndex),
|
|
12479
|
-
setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
|
|
12480
|
-
setIsTransitioning(!1), currentOnSlideChange?.(prevIndex);
|
|
12481
|
-
}), currentSpeed), prevIndex;
|
|
12482
|
-
}
|
|
12483
|
-
// Normal direction
|
|
12484
|
-
return setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex),
|
|
12485
|
-
setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
|
|
12486
|
-
setIsTransitioning(!1), currentOnSlideChange?.(nextIndex),
|
|
12487
|
-
// Reposition after transition ends for looped sliders
|
|
12488
|
-
currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
|
|
12489
|
-
setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
|
|
12490
|
-
repositioningRef.current = !1;
|
|
12491
|
-
}), 0));
|
|
12492
|
-
}), currentSpeed), nextIndex;
|
|
12493
|
-
}));
|
|
12494
|
-
}), delay), setAutoplayRunning(!0);
|
|
12495
|
-
// Handle pause on mouse enter/leave if enabled
|
|
12496
|
-
let containerElement = null;
|
|
12497
|
-
const handleMouseEnter = () => {
|
|
12498
|
-
autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null,
|
|
12499
|
-
setAutoplayRunning(!1));
|
|
12500
|
-
}, handleMouseLeave = () => {
|
|
12501
|
-
// Restart autoplay
|
|
12502
|
-
autoplayRef.current && clearInterval(autoplayRef.current), autoplayRef.current = setInterval((() => {
|
|
12503
|
-
const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
|
|
12504
|
-
setRealIndex((prevRealIndex => {
|
|
12505
|
-
if (currentIsTransitioning) return prevRealIndex;
|
|
12506
|
-
let nextIndex;
|
|
12507
|
-
return nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
|
|
12508
|
-
setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex), setIsTransitioning(!0),
|
|
12509
|
-
setDragOffset(0), setTimeout((() => {
|
|
12510
|
-
setIsTransitioning(!1), currentOnSlideChange?.(nextIndex), currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
|
|
12511
|
-
setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
|
|
12512
|
-
repositioningRef.current = !1;
|
|
12513
|
-
}), 0));
|
|
12514
|
-
}), currentSpeed), nextIndex;
|
|
12515
|
-
}));
|
|
12516
|
-
}), delay), setAutoplayRunning(!0);
|
|
12517
|
-
};
|
|
12518
|
-
// Cleanup
|
|
12519
|
-
return pauseOnMouseEnter && containerRef.current && (containerElement = containerRef.current,
|
|
12520
|
-
containerElement.addEventListener("mouseenter", handleMouseEnter), containerElement.addEventListener("mouseleave", handleMouseLeave)),
|
|
12521
|
-
() => {
|
|
12522
|
-
autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null),
|
|
12523
|
-
containerElement && (containerElement.removeEventListener("mouseenter", handleMouseEnter),
|
|
12524
|
-
containerElement.removeEventListener("mouseleave", handleMouseLeave)), setAutoplayRunning(!1);
|
|
12525
|
-
};
|
|
12526
|
-
}), [ autoplay, repositioningRef ]),
|
|
12527
|
-
// Initialize
|
|
12528
|
-
React.useEffect((() => {
|
|
12529
|
-
setInternalIndex(loop ? slides.length + initialSlide : initialSlide);
|
|
12530
|
-
}), [ loop, slides.length, initialSlide ]), React.useEffect((() => {
|
|
12531
|
-
const updateSize = () => {
|
|
12532
|
-
if (containerRef.current) {
|
|
12533
|
-
const size = "horizontal" === direction ? containerRef.current.offsetWidth : containerRef.current.offsetHeight;
|
|
12534
|
-
setContainerSize(size);
|
|
12535
|
-
}
|
|
12536
|
-
};
|
|
12537
|
-
return updateSize(), window.addEventListener("resize", updateSize), () => window.removeEventListener("resize", updateSize);
|
|
12538
|
-
}), [ direction ]);
|
|
12539
|
-
const slideNext = React.useCallback((() => {
|
|
12540
|
-
if (!isTransitioning) if (
|
|
12541
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12542
|
-
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12543
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), loop) {
|
|
12544
|
-
const nextRealIndex = (realIndex + 1) % slides.length, nextInternalIndex = internalIndex + 1;
|
|
12545
|
-
setRealIndex(nextRealIndex), setInternalIndex(nextInternalIndex), setIsTransitioning(!0),
|
|
12546
|
-
setDragOffset(0), setTimeout((() => {
|
|
12547
|
-
setIsTransitioning(!1), onSlideChange?.(nextRealIndex),
|
|
12548
|
-
// Reposition after transition ends
|
|
12549
|
-
nextInternalIndex >= 2 * slides.length && (repositioningRef.current = !0, setInternalIndex(slides.length + nextRealIndex),
|
|
12550
|
-
setTimeout((() => {
|
|
12551
|
-
repositioningRef.current = !1;
|
|
12552
|
-
}), 0));
|
|
12553
|
-
}), speed);
|
|
12554
|
-
} else {
|
|
12555
|
-
const nextIndex = Math.min(realIndex + 1, slides.length - slidesToShow);
|
|
12556
|
-
setRealIndex(nextIndex), setInternalIndex(nextIndex), setIsTransitioning(!0), setDragOffset(0),
|
|
12557
|
-
setTimeout((() => {
|
|
12558
|
-
setIsTransitioning(!1), onSlideChange?.(nextIndex);
|
|
12559
|
-
}), speed);
|
|
12560
|
-
}
|
|
12561
|
-
}), [ realIndex, internalIndex, slides.length, slidesToShow, loop, isTransitioning, speed, onSlideChange, allSlides.length, loopedSlides, autoplay ]), slidePrev = React.useCallback((() => {
|
|
12562
|
-
if (!isTransitioning) if (
|
|
12563
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12564
|
-
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12565
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), loop) {
|
|
12566
|
-
const prevRealIndex = 0 === realIndex ? slides.length - 1 : realIndex - 1, prevInternalIndex = internalIndex - 1;
|
|
12567
|
-
setRealIndex(prevRealIndex), setInternalIndex(prevInternalIndex), setIsTransitioning(!0),
|
|
12568
|
-
setDragOffset(0), setTimeout((() => {
|
|
12569
|
-
setIsTransitioning(!1), onSlideChange?.(prevRealIndex),
|
|
12570
|
-
// Reposition after transition ends
|
|
12571
|
-
prevInternalIndex < slides.length && (repositioningRef.current = !0, setInternalIndex(slides.length + prevRealIndex),
|
|
12572
|
-
setTimeout((() => {
|
|
12573
|
-
repositioningRef.current = !1;
|
|
12574
|
-
}), 0));
|
|
12575
|
-
}), speed);
|
|
12576
|
-
} else {
|
|
12577
|
-
const prevIndex = Math.max(realIndex - 1, 0);
|
|
12578
|
-
setRealIndex(prevIndex), setInternalIndex(prevIndex), setIsTransitioning(!0), setDragOffset(0),
|
|
12579
|
-
setTimeout((() => {
|
|
12580
|
-
setIsTransitioning(!1), onSlideChange?.(prevIndex);
|
|
12581
|
-
}), speed);
|
|
12582
|
-
}
|
|
12583
|
-
}), [ realIndex, internalIndex, slides.length, loop, isTransitioning, speed, onSlideChange, allSlides.length, loopedSlides, autoplay ]), goToSlide = React.useCallback((index => {
|
|
12584
|
-
isTransitioning || index === realIndex || (
|
|
12585
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12586
|
-
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12587
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), setIsTransitioning(!0), setDragOffset(0),
|
|
12588
|
-
setRealIndex(index), setInternalIndex(loop ? slides.length + index : index), setTimeout((() => {
|
|
12589
|
-
setIsTransitioning(!1), onSlideChange?.(index);
|
|
12590
|
-
}), speed));
|
|
12591
|
-
}), [ realIndex, isTransitioning, speed, onSlideChange, loop, loopedSlides, autoplay ]), handleTouchStart = React.useCallback((e => {
|
|
12592
|
-
if (!allowTouchMove) return;
|
|
12593
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12594
|
-
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12595
|
-
autoplayRef.current = null, setAutoplayRunning(!1));
|
|
12596
|
-
const client = "horizontal" === direction ? "touches" in e ? e.touches[0]?.clientX || 0 : e.clientX : "touches" in e ? e.touches[0]?.clientY || 0 : e.clientY;
|
|
12597
|
-
setTouchStart(client), setTouching(!0), setDragOffset(0);
|
|
12598
|
-
}), [ allowTouchMove, direction, autoplay ]), handleTouchMove = React.useCallback((e => {
|
|
12599
|
-
if (!touching || !allowTouchMove) return;
|
|
12600
|
-
const client = "horizontal" === direction ? "touches" in e ? e.touches[0]?.clientX || 0 : e.clientX : "touches" in e ? e.touches[0]?.clientY || 0 : e.clientY, diff = touchStart - client;
|
|
12601
|
-
Math.abs(diff) > 10 && (e.preventDefault(), setDragOffset(.5 * -diff));
|
|
12602
|
-
}), [ touching, touchStart, allowTouchMove, direction ]), handleTouchEnd = React.useCallback((e => {
|
|
12603
|
-
if (!touching || !allowTouchMove) return;
|
|
12604
|
-
const client = "horizontal" === direction ? "changedTouches" in e ? e.changedTouches[0]?.clientX || 0 : e.clientX : "changedTouches" in e ? e.changedTouches[0]?.clientY || 0 : e.clientY, diff = touchStart - client;
|
|
12605
|
-
setTouching(!1), setDragOffset(0), Math.abs(diff) > threshold && (diff > 0 ? slideNext() : slidePrev());
|
|
12606
|
-
}), [ touching, touchStart, threshold, slideNext, slidePrev, allowTouchMove, direction ]), canSlideNext = loop || realIndex < slides.length - slidesToShow, canSlidePrev = loop || realIndex > 0;
|
|
12607
|
-
return {
|
|
12608
|
-
activeIndex: realIndex,
|
|
12609
|
-
realIndex: realIndex,
|
|
12610
|
-
previousIndex: realIndex,
|
|
12611
|
-
isBeginning: !loop && 0 === realIndex,
|
|
12612
|
-
isEnd: !loop && realIndex >= slides.length - slidesToShow,
|
|
12613
|
-
progress: slides.length > 0 ? realIndex / (slides.length - 1) : 0,
|
|
12614
|
-
autoplayRunning: autoplayRunning,
|
|
12615
|
-
transitioning: isTransitioning,
|
|
12616
|
-
touching: touching,
|
|
12617
|
-
translate: translateValue,
|
|
12618
|
-
slidesPerView: slidesToShow,
|
|
12619
|
-
slidesCount: slides.length,
|
|
12620
|
-
isLocked: !1,
|
|
12621
|
-
destroyed: !1,
|
|
12622
|
-
size: containerSize,
|
|
12623
|
-
touches: {
|
|
12624
|
-
startX: 0,
|
|
12625
|
-
startY: 0,
|
|
12626
|
-
currentX: 0,
|
|
12627
|
-
currentY: 0,
|
|
12628
|
-
diff: 0
|
|
12629
|
-
},
|
|
12630
|
-
allowSlideNext: canSlideNext,
|
|
12631
|
-
allowSlidePrev: canSlidePrev,
|
|
12632
|
-
allowTouchMove: allowTouchMove,
|
|
12633
|
-
animating: isTransitioning,
|
|
12634
|
-
enabled: !0,
|
|
12635
|
-
initialized: !0,
|
|
12636
|
-
slideNext: slideNext,
|
|
12637
|
-
slidePrev: slidePrev,
|
|
12638
|
-
goToSlide: goToSlide,
|
|
12639
|
-
canSlideNext: canSlideNext,
|
|
12640
|
-
canSlidePrev: canSlidePrev,
|
|
12641
|
-
containerRef: containerRef,
|
|
12642
|
-
wrapperRef: wrapperRef,
|
|
12643
|
-
handleTouchStart: handleTouchStart,
|
|
12644
|
-
handleTouchMove: handleTouchMove,
|
|
12645
|
-
handleTouchEnd: handleTouchEnd,
|
|
12646
|
-
allSlides: allSlides,
|
|
12647
|
-
translateValue: translateValue,
|
|
12648
|
-
slideWidth: slideWidth,
|
|
12649
|
-
currentSlidesToShow: slidesToShow,
|
|
12650
|
-
loopedSlides: loopedSlides,
|
|
12651
|
-
repositioningRef: repositioningRef
|
|
12652
|
-
};
|
|
12653
|
-
}
|
|
12654
|
-
|
|
12655
13494
|
/**
|
|
12656
13495
|
* Simplified hook for chart data processing
|
|
12657
13496
|
*/ function useChartData(data) {
|
|
@@ -12752,37 +13591,44 @@ function useSlider(options) {
|
|
|
12752
13591
|
// Accordion composables
|
|
12753
13592
|
var composablesImport = Object.freeze({
|
|
12754
13593
|
__proto__: null,
|
|
12755
|
-
|
|
13594
|
+
BALANCED_PRESET: BALANCED_PRESET,
|
|
13595
|
+
DEFAULT_BREAKPOINTS: DEFAULT_BREAKPOINTS,
|
|
13596
|
+
DeviceDetector: DeviceDetector,
|
|
13597
|
+
MOBILE_OPTIMIZED_BREAKPOINTS: MOBILE_OPTIMIZED_BREAKPOINTS,
|
|
13598
|
+
PERFORMANCE_PRESET: PERFORMANCE_PRESET,
|
|
13599
|
+
PerformanceOverlay: PerformanceOverlay,
|
|
13600
|
+
QUALITY_PRESET: QUALITY_PRESET,
|
|
13601
|
+
createBreakpoints: createBreakpoints$1,
|
|
13602
|
+
getDefaultBreakpoints: getDefaultBreakpoints,
|
|
13603
|
+
getDevicePreset: getDevicePreset,
|
|
13604
|
+
getMobileOptimizedParams: getMobileOptimizedParams,
|
|
13605
|
+
getQualityMultipliers: getQualityMultipliers,
|
|
12756
13606
|
useAccordion: useAccordion,
|
|
12757
13607
|
useAtomixGlass: useAtomixGlass,
|
|
12758
13608
|
useBadge: useBadge,
|
|
12759
13609
|
useBarChart: useBarChart,
|
|
12760
13610
|
useBlock: useBlock,
|
|
12761
|
-
useBreadcrumb: useBreadcrumb,
|
|
12762
|
-
useCard: useCard,
|
|
12763
13611
|
useChartData: useChartData,
|
|
12764
13612
|
useChartInteraction: useChartInteraction,
|
|
12765
13613
|
useChartScale: useChartScale,
|
|
12766
|
-
useDataTable: useDataTable,
|
|
12767
13614
|
useEdgePanel: useEdgePanel,
|
|
12768
13615
|
useForm: useForm,
|
|
12769
13616
|
useFormGroup: useFormGroup,
|
|
12770
13617
|
useHero: useHero,
|
|
12771
13618
|
useInput: useInput,
|
|
12772
13619
|
useLineChart: useLineChart,
|
|
12773
|
-
useModal: useModal$1,
|
|
12774
13620
|
useNav: useNav,
|
|
12775
13621
|
useNavDropdown: useNavDropdown,
|
|
12776
13622
|
useNavItem: useNavItem,
|
|
12777
13623
|
useNavbar: useNavbar,
|
|
12778
|
-
|
|
13624
|
+
usePerformanceMonitor: usePerformanceMonitor,
|
|
12779
13625
|
usePieChart: usePieChart,
|
|
12780
13626
|
useRadio: useRadio,
|
|
13627
|
+
useResponsiveGlass: useResponsiveGlass,
|
|
12781
13628
|
useRiver: useRiver,
|
|
12782
13629
|
useSelect: useSelect,
|
|
12783
13630
|
useSideMenu: useSideMenu,
|
|
12784
13631
|
useSideMenuItem: useSideMenuItem,
|
|
12785
|
-
useSlider: useSlider,
|
|
12786
13632
|
useSpinner: useSpinner,
|
|
12787
13633
|
useTextarea: useTextarea,
|
|
12788
13634
|
useTodo: useTodo
|
|
@@ -12873,7 +13719,10 @@ const Select = React.memo((({options: options, value: value, onChange: onChange
|
|
|
12873
13719
|
};
|
|
12874
13720
|
}), []);
|
|
12875
13721
|
// Toggle dropdown
|
|
12876
|
-
const
|
|
13722
|
+
const handleToggle = () => {
|
|
13723
|
+
disabled || (!isOpen && bodyRef.current && panelRef.current ? bodyRef.current.style.height = `${panelRef.current.clientHeight}px` : bodyRef.current && (bodyRef.current.style.height = "0px"),
|
|
13724
|
+
setIsOpen(!isOpen));
|
|
13725
|
+
}, handleItemClick = React.useCallback((option => {
|
|
12877
13726
|
if (setSelectedLabel(option.label), setIsOpen(!1), bodyRef.current && (bodyRef.current.style.height = "0px"),
|
|
12878
13727
|
nativeSelectRef.current && (nativeSelectRef.current.value = option.value), onChange) {
|
|
12879
13728
|
// Create a synthetic event
|
|
@@ -12917,7 +13766,15 @@ const Select = React.memo((({options: options, value: value, onChange: onChange
|
|
|
12917
13766
|
"aria-describedby": ariaDescribedBy,
|
|
12918
13767
|
"aria-invalid": invalid,
|
|
12919
13768
|
style: {
|
|
12920
|
-
|
|
13769
|
+
position: "absolute",
|
|
13770
|
+
width: "1px",
|
|
13771
|
+
height: "1px",
|
|
13772
|
+
padding: "0",
|
|
13773
|
+
margin: "-1px",
|
|
13774
|
+
overflow: "hidden",
|
|
13775
|
+
clip: "rect(0, 0, 0, 0)",
|
|
13776
|
+
whiteSpace: "nowrap",
|
|
13777
|
+
border: "0"
|
|
12921
13778
|
},
|
|
12922
13779
|
children: [ placeholder && jsxRuntime.jsx("option", {
|
|
12923
13780
|
value: "",
|
|
@@ -12930,11 +13787,29 @@ const Select = React.memo((({options: options, value: value, onChange: onChange
|
|
|
12930
13787
|
}, option.value))) ]
|
|
12931
13788
|
}), jsxRuntime.jsx("div", {
|
|
12932
13789
|
className: SELECT.CLASSES.SELECTED,
|
|
12933
|
-
onClick:
|
|
12934
|
-
|
|
12935
|
-
|
|
13790
|
+
onClick: handleToggle,
|
|
13791
|
+
onKeyDown: event => {
|
|
13792
|
+
if (!disabled) switch (event.key) {
|
|
13793
|
+
case "Enter":
|
|
13794
|
+
case " ":
|
|
13795
|
+
event.preventDefault(), handleToggle();
|
|
13796
|
+
break;
|
|
13797
|
+
|
|
13798
|
+
case "Escape":
|
|
13799
|
+
isOpen && (event.preventDefault(), setIsOpen(!1), bodyRef.current && (bodyRef.current.style.height = "0px"));
|
|
13800
|
+
break;
|
|
13801
|
+
|
|
13802
|
+
case "ArrowDown":
|
|
13803
|
+
case "ArrowUp":
|
|
13804
|
+
isOpen || (event.preventDefault(), handleToggle());
|
|
13805
|
+
}
|
|
12936
13806
|
},
|
|
12937
13807
|
"aria-disabled": disabled,
|
|
13808
|
+
tabIndex: disabled ? -1 : 0,
|
|
13809
|
+
role: "combobox",
|
|
13810
|
+
"aria-haspopup": "listbox",
|
|
13811
|
+
"aria-expanded": isOpen,
|
|
13812
|
+
"aria-controls": id ? `${id}-listbox` : void 0,
|
|
12938
13813
|
children: selectedLabel
|
|
12939
13814
|
}), jsxRuntime.jsx("i", {
|
|
12940
13815
|
className: `${SELECT.CLASSES.ICON_CARET} ${SELECT.CLASSES.TOGGLE_ICON}`
|
|
@@ -12949,10 +13824,16 @@ const Select = React.memo((({options: options, value: value, onChange: onChange
|
|
|
12949
13824
|
ref: panelRef,
|
|
12950
13825
|
children: jsxRuntime.jsx("ul", {
|
|
12951
13826
|
className: SELECT.CLASSES.SELECT_ITEMS,
|
|
13827
|
+
role: "listbox",
|
|
13828
|
+
id: id ? `${id}-listbox` : void 0,
|
|
13829
|
+
"aria-labelledby": id,
|
|
12952
13830
|
children: hasOptionsProp ? options.map(((option, index) => jsxRuntime.jsx("li", {
|
|
12953
13831
|
className: SELECT.CLASSES.SELECT_ITEM,
|
|
12954
13832
|
"data-value": option.value,
|
|
12955
13833
|
onClick: () => !option.disabled && handleItemClick(option),
|
|
13834
|
+
role: "option",
|
|
13835
|
+
"aria-selected": value === option.value,
|
|
13836
|
+
"aria-disabled": option.disabled,
|
|
12956
13837
|
children: jsxRuntime.jsxs("label", {
|
|
12957
13838
|
htmlFor: `SelectItem${index}`,
|
|
12958
13839
|
className: "c-checkbox",
|
|
@@ -14495,7 +15376,45 @@ const ModalImpl = React.memo((({children: children, isOpen: isOpen = !1, onOpen
|
|
|
14495
15376
|
onOpenChange: onOpenChange,
|
|
14496
15377
|
onClose: onClose,
|
|
14497
15378
|
onOpen: onOpen
|
|
14498
|
-
})
|
|
15379
|
+
}), contentRef =
|
|
15380
|
+
/**
|
|
15381
|
+
* Hook to trap focus within an element
|
|
15382
|
+
*/
|
|
15383
|
+
function(isOpen) {
|
|
15384
|
+
const containerRef = React.useRef(null), previouslyFocusedElement = React.useRef(null), getFocusableElements = React.useCallback((() => containerRef.current ? Array.from(containerRef.current.querySelectorAll('a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])')).filter((el => {
|
|
15385
|
+
// Check if visible
|
|
15386
|
+
const style = window.getComputedStyle(el);
|
|
15387
|
+
return "none" !== style.display && "hidden" !== style.visibility;
|
|
15388
|
+
})) : []), []), handleKeyDown = React.useCallback((event => {
|
|
15389
|
+
if ("Tab" !== event.key) return;
|
|
15390
|
+
const focusableElements = getFocusableElements();
|
|
15391
|
+
if (0 === focusableElements.length) return;
|
|
15392
|
+
const firstElement = focusableElements[0], lastElement = focusableElements[focusableElements.length - 1];
|
|
15393
|
+
event.shiftKey ?
|
|
15394
|
+
// Shift + Tab
|
|
15395
|
+
document.activeElement === firstElement && (event.preventDefault(), lastElement.focus()) :
|
|
15396
|
+
// Tab
|
|
15397
|
+
document.activeElement === lastElement && (event.preventDefault(), firstElement.focus());
|
|
15398
|
+
}), [ getFocusableElements ]);
|
|
15399
|
+
return React.useEffect((() => {
|
|
15400
|
+
if (isOpen) {
|
|
15401
|
+
previouslyFocusedElement.current = document.activeElement;
|
|
15402
|
+
const focusableElements = getFocusableElements();
|
|
15403
|
+
if (focusableElements.length > 0 && focusableElements[0]) {
|
|
15404
|
+
// Delay focus slightly to ensure element is rendered
|
|
15405
|
+
const firstEl = focusableElements[0];
|
|
15406
|
+
setTimeout((() => {
|
|
15407
|
+
firstEl.focus();
|
|
15408
|
+
}), 0);
|
|
15409
|
+
}
|
|
15410
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
15411
|
+
} else previouslyFocusedElement.current && previouslyFocusedElement.current.focus(),
|
|
15412
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
15413
|
+
return () => {
|
|
15414
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
15415
|
+
};
|
|
15416
|
+
}), [ isOpen, getFocusableElements, handleKeyDown ]), containerRef;
|
|
15417
|
+
}(isOpenState), instanceId = React.useId(), titleId = `modal-title-${instanceId}`, descId = `modal-desc-${instanceId}`;
|
|
14499
15418
|
// Handle keyboard events for Escape key
|
|
14500
15419
|
React.useEffect((() => {
|
|
14501
15420
|
if (!keyboard) return;
|
|
@@ -14513,15 +15432,19 @@ const ModalImpl = React.memo((({children: children, isOpen: isOpen = !1, onOpen
|
|
|
14513
15432
|
return React__default.default.isValidElement(child) && _includesInstanceProperty(_context = [ "ModalHeader", "ModalBody", "ModalFooter" ]).call(_context, child.type.displayName);
|
|
14514
15433
|
})), modalContent = jsxRuntime.jsx("div", {
|
|
14515
15434
|
className: "c-modal__content",
|
|
15435
|
+
ref: contentRef,
|
|
14516
15436
|
children: hasCompoundComponents ? React__default.default.Children.map(children, (child => React__default.default.isValidElement(child) && "ModalHeader" === child.type.displayName ? React__default.default.cloneElement(child, {
|
|
14517
|
-
onClose: child.props.onClose || close
|
|
15437
|
+
onClose: child.props.onClose || close,
|
|
15438
|
+
id: titleId
|
|
14518
15439
|
}) : child)) : jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
14519
15440
|
children: [ (title || closeButton) && jsxRuntime.jsx(ModalHeader, {
|
|
15441
|
+
id: titleId,
|
|
14520
15442
|
title: title,
|
|
14521
15443
|
subtitle: subtitle,
|
|
14522
15444
|
closeButton: closeButton,
|
|
14523
15445
|
onClose: close
|
|
14524
15446
|
}), jsxRuntime.jsx(ModalBody, {
|
|
15447
|
+
id: descId,
|
|
14525
15448
|
children: children
|
|
14526
15449
|
}), footer && jsxRuntime.jsx(ModalFooter, {
|
|
14527
15450
|
children: footer
|
|
@@ -14539,6 +15462,8 @@ const ModalImpl = React.memo((({children: children, isOpen: isOpen = !1, onOpen
|
|
|
14539
15462
|
role: "dialog",
|
|
14540
15463
|
"aria-modal": "true",
|
|
14541
15464
|
"aria-hidden": !isOpenState,
|
|
15465
|
+
"aria-labelledby": titleId,
|
|
15466
|
+
"aria-describedby": descId,
|
|
14542
15467
|
...props,
|
|
14543
15468
|
children: [ jsxRuntime.jsx("div", {
|
|
14544
15469
|
ref: backdropRef,
|
|
@@ -14791,7 +15716,27 @@ const Navbar = React.forwardRef((({brand: brand, children: children, variant: v
|
|
|
14791
15716
|
return window.addEventListener("resize", handleResize), () => {
|
|
14792
15717
|
window.removeEventListener("resize", handleResize);
|
|
14793
15718
|
};
|
|
14794
|
-
}), [ collapsible, expanded, onToggle ])
|
|
15719
|
+
}), [ collapsible, expanded, onToggle ]),
|
|
15720
|
+
// Handle Escape key to close mobile menu
|
|
15721
|
+
React.useEffect((() => {
|
|
15722
|
+
if (!navbarExpanded || !closeOnEscape) return;
|
|
15723
|
+
const handleEscapeKey = event => {
|
|
15724
|
+
"Escape" === event.key && ("function" == typeof onToggle ? onToggle(!1) : setNavbarExpanded(!1));
|
|
15725
|
+
};
|
|
15726
|
+
return document.addEventListener("keydown", handleEscapeKey), () => {
|
|
15727
|
+
document.removeEventListener("keydown", handleEscapeKey);
|
|
15728
|
+
};
|
|
15729
|
+
}), [ navbarExpanded, closeOnEscape, onToggle ]),
|
|
15730
|
+
// Handle outside click to close mobile menu
|
|
15731
|
+
React.useEffect((() => {
|
|
15732
|
+
if (!navbarExpanded || !closeOnOutsideClick) return;
|
|
15733
|
+
const handleClickOutside = event => {
|
|
15734
|
+
!collapseRef.current || collapseRef.current.contains(event.target) || event.target.closest(".c-navbar__toggler") || ("function" == typeof onToggle ? onToggle(!1) : setNavbarExpanded(!1));
|
|
15735
|
+
};
|
|
15736
|
+
return document.addEventListener("mousedown", handleClickOutside), () => {
|
|
15737
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
15738
|
+
};
|
|
15739
|
+
}), [ navbarExpanded, closeOnOutsideClick, onToggle ]);
|
|
14795
15740
|
// Generate the navbar class
|
|
14796
15741
|
const navbarClass = generateNavbarClass({
|
|
14797
15742
|
position: position,
|
|
@@ -17399,7 +18344,235 @@ const SectionIntro = ({title: title, label: label, text: text, actions: actions,
|
|
|
17399
18344
|
SectionIntro.displayName = "SectionIntro";
|
|
17400
18345
|
|
|
17401
18346
|
const Slider = React.forwardRef(((props, ref) => {
|
|
17402
|
-
const {slides: slides = [], height: height = 300, width: width = "100%", slidesToShow: slidesToShow = 1, spaceBetween: spaceBetween = 0, loop: loop = !1, initialSlide: initialSlide = 0, direction: direction = "horizontal", speed: speed = 300, allowTouchMove: allowTouchMove = !0, threshold: threshold = 50, grabCursor: grabCursor = !0, autoplay: autoplay, navigation: navigation, pagination: pagination, className: className, style: style, onSlideChange: onSlideChange, ...rest} = props, validSlides = Array.isArray(slides) ? slides : [], slider =
|
|
18347
|
+
const {slides: slides = [], height: height = 300, width: width = "100%", slidesToShow: slidesToShow = 1, spaceBetween: spaceBetween = 0, loop: loop = !1, initialSlide: initialSlide = 0, direction: direction = "horizontal", speed: speed = 300, allowTouchMove: allowTouchMove = !0, threshold: threshold = 50, grabCursor: grabCursor = !0, autoplay: autoplay, navigation: navigation, pagination: pagination, className: className, style: style, onSlideChange: onSlideChange, ...rest} = props, validSlides = Array.isArray(slides) ? slides : [], slider = function(options) {
|
|
18348
|
+
const {slides: rawSlides, 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, slides = Array.isArray(rawSlides) ? rawSlides : [], containerRef = React.useRef(null), wrapperRef = React.useRef(null), repositioningRef = React.useRef(!1), autoplayRef = React.useRef(null), [autoplayRunning, setAutoplayRunning] = React.useState(!1), sliderStateRef = React.useRef({
|
|
18349
|
+
isTransitioning: !1,
|
|
18350
|
+
loop: loop,
|
|
18351
|
+
slides: slides,
|
|
18352
|
+
slidesToShow: slidesToShow,
|
|
18353
|
+
speed: speed,
|
|
18354
|
+
onSlideChange: onSlideChange
|
|
18355
|
+
}), [realIndex, setRealIndex] = React.useState(initialSlide), [internalIndex, setInternalIndex] = React.useState(0), [isTransitioning, setIsTransitioning] = React.useState(!1), [containerSize, setContainerSize] = React.useState(0), [touching, setTouching] = React.useState(!1), [touchStart, setTouchStart] = React.useState(0), [dragOffset, setDragOffset] = React.useState(0), slideWidth = React.useMemo((() => 0 === containerSize ? 0 : (containerSize - spaceBetween * (slidesToShow - 1)) / slidesToShow), [ containerSize, spaceBetween, slidesToShow ]), allSlides = React.useMemo((() => loop && 0 !== slides.length ? [ ...slides.map(((slide, i) => ({
|
|
18356
|
+
...slide,
|
|
18357
|
+
id: `set1-${slide.id || i}`
|
|
18358
|
+
}))), ...slides.map(((slide, i) => ({
|
|
18359
|
+
...slide,
|
|
18360
|
+
id: `set2-${slide.id || i}`
|
|
18361
|
+
}))), ...slides.map(((slide, i) => ({
|
|
18362
|
+
...slide,
|
|
18363
|
+
id: `set3-${slide.id || i}`
|
|
18364
|
+
}))) ] : slides), [ slides, loop ]), loopedSlides = slides.length, translateValue = React.useMemo((() => 0 === slideWidth ? 0 : -internalIndex * slideWidth + dragOffset), [ slideWidth, internalIndex, dragOffset ]);
|
|
18365
|
+
// Update the ref whenever the relevant state/props change
|
|
18366
|
+
React.useEffect((() => {
|
|
18367
|
+
sliderStateRef.current = {
|
|
18368
|
+
isTransitioning: isTransitioning,
|
|
18369
|
+
loop: loop,
|
|
18370
|
+
slides: slides,
|
|
18371
|
+
slidesToShow: slidesToShow,
|
|
18372
|
+
speed: speed,
|
|
18373
|
+
onSlideChange: onSlideChange
|
|
18374
|
+
};
|
|
18375
|
+
}), [ isTransitioning, loop, slides, slidesToShow, speed, onSlideChange ]),
|
|
18376
|
+
// Autoplay effect
|
|
18377
|
+
React.useEffect((() => {
|
|
18378
|
+
if (!autoplay) return autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
18379
|
+
autoplayRef.current = null), void setAutoplayRunning(!1);
|
|
18380
|
+
const autoplayParams = "boolean" == typeof autoplay ? {
|
|
18381
|
+
delay: 3e3
|
|
18382
|
+
} : autoplay, {delay: delay = 3e3, pauseOnMouseEnter: pauseOnMouseEnter = !1, disableOnInteraction: disableOnInteraction = !1, reverseDirection: reverseDirection = !1} = autoplayParams;
|
|
18383
|
+
// Clear any existing interval
|
|
18384
|
+
autoplayRef.current && clearInterval(autoplayRef.current),
|
|
18385
|
+
// Create new interval
|
|
18386
|
+
autoplayRef.current = setInterval((() => {
|
|
18387
|
+
// Use ref to get the latest state without resetting the interval
|
|
18388
|
+
const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
|
|
18389
|
+
// We need to use a functional update to get the latest values
|
|
18390
|
+
setRealIndex((prevRealIndex => {
|
|
18391
|
+
if (currentIsTransitioning) return prevRealIndex;
|
|
18392
|
+
// Stop autoplay on interaction if disableOnInteraction is true
|
|
18393
|
+
let nextIndex;
|
|
18394
|
+
// Trigger the slide change
|
|
18395
|
+
if (disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
18396
|
+
autoplayRef.current = null, setAutoplayRunning(!1)), nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
|
|
18397
|
+
reverseDirection) {
|
|
18398
|
+
// For reverse direction, we would go to previous slide
|
|
18399
|
+
const prevIndex = currentLoop ? 0 === prevRealIndex ? currentSlides.length - 1 : prevRealIndex - 1 : Math.max(prevRealIndex - 1, 0);
|
|
18400
|
+
return setInternalIndex(currentLoop ? currentSlides.length + prevIndex : prevIndex),
|
|
18401
|
+
setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
|
|
18402
|
+
setIsTransitioning(!1), currentOnSlideChange?.(prevIndex);
|
|
18403
|
+
}), currentSpeed), prevIndex;
|
|
18404
|
+
}
|
|
18405
|
+
// Normal direction
|
|
18406
|
+
return setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex),
|
|
18407
|
+
setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
|
|
18408
|
+
setIsTransitioning(!1), currentOnSlideChange?.(nextIndex),
|
|
18409
|
+
// Reposition after transition ends for looped sliders
|
|
18410
|
+
currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
|
|
18411
|
+
setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
|
|
18412
|
+
repositioningRef.current = !1;
|
|
18413
|
+
}), 0));
|
|
18414
|
+
}), currentSpeed), nextIndex;
|
|
18415
|
+
}));
|
|
18416
|
+
}), delay), setAutoplayRunning(!0);
|
|
18417
|
+
// Handle pause on mouse enter/leave if enabled
|
|
18418
|
+
let containerElement = null;
|
|
18419
|
+
const handleMouseEnter = () => {
|
|
18420
|
+
autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null,
|
|
18421
|
+
setAutoplayRunning(!1));
|
|
18422
|
+
}, handleMouseLeave = () => {
|
|
18423
|
+
// Restart autoplay
|
|
18424
|
+
autoplayRef.current && clearInterval(autoplayRef.current), autoplayRef.current = setInterval((() => {
|
|
18425
|
+
const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
|
|
18426
|
+
setRealIndex((prevRealIndex => {
|
|
18427
|
+
if (currentIsTransitioning) return prevRealIndex;
|
|
18428
|
+
let nextIndex;
|
|
18429
|
+
return nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
|
|
18430
|
+
setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex), setIsTransitioning(!0),
|
|
18431
|
+
setDragOffset(0), setTimeout((() => {
|
|
18432
|
+
setIsTransitioning(!1), currentOnSlideChange?.(nextIndex), currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
|
|
18433
|
+
setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
|
|
18434
|
+
repositioningRef.current = !1;
|
|
18435
|
+
}), 0));
|
|
18436
|
+
}), currentSpeed), nextIndex;
|
|
18437
|
+
}));
|
|
18438
|
+
}), delay), setAutoplayRunning(!0);
|
|
18439
|
+
};
|
|
18440
|
+
// Cleanup
|
|
18441
|
+
return pauseOnMouseEnter && containerRef.current && (containerElement = containerRef.current,
|
|
18442
|
+
containerElement.addEventListener("mouseenter", handleMouseEnter), containerElement.addEventListener("mouseleave", handleMouseLeave)),
|
|
18443
|
+
() => {
|
|
18444
|
+
autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null),
|
|
18445
|
+
containerElement && (containerElement.removeEventListener("mouseenter", handleMouseEnter),
|
|
18446
|
+
containerElement.removeEventListener("mouseleave", handleMouseLeave)), setAutoplayRunning(!1);
|
|
18447
|
+
};
|
|
18448
|
+
}), [ autoplay, repositioningRef ]),
|
|
18449
|
+
// Initialize
|
|
18450
|
+
React.useEffect((() => {
|
|
18451
|
+
setInternalIndex(loop ? slides.length + initialSlide : initialSlide);
|
|
18452
|
+
}), [ loop, slides.length, initialSlide ]), React.useEffect((() => {
|
|
18453
|
+
const updateSize = () => {
|
|
18454
|
+
if (containerRef.current) {
|
|
18455
|
+
const size = "horizontal" === direction ? containerRef.current.offsetWidth : containerRef.current.offsetHeight;
|
|
18456
|
+
setContainerSize(size);
|
|
18457
|
+
}
|
|
18458
|
+
};
|
|
18459
|
+
return updateSize(), window.addEventListener("resize", updateSize), () => window.removeEventListener("resize", updateSize);
|
|
18460
|
+
}), [ direction ]);
|
|
18461
|
+
const slideNext = React.useCallback((() => {
|
|
18462
|
+
if (!isTransitioning) if (
|
|
18463
|
+
// Stop autoplay on interaction if disableOnInteraction is true
|
|
18464
|
+
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
18465
|
+
autoplayRef.current = null, setAutoplayRunning(!1)), loop) {
|
|
18466
|
+
const nextRealIndex = (realIndex + 1) % slides.length, nextInternalIndex = internalIndex + 1;
|
|
18467
|
+
setRealIndex(nextRealIndex), setInternalIndex(nextInternalIndex), setIsTransitioning(!0),
|
|
18468
|
+
setDragOffset(0), setTimeout((() => {
|
|
18469
|
+
setIsTransitioning(!1), onSlideChange?.(nextRealIndex),
|
|
18470
|
+
// Reposition after transition ends
|
|
18471
|
+
nextInternalIndex >= 2 * slides.length && (repositioningRef.current = !0, setInternalIndex(slides.length + nextRealIndex),
|
|
18472
|
+
setTimeout((() => {
|
|
18473
|
+
repositioningRef.current = !1;
|
|
18474
|
+
}), 0));
|
|
18475
|
+
}), speed);
|
|
18476
|
+
} else {
|
|
18477
|
+
const nextIndex = Math.min(realIndex + 1, slides.length - slidesToShow);
|
|
18478
|
+
setRealIndex(nextIndex), setInternalIndex(nextIndex), setIsTransitioning(!0), setDragOffset(0),
|
|
18479
|
+
setTimeout((() => {
|
|
18480
|
+
setIsTransitioning(!1), onSlideChange?.(nextIndex);
|
|
18481
|
+
}), speed);
|
|
18482
|
+
}
|
|
18483
|
+
}), [ realIndex, internalIndex, slides.length, slidesToShow, loop, isTransitioning, speed, onSlideChange, allSlides.length, loopedSlides, autoplay ]), slidePrev = React.useCallback((() => {
|
|
18484
|
+
if (!isTransitioning) if (
|
|
18485
|
+
// Stop autoplay on interaction if disableOnInteraction is true
|
|
18486
|
+
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
18487
|
+
autoplayRef.current = null, setAutoplayRunning(!1)), loop) {
|
|
18488
|
+
const prevRealIndex = 0 === realIndex ? slides.length - 1 : realIndex - 1, prevInternalIndex = internalIndex - 1;
|
|
18489
|
+
setRealIndex(prevRealIndex), setInternalIndex(prevInternalIndex), setIsTransitioning(!0),
|
|
18490
|
+
setDragOffset(0), setTimeout((() => {
|
|
18491
|
+
setIsTransitioning(!1), onSlideChange?.(prevRealIndex),
|
|
18492
|
+
// Reposition after transition ends
|
|
18493
|
+
prevInternalIndex < slides.length && (repositioningRef.current = !0, setInternalIndex(slides.length + prevRealIndex),
|
|
18494
|
+
setTimeout((() => {
|
|
18495
|
+
repositioningRef.current = !1;
|
|
18496
|
+
}), 0));
|
|
18497
|
+
}), speed);
|
|
18498
|
+
} else {
|
|
18499
|
+
const prevIndex = Math.max(realIndex - 1, 0);
|
|
18500
|
+
setRealIndex(prevIndex), setInternalIndex(prevIndex), setIsTransitioning(!0), setDragOffset(0),
|
|
18501
|
+
setTimeout((() => {
|
|
18502
|
+
setIsTransitioning(!1), onSlideChange?.(prevIndex);
|
|
18503
|
+
}), speed);
|
|
18504
|
+
}
|
|
18505
|
+
}), [ realIndex, internalIndex, slides.length, loop, isTransitioning, speed, onSlideChange, allSlides.length, loopedSlides, autoplay ]), goToSlide = React.useCallback((index => {
|
|
18506
|
+
isTransitioning || index === realIndex || (
|
|
18507
|
+
// Stop autoplay on interaction if disableOnInteraction is true
|
|
18508
|
+
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
18509
|
+
autoplayRef.current = null, setAutoplayRunning(!1)), setIsTransitioning(!0), setDragOffset(0),
|
|
18510
|
+
setRealIndex(index), setInternalIndex(loop ? slides.length + index : index), setTimeout((() => {
|
|
18511
|
+
setIsTransitioning(!1), onSlideChange?.(index);
|
|
18512
|
+
}), speed));
|
|
18513
|
+
}), [ realIndex, isTransitioning, speed, onSlideChange, loop, loopedSlides, autoplay ]), handleTouchStart = React.useCallback((e => {
|
|
18514
|
+
if (!allowTouchMove) return;
|
|
18515
|
+
// Stop autoplay on interaction if disableOnInteraction is true
|
|
18516
|
+
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
18517
|
+
autoplayRef.current = null, setAutoplayRunning(!1));
|
|
18518
|
+
const client = "horizontal" === direction ? "touches" in e ? e.touches[0]?.clientX || 0 : e.clientX : "touches" in e ? e.touches[0]?.clientY || 0 : e.clientY;
|
|
18519
|
+
setTouchStart(client), setTouching(!0), setDragOffset(0);
|
|
18520
|
+
}), [ allowTouchMove, direction, autoplay ]), handleTouchMove = React.useCallback((e => {
|
|
18521
|
+
if (!touching || !allowTouchMove) return;
|
|
18522
|
+
const client = "horizontal" === direction ? "touches" in e ? e.touches[0]?.clientX || 0 : e.clientX : "touches" in e ? e.touches[0]?.clientY || 0 : e.clientY, diff = touchStart - client;
|
|
18523
|
+
Math.abs(diff) > 10 && (e.preventDefault(), setDragOffset(.5 * -diff));
|
|
18524
|
+
}), [ touching, touchStart, allowTouchMove, direction ]), handleTouchEnd = React.useCallback((e => {
|
|
18525
|
+
if (!touching || !allowTouchMove) return;
|
|
18526
|
+
const client = "horizontal" === direction ? "changedTouches" in e ? e.changedTouches[0]?.clientX || 0 : e.clientX : "changedTouches" in e ? e.changedTouches[0]?.clientY || 0 : e.clientY, diff = touchStart - client;
|
|
18527
|
+
setTouching(!1), setDragOffset(0), Math.abs(diff) > threshold && (diff > 0 ? slideNext() : slidePrev());
|
|
18528
|
+
}), [ touching, touchStart, threshold, slideNext, slidePrev, allowTouchMove, direction ]), canSlideNext = loop || realIndex < slides.length - slidesToShow, canSlidePrev = loop || realIndex > 0;
|
|
18529
|
+
return {
|
|
18530
|
+
activeIndex: realIndex,
|
|
18531
|
+
realIndex: realIndex,
|
|
18532
|
+
previousIndex: realIndex,
|
|
18533
|
+
isBeginning: !loop && 0 === realIndex,
|
|
18534
|
+
isEnd: !loop && realIndex >= slides.length - slidesToShow,
|
|
18535
|
+
progress: slides.length > 0 ? realIndex / (slides.length - 1) : 0,
|
|
18536
|
+
autoplayRunning: autoplayRunning,
|
|
18537
|
+
transitioning: isTransitioning,
|
|
18538
|
+
touching: touching,
|
|
18539
|
+
translate: translateValue,
|
|
18540
|
+
slidesPerView: slidesToShow,
|
|
18541
|
+
slidesCount: slides.length,
|
|
18542
|
+
isLocked: !1,
|
|
18543
|
+
destroyed: !1,
|
|
18544
|
+
size: containerSize,
|
|
18545
|
+
touches: {
|
|
18546
|
+
startX: 0,
|
|
18547
|
+
startY: 0,
|
|
18548
|
+
currentX: 0,
|
|
18549
|
+
currentY: 0,
|
|
18550
|
+
diff: 0
|
|
18551
|
+
},
|
|
18552
|
+
allowSlideNext: canSlideNext,
|
|
18553
|
+
allowSlidePrev: canSlidePrev,
|
|
18554
|
+
allowTouchMove: allowTouchMove,
|
|
18555
|
+
animating: isTransitioning,
|
|
18556
|
+
enabled: !0,
|
|
18557
|
+
initialized: !0,
|
|
18558
|
+
slideNext: slideNext,
|
|
18559
|
+
slidePrev: slidePrev,
|
|
18560
|
+
goToSlide: goToSlide,
|
|
18561
|
+
canSlideNext: canSlideNext,
|
|
18562
|
+
canSlidePrev: canSlidePrev,
|
|
18563
|
+
containerRef: containerRef,
|
|
18564
|
+
wrapperRef: wrapperRef,
|
|
18565
|
+
handleTouchStart: handleTouchStart,
|
|
18566
|
+
handleTouchMove: handleTouchMove,
|
|
18567
|
+
handleTouchEnd: handleTouchEnd,
|
|
18568
|
+
allSlides: allSlides,
|
|
18569
|
+
translateValue: translateValue,
|
|
18570
|
+
slideWidth: slideWidth,
|
|
18571
|
+
currentSlidesToShow: slidesToShow,
|
|
18572
|
+
loopedSlides: loopedSlides,
|
|
18573
|
+
repositioningRef: repositioningRef
|
|
18574
|
+
};
|
|
18575
|
+
}({
|
|
17403
18576
|
slides: validSlides,
|
|
17404
18577
|
slidesToShow: slidesToShow,
|
|
17405
18578
|
spaceBetween: spaceBetween,
|
|
@@ -17426,7 +18599,8 @@ const Slider = React.forwardRef(((props, ref) => {
|
|
|
17426
18599
|
})
|
|
17427
18600
|
});
|
|
17428
18601
|
const containerClasses = [ "c-slider", "vertical" === direction && "c-slider--vertical", grabCursor && "c-slider--grab-cursor", touching && "c-slider--grabbing", loop && "c-slider--loop", className ].filter(Boolean).join(" ");
|
|
17429
|
-
|
|
18602
|
+
// Keyboard navigation
|
|
18603
|
+
return jsxRuntime.jsxs("div", {
|
|
17430
18604
|
ref: ref || containerRef,
|
|
17431
18605
|
className: containerClasses,
|
|
17432
18606
|
style: {
|
|
@@ -17444,9 +18618,32 @@ const Slider = React.forwardRef(((props, ref) => {
|
|
|
17444
18618
|
onMouseMove: handleTouchMove,
|
|
17445
18619
|
onMouseUp: handleTouchEnd,
|
|
17446
18620
|
onMouseLeave: handleTouchEnd,
|
|
18621
|
+
onKeyDown: event => {
|
|
18622
|
+
switch (event.key) {
|
|
18623
|
+
case "ArrowLeft":
|
|
18624
|
+
"horizontal" === direction && (event.preventDefault(), slidePrev());
|
|
18625
|
+
break;
|
|
18626
|
+
|
|
18627
|
+
case "ArrowRight":
|
|
18628
|
+
"horizontal" === direction && (event.preventDefault(), slideNext());
|
|
18629
|
+
break;
|
|
18630
|
+
|
|
18631
|
+
case "ArrowUp":
|
|
18632
|
+
"vertical" === direction && (event.preventDefault(), slidePrev());
|
|
18633
|
+
break;
|
|
18634
|
+
|
|
18635
|
+
case "ArrowDown":
|
|
18636
|
+
"vertical" === direction && (event.preventDefault(), slideNext());
|
|
18637
|
+
}
|
|
18638
|
+
},
|
|
18639
|
+
role: "region",
|
|
18640
|
+
"aria-roledescription": "carousel",
|
|
18641
|
+
"aria-label": rest["aria-label"] || "Image slider",
|
|
18642
|
+
tabIndex: 0,
|
|
17447
18643
|
children: [ jsxRuntime.jsx("div", {
|
|
17448
18644
|
ref: wrapperRef,
|
|
17449
18645
|
className: "c-slider__wrapper",
|
|
18646
|
+
"aria-live": autoplay ? "off" : "polite",
|
|
17450
18647
|
style: {
|
|
17451
18648
|
display: "flex",
|
|
17452
18649
|
flexDirection: "vertical" === direction ? "column" : "row",
|
|
@@ -17624,15 +18821,24 @@ Steps.displayName = "Steps", Steps.Item = StepsItem, Steps.Step = StepsItem;
|
|
|
17624
18821
|
// Context for compound usage
|
|
17625
18822
|
const TabsContext = React.createContext({
|
|
17626
18823
|
currentTab: 0,
|
|
17627
|
-
handleTabClick: () => {}
|
|
17628
|
-
|
|
17629
|
-
|
|
17630
|
-
|
|
17631
|
-
|
|
17632
|
-
|
|
17633
|
-
|
|
17634
|
-
|
|
17635
|
-
|
|
18824
|
+
handleTabClick: () => {},
|
|
18825
|
+
handleKeyDown: () => {},
|
|
18826
|
+
totalTabs: 0
|
|
18827
|
+
}), TabsList = React.forwardRef((({children: children, className: className = "", onKeyDown: onKeyDown, ...props}, ref) => {
|
|
18828
|
+
const {handleKeyDown: contextHandleKeyDown} = React.useContext(TabsContext), totalTabs = React__default.default.Children.count(children);
|
|
18829
|
+
return jsxRuntime.jsx("ul", {
|
|
18830
|
+
ref: ref,
|
|
18831
|
+
className: `c-tabs__nav ${className}`.trim(),
|
|
18832
|
+
role: "tablist",
|
|
18833
|
+
onKeyDown: e => {
|
|
18834
|
+
contextHandleKeyDown(e, totalTabs), onKeyDown?.(e);
|
|
18835
|
+
},
|
|
18836
|
+
...props,
|
|
18837
|
+
children: React__default.default.Children.map(children, ((child, index) => React__default.default.isValidElement(child) ? React__default.default.cloneElement(child, {
|
|
18838
|
+
index: index
|
|
18839
|
+
}) : child))
|
|
18840
|
+
});
|
|
18841
|
+
}));
|
|
17636
18842
|
|
|
17637
18843
|
// Compound components
|
|
17638
18844
|
TabsList.displayName = "TabsList";
|
|
@@ -17644,8 +18850,10 @@ const TabsTrigger = React.forwardRef((({children: children, className: classNam
|
|
|
17644
18850
|
const isActive = void 0 !== index && currentTab === index;
|
|
17645
18851
|
return jsxRuntime.jsx("li", {
|
|
17646
18852
|
className: "c-tabs__nav-item",
|
|
18853
|
+
role: "presentation",
|
|
17647
18854
|
children: jsxRuntime.jsx("button", {
|
|
17648
18855
|
ref: ref,
|
|
18856
|
+
id: `tab-nav-${index}`,
|
|
17649
18857
|
className: `c-tabs__nav-btn ${isActive ? TAB.CLASSES.ACTIVE : ""} ${className}`.trim(),
|
|
17650
18858
|
onClick: e => {
|
|
17651
18859
|
void 0 !== index && handleTabClick(index), onClick?.(e);
|
|
@@ -17654,6 +18862,7 @@ const TabsTrigger = React.forwardRef((({children: children, className: classNam
|
|
|
17654
18862
|
role: "tab",
|
|
17655
18863
|
"aria-selected": isActive,
|
|
17656
18864
|
"aria-controls": `tab-panel-${index}`,
|
|
18865
|
+
tabIndex: isActive ? 0 : -1,
|
|
17657
18866
|
type: "button",
|
|
17658
18867
|
...props,
|
|
17659
18868
|
children: children
|
|
@@ -17703,24 +18912,59 @@ TabsPanel.displayName = "TabsPanel";
|
|
|
17703
18912
|
const Tabs = React.memo((({items: items, activeIndex: activeIndex = TAB.DEFAULTS.ACTIVE_INDEX, onTabChange: onTabChange, className: className = "", style: style, glass: glass, children: children}) => {
|
|
17704
18913
|
const [currentTab, setCurrentTab] = React.useState(activeIndex), handleTabClick = index => {
|
|
17705
18914
|
setCurrentTab(index), onTabChange && onTabChange(index);
|
|
18915
|
+
}, handleKeyDown = (event, totalTabs) => {
|
|
18916
|
+
let newIndex = currentTab;
|
|
18917
|
+
switch (event.key) {
|
|
18918
|
+
case "ArrowRight":
|
|
18919
|
+
newIndex = (currentTab + 1) % totalTabs;
|
|
18920
|
+
break;
|
|
18921
|
+
|
|
18922
|
+
case "ArrowLeft":
|
|
18923
|
+
newIndex = (currentTab - 1 + totalTabs) % totalTabs;
|
|
18924
|
+
break;
|
|
18925
|
+
|
|
18926
|
+
case "Home":
|
|
18927
|
+
newIndex = 0;
|
|
18928
|
+
break;
|
|
18929
|
+
|
|
18930
|
+
case "End":
|
|
18931
|
+
newIndex = totalTabs - 1;
|
|
18932
|
+
break;
|
|
18933
|
+
|
|
18934
|
+
default:
|
|
18935
|
+
return;
|
|
18936
|
+
}
|
|
18937
|
+
event.preventDefault(), handleTabClick(newIndex),
|
|
18938
|
+
// Focus the newly active tab after it renders
|
|
18939
|
+
setTimeout((() => {
|
|
18940
|
+
const tabElement = document.getElementById(`tab-nav-${newIndex}`);
|
|
18941
|
+
tabElement && tabElement.focus();
|
|
18942
|
+
}), 0);
|
|
17706
18943
|
};
|
|
17707
18944
|
// Handle tab change
|
|
17708
18945
|
// Determine content based on mode (legacy items vs compound children)
|
|
17709
18946
|
let content;
|
|
17710
18947
|
// Use items prop if provided
|
|
17711
|
-
|
|
17712
|
-
|
|
18948
|
+
if (items && items.length > 0)
|
|
18949
|
+
// Legacy mode
|
|
18950
|
+
content = jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
17713
18951
|
children: [ jsxRuntime.jsx("ul", {
|
|
17714
18952
|
className: "c-tabs__nav",
|
|
18953
|
+
role: "tablist",
|
|
18954
|
+
onKeyDown: e => handleKeyDown(e, items.length),
|
|
17715
18955
|
children: items.map(((item, index) => jsxRuntime.jsx("li", {
|
|
17716
18956
|
className: "c-tabs__nav-item",
|
|
18957
|
+
role: "presentation",
|
|
17717
18958
|
children: jsxRuntime.jsx("button", {
|
|
18959
|
+
id: `tab-nav-${index}`,
|
|
17718
18960
|
className: `c-tabs__nav-btn ${index === currentTab ? TAB.CLASSES.ACTIVE : ""}`,
|
|
17719
18961
|
onClick: () => handleTabClick(index),
|
|
17720
18962
|
"data-tabindex": index,
|
|
17721
18963
|
role: "tab",
|
|
17722
18964
|
"aria-selected": index === currentTab,
|
|
17723
18965
|
"aria-controls": `tab-panel-${index}`,
|
|
18966
|
+
tabIndex: index === currentTab ? 0 : -1,
|
|
18967
|
+
type: "button",
|
|
17724
18968
|
children: item.label
|
|
17725
18969
|
})
|
|
17726
18970
|
}, `tab-nav-${index}`)))
|
|
@@ -17744,13 +18988,19 @@ const Tabs = React.memo((({items: items, activeIndex: activeIndex = TAB.DEFAULT
|
|
|
17744
18988
|
})
|
|
17745
18989
|
}, `tab-panel-${index}`)))
|
|
17746
18990
|
}) ]
|
|
17747
|
-
})
|
|
17748
|
-
|
|
17749
|
-
|
|
17750
|
-
|
|
17751
|
-
|
|
17752
|
-
|
|
17753
|
-
|
|
18991
|
+
}); else {
|
|
18992
|
+
// Compound mode
|
|
18993
|
+
const tabsList = React__default.default.Children.toArray(children).find((child => React__default.default.isValidElement(child) && "TabsList" === child.type.displayName)), totalTabsCount = tabsList ? React__default.default.Children.count(tabsList.props.children) : 0;
|
|
18994
|
+
content = jsxRuntime.jsx(TabsContext.Provider, {
|
|
18995
|
+
value: {
|
|
18996
|
+
currentTab: currentTab,
|
|
18997
|
+
handleTabClick: handleTabClick,
|
|
18998
|
+
handleKeyDown: handleKeyDown,
|
|
18999
|
+
totalTabs: totalTabsCount
|
|
19000
|
+
},
|
|
19001
|
+
children: children
|
|
19002
|
+
});
|
|
19003
|
+
}
|
|
17754
19004
|
const wrapper = jsxRuntime.jsx("div", {
|
|
17755
19005
|
className: `c-tabs js-atomix-tab ${className}`,
|
|
17756
19006
|
style: style,
|
|
@@ -17841,7 +19091,7 @@ const Testimonial = ({quote: quote, author: author, size: size = "", skeleton: s
|
|
|
17841
19091
|
className: "c-testimonial__author",
|
|
17842
19092
|
children: [ author.avatarSrc && jsxRuntime.jsx("img", {
|
|
17843
19093
|
src: author.avatarSrc,
|
|
17844
|
-
alt: author.avatarAlt ||
|
|
19094
|
+
alt: author.avatarAlt || `${author.name}'s avatar`,
|
|
17845
19095
|
className: "c-testimonial__author-avatar c-avatar c-avatar--xxl c-avatar--circle"
|
|
17846
19096
|
}), jsxRuntime.jsxs("div", {
|
|
17847
19097
|
className: "c-testimonial__info",
|
|
@@ -18117,7 +19367,17 @@ const Tooltip = React.memo((({content: content, children: children, position: p
|
|
|
18117
19367
|
cancelAnimationFrame(rafId), window.removeEventListener("resize", handleUpdate),
|
|
18118
19368
|
window.removeEventListener("scroll", handleUpdate, !0);
|
|
18119
19369
|
};
|
|
18120
|
-
}), [ isVisible, updatePosition ])
|
|
19370
|
+
}), [ isVisible, updatePosition ]),
|
|
19371
|
+
// Handle Escape key to close tooltip
|
|
19372
|
+
React.useEffect((() => {
|
|
19373
|
+
if (!isVisible) return;
|
|
19374
|
+
const handleKeyDown = event => {
|
|
19375
|
+
"Escape" === event.key && hideTooltip();
|
|
19376
|
+
};
|
|
19377
|
+
return document.addEventListener("keydown", handleKeyDown), () => {
|
|
19378
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
19379
|
+
};
|
|
19380
|
+
}), [ isVisible, hideTooltip ]);
|
|
18121
19381
|
// Setup trigger props
|
|
18122
19382
|
const triggerProps = {
|
|
18123
19383
|
"aria-describedby": isVisible ? tooltipId : void 0
|
|
@@ -18806,9 +20066,15 @@ const VideoPlayer = React.forwardRef((({src: src, type: type = "video", youtube
|
|
|
18806
20066
|
const rect = e.currentTarget.getBoundingClientRect(), percent = (e.clientX - rect.left) / rect.width;
|
|
18807
20067
|
setVolume(percent);
|
|
18808
20068
|
}), [ setVolume ]), handleDownload = React.useCallback((() => {
|
|
18809
|
-
if (src) {
|
|
18810
|
-
|
|
18811
|
-
|
|
20069
|
+
if (src) try {
|
|
20070
|
+
var _context;
|
|
20071
|
+
const url = new URL(src, window.location.origin);
|
|
20072
|
+
if (_includesInstanceProperty(_context = [ "http:", "https:", "blob:", "data:" ]).call(_context, url.protocol)) {
|
|
20073
|
+
const a = document.createElement("a");
|
|
20074
|
+
a.href = url.href, a.download = "video", a.click();
|
|
20075
|
+
}
|
|
20076
|
+
} catch (e) {
|
|
20077
|
+
// Ignore invalid URLs
|
|
18812
20078
|
}
|
|
18813
20079
|
}), [ src ]), handleShare = React.useCallback((async () => {
|
|
18814
20080
|
if (navigator.share) try {
|
|
@@ -19387,6 +20653,7 @@ var components = Object.freeze({
|
|
|
19387
20653
|
TODO: TODO,
|
|
19388
20654
|
TOGGLE: TOGGLE,
|
|
19389
20655
|
TOOLTIP: TOOLTIP,
|
|
20656
|
+
TYPEDBUTTON: TYPEDBUTTON,
|
|
19390
20657
|
UPLOAD: UPLOAD,
|
|
19391
20658
|
VIDEO_PLAYER: VIDEO_PLAYER,
|
|
19392
20659
|
sliderConstants: sliderConstants
|
|
@@ -25033,8 +26300,8 @@ exports.ACCORDION = ACCORDION, exports.ATOMIX_GLASS = ATOMIX_GLASS, exports.AVAT
|
|
|
25033
26300
|
exports.AVATAR_GROUP = AVATAR_GROUP, exports.Accordion = Accordion, exports.AreaChart = AreaChart,
|
|
25034
26301
|
exports.AtomixGlass = AtomixGlass, exports.AtomixLogo = AtomixLogo, exports.Avatar = Avatar,
|
|
25035
26302
|
exports.AvatarGroup = AvatarGroup, exports.BADGE = BADGE, exports.BADGE_CSS_VARS = BADGE_CSS_VARS,
|
|
25036
|
-
exports.
|
|
25037
|
-
exports.BUTTON_CSS_VARS = BUTTON_CSS_VARS, exports.BUTTON_GROUP = BUTTON_GROUP,
|
|
26303
|
+
exports.BALANCED_PRESET = BALANCED_PRESET, exports.BLOCK = BLOCK, exports.BREADCRUMB = BREADCRUMB,
|
|
26304
|
+
exports.BUTTON = BUTTON, exports.BUTTON_CSS_VARS = BUTTON_CSS_VARS, exports.BUTTON_GROUP = BUTTON_GROUP,
|
|
25038
26305
|
exports.Badge = Badge, exports.BarChart = BarChart, exports.Block = Block, exports.Breadcrumb = Breadcrumb,
|
|
25039
26306
|
exports.BubbleChart = BubbleChart, exports.Button = Button, exports.ButtonGroup = ButtonGroup,
|
|
25040
26307
|
exports.CALLOUT = CALLOUT, exports.CARD = CARD, exports.CARD_CSS_VARS = CARD_CSS_VARS,
|
|
@@ -25045,29 +26312,31 @@ exports.Card = Card, exports.Chart = Chart, exports.ChartRenderer = ChartRendere
|
|
|
25045
26312
|
exports.Checkbox = Checkbox, exports.ColorModeToggle = ColorModeToggle, exports.Container = Container,
|
|
25046
26313
|
exports.Countdown = Countdown, exports.DATA_TABLE_CLASSES = DATA_TABLE_CLASSES,
|
|
25047
26314
|
exports.DATA_TABLE_SELECTORS = DATA_TABLE_SELECTORS, exports.DATEPICKER = DATEPICKER,
|
|
25048
|
-
exports.DEFAULT_ATOMIX_FONTS = DEFAULT_ATOMIX_FONTS, exports.
|
|
25049
|
-
exports.
|
|
25050
|
-
exports.
|
|
25051
|
-
exports.
|
|
25052
|
-
exports.
|
|
25053
|
-
exports.
|
|
25054
|
-
exports.FooterSection = FooterSection, exports.FooterSocialLink = FooterSocialLink,
|
|
26315
|
+
exports.DEFAULT_ATOMIX_FONTS = DEFAULT_ATOMIX_FONTS, exports.DEFAULT_BREAKPOINTS = DEFAULT_BREAKPOINTS,
|
|
26316
|
+
exports.DROPDOWN = DROPDOWN, exports.DROPDOWN_CSS_VARS = DROPDOWN_CSS_VARS, exports.DataTable = DataTable,
|
|
26317
|
+
exports.DatePicker = DatePicker, exports.DesignTokensCustomizer = DesignTokensCustomizer,
|
|
26318
|
+
exports.DeviceDetector = DeviceDetector, exports.DonutChart = DonutChart, exports.Dropdown = Dropdown,
|
|
26319
|
+
exports.EDGE_PANEL = EDGE_PANEL, exports.EdgePanel = EdgePanel, exports.ElevationCard = ElevationCard,
|
|
26320
|
+
exports.FOOTER = FOOTER, exports.FORM = FORM, exports.FORM_GROUP = FORM_GROUP, exports.Footer = Footer,
|
|
26321
|
+
exports.FooterLink = FooterLink, exports.FooterSection = FooterSection, exports.FooterSocialLink = FooterSocialLink,
|
|
25055
26322
|
exports.Form = Form, exports.FormGroup = FormGroup, exports.FunnelChart = FunnelChart,
|
|
25056
26323
|
exports.GaugeChart = GaugeChart, exports.Grid = Grid, exports.GridCol = GridCol,
|
|
25057
26324
|
exports.HERO = HERO, exports.HeatmapChart = HeatmapChart, exports.Hero = Hero, exports.INPUT = INPUT,
|
|
25058
26325
|
exports.INPUT_CSS_VARS = INPUT_CSS_VARS, exports.Icon = Icon, exports.Input = Input,
|
|
25059
26326
|
exports.LIST = LIST, exports.LIST_GROUP = LIST_GROUP, exports.LineChart = LineChart,
|
|
25060
26327
|
exports.List = List, exports.ListGroup = ListGroup, exports.MESSAGES = MESSAGES,
|
|
25061
|
-
exports.
|
|
25062
|
-
exports.
|
|
25063
|
-
exports.
|
|
25064
|
-
exports.
|
|
25065
|
-
exports.
|
|
25066
|
-
exports.
|
|
25067
|
-
exports.
|
|
26328
|
+
exports.MOBILE_OPTIMIZED_BREAKPOINTS = MOBILE_OPTIMIZED_BREAKPOINTS, exports.MODAL = MODAL,
|
|
26329
|
+
exports.MODAL_CSS_VARS = MODAL_CSS_VARS, exports.MasonryGrid = MasonryGrid, exports.MasonryGridItem = MasonryGridItem,
|
|
26330
|
+
exports.MegaMenu = MegaMenu, exports.MegaMenuColumn = MegaMenuColumn, exports.MegaMenuLink = MegaMenuLink,
|
|
26331
|
+
exports.Menu = Menu, exports.MenuDivider = MenuDivider, exports.MenuItem = MenuItem,
|
|
26332
|
+
exports.Messages = Messages, exports.Modal = Modal, exports.MultiAxisChart = MultiAxisChart,
|
|
26333
|
+
exports.NAV = NAV, exports.NAVBAR = NAVBAR, exports.Nav = Nav, exports.NavDropdown = NavDropdown,
|
|
26334
|
+
exports.NavItem = NavItem, exports.Navbar = Navbar, exports.PAGINATION_DEFAULTS = PAGINATION_DEFAULTS,
|
|
26335
|
+
exports.PERFORMANCE_PRESET = PERFORMANCE_PRESET, exports.PHOTOVIEWER = PHOTOVIEWER,
|
|
25068
26336
|
exports.POPOVER = POPOVER, exports.PROGRESS = PROGRESS, exports.PROGRESS_CSS_VARS = PROGRESS_CSS_VARS,
|
|
25069
|
-
exports.Pagination = Pagination, exports.
|
|
25070
|
-
exports.
|
|
26337
|
+
exports.Pagination = Pagination, exports.PerformanceOverlay = PerformanceOverlay,
|
|
26338
|
+
exports.PhotoViewer = PhotoViewer, exports.PieChart = PieChart, exports.Popover = Popover,
|
|
26339
|
+
exports.ProductReview = ProductReview, exports.Progress = Progress, exports.QUALITY_PRESET = QUALITY_PRESET,
|
|
25071
26340
|
exports.RADIO = RADIO, exports.RADIO_CSS_VARS = RADIO_CSS_VARS, exports.RATING = RATING,
|
|
25072
26341
|
exports.RIVER = RIVER, exports.RTLManager = RTLManager, exports.RadarChart = RadarChart,
|
|
25073
26342
|
exports.Radio = Radio, exports.Rating = Rating, exports.River = River, exports.Row = Row,
|
|
@@ -25079,8 +26348,8 @@ exports.Slider = Slider, exports.Spinner = Spinner, exports.Steps = Steps, expor
|
|
|
25079
26348
|
exports.TABS_CSS_VARS = TABS_CSS_VARS, exports.TESTIMONIAL = TESTIMONIAL, exports.TEXTAREA = TEXTAREA,
|
|
25080
26349
|
exports.THEME_COLORS = THEME_COLORS, exports.THEME_NAMING = THEME_NAMING, exports.TODO = TODO,
|
|
25081
26350
|
exports.TOGGLE = TOGGLE, exports.TOOLTIP = TOOLTIP, exports.TOOLTIP_CSS_VARS = TOOLTIP_CSS_VARS,
|
|
25082
|
-
exports.
|
|
25083
|
-
exports.ThemeApplicator = ThemeApplicator, exports.ThemeComparator = ThemeComparator,
|
|
26351
|
+
exports.TYPEDBUTTON = TYPEDBUTTON, exports.Tabs = Tabs, exports.Testimonial = Testimonial,
|
|
26352
|
+
exports.Textarea = Textarea, exports.ThemeApplicator = ThemeApplicator, exports.ThemeComparator = ThemeComparator,
|
|
25084
26353
|
exports.ThemeContext = ThemeContext, exports.ThemeErrorBoundary = ThemeErrorBoundary,
|
|
25085
26354
|
exports.ThemeInspector = ThemeInspector, exports.ThemeLiveEditor = ThemeLiveEditor,
|
|
25086
26355
|
exports.ThemePreview = ThemePreview, exports.ThemeProvider = ThemeProvider, exports.ThemeValidator = ThemeValidator,
|
|
@@ -25153,8 +26422,8 @@ function(cssVars, baseStyle) {
|
|
|
25153
26422
|
* ```
|
|
25154
26423
|
*/ , exports.applyComponentTheme = applyComponentTheme, exports.applyPartStyles = applyPartStyles,
|
|
25155
26424
|
exports.applyTheme = applyTheme, exports.camelToKebab = camelToKebab, exports.clearThemes = clearThemes,
|
|
25156
|
-
exports.composables = composables, exports.constants = constants, exports.
|
|
25157
|
-
exports.createDarkVariant =
|
|
26425
|
+
exports.composables = composables, exports.constants = constants, exports.createBreakpoints = createBreakpoints$1,
|
|
26426
|
+
exports.createCSSVarStyle = createCSSVarStyle, exports.createDarkVariant =
|
|
25158
26427
|
/**
|
|
25159
26428
|
* Create a dark theme variant from a light theme
|
|
25160
26429
|
*/
|
|
@@ -25272,7 +26541,9 @@ exports.getAllThemes = getAllThemes, exports.getCSSVariable = getCSSVariable, ex
|
|
|
25272
26541
|
*/
|
|
25273
26542
|
function(component) {
|
|
25274
26543
|
return COMPONENT_CSS_VARS[component];
|
|
25275
|
-
}, exports.getComponentThemeValue = getComponentThemeValue, exports.
|
|
26544
|
+
}, exports.getComponentThemeValue = getComponentThemeValue, exports.getDefaultBreakpoints = getDefaultBreakpoints,
|
|
26545
|
+
exports.getDevicePreset = getDevicePreset, exports.getMobileOptimizedParams = getMobileOptimizedParams,
|
|
26546
|
+
exports.getPartStyles = getPartStyles, exports.getQualityMultipliers = getQualityMultipliers,
|
|
25276
26547
|
exports.getTheme = getTheme, exports.getThemeApplicator = getThemeApplicator, exports.getThemeCount = getThemeCount,
|
|
25277
26548
|
exports.getThemeIds = getThemeIds, exports.getThemeMetadata =
|
|
25278
26549
|
/**
|
|
@@ -25354,8 +26625,7 @@ function(theme, selector = ":root") {
|
|
|
25354
26625
|
});
|
|
25355
26626
|
}, exports.types = types, exports.unregisterTheme = unregisterTheme, exports.useAccordion = useAccordion,
|
|
25356
26627
|
exports.useAtomixGlass = useAtomixGlass, exports.useBadge = useBadge, exports.useBarChart = useBarChart,
|
|
25357
|
-
exports.useBlock = useBlock, exports.
|
|
25358
|
-
exports.useChartData = useChartData, exports.useChartInteraction = useChartInteraction,
|
|
26628
|
+
exports.useBlock = useBlock, exports.useChartData = useChartData, exports.useChartInteraction = useChartInteraction,
|
|
25359
26629
|
exports.useChartScale = useChartScale, exports.useComponentCustomization =
|
|
25360
26630
|
/**
|
|
25361
26631
|
* Hook to merge theme overrides with component props
|
|
@@ -25404,19 +26674,19 @@ function(component, props) {
|
|
|
25404
26674
|
}
|
|
25405
26675
|
/**
|
|
25406
26676
|
* Hook to merge default props with provided props
|
|
25407
|
-
*/ , exports.useComponentTheme = useComponentTheme, exports.
|
|
25408
|
-
exports.
|
|
25409
|
-
exports.
|
|
25410
|
-
exports.
|
|
26677
|
+
*/ , exports.useComponentTheme = useComponentTheme, exports.useEdgePanel = useEdgePanel,
|
|
26678
|
+
exports.useForm = useForm, exports.useFormGroup = useFormGroup, exports.useHero = useHero,
|
|
26679
|
+
exports.useHistory = useHistory, exports.useInput = useInput, exports.useLineChart = useLineChart,
|
|
26680
|
+
exports.useMergedProps = function(defaultProps, props) {
|
|
25411
26681
|
return React.useMemo((() => ({
|
|
25412
26682
|
...defaultProps,
|
|
25413
26683
|
...props
|
|
25414
26684
|
})), [ defaultProps, props ]);
|
|
25415
|
-
}, exports.
|
|
25416
|
-
exports.
|
|
25417
|
-
exports.usePieChart = usePieChart, exports.useRadio = useRadio, exports.
|
|
25418
|
-
exports.
|
|
25419
|
-
exports.
|
|
26685
|
+
}, exports.useNav = useNav, exports.useNavDropdown = useNavDropdown, exports.useNavItem = useNavItem,
|
|
26686
|
+
exports.useNavbar = useNavbar, exports.usePerformanceMonitor = usePerformanceMonitor,
|
|
26687
|
+
exports.usePieChart = usePieChart, exports.useRadio = useRadio, exports.useResponsiveGlass = useResponsiveGlass,
|
|
26688
|
+
exports.useRiver = useRiver, exports.useSelect = useSelect, exports.useSideMenu = useSideMenu,
|
|
26689
|
+
exports.useSideMenuItem = useSideMenuItem, exports.useSlot = function(slot, props, fallback) {
|
|
25420
26690
|
return React__default.default.useMemo((() => renderSlot(slot, props, fallback)), [ slot, props, fallback ]);
|
|
25421
26691
|
}, exports.useSpinner = useSpinner, exports.useTextarea = useTextarea, exports.useTheme = useTheme,
|
|
25422
26692
|
exports.useThemeTokens = useThemeTokens, exports.useTodo = useTodo, exports.utils = utils,
|