@shohojdhara/atomix 0.4.8 → 0.5.0
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 +148 -120
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.d.ts +33 -0
- package/dist/charts.js +1227 -122
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +33 -10
- package/dist/core.js +1052 -41
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +33 -0
- package/dist/forms.js +2086 -1035
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +42 -1
- package/dist/heavy.js +1620 -600
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +441 -270
- package/dist/index.esm.js +1900 -638
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1935 -670
- 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 +148 -4
- 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 +4 -1
- package/scripts/cli/commands/clean.js +109 -0
- package/scripts/cli/commands/doctor.js +88 -0
- package/scripts/cli/commands/generate.js +135 -14
- package/scripts/cli/commands/init.js +45 -18
- 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/component-validator.js +443 -0
- package/scripts/cli/internal/config-loader.js +162 -0
- package/scripts/cli/internal/filesystem.js +102 -2
- package/scripts/cli/internal/generator.js +359 -39
- 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 +60 -6
- 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 +45 -3
- package/scripts/cli/utils/helpers.js +24 -0
- package/scripts/cli/utils/logger.js +1 -1
- package/scripts/cli/utils/security.js +302 -0
- package/scripts/cli/utils/telemetry.js +115 -0
- package/scripts/cli/utils/validation.js +4 -38
- package/scripts/cli/utils.js +46 -0
- 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.tsx +102 -2
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +125 -12
- package/src/components/AtomixGlass/PerformanceDashboard.tsx +219 -0
- package/src/components/AtomixGlass/README.md +25 -10
- package/src/components/AtomixGlass/animation-system.ts +578 -0
- package/src/components/AtomixGlass/shader-utils.ts +3 -0
- package/src/components/AtomixGlass/stories/AnimationFeatures.stories.tsx +653 -0
- package/src/components/AtomixGlass/stories/AnimationTests.stories.tsx +95 -0
- package/src/components/AtomixGlass/stories/CardExamples.stories.tsx +212 -0
- package/src/components/AtomixGlass/stories/DashboardExamples.stories.tsx +348 -0
- package/src/components/AtomixGlass/stories/EcommerceExamples.stories.tsx +410 -0
- package/src/components/AtomixGlass/stories/FormExamples.stories.tsx +436 -0
- package/src/components/AtomixGlass/stories/HeroExamples.stories.tsx +264 -0
- package/src/components/AtomixGlass/stories/InteractivePlayground.stories.tsx +247 -0
- package/src/components/AtomixGlass/stories/MobileUIExamples.stories.tsx +418 -0
- package/src/components/AtomixGlass/stories/ModalExamples.stories.tsx +402 -0
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +157 -6
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +658 -93
- package/src/components/AtomixGlass/stories/PresetGallery.stories.tsx +335 -0
- package/src/components/AtomixGlass/stories/WidgetExamples.stories.tsx +441 -0
- package/src/components/AtomixGlass/stories/argTypes.ts +384 -0
- package/src/components/AtomixGlass/stories/shared-components.tsx +91 -1
- package/src/components/AtomixGlass/stories/types.ts +127 -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 +144 -5
- 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 +55 -0
- 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.testbutton.scss +212 -0
- package/src/styles/06-components/_components.testtypecheck.scss +212 -0
- 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/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",
|
|
@@ -1750,7 +1758,16 @@ const THEME_COLORS = [ "primary", "secondary", "success", "info", "warning", "er
|
|
|
1750
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
1773
|
ACTIVATION_ZONE: 200,
|
|
@@ -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;
|
|
@@ -2220,14 +2273,16 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2220
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 = {
|
|
2221
2274
|
width: 0,
|
|
2222
2275
|
height: 0
|
|
2223
|
-
}, 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) => {
|
|
2224
2279
|
// Generate a stable, deterministic ID for SSR compatibility
|
|
2225
2280
|
// Use a module-level counter that's consistent across server and client
|
|
2226
|
-
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);
|
|
2227
2282
|
// Lazy load shader utilities only when shader mode is needed
|
|
2228
2283
|
React.useEffect((() => {
|
|
2229
2284
|
"shader" === mode ?
|
|
2230
|
-
// Dynamic import shader utilities
|
|
2285
|
+
// Dynamic import shader utilities with animation support
|
|
2231
2286
|
Promise.resolve().then((function() {
|
|
2232
2287
|
return shaderUtils;
|
|
2233
2288
|
})).then((shaderUtils => {
|
|
@@ -2244,7 +2299,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2244
2299
|
// Generate shader map with debouncing and caching
|
|
2245
2300
|
React.useEffect((() => {
|
|
2246
2301
|
// Enhanced validation for shader mode
|
|
2247
|
-
if ("shader" === mode && glassSize && validateGlassSize(glassSize)
|
|
2302
|
+
if ("shader" === mode && glassSize && validateGlassSize(glassSize)) {
|
|
2248
2303
|
// Create cache key from size and variant
|
|
2249
2304
|
const cacheKey = `${glassSize.width}x${glassSize.height}-${shaderVariant}`, cachedUrl = (key => {
|
|
2250
2305
|
const entry = sharedShaderCache.get(key);
|
|
@@ -2266,11 +2321,9 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2266
2321
|
width: glassSize.width,
|
|
2267
2322
|
height: glassSize.height,
|
|
2268
2323
|
fragment: selectedShader
|
|
2269
|
-
}),
|
|
2270
|
-
// Defer shader generation with longer delay to avoid blocking
|
|
2271
|
-
setTimeout((() => {
|
|
2324
|
+
}), shaderUpdateTimeoutRef.current = setTimeout((() => {
|
|
2272
2325
|
const url = shaderGeneratorRef.current?.updateShader() || "";
|
|
2273
|
-
((key, url) => {
|
|
2326
|
+
url && ((key, url) => {
|
|
2274
2327
|
// Evict oldest entries if at capacity
|
|
2275
2328
|
if (sharedShaderCache.size >= 15) {
|
|
2276
2329
|
const entries = Array.from(sharedShaderCache.entries());
|
|
@@ -2302,7 +2355,8 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2302
2355
|
// Cleanup function with error handling
|
|
2303
2356
|
return () => {
|
|
2304
2357
|
shaderDebounceTimeoutRef.current && (clearTimeout(shaderDebounceTimeoutRef.current),
|
|
2305
|
-
shaderDebounceTimeoutRef.current = null)
|
|
2358
|
+
shaderDebounceTimeoutRef.current = null), shaderUpdateTimeoutRef.current && (clearTimeout(shaderUpdateTimeoutRef.current),
|
|
2359
|
+
shaderUpdateTimeoutRef.current = null);
|
|
2306
2360
|
try {
|
|
2307
2361
|
shaderGeneratorRef.current?.destroy();
|
|
2308
2362
|
} catch (error) {
|
|
@@ -2311,7 +2365,37 @@ const sharedShaderCache = new Map, AtomixGlassContainer = React.forwardRef((({c
|
|
|
2311
2365
|
shaderGeneratorRef.current = null;
|
|
2312
2366
|
}
|
|
2313
2367
|
};
|
|
2314
|
-
}), [ 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 ]);
|
|
2315
2399
|
// Removed forced reflow to avoid layout thrash and potential feedback sizing loops
|
|
2316
2400
|
const [rectCache, setRectCache] = React.useState(null);
|
|
2317
2401
|
React.useEffect((() => {
|
|
@@ -2645,12 +2729,144 @@ class {
|
|
|
2645
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)"),
|
|
2646
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)");
|
|
2647
2731
|
}
|
|
2648
|
-
}
|
|
2732
|
+
};
|
|
2649
2733
|
|
|
2650
2734
|
/**
|
|
2651
2735
|
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
2652
2736
|
* to avoid React re-renders on mouse movement.
|
|
2653
|
-
*/
|
|
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) => {
|
|
2654
2870
|
parentElement && backgroundDetectionCache.set(parentElement, {
|
|
2655
2871
|
result: result,
|
|
2656
2872
|
timestamp: Date.now(),
|
|
@@ -2663,7 +2879,9 @@ class {
|
|
|
2663
2879
|
* Composable hook for AtomixGlass component logic
|
|
2664
2880
|
* Manages all state, calculations, and event handlers
|
|
2665
2881
|
*/
|
|
2666
|
-
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
|
|
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}) {
|
|
2667
2885
|
// State
|
|
2668
2886
|
const [isHovered, setIsHovered] = React.useState(!1), [isActive, setIsActive] = React.useState(!1), cachedRectRef = React.useRef(null), internalGlobalMousePositionRef = React.useRef({
|
|
2669
2887
|
x: 0,
|
|
@@ -2677,7 +2895,47 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2677
2895
|
}), targetGlobalMousePositionRef = React.useRef({
|
|
2678
2896
|
x: 0,
|
|
2679
2897
|
y: 0
|
|
2680
|
-
}), 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}) {
|
|
2681
2939
|
const [glassSize, setGlassSize] = React.useState({
|
|
2682
2940
|
width: 270,
|
|
2683
2941
|
height: 69
|
|
@@ -2736,7 +2994,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2736
2994
|
glassRef: glassRef,
|
|
2737
2995
|
effectiveBorderRadius: effectiveBorderRadius,
|
|
2738
2996
|
cachedRectRef: cachedRectRef
|
|
2739
|
-
}),
|
|
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
|
+
*/
|
|
2740
3001
|
// Extract border-radius from children
|
|
2741
3002
|
React.useEffect((() => {
|
|
2742
3003
|
const extractRadius = () => {
|
|
@@ -2939,6 +3200,8 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2939
3200
|
lerpActiveRef.current = !0;
|
|
2940
3201
|
const LERP_T = CONSTANTS.LERP_FACTOR, tick = () => {
|
|
2941
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);
|
|
2942
3205
|
const cur = internalMouseOffsetRef.current, tgt = targetMouseOffsetRef.current, dx = tgt.x - cur.x, dy = tgt.y - cur.y;
|
|
2943
3206
|
// If we're close enough, snap and park
|
|
2944
3207
|
if (Math.abs(dx) < .05 && Math.abs(dy) < .05) internalMouseOffsetRef.current = {
|
|
@@ -2947,17 +3210,17 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2947
3210
|
...targetGlobalMousePositionRef.current
|
|
2948
3211
|
}; else {
|
|
2949
3212
|
internalMouseOffsetRef.current = {
|
|
2950
|
-
x: lerp(cur.x, tgt.x, LERP_T),
|
|
2951
|
-
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)
|
|
2952
3215
|
};
|
|
2953
3216
|
const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
|
|
2954
3217
|
internalGlobalMousePositionRef.current = {
|
|
2955
|
-
x: lerp(curG.x, tgtG.x, LERP_T),
|
|
2956
|
-
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)
|
|
2957
3220
|
};
|
|
2958
3221
|
}
|
|
2959
3222
|
// Imperative style update with the smoothed values
|
|
2960
|
-
updateAtomixGlassStyles(wrapperRef
|
|
3223
|
+
updateAtomixGlassStyles(wrapperRef.current, glassRef.current, {
|
|
2961
3224
|
mouseOffset: internalMouseOffsetRef.current,
|
|
2962
3225
|
globalMousePosition: internalGlobalMousePositionRef.current,
|
|
2963
3226
|
glassSize: glassSize,
|
|
@@ -3048,6 +3311,8 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3048
3311
|
// This is now static (refs or props) unless prop changes
|
|
3049
3312
|
overLightConfig: overLightConfig,
|
|
3050
3313
|
transformStyle: transformStyle,
|
|
3314
|
+
getShaderTime: getShaderTime,
|
|
3315
|
+
applyTimeBasedDistortion: applyTimeBasedDistortion,
|
|
3051
3316
|
handleMouseEnter: handleMouseEnter,
|
|
3052
3317
|
handleMouseLeave: handleMouseLeave,
|
|
3053
3318
|
handleMouseDown: handleMouseDown,
|
|
@@ -3056,6 +3321,800 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3056
3321
|
};
|
|
3057
3322
|
}
|
|
3058
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
|
+
|
|
3059
4118
|
/**
|
|
3060
4119
|
* AtomixGlass - A high-performance glass morphism component with liquid distortion effects
|
|
3061
4120
|
*
|
|
@@ -3070,6 +4129,8 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3070
4129
|
* - Focus ring support for keyboard navigation
|
|
3071
4130
|
* - Responsive breakpoints for mobile optimization
|
|
3072
4131
|
* - Enhanced ARIA attributes for screen readers
|
|
4132
|
+
* - Time-based animation system with FBM distortion
|
|
4133
|
+
* - Device preset optimization for performance/quality balance
|
|
3073
4134
|
*
|
|
3074
4135
|
* Design System Compliance:
|
|
3075
4136
|
* - Uses design tokens for opacity, spacing, and colors
|
|
@@ -3126,8 +4187,14 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3126
4187
|
* <AtomixGlass overLight="auto" debugOverLight={true}>
|
|
3127
4188
|
* <div>Content with debug logging enabled</div>
|
|
3128
4189
|
* </AtomixGlass>
|
|
3129
|
-
|
|
3130
|
-
|
|
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({
|
|
3131
4198
|
glassRef: glassRef,
|
|
3132
4199
|
contentRef: contentRef,
|
|
3133
4200
|
borderRadius: borderRadius,
|
|
@@ -3140,7 +4207,6 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3140
4207
|
withoutEffects: withoutEffects,
|
|
3141
4208
|
elasticity: elasticity,
|
|
3142
4209
|
onClick: onClick,
|
|
3143
|
-
debugBorderRadius: debugBorderRadius,
|
|
3144
4210
|
debugOverLight: debugOverLight,
|
|
3145
4211
|
debugPerformance: debugPerformance,
|
|
3146
4212
|
children: children,
|
|
@@ -3149,8 +4215,48 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3149
4215
|
withLiquidBlur: withLiquidBlur,
|
|
3150
4216
|
padding: padding,
|
|
3151
4217
|
style: style,
|
|
3152
|
-
isFixedOrSticky: isFixedOrSticky
|
|
3153
|
-
|
|
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((() => {
|
|
3154
4260
|
if (!isFixedOrSticky) return {};
|
|
3155
4261
|
const {position: p, top: t, left: l, right: r, bottom: b} = restStyle;
|
|
3156
4262
|
return {
|
|
@@ -3336,6 +4442,15 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3336
4442
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
3337
4443
|
shaderVariant: shaderVariant,
|
|
3338
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,
|
|
3339
4454
|
children: children
|
|
3340
4455
|
}), Boolean(onClick) && jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
3341
4456
|
children: [ jsxRuntime.jsx("div", {
|
|
@@ -3359,6 +4474,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3359
4474
|
}), jsxRuntime.jsx("span", {
|
|
3360
4475
|
className: ATOMIX_GLASS.BORDER_2_CLASS
|
|
3361
4476
|
}) ]
|
|
4477
|
+
}), debugPerformance && performanceMetrics && jsxRuntime.jsx(PerformanceDashboard, {
|
|
4478
|
+
metrics: performanceMetrics,
|
|
4479
|
+
isVisible: !0,
|
|
4480
|
+
onClose: () => {}
|
|
3362
4481
|
}) ]
|
|
3363
4482
|
});
|
|
3364
4483
|
}
|
|
@@ -3425,16 +4544,14 @@ const AccordionBody = React.forwardRef((({children: children, className: classN
|
|
|
3425
4544
|
|
|
3426
4545
|
AccordionBody.displayName = "AccordionBody";
|
|
3427
4546
|
|
|
3428
|
-
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}) => {
|
|
3429
4548
|
// Generate unique IDs for accessibility
|
|
3430
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({
|
|
3431
4550
|
defaultOpen: defaultOpen,
|
|
3432
4551
|
disabled: disabled,
|
|
3433
4552
|
iconPosition: iconPosition,
|
|
3434
4553
|
isOpen: controlledOpen,
|
|
3435
|
-
onOpenChange: onOpenChange
|
|
3436
|
-
onOpen: onOpen,
|
|
3437
|
-
onClose: onClose
|
|
4554
|
+
onOpenChange: onOpenChange
|
|
3438
4555
|
}), headerClassNames = generateHeaderClassNames(), panelClassNames = ACCORDION.SELECTORS.PANEL.replace(".", ""), hasCompoundComponents = React__default.default.Children.toArray(children).some((child => {
|
|
3439
4556
|
var _context;
|
|
3440
4557
|
|
|
@@ -3817,7 +4934,9 @@ var shaderUtils = Object.freeze({
|
|
|
3817
4934
|
return this.canvasDPI;
|
|
3818
4935
|
}
|
|
3819
4936
|
},
|
|
3820
|
-
|
|
4937
|
+
createFBMEngine: createFBMEngine,
|
|
4938
|
+
fragmentShaders: fragmentShaders,
|
|
4939
|
+
liquidGlassWithTime: liquidGlassWithTime
|
|
3821
4940
|
});
|
|
3822
4941
|
|
|
3823
4942
|
// Map string sizes to pixel values
|
|
@@ -3852,7 +4971,7 @@ const sizeMap = {
|
|
|
3852
4971
|
* Icon component that displays a Phosphor icon
|
|
3853
4972
|
*/ Icon.displayName = "Icon";
|
|
3854
4973
|
|
|
3855
|
-
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}) => {
|
|
3856
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(" ");
|
|
3857
4976
|
return jsxRuntime.jsx("div", {
|
|
3858
4977
|
className: avatarClasses,
|
|
@@ -4325,7 +5444,7 @@ class ThemeNaming {
|
|
|
4325
5444
|
ThemeNaming.prefix = "atomix";
|
|
4326
5445
|
|
|
4327
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) => {
|
|
4328
|
-
const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href
|
|
5447
|
+
const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href), iconElement = iconName ? jsxRuntime.jsx(Icon, {
|
|
4329
5448
|
name: iconName,
|
|
4330
5449
|
size: iconSize
|
|
4331
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 => {
|
|
@@ -4381,8 +5500,8 @@ const Button = React__default.default.memo( React.forwardRef((({label: label, c
|
|
|
4381
5500
|
...buttonProps,
|
|
4382
5501
|
ref: ref,
|
|
4383
5502
|
// linkComponent usually forwards ref to anchor
|
|
4384
|
-
href: href,
|
|
4385
|
-
to: href,
|
|
5503
|
+
href: isDisabled ? void 0 : href,
|
|
5504
|
+
to: isDisabled ? void 0 : href,
|
|
4386
5505
|
target: target,
|
|
4387
5506
|
rel: "_blank" === target ? "noopener noreferrer" : void 0
|
|
4388
5507
|
};
|
|
@@ -4395,7 +5514,7 @@ const Button = React__default.default.memo( React.forwardRef((({label: label, c
|
|
|
4395
5514
|
content = jsxRuntime.jsx("a", {
|
|
4396
5515
|
...buttonProps,
|
|
4397
5516
|
ref: ref,
|
|
4398
|
-
href: href,
|
|
5517
|
+
href: isDisabled ? void 0 : href,
|
|
4399
5518
|
target: target,
|
|
4400
5519
|
rel: "_blank" === target ? "noopener noreferrer" : void 0,
|
|
4401
5520
|
children: buttonContent
|
|
@@ -4674,7 +5793,7 @@ row: row = !1, flat: flat = !1,
|
|
|
4674
5793
|
// States
|
|
4675
5794
|
active: active = !1, disabled: disabled = !1, loading: loading = !1, selected: selected = !1, interactive: interactive = !1,
|
|
4676
5795
|
// Content
|
|
4677
|
-
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,
|
|
4678
5797
|
// Interaction
|
|
4679
5798
|
onClick: onClick, onHover: onHover, onFocus: onFocus, href: href, target: target,
|
|
4680
5799
|
// Custom Link
|
|
@@ -4877,50 +5996,50 @@ Card.Header = CardHeader, Card.Body = CardBody, Card.Footer = CardFooter;
|
|
|
4877
5996
|
* @param options - Configuration options for the card
|
|
4878
5997
|
* @returns Card state and handlers
|
|
4879
5998
|
*/
|
|
4880
|
-
const
|
|
4881
|
-
const {
|
|
4882
|
-
flipEffect
|
|
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
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
}
|
|
4923
|
-
|
|
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
|
+
})({
|
|
4924
6043
|
elevationEffect: !0,
|
|
4925
6044
|
elevationClass: elevationClass,
|
|
4926
6045
|
clickable: Boolean(onClick),
|
|
@@ -9304,216 +10423,13 @@ function getRowId$1(row, rowKey) {
|
|
|
9304
10423
|
|
|
9305
10424
|
/**
|
|
9306
10425
|
* Hook for managing DataTable state and behavior
|
|
9307
|
-
*/
|
|
9308
|
-
// Sort state
|
|
9309
|
-
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((() => {
|
|
9310
|
-
const visibility = {};
|
|
9311
|
-
return columns.forEach((col => {
|
|
9312
|
-
visibility[col.key] = !1 !== col.visible;
|
|
9313
|
-
})), visibility;
|
|
9314
|
-
})), [columnFilterValues, setColumnFilterValues] = React.useState({});
|
|
9315
|
-
// Pagination state
|
|
9316
|
-
// Update column order when columns prop changes
|
|
9317
|
-
React.useEffect((() => {
|
|
9318
|
-
const newOrder = columns.map((col => col.key)), currentOrderSet = new Set(columnOrder), newOrderSet = new Set(newOrder);
|
|
9319
|
-
// Only update if there are actual differences
|
|
9320
|
-
newOrder.length === columnOrder.length && newOrder.every((key => currentOrderSet.has(key))) && columnOrder.every((key => newOrderSet.has(key))) || setColumnOrder(newOrder);
|
|
9321
|
-
}), [ columns ]),
|
|
9322
|
-
// Update column visibility when columns prop changes
|
|
9323
|
-
React.useEffect((() => {
|
|
9324
|
-
setColumnVisibility((prev => {
|
|
9325
|
-
const updated = {
|
|
9326
|
-
...prev
|
|
9327
|
-
};
|
|
9328
|
-
return columns.forEach((col => {
|
|
9329
|
-
col.key in updated || (updated[col.key] = !1 !== col.visible);
|
|
9330
|
-
})), updated;
|
|
9331
|
-
}));
|
|
9332
|
-
}), [ columns ]);
|
|
9333
|
-
// Visible columns based on order and visibility
|
|
9334
|
-
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 => {
|
|
9335
|
-
if (!sortable) return;
|
|
9336
|
-
let direction = "asc";
|
|
9337
|
-
sortConfig && sortConfig.key === key && "asc" === sortConfig.direction && (direction = "desc");
|
|
9338
|
-
const newSortConfig = {
|
|
9339
|
-
key: key,
|
|
9340
|
-
direction: direction
|
|
9341
|
-
};
|
|
9342
|
-
setSortConfig(newSortConfig), onSort && onSort(newSortConfig);
|
|
9343
|
-
}), [ sortable, sortConfig, onSort ]), handlePageChange = React.useCallback((page => {
|
|
9344
|
-
page < 1 || setCurrentPage(page);
|
|
9345
|
-
}), []), handleSearch = React.useCallback((query => {
|
|
9346
|
-
setSearchQuery(query), setCurrentPage(1);
|
|
9347
|
-
} // Reset to first page when searching
|
|
9348
|
-
), []), handleColumnFilterChange = React.useCallback(((columnKey, value) => {
|
|
9349
|
-
setColumnFilterValues((prev => ({
|
|
9350
|
-
...prev,
|
|
9351
|
-
[columnKey]: value
|
|
9352
|
-
}))), setCurrentPage(1);
|
|
9353
|
-
} // Reset to first page when filtering
|
|
9354
|
-
), []), clearColumnFilters = React.useCallback((() => {
|
|
9355
|
-
setColumnFilterValues({}), setCurrentPage(1);
|
|
9356
|
-
}), []), activeColumnFilters = React.useMemo((() => columnFilters ? Object.entries(columnFilterValues).filter((([, value]) => null != value && "" !== value)).map((([columnKey, value]) => {
|
|
9357
|
-
const column = columns.find((col => col.key === columnKey));
|
|
9358
|
-
return column && column.filterable ? {
|
|
9359
|
-
key: columnKey,
|
|
9360
|
-
value: value,
|
|
9361
|
-
lowercaseValue: "string" == typeof value ? value.toLowerCase() : String(value).toLowerCase(),
|
|
9362
|
-
column: column
|
|
9363
|
-
} : null;
|
|
9364
|
-
})).filter((f => null !== f)) : []), [ columnFilters, columnFilterValues, columns ]), filteredData = React.useMemo((() => {
|
|
9365
|
-
if (!searchQuery && 0 === activeColumnFilters.length) return data;
|
|
9366
|
-
const lowercaseQuery = searchQuery ? searchQuery.toLowerCase() : "";
|
|
9367
|
-
return data.filter((row => {
|
|
9368
|
-
// Apply global search
|
|
9369
|
-
if (searchQuery && !visibleColumns.some((column => {
|
|
9370
|
-
var _context;
|
|
9371
|
-
const value = row[column.key];
|
|
9372
|
-
return null != value && _includesInstanceProperty(_context = String(value).toLowerCase()).call(_context, lowercaseQuery);
|
|
9373
|
-
}))) return !1;
|
|
9374
|
-
// Apply column-specific filters
|
|
9375
|
-
for (let i = 0; i < activeColumnFilters.length; i++) {
|
|
9376
|
-
const filter = activeColumnFilters[i];
|
|
9377
|
-
if (!filter) continue;
|
|
9378
|
-
const {key: key, value: value, lowercaseValue: lowercaseValue, column: column} = filter, cellValue = row[key];
|
|
9379
|
-
if (null == cellValue) return !1;
|
|
9380
|
-
// Use custom filter function if provided
|
|
9381
|
-
var _context2;
|
|
9382
|
-
// Default text filter
|
|
9383
|
-
if (column.filterFunction) {
|
|
9384
|
-
if (!column.filterFunction(cellValue, value)) return !1;
|
|
9385
|
-
} else if (!_includesInstanceProperty(_context2 = String(cellValue).toLowerCase()).call(_context2, lowercaseValue)) return !1;
|
|
9386
|
-
}
|
|
9387
|
-
return !0;
|
|
9388
|
-
}));
|
|
9389
|
-
}), [ data, visibleColumns, searchQuery, activeColumnFilters ]), sortedData = React.useMemo((() => sortConfig && sortable ? [ ...filteredData ].sort(((a, b) => {
|
|
9390
|
-
const aValue = a[sortConfig.key], bValue = b[sortConfig.key];
|
|
9391
|
-
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;
|
|
9392
|
-
})) : filteredData), [ filteredData, sortConfig, sortable ]), paginatedData = React.useMemo((() => {
|
|
9393
|
-
if (!paginated) return sortedData;
|
|
9394
|
-
const startIndex = (currentPage - 1) * pageSize;
|
|
9395
|
-
return sortedData.slice(startIndex, startIndex + pageSize);
|
|
9396
|
-
}), [ 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) => {
|
|
9397
|
-
if ("none" === selectionMode) return;
|
|
9398
|
-
let newSelectedIds;
|
|
9399
|
-
if (newSelectedIds = "single" === selectionMode ? selected ? [ rowId ] : [] :
|
|
9400
|
-
// multiple
|
|
9401
|
-
selected ? [ ...selectedRowIds, rowId ] : selectedRowIds.filter((id => id !== rowId)),
|
|
9402
|
-
controlledSelectedRowIds || setInternalSelectedRowIds(newSelectedIds), onSelectionChange) {
|
|
9403
|
-
const selectedRowsData = sortedData.filter((row => _includesInstanceProperty(newSelectedIds).call(newSelectedIds, getRowId$1(row, rowKey))));
|
|
9404
|
-
onSelectionChange(selectedRowsData, newSelectedIds);
|
|
9405
|
-
}
|
|
9406
|
-
}), [ selectionMode, selectedRowIds, controlledSelectedRowIds, onSelectionChange, sortedData, rowKey ]), handleSelectAll = React.useCallback((selected => {
|
|
9407
|
-
if ("multiple" !== selectionMode) return;
|
|
9408
|
-
const newSelectedIds = selected ? paginatedData.map((row => getRowId$1(row, rowKey))) : [];
|
|
9409
|
-
if (controlledSelectedRowIds || setInternalSelectedRowIds(newSelectedIds), onSelectionChange) {
|
|
9410
|
-
const selectedRowsData = sortedData.filter((row => _includesInstanceProperty(newSelectedIds).call(newSelectedIds, getRowId$1(row, rowKey))));
|
|
9411
|
-
onSelectionChange(selectedRowsData, newSelectedIds);
|
|
9412
|
-
}
|
|
9413
|
-
}), [ 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((() => {
|
|
9414
|
-
if ("multiple" !== selectionMode || 0 === paginatedData.length) return !1;
|
|
9415
|
-
const selectedCount = paginatedData.filter((row => _includesInstanceProperty(selectedRowIds).call(selectedRowIds, getRowId$1(row, rowKey)))).length;
|
|
9416
|
-
return selectedCount > 0 && selectedCount < paginatedData.length;
|
|
9417
|
-
}), [ selectionMode, paginatedData, selectedRowIds, rowKey ]), handleColumnVisibilityToggle = React.useCallback((columnKey => {
|
|
9418
|
-
setColumnVisibility((prev => {
|
|
9419
|
-
const updated = {
|
|
9420
|
-
...prev,
|
|
9421
|
-
[columnKey]: !prev[columnKey]
|
|
9422
|
-
};
|
|
9423
|
-
if (onColumnVisibilityChange) {
|
|
9424
|
-
const visibleKeys = Object.entries(updated).filter((([, visible]) => visible)).map((([key]) => key));
|
|
9425
|
-
onColumnVisibilityChange(visibleKeys);
|
|
9426
|
-
}
|
|
9427
|
-
return updated;
|
|
9428
|
-
}));
|
|
9429
|
-
}), [ onColumnVisibilityChange ]);
|
|
9430
|
-
// Handle sorting
|
|
9431
|
-
// Handle column reorder
|
|
9432
|
-
return React.useCallback(((fromIndex, toIndex) => {
|
|
9433
|
-
const newOrder = [ ...columnOrder ], [removed] = newOrder.splice(fromIndex, 1);
|
|
9434
|
-
removed && (newOrder.splice(toIndex, 0, removed), setColumnOrder(newOrder), onColumnReorder && onColumnReorder(newOrder));
|
|
9435
|
-
}), [ columnOrder, onColumnReorder ]),
|
|
9436
|
-
// Reset to first page when data changes
|
|
9437
|
-
React.useEffect((() => {
|
|
9438
|
-
setCurrentPage(1);
|
|
9439
|
-
}), [ data ]),
|
|
9440
|
-
// Reset current page if it's out of bounds
|
|
9441
|
-
React.useEffect((() => {
|
|
9442
|
-
currentPage > totalPages && totalPages > 0 && setCurrentPage(Math.max(1, totalPages));
|
|
9443
|
-
}), [ currentPage, totalPages ]), {
|
|
9444
|
-
displayData: paginatedData,
|
|
9445
|
-
sortConfig: sortConfig,
|
|
9446
|
-
currentPage: currentPage,
|
|
9447
|
-
totalPages: totalPages,
|
|
9448
|
-
handleSort: handleSort,
|
|
9449
|
-
handlePageChange: handlePageChange,
|
|
9450
|
-
handleSearch: handleSearch,
|
|
9451
|
-
selectedRowIds: selectedRowIds,
|
|
9452
|
-
selectedRows: selectedRows,
|
|
9453
|
-
handleRowSelect: handleRowSelect,
|
|
9454
|
-
handleSelectAll: handleSelectAll,
|
|
9455
|
-
isAllSelected: isAllSelected,
|
|
9456
|
-
isIndeterminate: isIndeterminate,
|
|
9457
|
-
columnOrder: columnOrder,
|
|
9458
|
-
visibleColumns: visibleColumns,
|
|
9459
|
-
columnVisibility: columnVisibility,
|
|
9460
|
-
handleColumnVisibilityToggle: handleColumnVisibilityToggle,
|
|
9461
|
-
columnFilterValues: columnFilterValues,
|
|
9462
|
-
handleColumnFilterChange: handleColumnFilterChange,
|
|
9463
|
-
clearColumnFilters: clearColumnFilters
|
|
9464
|
-
};
|
|
9465
|
-
}
|
|
9466
|
-
|
|
9467
|
-
Countdown.displayName = "Countdown";
|
|
10426
|
+
*/ Countdown.displayName = "Countdown";
|
|
9468
10427
|
|
|
9469
10428
|
const range = (start, end) => {
|
|
9470
10429
|
const length = end - start + 1;
|
|
9471
10430
|
return Array.from({
|
|
9472
10431
|
length: length
|
|
9473
10432
|
}, ((_, idx) => idx + start));
|
|
9474
|
-
}, usePagination = ({currentPage: currentPage, totalPages: totalPages, siblingCount: siblingCount = 1, onPageChange: onPageChange}) => {
|
|
9475
|
-
const paginationRange = React.useMemo((() => {
|
|
9476
|
-
// siblingCount + firstPage + lastPage + currentPage + 2*DOTS
|
|
9477
|
-
/*
|
|
9478
|
-
Case 1: If the number of pages is less than the page numbers we want to show in our
|
|
9479
|
-
paginationComponent, we return the range [1..totalPages]
|
|
9480
|
-
*/
|
|
9481
|
-
if (siblingCount + 5 >= totalPages) return range(1, totalPages);
|
|
9482
|
-
const leftSiblingIndex = Math.max(currentPage - siblingCount, 1), rightSiblingIndex = Math.min(currentPage + siblingCount, totalPages), shouldShowLeftDots = leftSiblingIndex > 2, shouldShowRightDots = rightSiblingIndex < totalPages - 2, lastPageIndex = totalPages;
|
|
9483
|
-
/*
|
|
9484
|
-
Case 2: No left dots to show, but rights dots to be shown
|
|
9485
|
-
*/
|
|
9486
|
-
return !shouldShowLeftDots && shouldShowRightDots ? [ ...range(1, 3 + 2 * siblingCount), "...", totalPages ] :
|
|
9487
|
-
/*
|
|
9488
|
-
Case 3: No right dots to show, but left dots to be shown
|
|
9489
|
-
*/
|
|
9490
|
-
shouldShowLeftDots && !shouldShowRightDots ? [ 1, "...", ...range(totalPages - (3 + 2 * siblingCount) + 1, totalPages) ] :
|
|
9491
|
-
/*
|
|
9492
|
-
Case 4: Both left and right dots to be shown
|
|
9493
|
-
*/
|
|
9494
|
-
shouldShowLeftDots && shouldShowRightDots ? [ 1, "...", ...range(leftSiblingIndex, rightSiblingIndex), "...", lastPageIndex ] : [];
|
|
9495
|
-
}), [ totalPages, siblingCount, currentPage ]), goToPage = page => {
|
|
9496
|
-
page >= 1 && page <= totalPages && page !== currentPage && onPageChange(page);
|
|
9497
|
-
};
|
|
9498
|
-
return {
|
|
9499
|
-
paginationRange: paginationRange,
|
|
9500
|
-
currentPage: currentPage,
|
|
9501
|
-
totalPages: totalPages,
|
|
9502
|
-
goToPage: goToPage,
|
|
9503
|
-
nextPage: () => {
|
|
9504
|
-
goToPage(currentPage + 1);
|
|
9505
|
-
},
|
|
9506
|
-
prevPage: () => {
|
|
9507
|
-
goToPage(currentPage - 1);
|
|
9508
|
-
},
|
|
9509
|
-
firstPage: () => {
|
|
9510
|
-
goToPage(1);
|
|
9511
|
-
},
|
|
9512
|
-
lastPage: () => {
|
|
9513
|
-
goToPage(totalPages);
|
|
9514
|
-
},
|
|
9515
|
-
DOTS: "..."
|
|
9516
|
-
};
|
|
9517
10433
|
}, PaginationNavButton = React.memo((({type: type, onClick: onClick, disabled: disabled, label: label, iconName: iconName}) => jsxRuntime.jsx("li", {
|
|
9518
10434
|
className: `c-pagination__item c-pagination__item--${type} ${disabled ? "is-disabled" : ""}`,
|
|
9519
10435
|
"aria-disabled": disabled,
|
|
@@ -9530,7 +10446,50 @@ const range = (start, end) => {
|
|
|
9530
10446
|
})
|
|
9531
10447
|
})
|
|
9532
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}) => {
|
|
9533
|
-
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
|
+
})({
|
|
9534
10493
|
currentPage: currentPage,
|
|
9535
10494
|
totalPages: totalPages,
|
|
9536
10495
|
siblingCount: siblingCount,
|
|
@@ -9742,14 +10701,13 @@ const DropdownContext = React.createContext({
|
|
|
9742
10701
|
id: "",
|
|
9743
10702
|
trigger: "click"
|
|
9744
10703
|
}), DropdownMenu = React.forwardRef((({children: children, className: className = "", ...props}, ref) => {
|
|
9745
|
-
const {glass: glass} = React.useContext(DropdownStyleContext);
|
|
9746
|
-
|
|
9747
|
-
// Wait, the original code wrapped <ul> in Context Provider.
|
|
9748
|
-
// And applied glass wrapper around <ul>.
|
|
9749
|
-
// If we use Compound Component, DropdownMenu should be the list.
|
|
9750
|
-
return jsxRuntime.jsx("ul", {
|
|
10704
|
+
const {glass: glass} = React.useContext(DropdownStyleContext), {id: id} = React.useContext(DropdownContext);
|
|
10705
|
+
return jsxRuntime.jsx("ul", {
|
|
9751
10706
|
ref: ref,
|
|
10707
|
+
id: `${id}-menu`,
|
|
9752
10708
|
className: `c-dropdown__menu ${glass ? "c-dropdown__menu--glass" : ""} ${className}`.trim(),
|
|
10709
|
+
role: "menu",
|
|
10710
|
+
"aria-labelledby": `${id}-trigger`,
|
|
9753
10711
|
...props,
|
|
9754
10712
|
children: children
|
|
9755
10713
|
});
|
|
@@ -9758,14 +10716,23 @@ const DropdownContext = React.createContext({
|
|
|
9758
10716
|
// Compound Components
|
|
9759
10717
|
DropdownMenu.displayName = "DropdownMenu";
|
|
9760
10718
|
|
|
9761
|
-
const DropdownTrigger = React.forwardRef((({children: children, className: className = "", onClick: onClick, onKeyDown: onKeyDown, ...props}, ref) =>
|
|
9762
|
-
|
|
9763
|
-
|
|
9764
|
-
|
|
9765
|
-
|
|
9766
|
-
|
|
9767
|
-
|
|
9768
|
-
|
|
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
|
+
}));
|
|
9769
10736
|
|
|
9770
10737
|
DropdownTrigger.displayName = "DropdownTrigger";
|
|
9771
10738
|
|
|
@@ -10014,7 +10981,165 @@ Dropdown.Item = DropdownItem, Dropdown.Divider = DropdownDivider, Dropdown.Heade
|
|
|
10014
10981
|
* ```
|
|
10015
10982
|
*/
|
|
10016
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}) => {
|
|
10017
|
-
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
|
+
}({
|
|
10018
11143
|
data: data,
|
|
10019
11144
|
columns: columns,
|
|
10020
11145
|
sortable: sortable,
|
|
@@ -12366,297 +13491,6 @@ const DEFAULT_ATOMIX_FONTS = [ {
|
|
|
12366
13491
|
};
|
|
12367
13492
|
}
|
|
12368
13493
|
|
|
12369
|
-
/**
|
|
12370
|
-
* Breadcrumb state and functionality
|
|
12371
|
-
* @param initialOptions - Initial breadcrumb options
|
|
12372
|
-
* @returns Breadcrumb state and methods
|
|
12373
|
-
*/ function useBreadcrumb(initialOptions) {
|
|
12374
|
-
return {
|
|
12375
|
-
defaultOptions: {
|
|
12376
|
-
items: [],
|
|
12377
|
-
divider: BREADCRUMB.DEFAULTS.DIVIDER,
|
|
12378
|
-
className: "",
|
|
12379
|
-
"aria-label": "Breadcrumb",
|
|
12380
|
-
...initialOptions
|
|
12381
|
-
},
|
|
12382
|
-
generateBreadcrumbClass: options => {
|
|
12383
|
-
const {className: className = ""} = options;
|
|
12384
|
-
return [ BREADCRUMB.CLASSES.BASE, className ].filter(Boolean).join(" ").trim();
|
|
12385
|
-
},
|
|
12386
|
-
generateItemClass: (item, isLast) => [ BREADCRUMB.CLASSES.ITEM, item.active || isLast ? BREADCRUMB.CLASSES.ACTIVE : "" ].filter(Boolean).join(" ").trim(),
|
|
12387
|
-
isItemLink: (item, isLast) => Boolean(item.href && !item.active && !isLast),
|
|
12388
|
-
parseItemsFromJson: jsonString => {
|
|
12389
|
-
try {
|
|
12390
|
-
return JSON.parse(jsonString);
|
|
12391
|
-
} catch (error) {
|
|
12392
|
-
return console.error("Error parsing breadcrumb items:", error), [];
|
|
12393
|
-
}
|
|
12394
|
-
}
|
|
12395
|
-
};
|
|
12396
|
-
}
|
|
12397
|
-
|
|
12398
|
-
/**
|
|
12399
|
-
* Hook for managing modal state
|
|
12400
|
-
*/ function useModal$1({isOpen: isOpenProp, onOpenChange: onOpenChange, onOpen: onOpen, onClose: onClose} = {}) {
|
|
12401
|
-
// For uncontrolled usage
|
|
12402
|
-
const [isOpenState, setIsOpenState] = React.useState(!1), isControlled = void 0 !== isOpenProp, isOpen = isControlled ? !!isOpenProp : isOpenState;
|
|
12403
|
-
// Determine if we're in controlled or uncontrolled mode
|
|
12404
|
-
// Update internal state when prop changes (for controlled mode)
|
|
12405
|
-
React.useEffect((() => {
|
|
12406
|
-
isControlled && setIsOpenState(!!isOpenProp);
|
|
12407
|
-
}), [ isOpenProp, isControlled ]);
|
|
12408
|
-
const updateOpen = React.useCallback((nextIsOpen => {
|
|
12409
|
-
// For uncontrolled mode, update internal state
|
|
12410
|
-
isControlled || setIsOpenState(nextIsOpen),
|
|
12411
|
-
// Call the change handler in either mode
|
|
12412
|
-
onOpenChange && onOpenChange(nextIsOpen),
|
|
12413
|
-
// Call the specific handler
|
|
12414
|
-
nextIsOpen && onOpen ? onOpen() : !nextIsOpen && onClose && onClose();
|
|
12415
|
-
}), [ isControlled, onOpenChange, onOpen, onClose ]), open = React.useCallback((() => {
|
|
12416
|
-
updateOpen(!0);
|
|
12417
|
-
}), [ updateOpen ]), close = React.useCallback((() => {
|
|
12418
|
-
updateOpen(!1);
|
|
12419
|
-
}), [ updateOpen ]), toggle = React.useCallback((() => {
|
|
12420
|
-
updateOpen(!isOpen);
|
|
12421
|
-
}), [ isOpen, updateOpen ]);
|
|
12422
|
-
return {
|
|
12423
|
-
isOpen: isOpen,
|
|
12424
|
-
open: open,
|
|
12425
|
-
close: close,
|
|
12426
|
-
toggle: toggle
|
|
12427
|
-
};
|
|
12428
|
-
}
|
|
12429
|
-
|
|
12430
|
-
function useSlider(options) {
|
|
12431
|
-
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({
|
|
12432
|
-
isTransitioning: !1,
|
|
12433
|
-
loop: loop,
|
|
12434
|
-
slides: slides,
|
|
12435
|
-
slidesToShow: slidesToShow,
|
|
12436
|
-
speed: speed,
|
|
12437
|
-
onSlideChange: onSlideChange
|
|
12438
|
-
}), [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) => ({
|
|
12439
|
-
...slide,
|
|
12440
|
-
id: `set1-${slide.id || i}`
|
|
12441
|
-
}))), ...slides.map(((slide, i) => ({
|
|
12442
|
-
...slide,
|
|
12443
|
-
id: `set2-${slide.id || i}`
|
|
12444
|
-
}))), ...slides.map(((slide, i) => ({
|
|
12445
|
-
...slide,
|
|
12446
|
-
id: `set3-${slide.id || i}`
|
|
12447
|
-
}))) ] : slides), [ slides, loop ]), loopedSlides = slides.length, translateValue = React.useMemo((() => 0 === slideWidth ? 0 : -internalIndex * slideWidth + dragOffset), [ slideWidth, internalIndex, dragOffset ]);
|
|
12448
|
-
// Update the ref whenever the relevant state/props change
|
|
12449
|
-
React.useEffect((() => {
|
|
12450
|
-
sliderStateRef.current = {
|
|
12451
|
-
isTransitioning: isTransitioning,
|
|
12452
|
-
loop: loop,
|
|
12453
|
-
slides: slides,
|
|
12454
|
-
slidesToShow: slidesToShow,
|
|
12455
|
-
speed: speed,
|
|
12456
|
-
onSlideChange: onSlideChange
|
|
12457
|
-
};
|
|
12458
|
-
}), [ isTransitioning, loop, slides, slidesToShow, speed, onSlideChange ]),
|
|
12459
|
-
// Autoplay effect
|
|
12460
|
-
React.useEffect((() => {
|
|
12461
|
-
if (!autoplay) return autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12462
|
-
autoplayRef.current = null), void setAutoplayRunning(!1);
|
|
12463
|
-
const autoplayParams = "boolean" == typeof autoplay ? {
|
|
12464
|
-
delay: 3e3
|
|
12465
|
-
} : autoplay, {delay: delay = 3e3, pauseOnMouseEnter: pauseOnMouseEnter = !1, disableOnInteraction: disableOnInteraction = !1, reverseDirection: reverseDirection = !1} = autoplayParams;
|
|
12466
|
-
// Clear any existing interval
|
|
12467
|
-
autoplayRef.current && clearInterval(autoplayRef.current),
|
|
12468
|
-
// Create new interval
|
|
12469
|
-
autoplayRef.current = setInterval((() => {
|
|
12470
|
-
// Use ref to get the latest state without resetting the interval
|
|
12471
|
-
const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
|
|
12472
|
-
// We need to use a functional update to get the latest values
|
|
12473
|
-
setRealIndex((prevRealIndex => {
|
|
12474
|
-
if (currentIsTransitioning) return prevRealIndex;
|
|
12475
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12476
|
-
let nextIndex;
|
|
12477
|
-
// Trigger the slide change
|
|
12478
|
-
if (disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12479
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
|
|
12480
|
-
reverseDirection) {
|
|
12481
|
-
// For reverse direction, we would go to previous slide
|
|
12482
|
-
const prevIndex = currentLoop ? 0 === prevRealIndex ? currentSlides.length - 1 : prevRealIndex - 1 : Math.max(prevRealIndex - 1, 0);
|
|
12483
|
-
return setInternalIndex(currentLoop ? currentSlides.length + prevIndex : prevIndex),
|
|
12484
|
-
setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
|
|
12485
|
-
setIsTransitioning(!1), currentOnSlideChange?.(prevIndex);
|
|
12486
|
-
}), currentSpeed), prevIndex;
|
|
12487
|
-
}
|
|
12488
|
-
// Normal direction
|
|
12489
|
-
return setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex),
|
|
12490
|
-
setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
|
|
12491
|
-
setIsTransitioning(!1), currentOnSlideChange?.(nextIndex),
|
|
12492
|
-
// Reposition after transition ends for looped sliders
|
|
12493
|
-
currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
|
|
12494
|
-
setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
|
|
12495
|
-
repositioningRef.current = !1;
|
|
12496
|
-
}), 0));
|
|
12497
|
-
}), currentSpeed), nextIndex;
|
|
12498
|
-
}));
|
|
12499
|
-
}), delay), setAutoplayRunning(!0);
|
|
12500
|
-
// Handle pause on mouse enter/leave if enabled
|
|
12501
|
-
let containerElement = null;
|
|
12502
|
-
const handleMouseEnter = () => {
|
|
12503
|
-
autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null,
|
|
12504
|
-
setAutoplayRunning(!1));
|
|
12505
|
-
}, handleMouseLeave = () => {
|
|
12506
|
-
// Restart autoplay
|
|
12507
|
-
autoplayRef.current && clearInterval(autoplayRef.current), autoplayRef.current = setInterval((() => {
|
|
12508
|
-
const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
|
|
12509
|
-
setRealIndex((prevRealIndex => {
|
|
12510
|
-
if (currentIsTransitioning) return prevRealIndex;
|
|
12511
|
-
let nextIndex;
|
|
12512
|
-
return nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
|
|
12513
|
-
setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex), setIsTransitioning(!0),
|
|
12514
|
-
setDragOffset(0), setTimeout((() => {
|
|
12515
|
-
setIsTransitioning(!1), currentOnSlideChange?.(nextIndex), currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
|
|
12516
|
-
setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
|
|
12517
|
-
repositioningRef.current = !1;
|
|
12518
|
-
}), 0));
|
|
12519
|
-
}), currentSpeed), nextIndex;
|
|
12520
|
-
}));
|
|
12521
|
-
}), delay), setAutoplayRunning(!0);
|
|
12522
|
-
};
|
|
12523
|
-
// Cleanup
|
|
12524
|
-
return pauseOnMouseEnter && containerRef.current && (containerElement = containerRef.current,
|
|
12525
|
-
containerElement.addEventListener("mouseenter", handleMouseEnter), containerElement.addEventListener("mouseleave", handleMouseLeave)),
|
|
12526
|
-
() => {
|
|
12527
|
-
autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null),
|
|
12528
|
-
containerElement && (containerElement.removeEventListener("mouseenter", handleMouseEnter),
|
|
12529
|
-
containerElement.removeEventListener("mouseleave", handleMouseLeave)), setAutoplayRunning(!1);
|
|
12530
|
-
};
|
|
12531
|
-
}), [ autoplay, repositioningRef ]),
|
|
12532
|
-
// Initialize
|
|
12533
|
-
React.useEffect((() => {
|
|
12534
|
-
setInternalIndex(loop ? slides.length + initialSlide : initialSlide);
|
|
12535
|
-
}), [ loop, slides.length, initialSlide ]), React.useEffect((() => {
|
|
12536
|
-
const updateSize = () => {
|
|
12537
|
-
if (containerRef.current) {
|
|
12538
|
-
const size = "horizontal" === direction ? containerRef.current.offsetWidth : containerRef.current.offsetHeight;
|
|
12539
|
-
setContainerSize(size);
|
|
12540
|
-
}
|
|
12541
|
-
};
|
|
12542
|
-
return updateSize(), window.addEventListener("resize", updateSize), () => window.removeEventListener("resize", updateSize);
|
|
12543
|
-
}), [ direction ]);
|
|
12544
|
-
const slideNext = React.useCallback((() => {
|
|
12545
|
-
if (!isTransitioning) if (
|
|
12546
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12547
|
-
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12548
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), loop) {
|
|
12549
|
-
const nextRealIndex = (realIndex + 1) % slides.length, nextInternalIndex = internalIndex + 1;
|
|
12550
|
-
setRealIndex(nextRealIndex), setInternalIndex(nextInternalIndex), setIsTransitioning(!0),
|
|
12551
|
-
setDragOffset(0), setTimeout((() => {
|
|
12552
|
-
setIsTransitioning(!1), onSlideChange?.(nextRealIndex),
|
|
12553
|
-
// Reposition after transition ends
|
|
12554
|
-
nextInternalIndex >= 2 * slides.length && (repositioningRef.current = !0, setInternalIndex(slides.length + nextRealIndex),
|
|
12555
|
-
setTimeout((() => {
|
|
12556
|
-
repositioningRef.current = !1;
|
|
12557
|
-
}), 0));
|
|
12558
|
-
}), speed);
|
|
12559
|
-
} else {
|
|
12560
|
-
const nextIndex = Math.min(realIndex + 1, slides.length - slidesToShow);
|
|
12561
|
-
setRealIndex(nextIndex), setInternalIndex(nextIndex), setIsTransitioning(!0), setDragOffset(0),
|
|
12562
|
-
setTimeout((() => {
|
|
12563
|
-
setIsTransitioning(!1), onSlideChange?.(nextIndex);
|
|
12564
|
-
}), speed);
|
|
12565
|
-
}
|
|
12566
|
-
}), [ realIndex, internalIndex, slides.length, slidesToShow, loop, isTransitioning, speed, onSlideChange, allSlides.length, loopedSlides, autoplay ]), slidePrev = React.useCallback((() => {
|
|
12567
|
-
if (!isTransitioning) if (
|
|
12568
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12569
|
-
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12570
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), loop) {
|
|
12571
|
-
const prevRealIndex = 0 === realIndex ? slides.length - 1 : realIndex - 1, prevInternalIndex = internalIndex - 1;
|
|
12572
|
-
setRealIndex(prevRealIndex), setInternalIndex(prevInternalIndex), setIsTransitioning(!0),
|
|
12573
|
-
setDragOffset(0), setTimeout((() => {
|
|
12574
|
-
setIsTransitioning(!1), onSlideChange?.(prevRealIndex),
|
|
12575
|
-
// Reposition after transition ends
|
|
12576
|
-
prevInternalIndex < slides.length && (repositioningRef.current = !0, setInternalIndex(slides.length + prevRealIndex),
|
|
12577
|
-
setTimeout((() => {
|
|
12578
|
-
repositioningRef.current = !1;
|
|
12579
|
-
}), 0));
|
|
12580
|
-
}), speed);
|
|
12581
|
-
} else {
|
|
12582
|
-
const prevIndex = Math.max(realIndex - 1, 0);
|
|
12583
|
-
setRealIndex(prevIndex), setInternalIndex(prevIndex), setIsTransitioning(!0), setDragOffset(0),
|
|
12584
|
-
setTimeout((() => {
|
|
12585
|
-
setIsTransitioning(!1), onSlideChange?.(prevIndex);
|
|
12586
|
-
}), speed);
|
|
12587
|
-
}
|
|
12588
|
-
}), [ realIndex, internalIndex, slides.length, loop, isTransitioning, speed, onSlideChange, allSlides.length, loopedSlides, autoplay ]), goToSlide = React.useCallback((index => {
|
|
12589
|
-
isTransitioning || index === realIndex || (
|
|
12590
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12591
|
-
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12592
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), setIsTransitioning(!0), setDragOffset(0),
|
|
12593
|
-
setRealIndex(index), setInternalIndex(loop ? slides.length + index : index), setTimeout((() => {
|
|
12594
|
-
setIsTransitioning(!1), onSlideChange?.(index);
|
|
12595
|
-
}), speed));
|
|
12596
|
-
}), [ realIndex, isTransitioning, speed, onSlideChange, loop, loopedSlides, autoplay ]), handleTouchStart = React.useCallback((e => {
|
|
12597
|
-
if (!allowTouchMove) return;
|
|
12598
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12599
|
-
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12600
|
-
autoplayRef.current = null, setAutoplayRunning(!1));
|
|
12601
|
-
const client = "horizontal" === direction ? "touches" in e ? e.touches[0]?.clientX || 0 : e.clientX : "touches" in e ? e.touches[0]?.clientY || 0 : e.clientY;
|
|
12602
|
-
setTouchStart(client), setTouching(!0), setDragOffset(0);
|
|
12603
|
-
}), [ allowTouchMove, direction, autoplay ]), handleTouchMove = React.useCallback((e => {
|
|
12604
|
-
if (!touching || !allowTouchMove) return;
|
|
12605
|
-
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;
|
|
12606
|
-
Math.abs(diff) > 10 && (e.preventDefault(), setDragOffset(.5 * -diff));
|
|
12607
|
-
}), [ touching, touchStart, allowTouchMove, direction ]), handleTouchEnd = React.useCallback((e => {
|
|
12608
|
-
if (!touching || !allowTouchMove) return;
|
|
12609
|
-
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;
|
|
12610
|
-
setTouching(!1), setDragOffset(0), Math.abs(diff) > threshold && (diff > 0 ? slideNext() : slidePrev());
|
|
12611
|
-
}), [ touching, touchStart, threshold, slideNext, slidePrev, allowTouchMove, direction ]), canSlideNext = loop || realIndex < slides.length - slidesToShow, canSlidePrev = loop || realIndex > 0;
|
|
12612
|
-
return {
|
|
12613
|
-
activeIndex: realIndex,
|
|
12614
|
-
realIndex: realIndex,
|
|
12615
|
-
previousIndex: realIndex,
|
|
12616
|
-
isBeginning: !loop && 0 === realIndex,
|
|
12617
|
-
isEnd: !loop && realIndex >= slides.length - slidesToShow,
|
|
12618
|
-
progress: slides.length > 0 ? realIndex / (slides.length - 1) : 0,
|
|
12619
|
-
autoplayRunning: autoplayRunning,
|
|
12620
|
-
transitioning: isTransitioning,
|
|
12621
|
-
touching: touching,
|
|
12622
|
-
translate: translateValue,
|
|
12623
|
-
slidesPerView: slidesToShow,
|
|
12624
|
-
slidesCount: slides.length,
|
|
12625
|
-
isLocked: !1,
|
|
12626
|
-
destroyed: !1,
|
|
12627
|
-
size: containerSize,
|
|
12628
|
-
touches: {
|
|
12629
|
-
startX: 0,
|
|
12630
|
-
startY: 0,
|
|
12631
|
-
currentX: 0,
|
|
12632
|
-
currentY: 0,
|
|
12633
|
-
diff: 0
|
|
12634
|
-
},
|
|
12635
|
-
allowSlideNext: canSlideNext,
|
|
12636
|
-
allowSlidePrev: canSlidePrev,
|
|
12637
|
-
allowTouchMove: allowTouchMove,
|
|
12638
|
-
animating: isTransitioning,
|
|
12639
|
-
enabled: !0,
|
|
12640
|
-
initialized: !0,
|
|
12641
|
-
slideNext: slideNext,
|
|
12642
|
-
slidePrev: slidePrev,
|
|
12643
|
-
goToSlide: goToSlide,
|
|
12644
|
-
canSlideNext: canSlideNext,
|
|
12645
|
-
canSlidePrev: canSlidePrev,
|
|
12646
|
-
containerRef: containerRef,
|
|
12647
|
-
wrapperRef: wrapperRef,
|
|
12648
|
-
handleTouchStart: handleTouchStart,
|
|
12649
|
-
handleTouchMove: handleTouchMove,
|
|
12650
|
-
handleTouchEnd: handleTouchEnd,
|
|
12651
|
-
allSlides: allSlides,
|
|
12652
|
-
translateValue: translateValue,
|
|
12653
|
-
slideWidth: slideWidth,
|
|
12654
|
-
currentSlidesToShow: slidesToShow,
|
|
12655
|
-
loopedSlides: loopedSlides,
|
|
12656
|
-
repositioningRef: repositioningRef
|
|
12657
|
-
};
|
|
12658
|
-
}
|
|
12659
|
-
|
|
12660
13494
|
/**
|
|
12661
13495
|
* Simplified hook for chart data processing
|
|
12662
13496
|
*/ function useChartData(data) {
|
|
@@ -12757,37 +13591,44 @@ function useSlider(options) {
|
|
|
12757
13591
|
// Accordion composables
|
|
12758
13592
|
var composablesImport = Object.freeze({
|
|
12759
13593
|
__proto__: null,
|
|
12760
|
-
|
|
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,
|
|
12761
13606
|
useAccordion: useAccordion,
|
|
12762
13607
|
useAtomixGlass: useAtomixGlass,
|
|
12763
13608
|
useBadge: useBadge,
|
|
12764
13609
|
useBarChart: useBarChart,
|
|
12765
13610
|
useBlock: useBlock,
|
|
12766
|
-
useBreadcrumb: useBreadcrumb,
|
|
12767
|
-
useCard: useCard,
|
|
12768
13611
|
useChartData: useChartData,
|
|
12769
13612
|
useChartInteraction: useChartInteraction,
|
|
12770
13613
|
useChartScale: useChartScale,
|
|
12771
|
-
useDataTable: useDataTable,
|
|
12772
13614
|
useEdgePanel: useEdgePanel,
|
|
12773
13615
|
useForm: useForm,
|
|
12774
13616
|
useFormGroup: useFormGroup,
|
|
12775
13617
|
useHero: useHero,
|
|
12776
13618
|
useInput: useInput,
|
|
12777
13619
|
useLineChart: useLineChart,
|
|
12778
|
-
useModal: useModal$1,
|
|
12779
13620
|
useNav: useNav,
|
|
12780
13621
|
useNavDropdown: useNavDropdown,
|
|
12781
13622
|
useNavItem: useNavItem,
|
|
12782
13623
|
useNavbar: useNavbar,
|
|
12783
|
-
|
|
13624
|
+
usePerformanceMonitor: usePerformanceMonitor,
|
|
12784
13625
|
usePieChart: usePieChart,
|
|
12785
13626
|
useRadio: useRadio,
|
|
13627
|
+
useResponsiveGlass: useResponsiveGlass,
|
|
12786
13628
|
useRiver: useRiver,
|
|
12787
13629
|
useSelect: useSelect,
|
|
12788
13630
|
useSideMenu: useSideMenu,
|
|
12789
13631
|
useSideMenuItem: useSideMenuItem,
|
|
12790
|
-
useSlider: useSlider,
|
|
12791
13632
|
useSpinner: useSpinner,
|
|
12792
13633
|
useTextarea: useTextarea,
|
|
12793
13634
|
useTodo: useTodo
|
|
@@ -12878,7 +13719,10 @@ const Select = React.memo((({options: options, value: value, onChange: onChange
|
|
|
12878
13719
|
};
|
|
12879
13720
|
}), []);
|
|
12880
13721
|
// Toggle dropdown
|
|
12881
|
-
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 => {
|
|
12882
13726
|
if (setSelectedLabel(option.label), setIsOpen(!1), bodyRef.current && (bodyRef.current.style.height = "0px"),
|
|
12883
13727
|
nativeSelectRef.current && (nativeSelectRef.current.value = option.value), onChange) {
|
|
12884
13728
|
// Create a synthetic event
|
|
@@ -12922,7 +13766,15 @@ const Select = React.memo((({options: options, value: value, onChange: onChange
|
|
|
12922
13766
|
"aria-describedby": ariaDescribedBy,
|
|
12923
13767
|
"aria-invalid": invalid,
|
|
12924
13768
|
style: {
|
|
12925
|
-
|
|
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"
|
|
12926
13778
|
},
|
|
12927
13779
|
children: [ placeholder && jsxRuntime.jsx("option", {
|
|
12928
13780
|
value: "",
|
|
@@ -12935,11 +13787,29 @@ const Select = React.memo((({options: options, value: value, onChange: onChange
|
|
|
12935
13787
|
}, option.value))) ]
|
|
12936
13788
|
}), jsxRuntime.jsx("div", {
|
|
12937
13789
|
className: SELECT.CLASSES.SELECTED,
|
|
12938
|
-
onClick:
|
|
12939
|
-
|
|
12940
|
-
|
|
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
|
+
}
|
|
12941
13806
|
},
|
|
12942
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,
|
|
12943
13813
|
children: selectedLabel
|
|
12944
13814
|
}), jsxRuntime.jsx("i", {
|
|
12945
13815
|
className: `${SELECT.CLASSES.ICON_CARET} ${SELECT.CLASSES.TOGGLE_ICON}`
|
|
@@ -12954,10 +13824,16 @@ const Select = React.memo((({options: options, value: value, onChange: onChange
|
|
|
12954
13824
|
ref: panelRef,
|
|
12955
13825
|
children: jsxRuntime.jsx("ul", {
|
|
12956
13826
|
className: SELECT.CLASSES.SELECT_ITEMS,
|
|
13827
|
+
role: "listbox",
|
|
13828
|
+
id: id ? `${id}-listbox` : void 0,
|
|
13829
|
+
"aria-labelledby": id,
|
|
12957
13830
|
children: hasOptionsProp ? options.map(((option, index) => jsxRuntime.jsx("li", {
|
|
12958
13831
|
className: SELECT.CLASSES.SELECT_ITEM,
|
|
12959
13832
|
"data-value": option.value,
|
|
12960
13833
|
onClick: () => !option.disabled && handleItemClick(option),
|
|
13834
|
+
role: "option",
|
|
13835
|
+
"aria-selected": value === option.value,
|
|
13836
|
+
"aria-disabled": option.disabled,
|
|
12961
13837
|
children: jsxRuntime.jsxs("label", {
|
|
12962
13838
|
htmlFor: `SelectItem${index}`,
|
|
12963
13839
|
className: "c-checkbox",
|
|
@@ -14500,7 +15376,45 @@ const ModalImpl = React.memo((({children: children, isOpen: isOpen = !1, onOpen
|
|
|
14500
15376
|
onOpenChange: onOpenChange,
|
|
14501
15377
|
onClose: onClose,
|
|
14502
15378
|
onOpen: onOpen
|
|
14503
|
-
})
|
|
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}`;
|
|
14504
15418
|
// Handle keyboard events for Escape key
|
|
14505
15419
|
React.useEffect((() => {
|
|
14506
15420
|
if (!keyboard) return;
|
|
@@ -14518,15 +15432,19 @@ const ModalImpl = React.memo((({children: children, isOpen: isOpen = !1, onOpen
|
|
|
14518
15432
|
return React__default.default.isValidElement(child) && _includesInstanceProperty(_context = [ "ModalHeader", "ModalBody", "ModalFooter" ]).call(_context, child.type.displayName);
|
|
14519
15433
|
})), modalContent = jsxRuntime.jsx("div", {
|
|
14520
15434
|
className: "c-modal__content",
|
|
15435
|
+
ref: contentRef,
|
|
14521
15436
|
children: hasCompoundComponents ? React__default.default.Children.map(children, (child => React__default.default.isValidElement(child) && "ModalHeader" === child.type.displayName ? React__default.default.cloneElement(child, {
|
|
14522
|
-
onClose: child.props.onClose || close
|
|
15437
|
+
onClose: child.props.onClose || close,
|
|
15438
|
+
id: titleId
|
|
14523
15439
|
}) : child)) : jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
14524
15440
|
children: [ (title || closeButton) && jsxRuntime.jsx(ModalHeader, {
|
|
15441
|
+
id: titleId,
|
|
14525
15442
|
title: title,
|
|
14526
15443
|
subtitle: subtitle,
|
|
14527
15444
|
closeButton: closeButton,
|
|
14528
15445
|
onClose: close
|
|
14529
15446
|
}), jsxRuntime.jsx(ModalBody, {
|
|
15447
|
+
id: descId,
|
|
14530
15448
|
children: children
|
|
14531
15449
|
}), footer && jsxRuntime.jsx(ModalFooter, {
|
|
14532
15450
|
children: footer
|
|
@@ -14544,6 +15462,8 @@ const ModalImpl = React.memo((({children: children, isOpen: isOpen = !1, onOpen
|
|
|
14544
15462
|
role: "dialog",
|
|
14545
15463
|
"aria-modal": "true",
|
|
14546
15464
|
"aria-hidden": !isOpenState,
|
|
15465
|
+
"aria-labelledby": titleId,
|
|
15466
|
+
"aria-describedby": descId,
|
|
14547
15467
|
...props,
|
|
14548
15468
|
children: [ jsxRuntime.jsx("div", {
|
|
14549
15469
|
ref: backdropRef,
|
|
@@ -14796,7 +15716,27 @@ const Navbar = React.forwardRef((({brand: brand, children: children, variant: v
|
|
|
14796
15716
|
return window.addEventListener("resize", handleResize), () => {
|
|
14797
15717
|
window.removeEventListener("resize", handleResize);
|
|
14798
15718
|
};
|
|
14799
|
-
}), [ 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 ]);
|
|
14800
15740
|
// Generate the navbar class
|
|
14801
15741
|
const navbarClass = generateNavbarClass({
|
|
14802
15742
|
position: position,
|
|
@@ -17404,7 +18344,235 @@ const SectionIntro = ({title: title, label: label, text: text, actions: actions,
|
|
|
17404
18344
|
SectionIntro.displayName = "SectionIntro";
|
|
17405
18345
|
|
|
17406
18346
|
const Slider = React.forwardRef(((props, ref) => {
|
|
17407
|
-
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
|
+
}({
|
|
17408
18576
|
slides: validSlides,
|
|
17409
18577
|
slidesToShow: slidesToShow,
|
|
17410
18578
|
spaceBetween: spaceBetween,
|
|
@@ -17431,7 +18599,8 @@ const Slider = React.forwardRef(((props, ref) => {
|
|
|
17431
18599
|
})
|
|
17432
18600
|
});
|
|
17433
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(" ");
|
|
17434
|
-
|
|
18602
|
+
// Keyboard navigation
|
|
18603
|
+
return jsxRuntime.jsxs("div", {
|
|
17435
18604
|
ref: ref || containerRef,
|
|
17436
18605
|
className: containerClasses,
|
|
17437
18606
|
style: {
|
|
@@ -17449,9 +18618,32 @@ const Slider = React.forwardRef(((props, ref) => {
|
|
|
17449
18618
|
onMouseMove: handleTouchMove,
|
|
17450
18619
|
onMouseUp: handleTouchEnd,
|
|
17451
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,
|
|
17452
18643
|
children: [ jsxRuntime.jsx("div", {
|
|
17453
18644
|
ref: wrapperRef,
|
|
17454
18645
|
className: "c-slider__wrapper",
|
|
18646
|
+
"aria-live": autoplay ? "off" : "polite",
|
|
17455
18647
|
style: {
|
|
17456
18648
|
display: "flex",
|
|
17457
18649
|
flexDirection: "vertical" === direction ? "column" : "row",
|
|
@@ -17629,15 +18821,24 @@ Steps.displayName = "Steps", Steps.Item = StepsItem, Steps.Step = StepsItem;
|
|
|
17629
18821
|
// Context for compound usage
|
|
17630
18822
|
const TabsContext = React.createContext({
|
|
17631
18823
|
currentTab: 0,
|
|
17632
|
-
handleTabClick: () => {}
|
|
17633
|
-
|
|
17634
|
-
|
|
17635
|
-
|
|
17636
|
-
|
|
17637
|
-
|
|
17638
|
-
|
|
17639
|
-
|
|
17640
|
-
|
|
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
|
+
}));
|
|
17641
18842
|
|
|
17642
18843
|
// Compound components
|
|
17643
18844
|
TabsList.displayName = "TabsList";
|
|
@@ -17649,8 +18850,10 @@ const TabsTrigger = React.forwardRef((({children: children, className: classNam
|
|
|
17649
18850
|
const isActive = void 0 !== index && currentTab === index;
|
|
17650
18851
|
return jsxRuntime.jsx("li", {
|
|
17651
18852
|
className: "c-tabs__nav-item",
|
|
18853
|
+
role: "presentation",
|
|
17652
18854
|
children: jsxRuntime.jsx("button", {
|
|
17653
18855
|
ref: ref,
|
|
18856
|
+
id: `tab-nav-${index}`,
|
|
17654
18857
|
className: `c-tabs__nav-btn ${isActive ? TAB.CLASSES.ACTIVE : ""} ${className}`.trim(),
|
|
17655
18858
|
onClick: e => {
|
|
17656
18859
|
void 0 !== index && handleTabClick(index), onClick?.(e);
|
|
@@ -17659,6 +18862,7 @@ const TabsTrigger = React.forwardRef((({children: children, className: classNam
|
|
|
17659
18862
|
role: "tab",
|
|
17660
18863
|
"aria-selected": isActive,
|
|
17661
18864
|
"aria-controls": `tab-panel-${index}`,
|
|
18865
|
+
tabIndex: isActive ? 0 : -1,
|
|
17662
18866
|
type: "button",
|
|
17663
18867
|
...props,
|
|
17664
18868
|
children: children
|
|
@@ -17708,24 +18912,59 @@ TabsPanel.displayName = "TabsPanel";
|
|
|
17708
18912
|
const Tabs = React.memo((({items: items, activeIndex: activeIndex = TAB.DEFAULTS.ACTIVE_INDEX, onTabChange: onTabChange, className: className = "", style: style, glass: glass, children: children}) => {
|
|
17709
18913
|
const [currentTab, setCurrentTab] = React.useState(activeIndex), handleTabClick = index => {
|
|
17710
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);
|
|
17711
18943
|
};
|
|
17712
18944
|
// Handle tab change
|
|
17713
18945
|
// Determine content based on mode (legacy items vs compound children)
|
|
17714
18946
|
let content;
|
|
17715
18947
|
// Use items prop if provided
|
|
17716
|
-
|
|
17717
|
-
|
|
18948
|
+
if (items && items.length > 0)
|
|
18949
|
+
// Legacy mode
|
|
18950
|
+
content = jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
17718
18951
|
children: [ jsxRuntime.jsx("ul", {
|
|
17719
18952
|
className: "c-tabs__nav",
|
|
18953
|
+
role: "tablist",
|
|
18954
|
+
onKeyDown: e => handleKeyDown(e, items.length),
|
|
17720
18955
|
children: items.map(((item, index) => jsxRuntime.jsx("li", {
|
|
17721
18956
|
className: "c-tabs__nav-item",
|
|
18957
|
+
role: "presentation",
|
|
17722
18958
|
children: jsxRuntime.jsx("button", {
|
|
18959
|
+
id: `tab-nav-${index}`,
|
|
17723
18960
|
className: `c-tabs__nav-btn ${index === currentTab ? TAB.CLASSES.ACTIVE : ""}`,
|
|
17724
18961
|
onClick: () => handleTabClick(index),
|
|
17725
18962
|
"data-tabindex": index,
|
|
17726
18963
|
role: "tab",
|
|
17727
18964
|
"aria-selected": index === currentTab,
|
|
17728
18965
|
"aria-controls": `tab-panel-${index}`,
|
|
18966
|
+
tabIndex: index === currentTab ? 0 : -1,
|
|
18967
|
+
type: "button",
|
|
17729
18968
|
children: item.label
|
|
17730
18969
|
})
|
|
17731
18970
|
}, `tab-nav-${index}`)))
|
|
@@ -17749,13 +18988,19 @@ const Tabs = React.memo((({items: items, activeIndex: activeIndex = TAB.DEFAULT
|
|
|
17749
18988
|
})
|
|
17750
18989
|
}, `tab-panel-${index}`)))
|
|
17751
18990
|
}) ]
|
|
17752
|
-
})
|
|
17753
|
-
|
|
17754
|
-
|
|
17755
|
-
|
|
17756
|
-
|
|
17757
|
-
|
|
17758
|
-
|
|
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
|
+
}
|
|
17759
19004
|
const wrapper = jsxRuntime.jsx("div", {
|
|
17760
19005
|
className: `c-tabs js-atomix-tab ${className}`,
|
|
17761
19006
|
style: style,
|
|
@@ -17846,7 +19091,7 @@ const Testimonial = ({quote: quote, author: author, size: size = "", skeleton: s
|
|
|
17846
19091
|
className: "c-testimonial__author",
|
|
17847
19092
|
children: [ author.avatarSrc && jsxRuntime.jsx("img", {
|
|
17848
19093
|
src: author.avatarSrc,
|
|
17849
|
-
alt: author.avatarAlt ||
|
|
19094
|
+
alt: author.avatarAlt || `${author.name}'s avatar`,
|
|
17850
19095
|
className: "c-testimonial__author-avatar c-avatar c-avatar--xxl c-avatar--circle"
|
|
17851
19096
|
}), jsxRuntime.jsxs("div", {
|
|
17852
19097
|
className: "c-testimonial__info",
|
|
@@ -18122,7 +19367,17 @@ const Tooltip = React.memo((({content: content, children: children, position: p
|
|
|
18122
19367
|
cancelAnimationFrame(rafId), window.removeEventListener("resize", handleUpdate),
|
|
18123
19368
|
window.removeEventListener("scroll", handleUpdate, !0);
|
|
18124
19369
|
};
|
|
18125
|
-
}), [ 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 ]);
|
|
18126
19381
|
// Setup trigger props
|
|
18127
19382
|
const triggerProps = {
|
|
18128
19383
|
"aria-describedby": isVisible ? tooltipId : void 0
|
|
@@ -18811,9 +20066,15 @@ const VideoPlayer = React.forwardRef((({src: src, type: type = "video", youtube
|
|
|
18811
20066
|
const rect = e.currentTarget.getBoundingClientRect(), percent = (e.clientX - rect.left) / rect.width;
|
|
18812
20067
|
setVolume(percent);
|
|
18813
20068
|
}), [ setVolume ]), handleDownload = React.useCallback((() => {
|
|
18814
|
-
if (src) {
|
|
18815
|
-
|
|
18816
|
-
|
|
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
|
|
18817
20078
|
}
|
|
18818
20079
|
}), [ src ]), handleShare = React.useCallback((async () => {
|
|
18819
20080
|
if (navigator.share) try {
|
|
@@ -19392,6 +20653,7 @@ var components = Object.freeze({
|
|
|
19392
20653
|
TODO: TODO,
|
|
19393
20654
|
TOGGLE: TOGGLE,
|
|
19394
20655
|
TOOLTIP: TOOLTIP,
|
|
20656
|
+
TYPEDBUTTON: TYPEDBUTTON,
|
|
19395
20657
|
UPLOAD: UPLOAD,
|
|
19396
20658
|
VIDEO_PLAYER: VIDEO_PLAYER,
|
|
19397
20659
|
sliderConstants: sliderConstants
|
|
@@ -25038,8 +26300,8 @@ exports.ACCORDION = ACCORDION, exports.ATOMIX_GLASS = ATOMIX_GLASS, exports.AVAT
|
|
|
25038
26300
|
exports.AVATAR_GROUP = AVATAR_GROUP, exports.Accordion = Accordion, exports.AreaChart = AreaChart,
|
|
25039
26301
|
exports.AtomixGlass = AtomixGlass, exports.AtomixLogo = AtomixLogo, exports.Avatar = Avatar,
|
|
25040
26302
|
exports.AvatarGroup = AvatarGroup, exports.BADGE = BADGE, exports.BADGE_CSS_VARS = BADGE_CSS_VARS,
|
|
25041
|
-
exports.
|
|
25042
|
-
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,
|
|
25043
26305
|
exports.Badge = Badge, exports.BarChart = BarChart, exports.Block = Block, exports.Breadcrumb = Breadcrumb,
|
|
25044
26306
|
exports.BubbleChart = BubbleChart, exports.Button = Button, exports.ButtonGroup = ButtonGroup,
|
|
25045
26307
|
exports.CALLOUT = CALLOUT, exports.CARD = CARD, exports.CARD_CSS_VARS = CARD_CSS_VARS,
|
|
@@ -25050,29 +26312,31 @@ exports.Card = Card, exports.Chart = Chart, exports.ChartRenderer = ChartRendere
|
|
|
25050
26312
|
exports.Checkbox = Checkbox, exports.ColorModeToggle = ColorModeToggle, exports.Container = Container,
|
|
25051
26313
|
exports.Countdown = Countdown, exports.DATA_TABLE_CLASSES = DATA_TABLE_CLASSES,
|
|
25052
26314
|
exports.DATA_TABLE_SELECTORS = DATA_TABLE_SELECTORS, exports.DATEPICKER = DATEPICKER,
|
|
25053
|
-
exports.DEFAULT_ATOMIX_FONTS = DEFAULT_ATOMIX_FONTS, exports.
|
|
25054
|
-
exports.
|
|
25055
|
-
exports.
|
|
25056
|
-
exports.
|
|
25057
|
-
exports.
|
|
25058
|
-
exports.
|
|
25059
|
-
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,
|
|
25060
26322
|
exports.Form = Form, exports.FormGroup = FormGroup, exports.FunnelChart = FunnelChart,
|
|
25061
26323
|
exports.GaugeChart = GaugeChart, exports.Grid = Grid, exports.GridCol = GridCol,
|
|
25062
26324
|
exports.HERO = HERO, exports.HeatmapChart = HeatmapChart, exports.Hero = Hero, exports.INPUT = INPUT,
|
|
25063
26325
|
exports.INPUT_CSS_VARS = INPUT_CSS_VARS, exports.Icon = Icon, exports.Input = Input,
|
|
25064
26326
|
exports.LIST = LIST, exports.LIST_GROUP = LIST_GROUP, exports.LineChart = LineChart,
|
|
25065
26327
|
exports.List = List, exports.ListGroup = ListGroup, exports.MESSAGES = MESSAGES,
|
|
25066
|
-
exports.
|
|
25067
|
-
exports.
|
|
25068
|
-
exports.
|
|
25069
|
-
exports.
|
|
25070
|
-
exports.
|
|
25071
|
-
exports.
|
|
25072
|
-
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,
|
|
25073
26336
|
exports.POPOVER = POPOVER, exports.PROGRESS = PROGRESS, exports.PROGRESS_CSS_VARS = PROGRESS_CSS_VARS,
|
|
25074
|
-
exports.Pagination = Pagination, exports.
|
|
25075
|
-
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,
|
|
25076
26340
|
exports.RADIO = RADIO, exports.RADIO_CSS_VARS = RADIO_CSS_VARS, exports.RATING = RATING,
|
|
25077
26341
|
exports.RIVER = RIVER, exports.RTLManager = RTLManager, exports.RadarChart = RadarChart,
|
|
25078
26342
|
exports.Radio = Radio, exports.Rating = Rating, exports.River = River, exports.Row = Row,
|
|
@@ -25084,8 +26348,8 @@ exports.Slider = Slider, exports.Spinner = Spinner, exports.Steps = Steps, expor
|
|
|
25084
26348
|
exports.TABS_CSS_VARS = TABS_CSS_VARS, exports.TESTIMONIAL = TESTIMONIAL, exports.TEXTAREA = TEXTAREA,
|
|
25085
26349
|
exports.THEME_COLORS = THEME_COLORS, exports.THEME_NAMING = THEME_NAMING, exports.TODO = TODO,
|
|
25086
26350
|
exports.TOGGLE = TOGGLE, exports.TOOLTIP = TOOLTIP, exports.TOOLTIP_CSS_VARS = TOOLTIP_CSS_VARS,
|
|
25087
|
-
exports.
|
|
25088
|
-
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,
|
|
25089
26353
|
exports.ThemeContext = ThemeContext, exports.ThemeErrorBoundary = ThemeErrorBoundary,
|
|
25090
26354
|
exports.ThemeInspector = ThemeInspector, exports.ThemeLiveEditor = ThemeLiveEditor,
|
|
25091
26355
|
exports.ThemePreview = ThemePreview, exports.ThemeProvider = ThemeProvider, exports.ThemeValidator = ThemeValidator,
|
|
@@ -25158,8 +26422,8 @@ function(cssVars, baseStyle) {
|
|
|
25158
26422
|
* ```
|
|
25159
26423
|
*/ , exports.applyComponentTheme = applyComponentTheme, exports.applyPartStyles = applyPartStyles,
|
|
25160
26424
|
exports.applyTheme = applyTheme, exports.camelToKebab = camelToKebab, exports.clearThemes = clearThemes,
|
|
25161
|
-
exports.composables = composables, exports.constants = constants, exports.
|
|
25162
|
-
exports.createDarkVariant =
|
|
26425
|
+
exports.composables = composables, exports.constants = constants, exports.createBreakpoints = createBreakpoints$1,
|
|
26426
|
+
exports.createCSSVarStyle = createCSSVarStyle, exports.createDarkVariant =
|
|
25163
26427
|
/**
|
|
25164
26428
|
* Create a dark theme variant from a light theme
|
|
25165
26429
|
*/
|
|
@@ -25277,7 +26541,9 @@ exports.getAllThemes = getAllThemes, exports.getCSSVariable = getCSSVariable, ex
|
|
|
25277
26541
|
*/
|
|
25278
26542
|
function(component) {
|
|
25279
26543
|
return COMPONENT_CSS_VARS[component];
|
|
25280
|
-
}, 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,
|
|
25281
26547
|
exports.getTheme = getTheme, exports.getThemeApplicator = getThemeApplicator, exports.getThemeCount = getThemeCount,
|
|
25282
26548
|
exports.getThemeIds = getThemeIds, exports.getThemeMetadata =
|
|
25283
26549
|
/**
|
|
@@ -25359,8 +26625,7 @@ function(theme, selector = ":root") {
|
|
|
25359
26625
|
});
|
|
25360
26626
|
}, exports.types = types, exports.unregisterTheme = unregisterTheme, exports.useAccordion = useAccordion,
|
|
25361
26627
|
exports.useAtomixGlass = useAtomixGlass, exports.useBadge = useBadge, exports.useBarChart = useBarChart,
|
|
25362
|
-
exports.useBlock = useBlock, exports.
|
|
25363
|
-
exports.useChartData = useChartData, exports.useChartInteraction = useChartInteraction,
|
|
26628
|
+
exports.useBlock = useBlock, exports.useChartData = useChartData, exports.useChartInteraction = useChartInteraction,
|
|
25364
26629
|
exports.useChartScale = useChartScale, exports.useComponentCustomization =
|
|
25365
26630
|
/**
|
|
25366
26631
|
* Hook to merge theme overrides with component props
|
|
@@ -25409,19 +26674,19 @@ function(component, props) {
|
|
|
25409
26674
|
}
|
|
25410
26675
|
/**
|
|
25411
26676
|
* Hook to merge default props with provided props
|
|
25412
|
-
*/ , exports.useComponentTheme = useComponentTheme, exports.
|
|
25413
|
-
exports.
|
|
25414
|
-
exports.
|
|
25415
|
-
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) {
|
|
25416
26681
|
return React.useMemo((() => ({
|
|
25417
26682
|
...defaultProps,
|
|
25418
26683
|
...props
|
|
25419
26684
|
})), [ defaultProps, props ]);
|
|
25420
|
-
}, exports.
|
|
25421
|
-
exports.
|
|
25422
|
-
exports.usePieChart = usePieChart, exports.useRadio = useRadio, exports.
|
|
25423
|
-
exports.
|
|
25424
|
-
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) {
|
|
25425
26690
|
return React__default.default.useMemo((() => renderSlot(slot, props, fallback)), [ slot, props, fallback ]);
|
|
25426
26691
|
}, exports.useSpinner = useSpinner, exports.useTextarea = useTextarea, exports.useTheme = useTheme,
|
|
25427
26692
|
exports.useThemeTokens = useThemeTokens, exports.useTodo = useTodo, exports.utils = utils,
|