@shohojdhara/atomix 0.4.7 → 0.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/atomix.config.ts +58 -1
- package/dist/atomix.css +172 -157
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +4 -4
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.d.ts +33 -0
- package/dist/charts.js +1274 -164
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +33 -10
- package/dist/core.js +1099 -83
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +33 -0
- package/dist/forms.js +2106 -1050
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +42 -1
- package/dist/heavy.js +1663 -638
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +442 -270
- package/dist/index.esm.js +1947 -680
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1982 -712
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +6 -3
- package/scripts/atomix-cli.js +136 -1827
- package/scripts/cli/__tests__/basic.test.js +3 -2
- package/scripts/cli/__tests__/clean.test.js +278 -0
- package/scripts/cli/__tests__/component-validator.test.js +433 -0
- package/scripts/cli/__tests__/generator.test.js +613 -0
- package/scripts/cli/__tests__/glass-motion.test.js +256 -0
- package/scripts/cli/__tests__/integration.test.js +719 -108
- package/scripts/cli/__tests__/migrate.test.js +74 -0
- package/scripts/cli/__tests__/security.test.js +206 -0
- package/scripts/cli/__tests__/test-setup.js +3 -1
- package/scripts/cli/__tests__/theme-bridge.test.js +507 -0
- package/scripts/cli/__tests__/token-provider.test.js +361 -0
- package/scripts/cli/__tests__/utils.test.js +5 -5
- package/scripts/cli/commands/benchmark.js +105 -0
- package/scripts/cli/commands/build-theme.js +115 -0
- package/scripts/cli/commands/clean.js +109 -0
- package/scripts/cli/commands/doctor.js +88 -0
- package/scripts/cli/commands/generate.js +218 -0
- package/scripts/cli/commands/init.js +73 -0
- package/scripts/cli/commands/migrate.js +106 -0
- package/scripts/cli/commands/sync-tokens.js +206 -0
- package/scripts/cli/commands/theme-bridge.js +248 -0
- package/scripts/cli/commands/tokens.js +157 -0
- package/scripts/cli/commands/validate.js +194 -0
- package/scripts/cli/internal/ai-engine.js +156 -0
- package/scripts/cli/internal/compiler.js +114 -0
- package/scripts/cli/internal/component-validator.js +443 -0
- package/scripts/cli/internal/config-loader.js +162 -0
- package/scripts/cli/internal/filesystem.js +158 -0
- package/scripts/cli/internal/generator.js +430 -0
- package/scripts/cli/internal/glass-generator.js +398 -0
- package/scripts/cli/internal/hook-generator.js +369 -0
- package/scripts/cli/internal/hooks.js +61 -0
- package/scripts/cli/internal/itcss-generator.js +565 -0
- package/scripts/cli/internal/motion-generator.js +679 -0
- package/scripts/cli/internal/template-engine.js +301 -0
- package/scripts/cli/internal/theme-bridge.js +664 -0
- package/scripts/cli/internal/tokens/engine.js +122 -0
- package/scripts/cli/internal/tokens/provider.js +34 -0
- package/scripts/cli/internal/tokens/providers/figma.js +50 -0
- package/scripts/cli/internal/tokens/providers/style-dictionary.js +48 -0
- package/scripts/cli/internal/tokens/providers/w3c.js +48 -0
- package/scripts/cli/internal/tokens/token-provider.js +443 -0
- package/scripts/cli/internal/tokens/token-validator.js +513 -0
- package/scripts/cli/internal/validator.js +276 -0
- package/scripts/cli/internal/wizard.js +115 -0
- package/scripts/cli/mappings.js +23 -0
- package/scripts/cli/migration-tools.js +164 -94
- package/scripts/cli/plugins/style-dictionary.js +46 -0
- package/scripts/cli/templates/README.md +525 -95
- package/scripts/cli/templates/common-templates.js +40 -14
- package/scripts/cli/templates/components/react-component.ts +282 -0
- package/scripts/cli/templates/config/project-config.ts +112 -0
- package/scripts/cli/templates/hooks/use-component.ts +477 -0
- package/scripts/cli/templates/index.js +19 -4
- package/scripts/cli/templates/index.ts +171 -0
- package/scripts/cli/templates/next-templates.js +72 -0
- package/scripts/cli/templates/react-templates.js +70 -126
- package/scripts/cli/templates/scss-templates.js +35 -35
- package/scripts/cli/templates/stories/storybook-story.ts +241 -0
- package/scripts/cli/templates/styles/scss-component.ts +255 -0
- package/scripts/cli/templates/tests/vitest-test.ts +229 -0
- package/scripts/cli/templates/token-templates.js +337 -1
- package/scripts/cli/templates/tokens/token-generators.ts +1088 -0
- package/scripts/cli/templates/types/component-types.ts +145 -0
- package/scripts/cli/templates/utils/testing-utils.ts +144 -0
- package/scripts/cli/templates/vanilla-templates.js +39 -0
- package/scripts/cli/token-manager.js +8 -2
- package/scripts/cli/utils/cache-manager.js +240 -0
- package/scripts/cli/utils/detector.js +46 -0
- package/scripts/cli/utils/diagnostics.js +289 -0
- package/scripts/cli/utils/error.js +89 -0
- package/scripts/cli/utils/helpers.js +67 -0
- package/scripts/cli/utils/logger.js +75 -0
- package/scripts/cli/utils/security.js +302 -0
- package/scripts/cli/utils/telemetry.js +115 -0
- package/scripts/cli/utils/validation.js +37 -0
- package/scripts/cli/utils.js +28 -341
- package/src/components/Accordion/Accordion.stories.tsx +0 -18
- package/src/components/Accordion/Accordion.test.tsx +0 -17
- package/src/components/Accordion/Accordion.tsx +0 -4
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +37 -3
- package/src/components/AtomixGlass/AtomixGlass.tsx +143 -31
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +129 -31
- package/src/components/AtomixGlass/PerformanceDashboard.tsx +219 -0
- package/src/components/AtomixGlass/README.md +25 -10
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +216 -0
- package/src/components/AtomixGlass/animation-system.ts +578 -0
- package/src/components/AtomixGlass/shader-utils.ts +4 -1
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +157 -6
- package/src/components/AtomixGlass/stories/Phase1-Animation.stories.tsx +653 -0
- package/src/components/AtomixGlass/stories/Phase1-Test.stories.tsx +95 -0
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +51 -51
- package/src/components/AtomixGlass/stories/shared-components.tsx +6 -0
- package/src/components/Avatar/Avatar.tsx +1 -1
- package/src/components/Button/Button.stories.disabled-link.tsx +10 -0
- package/src/components/Button/Button.stories.tsx +10 -0
- package/src/components/Button/Button.test.tsx +16 -11
- package/src/components/Button/Button.tsx +4 -4
- package/src/components/Card/Card.tsx +1 -1
- package/src/components/Dropdown/Dropdown.tsx +12 -12
- package/src/components/Form/Select.tsx +62 -3
- package/src/components/Modal/Modal.tsx +14 -3
- package/src/components/Navigation/Navbar/Navbar.tsx +44 -0
- package/src/components/Slider/Slider.stories.tsx +3 -3
- package/src/components/Slider/Slider.tsx +38 -0
- package/src/components/Steps/Steps.tsx +3 -3
- package/src/components/Tabs/Tabs.tsx +77 -8
- package/src/components/Testimonial/Testimonial.tsx +1 -1
- package/src/components/TypedButton/TypedButton.stories.tsx +59 -0
- package/src/components/TypedButton/TypedButton.tsx +39 -0
- package/src/components/TypedButton/index.ts +2 -0
- package/src/components/VideoPlayer/VideoPlayer.tsx +11 -4
- package/src/lib/composables/index.ts +4 -7
- package/src/lib/composables/types.ts +45 -0
- package/src/lib/composables/useAccordion.ts +0 -7
- package/src/lib/composables/useAtomixGlass.ts +148 -6
- package/src/lib/composables/useAtomixGlassStyles.ts +9 -7
- package/src/lib/composables/useChartExport.ts +3 -13
- package/src/lib/composables/useDropdown.ts +66 -0
- package/src/lib/composables/useFocusTrap.ts +80 -0
- package/src/lib/composables/usePerformanceMonitor.ts +448 -0
- package/src/lib/composables/useResponsiveGlass.presets.ts +192 -0
- package/src/lib/composables/useResponsiveGlass.ts +441 -0
- package/src/lib/composables/useTooltip.ts +16 -0
- package/src/lib/composables/useTypedButton.ts +66 -0
- package/src/lib/config/index.ts +62 -5
- package/src/lib/constants/components.ts +62 -7
- package/src/lib/theme/devtools/__tests__/useHistory.test.tsx +150 -0
- package/src/lib/theme/tokens/centralized-tokens.ts +120 -0
- package/src/lib/theme/utils/__tests__/domUtils.test.ts +101 -0
- package/src/lib/types/components.ts +37 -11
- package/src/lib/types/glass.ts +35 -0
- package/src/lib/types/index.ts +1 -0
- package/src/lib/utils/displacement-generator.ts +1 -1
- package/src/styles/01-settings/_settings.testtypecheck.scss +53 -0
- package/src/styles/01-settings/_settings.typedbutton.scss +53 -0
- package/src/styles/06-components/_components.atomix-glass.scss +17 -21
- package/src/styles/06-components/_components.edge-panel.scss +1 -5
- package/src/styles/06-components/_components.modal.scss +1 -4
- package/src/styles/06-components/_components.navbar.scss +1 -1
- package/src/styles/06-components/_components.testbutton.scss +212 -0
- package/src/styles/06-components/_components.testtypecheck.scss +212 -0
- package/src/styles/06-components/_components.tooltip.scss +9 -5
- package/src/styles/06-components/_components.typedbutton.scss +212 -0
- package/src/styles/99-utilities/_index.scss +1 -0
- package/src/styles/99-utilities/_utilities.text.scss +1 -1
- package/src/styles/99-utilities/_utilities.touch-target.scss +36 -0
- package/scripts/cli/component-generator.js +0 -564
- package/scripts/cli/interactive-init.js +0 -357
- package/src/styles/06-components/old.chart.styles.scss +0 -2788
package/dist/index.esm.js
CHANGED
|
@@ -390,6 +390,14 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
390
390
|
ICON_ELEMENT: "icon",
|
|
391
391
|
LABEL_ELEMENT: "label",
|
|
392
392
|
SPINNER_ELEMENT: "spinner"
|
|
393
|
+
}, TYPEDBUTTON = {
|
|
394
|
+
BASE_CLASS: "c-typedbutton",
|
|
395
|
+
VARIANT_PREFIX: "c-typedbutton--",
|
|
396
|
+
CLASSES: {
|
|
397
|
+
BASE: "c-typedbutton",
|
|
398
|
+
DISABLED: "c-typedbutton--disabled",
|
|
399
|
+
GLASS: "c-typedbutton--glass"
|
|
400
|
+
}
|
|
393
401
|
}, BUTTON = {
|
|
394
402
|
BASE_CLASS: "c-btn",
|
|
395
403
|
ICON_CLASS: "c-btn__icon",
|
|
@@ -1717,20 +1725,29 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1717
1725
|
SHADER: "c-atomix-glass--shader"
|
|
1718
1726
|
},
|
|
1719
1727
|
DEFAULTS: {
|
|
1720
|
-
DISPLACEMENT_SCALE:
|
|
1721
|
-
BLUR_AMOUNT:
|
|
1728
|
+
DISPLACEMENT_SCALE: 70,
|
|
1729
|
+
BLUR_AMOUNT: 0,
|
|
1722
1730
|
SATURATION: 140,
|
|
1723
|
-
ABERRATION_INTENSITY: 2
|
|
1724
|
-
ELASTICITY: .
|
|
1725
|
-
CORNER_RADIUS:
|
|
1731
|
+
ABERRATION_INTENSITY: 2,
|
|
1732
|
+
ELASTICITY: .15,
|
|
1733
|
+
CORNER_RADIUS: 20,
|
|
1726
1734
|
// Default border-radius matching design system
|
|
1727
|
-
PADDING: "0
|
|
1735
|
+
PADDING: "0",
|
|
1728
1736
|
MODE: "standard",
|
|
1729
1737
|
OVER_LIGHT: !1,
|
|
1730
|
-
ENABLE_OVER_LIGHT_LAYERS: !0
|
|
1738
|
+
ENABLE_OVER_LIGHT_LAYERS: !0,
|
|
1739
|
+
// Phase 1: Time-Based Animation System defaults
|
|
1740
|
+
WITH_TIME_ANIMATION: !0,
|
|
1741
|
+
ANIMATION_SPEED: 1,
|
|
1742
|
+
// Phase 1: Multi-Layer Distortion System defaults
|
|
1743
|
+
WITH_MULTI_LAYER_DISTORTION: !1,
|
|
1744
|
+
DISTORTION_OCTAVES: 5,
|
|
1745
|
+
DISTORTION_LACUNARITY: 2,
|
|
1746
|
+
DISTORTION_GAIN: .5,
|
|
1747
|
+
DISTORTION_QUALITY: "high"
|
|
1731
1748
|
},
|
|
1732
1749
|
CONSTANTS: {
|
|
1733
|
-
ACTIVATION_ZONE:
|
|
1750
|
+
ACTIVATION_ZONE: 200,
|
|
1734
1751
|
LERP_FACTOR: .08,
|
|
1735
1752
|
SMOOTHSTEP_POWER: 2.5,
|
|
1736
1753
|
MIN_BLUR: .1,
|
|
@@ -1890,6 +1907,44 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1890
1907
|
// Saturation constants
|
|
1891
1908
|
SATURATION: {
|
|
1892
1909
|
HIGH_CONTRAST: 200
|
|
1910
|
+
},
|
|
1911
|
+
// Phase 1: Animation System Constants
|
|
1912
|
+
ANIMATION: {
|
|
1913
|
+
// Breathing effect timing (in milliseconds)
|
|
1914
|
+
BREATHING_CYCLE: 2e3,
|
|
1915
|
+
// 2-second breathing cycle
|
|
1916
|
+
// Flow animation speed
|
|
1917
|
+
FLOW_SPEED_X: .1,
|
|
1918
|
+
// Horizontal flow speed
|
|
1919
|
+
FLOW_SPEED_Y: .15,
|
|
1920
|
+
// Vertical flow speed
|
|
1921
|
+
// Wave propagation
|
|
1922
|
+
WAVE_SPEED: .05,
|
|
1923
|
+
// Radial wave speed
|
|
1924
|
+
WAVE_AMPLITUDE: .02
|
|
1925
|
+
},
|
|
1926
|
+
// Phase 1: Multi-Layer Distortion Quality Presets
|
|
1927
|
+
DISTORTION_QUALITY_PRESETS: {
|
|
1928
|
+
low: {
|
|
1929
|
+
octaves: 2,
|
|
1930
|
+
lacunarity: 2,
|
|
1931
|
+
gain: .5
|
|
1932
|
+
},
|
|
1933
|
+
medium: {
|
|
1934
|
+
octaves: 4,
|
|
1935
|
+
lacunarity: 2,
|
|
1936
|
+
gain: .5
|
|
1937
|
+
},
|
|
1938
|
+
high: {
|
|
1939
|
+
octaves: 5,
|
|
1940
|
+
lacunarity: 2,
|
|
1941
|
+
gain: .5
|
|
1942
|
+
},
|
|
1943
|
+
ultra: {
|
|
1944
|
+
octaves: 7,
|
|
1945
|
+
lacunarity: 2,
|
|
1946
|
+
gain: .5
|
|
1947
|
+
}
|
|
1893
1948
|
}
|
|
1894
1949
|
}
|
|
1895
1950
|
};
|
|
@@ -1938,9 +1993,7 @@ function useAccordion(initialProps) {
|
|
|
1938
1993
|
toggle: () => {
|
|
1939
1994
|
if (!defaultProps.disabled) {
|
|
1940
1995
|
const nextOpen = !isOpen;
|
|
1941
|
-
isControlled || setInternalOpen(nextOpen), defaultProps.onOpenChange?.(nextOpen)
|
|
1942
|
-
// Call legacy handlers
|
|
1943
|
-
nextOpen ? defaultProps.onOpen?.() : defaultProps.onClose?.();
|
|
1996
|
+
isControlled || setInternalOpen(nextOpen), defaultProps.onOpenChange?.(nextOpen);
|
|
1944
1997
|
}
|
|
1945
1998
|
},
|
|
1946
1999
|
updatePanelHeight: updatePanelHeight,
|
|
@@ -2027,7 +2080,7 @@ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
|
|
|
2027
2080
|
// Silently handle errors
|
|
2028
2081
|
}
|
|
2029
2082
|
return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
2030
|
-
}, 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) => {
|
|
2083
|
+
}, 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) => {
|
|
2031
2084
|
switch (mode) {
|
|
2032
2085
|
case "standard":
|
|
2033
2086
|
return displacementMap;
|
|
@@ -2194,20 +2247,19 @@ let idCounter = 0;
|
|
|
2194
2247
|
const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({children: children, className: className = "", style: style, displacementScale: displacementScale = 25, blurAmount: blurAmount = .0625, saturation: saturation = 180, aberrationIntensity: aberrationIntensity = 2, mouseOffset: mouseOffset = {
|
|
2195
2248
|
x: 0,
|
|
2196
2249
|
y: 0
|
|
2197
|
-
},
|
|
2198
|
-
x: 0,
|
|
2199
|
-
y: 0
|
|
2200
|
-
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isHovered: isHovered = !1, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0, padding: padding = "0 0", glassSize: glassSize = {
|
|
2250
|
+
}, 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 = {
|
|
2201
2251
|
width: 0,
|
|
2202
2252
|
height: 0
|
|
2203
|
-
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1,
|
|
2253
|
+
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1,
|
|
2254
|
+
// Phase 1: Animation System props
|
|
2255
|
+
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) => {
|
|
2204
2256
|
// Generate a stable, deterministic ID for SSR compatibility
|
|
2205
2257
|
// Use a module-level counter that's consistent across server and client
|
|
2206
|
-
const filterId = useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null);
|
|
2258
|
+
const filterId = useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null), shaderUpdateTimeoutRef = useRef(null), animationFrameRef = useRef(null);
|
|
2207
2259
|
// Lazy load shader utilities only when shader mode is needed
|
|
2208
2260
|
useEffect((() => {
|
|
2209
2261
|
"shader" === mode ?
|
|
2210
|
-
// Dynamic import shader utilities
|
|
2262
|
+
// Dynamic import shader utilities with animation support
|
|
2211
2263
|
Promise.resolve().then((() => shaderUtils)).then((shaderUtils => {
|
|
2212
2264
|
shaderUtilsRef.current = {
|
|
2213
2265
|
ShaderDisplacementGenerator: shaderUtils.ShaderDisplacementGenerator,
|
|
@@ -2222,7 +2274,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2222
2274
|
// Generate shader map with debouncing and caching
|
|
2223
2275
|
useEffect((() => {
|
|
2224
2276
|
// Enhanced validation for shader mode
|
|
2225
|
-
if ("shader" === mode && glassSize && validateGlassSize(glassSize)
|
|
2277
|
+
if ("shader" === mode && glassSize && validateGlassSize(glassSize)) {
|
|
2226
2278
|
// Create cache key from size and variant
|
|
2227
2279
|
const cacheKey = `${glassSize.width}x${glassSize.height}-${shaderVariant}`, cachedUrl = (key => {
|
|
2228
2280
|
const entry = sharedShaderCache.get(key);
|
|
@@ -2244,11 +2296,9 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2244
2296
|
width: glassSize.width,
|
|
2245
2297
|
height: glassSize.height,
|
|
2246
2298
|
fragment: selectedShader
|
|
2247
|
-
}),
|
|
2248
|
-
// Defer shader generation with longer delay to avoid blocking
|
|
2249
|
-
setTimeout((() => {
|
|
2299
|
+
}), shaderUpdateTimeoutRef.current = setTimeout((() => {
|
|
2250
2300
|
const url = shaderGeneratorRef.current?.updateShader() || "";
|
|
2251
|
-
((key, url) => {
|
|
2301
|
+
url && ((key, url) => {
|
|
2252
2302
|
// Evict oldest entries if at capacity
|
|
2253
2303
|
if (sharedShaderCache.size >= 15) {
|
|
2254
2304
|
const entries = Array.from(sharedShaderCache.entries());
|
|
@@ -2280,7 +2330,8 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2280
2330
|
// Cleanup function with error handling
|
|
2281
2331
|
return () => {
|
|
2282
2332
|
shaderDebounceTimeoutRef.current && (clearTimeout(shaderDebounceTimeoutRef.current),
|
|
2283
|
-
shaderDebounceTimeoutRef.current = null)
|
|
2333
|
+
shaderDebounceTimeoutRef.current = null), shaderUpdateTimeoutRef.current && (clearTimeout(shaderUpdateTimeoutRef.current),
|
|
2334
|
+
shaderUpdateTimeoutRef.current = null);
|
|
2284
2335
|
try {
|
|
2285
2336
|
shaderGeneratorRef.current?.destroy();
|
|
2286
2337
|
} catch (error) {
|
|
@@ -2289,7 +2340,37 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2289
2340
|
shaderGeneratorRef.current = null;
|
|
2290
2341
|
}
|
|
2291
2342
|
};
|
|
2292
|
-
}), [ mode, glassSize, shaderVariant ])
|
|
2343
|
+
}), [ mode, glassSize, shaderVariant ]),
|
|
2344
|
+
// Phase 1: Time-Based Animation Loop - Continuous shader regeneration
|
|
2345
|
+
useEffect((() => {
|
|
2346
|
+
// Only run animations in shader mode with time animation enabled
|
|
2347
|
+
if ("shader" !== mode || !withTimeAnimation || effectiveReducedMotion || effectiveWithoutEffects)
|
|
2348
|
+
// Cancel any existing animation frame
|
|
2349
|
+
return void (null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
|
|
2350
|
+
animationFrameRef.current = null));
|
|
2351
|
+
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)));
|
|
2352
|
+
let lastUpdate = 0, isCancelled = !1;
|
|
2353
|
+
const animate = currentTime => {
|
|
2354
|
+
if (!isCancelled) {
|
|
2355
|
+
if (currentTime - lastUpdate >= frameInterval && shaderGeneratorRef.current) {
|
|
2356
|
+
lastUpdate = currentTime;
|
|
2357
|
+
try {
|
|
2358
|
+
const animatedShaderUrl = shaderGeneratorRef.current.updateShader();
|
|
2359
|
+
animatedShaderUrl && setShaderMapUrl(animatedShaderUrl);
|
|
2360
|
+
} catch (error) {
|
|
2361
|
+
console.warn("AtomixGlassContainer: Error in animation loop", error);
|
|
2362
|
+
}
|
|
2363
|
+
}
|
|
2364
|
+
animationFrameRef.current = requestAnimationFrame(animate);
|
|
2365
|
+
}
|
|
2366
|
+
};
|
|
2367
|
+
// Start animation loop
|
|
2368
|
+
// Cleanup animation on unmount or dependency change
|
|
2369
|
+
return animationFrameRef.current = requestAnimationFrame(animate), () => {
|
|
2370
|
+
isCancelled = !0, null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
|
|
2371
|
+
animationFrameRef.current = null);
|
|
2372
|
+
};
|
|
2373
|
+
}), [ mode, withTimeAnimation, animationSpeed, displacementScale, withMultiLayerDistortion, distortionOctaves, distortionLacunarity, distortionGain, distortionQuality, effectiveReducedMotion, effectiveWithoutEffects, glassSize ]);
|
|
2293
2374
|
// Removed forced reflow to avoid layout thrash and potential feedback sizing loops
|
|
2294
2375
|
const [rectCache, setRectCache] = useState(null);
|
|
2295
2376
|
useEffect((() => {
|
|
@@ -2341,21 +2422,18 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2341
2422
|
backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
|
|
2342
2423
|
};
|
|
2343
2424
|
}
|
|
2344
|
-
}), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur ]), containerVars = useMemo((() => {
|
|
2425
|
+
}), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur, overLightConfig ]), containerVars = useMemo((() => {
|
|
2345
2426
|
try {
|
|
2346
2427
|
// Safe extraction of mouse offset values
|
|
2347
2428
|
const mx = mouseOffset && "number" == typeof mouseOffset.x && !isNaN(mouseOffset.x) ? mouseOffset.x : 0, my = mouseOffset && "number" == typeof mouseOffset.y && !isNaN(mouseOffset.y) ? mouseOffset.y : 0;
|
|
2348
2429
|
return {
|
|
2349
|
-
"--atomix-glass-container-width": `${glassSize?.width}`,
|
|
2350
|
-
"--atomix-glass-container-height": `${glassSize?.height}`,
|
|
2351
|
-
"--atomix-glass-container-padding": padding || "0 0",
|
|
2352
2430
|
"--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`,
|
|
2353
2431
|
"--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
|
|
2354
2432
|
"--atomix-glass-container-shadow": overLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.4 + .002 * mx) * (overLightConfig?.shadowIntensity || 1)})`, `inset 0 -1px 0 rgba(0, 0, 0, ${(.2 + .001 * Math.abs(my)) * (overLightConfig?.shadowIntensity || 1)})`, `inset 0 0 20px rgba(0, 0, 0, ${(.08 + .001 * Math.abs(mx + my)) * (overLightConfig?.shadowIntensity || 1)})`, `0 2px 12px rgba(0, 0, 0, ${(.12 + .002 * Math.abs(my)) * (overLightConfig?.shadowIntensity || 1)})` ].join(", ") : "0 0 20px rgba(0, 0, 0, 0.15) inset, 0 4px 8px rgba(0, 0, 0, 0.08) inset",
|
|
2355
2433
|
"--atomix-glass-container-shadow-opacity": effectiveWithoutEffects ? 0 : 1,
|
|
2356
2434
|
// Background and shadow values use design token-aligned RGB values
|
|
2357
2435
|
"--atomix-glass-container-bg": overLight ? `linear-gradient(${180 + .5 * mx}deg, rgba(255, 255, 255, 0.1) 0%, transparent 20%, transparent 80%, rgba(0, 0, 0, 0.05) 100%)` : "none",
|
|
2358
|
-
"--atomix-glass-container-text-shadow": overLight ? "0px 2px
|
|
2436
|
+
"--atomix-glass-container-text-shadow": overLight ? "0px 1px 2px rgba(255, 255, 255, 0.15)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
|
|
2359
2437
|
"--atomix-glass-container-box-shadow": overLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0px 12px 40px rgba(0, 0, 0, 0.25)"
|
|
2360
2438
|
};
|
|
2361
2439
|
} catch (error) {
|
|
@@ -2370,7 +2448,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2370
2448
|
"--atomix-glass-container-text-shadow": "none"
|
|
2371
2449
|
};
|
|
2372
2450
|
}
|
|
2373
|
-
}), [
|
|
2451
|
+
}), [ borderRadius, backdropStyle, mouseOffset, overLight, effectiveWithoutEffects, overLightConfig ]);
|
|
2374
2452
|
return jsx("div", {
|
|
2375
2453
|
ref: el => {
|
|
2376
2454
|
// Apply force no-transition
|
|
@@ -2399,10 +2477,6 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2399
2477
|
aberrationIntensity: "number" != typeof aberrationIntensity || isNaN(aberrationIntensity) ? 0 : aberrationIntensity,
|
|
2400
2478
|
shaderMapUrl: shaderMapUrl
|
|
2401
2479
|
}), jsx("div", {
|
|
2402
|
-
ref: el => {
|
|
2403
|
-
el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
|
|
2404
|
-
el.style.setProperty("transition-delay", "0s", "important"));
|
|
2405
|
-
},
|
|
2406
2480
|
className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
|
|
2407
2481
|
style: {
|
|
2408
2482
|
filter: `url(#${filterId})`
|
|
@@ -2507,7 +2581,7 @@ class {
|
|
|
2507
2581
|
}
|
|
2508
2582
|
}, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
|
|
2509
2583
|
if (!wrapperElement && !containerElement) return;
|
|
2510
|
-
const {mouseOffset: mouseOffset, globalMousePosition: globalMousePosition, glassSize: glassSize, isHovered: isHovered, isActive: isActive, isOverLight: isOverLight, baseOverLightConfig: baseOverLightConfig, effectiveBorderRadius: effectiveBorderRadius, effectiveWithoutEffects: effectiveWithoutEffects, effectiveReducedMotion: effectiveReducedMotion, elasticity: elasticity, directionalScale: directionalScale, onClick: onClick, withLiquidBlur: withLiquidBlur, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, padding: padding = ATOMIX_GLASS.DEFAULTS.PADDING} = params, mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, overLightConfig = {
|
|
2584
|
+
const {mouseOffset: mouseOffset, globalMousePosition: globalMousePosition, glassSize: glassSize, isHovered: isHovered, isActive: isActive, isOverLight: isOverLight, baseOverLightConfig: baseOverLightConfig, effectiveBorderRadius: effectiveBorderRadius, effectiveWithoutEffects: effectiveWithoutEffects, effectiveReducedMotion: effectiveReducedMotion, elasticity: elasticity, directionalScale: directionalScale, onClick: onClick, withLiquidBlur: withLiquidBlur, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, padding: padding = ATOMIX_GLASS.DEFAULTS.PADDING, isFixedOrSticky: isFixedOrSticky = !1} = params, mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, overLightConfig = {
|
|
2511
2585
|
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
2512
2586
|
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
2513
2587
|
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
@@ -2597,7 +2671,7 @@ class {
|
|
|
2597
2671
|
}
|
|
2598
2672
|
// Update Container Styles (containerVars)
|
|
2599
2673
|
if (containerElement) {
|
|
2600
|
-
const mx = mouseOffset.x, my = mouseOffset.y, EDGE_BLUR_MULTIPLIER =
|
|
2674
|
+
const mx = mouseOffset.x, my = mouseOffset.y, EDGE_BLUR_MULTIPLIER = .5, CENTER_BLUR_MULTIPLIER = .2, FLOW_BLUR_MULTIPLIER = .3, MOUSE_INFLUENCE_BLUR_FACTOR = .4, EDGE_INTENSITY_MOUSE_FACTOR = .15, CENTER_INTENSITY_MOUSE_FACTOR = .1, MAX_BLUR_RELATIVE = 2, rect = containerElement.getBoundingClientRect();
|
|
2601
2675
|
let liquidBlur = {
|
|
2602
2676
|
baseBlur: blurAmount,
|
|
2603
2677
|
edgeBlur: blurAmount * EDGE_BLUR_MULTIPLIER,
|
|
@@ -2619,22 +2693,155 @@ class {
|
|
|
2619
2693
|
backdropFilterString = !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? `blur(${clampBlur(Math.max(liquidBlur.baseBlur, .8 * liquidBlur.edgeBlur, 1.1 * liquidBlur.centerBlur, .9 * liquidBlur.flowBlur))}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig.contrast}) brightness(${overLightConfig.brightness})` : `blur(${clampBlur(.4 * liquidBlur.baseBlur + .25 * liquidBlur.edgeBlur + .15 * liquidBlur.centerBlur + .2 * liquidBlur.flowBlur)}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig.contrast}) brightness(${overLightConfig.brightness})`;
|
|
2620
2694
|
// Container variables
|
|
2621
2695
|
const style = containerElement.style;
|
|
2622
|
-
style.setProperty("--atomix-glass-container-width", `${glassSize.width}`
|
|
2696
|
+
style.setProperty("--atomix-glass-container-width", isFixedOrSticky ? `${glassSize.width}` : "100%"),
|
|
2697
|
+
style.setProperty("--atomix-glass-container-height", isFixedOrSticky ? `${glassSize.height}` : "100%"),
|
|
2623
2698
|
style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
|
|
2624
2699
|
style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
|
|
2625
2700
|
// Shadows
|
|
2626
2701
|
style.setProperty("--atomix-glass-container-shadow", isOverLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.4 + .002 * mx) * (overLightConfig.shadowIntensity || 1)})`, `inset 0 -1px 0 rgba(0, 0, 0, ${(.2 + .001 * Math.abs(my)) * (overLightConfig.shadowIntensity || 1)})`, `inset 0 0 20px rgba(0, 0, 0, ${(.08 + .001 * Math.abs(mx + my)) * (overLightConfig.shadowIntensity || 1)})`, `0 2px 12px rgba(0, 0, 0, ${(.12 + .002 * Math.abs(my)) * (overLightConfig.shadowIntensity || 1)})` ].join(", ") : "0 0 20px rgba(0, 0, 0, 0.15) inset, 0 4px 8px rgba(0, 0, 0, 0.08) inset"),
|
|
2627
2702
|
style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
|
|
2628
2703
|
style.setProperty("--atomix-glass-container-bg", isOverLight ? `linear-gradient(${180 + .5 * mx}deg, rgba(255, 255, 255, 0.1) 0%, transparent 20%, transparent 80%, rgba(0, 0, 0, 0.05) 100%)` : "none"),
|
|
2629
|
-
style.setProperty("--atomix-glass-container-text-shadow", isOverLight ? "0px 2px
|
|
2704
|
+
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)"),
|
|
2630
2705
|
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)");
|
|
2631
2706
|
}
|
|
2632
|
-
}
|
|
2707
|
+
};
|
|
2633
2708
|
|
|
2634
2709
|
/**
|
|
2635
2710
|
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
2636
2711
|
* to avoid React re-renders on mouse movement.
|
|
2637
|
-
*/
|
|
2712
|
+
*/
|
|
2713
|
+
/**
|
|
2714
|
+
* Animation System for AtomixGlass Component
|
|
2715
|
+
*
|
|
2716
|
+
* Implements Phase 1 features from the AtomixGlass Feature Implementation Roadmap:
|
|
2717
|
+
* - Feature 1.1: Time-Based Animation System
|
|
2718
|
+
* - Feature 1.2: Multi-Layer Distortion System (FBM)
|
|
2719
|
+
*
|
|
2720
|
+
* @packageDocumentation
|
|
2721
|
+
*/
|
|
2722
|
+
// ============================================================================
|
|
2723
|
+
// Noise Functions for FBM (Feature 1.2)
|
|
2724
|
+
// ============================================================================
|
|
2725
|
+
/**
|
|
2726
|
+
* Perlin noise implementation for smooth gradient noise
|
|
2727
|
+
*
|
|
2728
|
+
* @param x - X coordinate
|
|
2729
|
+
* @param y - Y coordinate
|
|
2730
|
+
* @returns Noise value in range [0, 1]
|
|
2731
|
+
*/
|
|
2732
|
+
function perlinNoise(x, y) {
|
|
2733
|
+
// Simplified Perlin noise using pseudo-random gradients
|
|
2734
|
+
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);
|
|
2735
|
+
// Scale to [0, 1] range
|
|
2736
|
+
return (lerp(lerpX1, lerpX2, v) + 1) / 2;
|
|
2737
|
+
}
|
|
2738
|
+
|
|
2739
|
+
// ============================================================================
|
|
2740
|
+
// Fractal Brownian Motion (FBM) Engine (Feature 1.2)
|
|
2741
|
+
// ============================================================================
|
|
2742
|
+
/**
|
|
2743
|
+
* Creates an FBM engine with configurable parameters
|
|
2744
|
+
*
|
|
2745
|
+
* @param config - FBM configuration (octaves, lacunarity, gain)
|
|
2746
|
+
* @returns Object with fbm function
|
|
2747
|
+
*
|
|
2748
|
+
* @example
|
|
2749
|
+
* ```typescript
|
|
2750
|
+
* const fbmEngine = createFBMEngine({ octaves: 5, lacunarity: 2, gain: 0.5 });
|
|
2751
|
+
*
|
|
2752
|
+
* // Generate noise at position (0.5, 0.5) with time animation
|
|
2753
|
+
* const noiseValue = fbmEngine.fbm(0.5, 0.5, Date.now());
|
|
2754
|
+
* ```
|
|
2755
|
+
*/ function createFBMEngine(config) {
|
|
2756
|
+
/**
|
|
2757
|
+
* Fractal Brownian Motion function
|
|
2758
|
+
* Combines multiple octaves of noise for complex, natural patterns
|
|
2759
|
+
*
|
|
2760
|
+
* @param x - X coordinate
|
|
2761
|
+
* @param y - Y coordinate
|
|
2762
|
+
* @param time - Optional time value for animation
|
|
2763
|
+
* @returns FBM noise value in range [0, 1]
|
|
2764
|
+
*/
|
|
2765
|
+
const fbm = (x, y, time = 0) => {
|
|
2766
|
+
let value = 0, amplitude = .5, frequency = 1, phase = .001 * time;
|
|
2767
|
+
// Convert to seconds for reasonable animation speed
|
|
2768
|
+
for (let i = 0; i < config.octaves; i++)
|
|
2769
|
+
// Apply time-based phase shift to all octaves
|
|
2770
|
+
value += perlinNoise(x * frequency + phase, y * frequency + phase) * amplitude,
|
|
2771
|
+
frequency *= config.lacunarity, // Increase frequency
|
|
2772
|
+
amplitude *= config.gain;
|
|
2773
|
+
return value;
|
|
2774
|
+
};
|
|
2775
|
+
/**
|
|
2776
|
+
* Get FBM with simple time factor
|
|
2777
|
+
*/ return {
|
|
2778
|
+
fbm: fbm,
|
|
2779
|
+
fbmWithTime: (x, y, time) => fbm(x, y, time)
|
|
2780
|
+
};
|
|
2781
|
+
}
|
|
2782
|
+
|
|
2783
|
+
/**
|
|
2784
|
+
* Gets optimal FBM config based on quality preset
|
|
2785
|
+
*
|
|
2786
|
+
* @param quality - Quality preset level
|
|
2787
|
+
* @returns FBM configuration for the quality level
|
|
2788
|
+
*/ const fbmEngineCache = new Map;
|
|
2789
|
+
|
|
2790
|
+
// ============================================================================
|
|
2791
|
+
// Shader Utility Functions for Time-Based Effects
|
|
2792
|
+
// ============================================================================
|
|
2793
|
+
/**
|
|
2794
|
+
* Liquid glass distortion with time-based animation
|
|
2795
|
+
* Uses FBM to create organic, flowing liquid effects
|
|
2796
|
+
*
|
|
2797
|
+
* @param uv - UV coordinates (normalized 0-1)
|
|
2798
|
+
* @param time - Elapsed time in milliseconds
|
|
2799
|
+
* @param config - FBM configuration
|
|
2800
|
+
* @returns Distorted UV coordinates
|
|
2801
|
+
*/ function liquidGlassWithTime(uv, time, config) {
|
|
2802
|
+
const configKey = `${config.octaves}-${config.lacunarity}-${config.gain}`;
|
|
2803
|
+
let fbmEngine = fbmEngineCache.get(configKey);
|
|
2804
|
+
fbmEngine || (fbmEngine = createFBMEngine(config), fbmEngineCache.set(configKey, fbmEngine));
|
|
2805
|
+
// Animate noise with time
|
|
2806
|
+
const animatedNoise = fbmEngine.fbmWithTime(2 * uv.x + 1e-4 * time, 2 * uv.y + 15e-5 * time, time);
|
|
2807
|
+
return {
|
|
2808
|
+
x: uv.x + .04 * (animatedNoise - .5),
|
|
2809
|
+
y: uv.y + .04 * (animatedNoise - .5)
|
|
2810
|
+
};
|
|
2811
|
+
}
|
|
2812
|
+
|
|
2813
|
+
// ============================================================================
|
|
2814
|
+
// Helper Functions
|
|
2815
|
+
// ============================================================================
|
|
2816
|
+
/**
|
|
2817
|
+
* Fade curve for smooth interpolation (Perlin's fade function)
|
|
2818
|
+
*/ function fade(t) {
|
|
2819
|
+
return t * t * t * (t * (6 * t - 15) + 10);
|
|
2820
|
+
}
|
|
2821
|
+
|
|
2822
|
+
/**
|
|
2823
|
+
* Linear interpolation
|
|
2824
|
+
*/ function lerp(a, b, t) {
|
|
2825
|
+
return a + t * (b - a);
|
|
2826
|
+
}
|
|
2827
|
+
|
|
2828
|
+
/**
|
|
2829
|
+
* Gradient calculation for Perlin noise
|
|
2830
|
+
*/ function grad(hash, x, y) {
|
|
2831
|
+
const h = 15 & hash, u = h < 8 ? x : y, v = h < 4 ? y : 12 === h || 14 === h ? x : 0;
|
|
2832
|
+
return (1 & h ? -u : u) + (2 & h ? -v : v);
|
|
2833
|
+
}
|
|
2834
|
+
|
|
2835
|
+
/**
|
|
2836
|
+
* Permutation table for Perlin noise
|
|
2837
|
+
*/ const p = (() => {
|
|
2838
|
+
const permutation = [];
|
|
2839
|
+
for (let i = 0; i < 256; i++) permutation[i] = Math.floor(256 * Math.random());
|
|
2840
|
+
// Duplicate for overflow handling
|
|
2841
|
+
return [ ...permutation, ...permutation ];
|
|
2842
|
+
})(), {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
|
|
2843
|
+
|
|
2844
|
+
const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
|
|
2638
2845
|
parentElement && backgroundDetectionCache.set(parentElement, {
|
|
2639
2846
|
result: result,
|
|
2640
2847
|
timestamp: Date.now(),
|
|
@@ -2647,7 +2854,9 @@ class {
|
|
|
2647
2854
|
* Composable hook for AtomixGlass component logic
|
|
2648
2855
|
* Manages all state, calculations, and event handlers
|
|
2649
2856
|
*/
|
|
2650
|
-
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,
|
|
2857
|
+
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:
|
|
2858
|
+
// Phase 1: Animation System Props
|
|
2859
|
+
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}) {
|
|
2651
2860
|
// State
|
|
2652
2861
|
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), cachedRectRef = useRef(null), internalGlobalMousePositionRef = useRef({
|
|
2653
2862
|
x: 0,
|
|
@@ -2661,7 +2870,47 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2661
2870
|
}), targetGlobalMousePositionRef = useRef({
|
|
2662
2871
|
x: 0,
|
|
2663
2872
|
y: 0
|
|
2664
|
-
}), lerpRafRef = useRef(null), lerpActiveRef = useRef(!1), [dynamicBorderRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1),
|
|
2873
|
+
}), lerpRafRef = useRef(null), lerpActiveRef = useRef(!1), [dynamicBorderRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), animationFrameIdRef = useRef(null), animationStartTimeRef = useRef(0), elapsedTimeRef = useRef(0), shaderTimeRef = useRef(0), fbmConfig = useMemo((() => {
|
|
2874
|
+
// If quality preset is provided, use it as base
|
|
2875
|
+
const preset = (quality = distortionQuality, ATOMIX_GLASS.CONSTANTS.DISTORTION_QUALITY_PRESETS[quality]);
|
|
2876
|
+
// Override with custom values if provided
|
|
2877
|
+
var quality;
|
|
2878
|
+
return {
|
|
2879
|
+
octaves: distortionOctaves ?? preset.octaves,
|
|
2880
|
+
lacunarity: distortionLacunarity ?? preset.lacunarity,
|
|
2881
|
+
gain: distortionGain ?? preset.gain
|
|
2882
|
+
};
|
|
2883
|
+
}), [ distortionQuality, distortionOctaves, distortionLacunarity, distortionGain ]), fbmEngine = useMemo((() => withMultiLayerDistortion ? createFBMEngine(fbmConfig) : null), [ withMultiLayerDistortion, fbmConfig ]), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveWithTimeAnimation = useMemo((() => withTimeAnimation && !effectiveReducedMotion), [ withTimeAnimation, effectiveReducedMotion ]);
|
|
2884
|
+
/**
|
|
2885
|
+
* Animation loop for time-based effects
|
|
2886
|
+
*/
|
|
2887
|
+
useEffect((() => {
|
|
2888
|
+
if (!effectiveWithTimeAnimation || "undefined" == typeof window) return;
|
|
2889
|
+
let lastFrameTime = performance.now();
|
|
2890
|
+
/**
|
|
2891
|
+
* Animation frame handler
|
|
2892
|
+
*/ const animate = currentTime => {
|
|
2893
|
+
// Calculate delta time
|
|
2894
|
+
const deltaTime = currentTime - lastFrameTime;
|
|
2895
|
+
lastFrameTime = currentTime;
|
|
2896
|
+
// Apply animation speed multiplier
|
|
2897
|
+
const scaledDelta = deltaTime * animationSpeed;
|
|
2898
|
+
elapsedTimeRef.current += scaledDelta, shaderTimeRef.current = elapsedTimeRef.current,
|
|
2899
|
+
// Continue animation loop
|
|
2900
|
+
animationFrameIdRef.current = requestAnimationFrame(animate);
|
|
2901
|
+
};
|
|
2902
|
+
// Start animation
|
|
2903
|
+
// Cleanup
|
|
2904
|
+
return animationStartTimeRef.current = performance.now(), animationFrameIdRef.current = requestAnimationFrame(animate),
|
|
2905
|
+
() => {
|
|
2906
|
+
null !== animationFrameIdRef.current && (cancelAnimationFrame(animationFrameIdRef.current),
|
|
2907
|
+
animationFrameIdRef.current = null);
|
|
2908
|
+
};
|
|
2909
|
+
}), [ effectiveWithTimeAnimation, animationSpeed ]);
|
|
2910
|
+
/**
|
|
2911
|
+
* Get current shader time for animations
|
|
2912
|
+
*/
|
|
2913
|
+
const getShaderTime = useCallback((() => shaderTimeRef.current), []), applyTimeBasedDistortion = useCallback((uv => effectiveWithTimeAnimation && fbmEngine ? liquidGlassWithTime(uv, shaderTimeRef.current, fbmConfig) : uv), [ effectiveWithTimeAnimation, fbmEngine, fbmConfig ]), effectiveBorderRadius = useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
|
|
2665
2914
|
const [glassSize, setGlassSize] = useState({
|
|
2666
2915
|
width: 270,
|
|
2667
2916
|
height: 69
|
|
@@ -2720,7 +2969,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2720
2969
|
glassRef: glassRef,
|
|
2721
2970
|
effectiveBorderRadius: effectiveBorderRadius,
|
|
2722
2971
|
cachedRectRef: cachedRectRef
|
|
2723
|
-
}),
|
|
2972
|
+
}), effectiveHighContrast = useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveWithoutEffects = useMemo((() => withoutEffects || effectiveReducedMotion), [ withoutEffects, effectiveReducedMotion ]), globalMousePosition = externalGlobalMousePosition || internalGlobalMousePositionRef.current, mouseOffset = externalMouseOffset || internalMouseOffsetRef.current;
|
|
2973
|
+
/**
|
|
2974
|
+
* Apply time-based distortion to UV coordinates
|
|
2975
|
+
*/
|
|
2724
2976
|
// Extract border-radius from children
|
|
2725
2977
|
useEffect((() => {
|
|
2726
2978
|
const extractRadius = () => {
|
|
@@ -2923,6 +3175,8 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2923
3175
|
lerpActiveRef.current = !0;
|
|
2924
3176
|
const LERP_T = CONSTANTS.LERP_FACTOR, tick = () => {
|
|
2925
3177
|
if (!lerpActiveRef.current) return;
|
|
3178
|
+
// Add ref validity check to prevent memory leaks
|
|
3179
|
+
if (!glassRef.current || !wrapperRef?.current) return void (lerpActiveRef.current = !1);
|
|
2926
3180
|
const cur = internalMouseOffsetRef.current, tgt = targetMouseOffsetRef.current, dx = tgt.x - cur.x, dy = tgt.y - cur.y;
|
|
2927
3181
|
// If we're close enough, snap and park
|
|
2928
3182
|
if (Math.abs(dx) < .05 && Math.abs(dy) < .05) internalMouseOffsetRef.current = {
|
|
@@ -2931,17 +3185,17 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2931
3185
|
...targetGlobalMousePositionRef.current
|
|
2932
3186
|
}; else {
|
|
2933
3187
|
internalMouseOffsetRef.current = {
|
|
2934
|
-
x: lerp(cur.x, tgt.x, LERP_T),
|
|
2935
|
-
y: lerp(cur.y, tgt.y, LERP_T)
|
|
3188
|
+
x: lerp$1(cur.x, tgt.x, LERP_T),
|
|
3189
|
+
y: lerp$1(cur.y, tgt.y, LERP_T)
|
|
2936
3190
|
};
|
|
2937
3191
|
const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
|
|
2938
3192
|
internalGlobalMousePositionRef.current = {
|
|
2939
|
-
x: lerp(curG.x, tgtG.x, LERP_T),
|
|
2940
|
-
y: lerp(curG.y, tgtG.y, LERP_T)
|
|
3193
|
+
x: lerp$1(curG.x, tgtG.x, LERP_T),
|
|
3194
|
+
y: lerp$1(curG.y, tgtG.y, LERP_T)
|
|
2941
3195
|
};
|
|
2942
3196
|
}
|
|
2943
3197
|
// Imperative style update with the smoothed values
|
|
2944
|
-
updateAtomixGlassStyles(wrapperRef
|
|
3198
|
+
updateAtomixGlassStyles(wrapperRef.current, glassRef.current, {
|
|
2945
3199
|
mouseOffset: internalMouseOffsetRef.current,
|
|
2946
3200
|
globalMousePosition: internalGlobalMousePositionRef.current,
|
|
2947
3201
|
glassSize: glassSize,
|
|
@@ -2958,12 +3212,13 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2958
3212
|
withLiquidBlur: withLiquidBlur,
|
|
2959
3213
|
blurAmount: blurAmount,
|
|
2960
3214
|
saturation: saturation,
|
|
2961
|
-
padding: padding
|
|
3215
|
+
padding: padding,
|
|
3216
|
+
isFixedOrSticky: isFixedOrSticky
|
|
2962
3217
|
}), lerpRafRef.current = requestAnimationFrame(tick);
|
|
2963
3218
|
};
|
|
2964
3219
|
// 0.08 – lower = more viscous
|
|
2965
3220
|
lerpRafRef.current = requestAnimationFrame(tick);
|
|
2966
|
-
}), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding ]), stopLerpLoop = useCallback((() => {
|
|
3221
|
+
}), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding, isFixedOrSticky ]), stopLerpLoop = useCallback((() => {
|
|
2967
3222
|
lerpActiveRef.current = !1, null !== lerpRafRef.current && (cancelAnimationFrame(lerpRafRef.current),
|
|
2968
3223
|
lerpRafRef.current = null);
|
|
2969
3224
|
}), []);
|
|
@@ -3031,6 +3286,8 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3031
3286
|
// This is now static (refs or props) unless prop changes
|
|
3032
3287
|
overLightConfig: overLightConfig,
|
|
3033
3288
|
transformStyle: transformStyle,
|
|
3289
|
+
getShaderTime: getShaderTime,
|
|
3290
|
+
applyTimeBasedDistortion: applyTimeBasedDistortion,
|
|
3034
3291
|
handleMouseEnter: handleMouseEnter,
|
|
3035
3292
|
handleMouseLeave: handleMouseLeave,
|
|
3036
3293
|
handleMouseDown: handleMouseDown,
|
|
@@ -3039,6 +3296,800 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3039
3296
|
};
|
|
3040
3297
|
}
|
|
3041
3298
|
|
|
3299
|
+
/**
|
|
3300
|
+
* Default responsive breakpoints configuration
|
|
3301
|
+
*
|
|
3302
|
+
* These breakpoints are optimized for glass effect performance across device classes:
|
|
3303
|
+
* - Mobile: Reduced complexity for 60 FPS target
|
|
3304
|
+
* - Tablet: Balanced quality and performance
|
|
3305
|
+
* - Desktop: Full fidelity effects
|
|
3306
|
+
*/ const DEFAULT_BREAKPOINTS = {
|
|
3307
|
+
mobile: {
|
|
3308
|
+
maxWidth: 640,
|
|
3309
|
+
params: {
|
|
3310
|
+
distortionOctaves: 3,
|
|
3311
|
+
displacementScale: .7,
|
|
3312
|
+
blurAmount: .8,
|
|
3313
|
+
animationSpeed: .8,
|
|
3314
|
+
chromaticIntensity: .5
|
|
3315
|
+
}
|
|
3316
|
+
},
|
|
3317
|
+
tablet: {
|
|
3318
|
+
minWidth: 641,
|
|
3319
|
+
maxWidth: 1024,
|
|
3320
|
+
params: {
|
|
3321
|
+
distortionOctaves: 4,
|
|
3322
|
+
displacementScale: .85,
|
|
3323
|
+
blurAmount: .9,
|
|
3324
|
+
animationSpeed: .9,
|
|
3325
|
+
chromaticIntensity: .75
|
|
3326
|
+
}
|
|
3327
|
+
},
|
|
3328
|
+
desktop: {
|
|
3329
|
+
minWidth: 1025,
|
|
3330
|
+
params: {
|
|
3331
|
+
distortionOctaves: 5,
|
|
3332
|
+
displacementScale: 1,
|
|
3333
|
+
blurAmount: 1,
|
|
3334
|
+
animationSpeed: 1,
|
|
3335
|
+
chromaticIntensity: 1
|
|
3336
|
+
}
|
|
3337
|
+
}
|
|
3338
|
+
};
|
|
3339
|
+
|
|
3340
|
+
/**
|
|
3341
|
+
* Device performance tier detection
|
|
3342
|
+
*
|
|
3343
|
+
* Uses Device Memory API and Hardware Concurrency API to classify devices
|
|
3344
|
+
* into performance tiers for automatic quality adjustment.
|
|
3345
|
+
*
|
|
3346
|
+
* @returns Performance tier classification
|
|
3347
|
+
*/
|
|
3348
|
+
/**
|
|
3349
|
+
* Responsive Glass Parameters Hook
|
|
3350
|
+
*
|
|
3351
|
+
* Automatically adjusts glass effect parameters based on:
|
|
3352
|
+
* 1. Screen size (mobile/tablet/desktop breakpoints)
|
|
3353
|
+
* 2. Device performance (RAM and CPU detection)
|
|
3354
|
+
* 3. Custom breakpoint configuration
|
|
3355
|
+
*
|
|
3356
|
+
* Features:
|
|
3357
|
+
* - Debounced resize handling
|
|
3358
|
+
* - Performance-based quality adjustment
|
|
3359
|
+
* - Smooth parameter transitions
|
|
3360
|
+
* - Debug mode for development
|
|
3361
|
+
*
|
|
3362
|
+
* @example
|
|
3363
|
+
* ```typescript
|
|
3364
|
+
* const { responsiveParams, currentBreakpoint } = useResponsiveGlass({
|
|
3365
|
+
* baseParams: {
|
|
3366
|
+
* distortionOctaves: 5,
|
|
3367
|
+
* displacementScale: 20,
|
|
3368
|
+
* blurAmount: 10,
|
|
3369
|
+
* },
|
|
3370
|
+
* debug: true,
|
|
3371
|
+
* });
|
|
3372
|
+
* ```
|
|
3373
|
+
*
|
|
3374
|
+
* @param options Hook configuration options
|
|
3375
|
+
* @returns Responsive parameters and metadata
|
|
3376
|
+
*/
|
|
3377
|
+
function useResponsiveGlass({baseParams: baseParams, breakpoints: breakpoints = DEFAULT_BREAKPOINTS, enabled: enabled = !0, enablePerformanceAdjustment: enablePerformanceAdjustment = !0, debug: debug = !1}) {
|
|
3378
|
+
const [responsiveParams, setResponsiveParams] = useState(baseParams), [currentBreakpoint, setCurrentBreakpoint] = useState("desktop"), [performanceTier, setPerformanceTier] = useState("high"), [isActive, setIsActive] = useState(enabled), baseParamsRef = useRef(baseParams), breakpointsRef = useRef(breakpoints);
|
|
3379
|
+
// Update refs when props change
|
|
3380
|
+
baseParamsRef.current = baseParams, breakpointsRef.current = breakpoints;
|
|
3381
|
+
/**
|
|
3382
|
+
* Calculate and apply responsive parameters
|
|
3383
|
+
*/
|
|
3384
|
+
const calculateParams = useCallback((() => {
|
|
3385
|
+
if (!enabled || "undefined" == typeof window) return setIsActive(!1), setResponsiveParams(baseParamsRef.current),
|
|
3386
|
+
void setCurrentBreakpoint("disabled");
|
|
3387
|
+
setIsActive(!0);
|
|
3388
|
+
// Get current screen width
|
|
3389
|
+
const width = window.innerWidth, {name: name, params: breakpointParams} = ((width, breakpoints) => {
|
|
3390
|
+
// Convert breakpoints to array and sort by minWidth descending
|
|
3391
|
+
const sortedBreakpoints = Object.entries(breakpoints).filter((([_, bp]) => void 0 !== bp.minWidth)).sort(((a, b) => (b[1].minWidth || 0) - (a[1].minWidth || 0)));
|
|
3392
|
+
// Find first breakpoint where width >= minWidth
|
|
3393
|
+
for (const [name, bp] of sortedBreakpoints) if (width >= (bp.minWidth || 0)) return {
|
|
3394
|
+
name: name,
|
|
3395
|
+
params: bp.params
|
|
3396
|
+
};
|
|
3397
|
+
// If no minWidth matched, check maxWidth breakpoints
|
|
3398
|
+
const maxWidthBreakpoints = Object.entries(breakpoints).filter((([_, bp]) => void 0 !== bp.maxWidth)).sort(((a, b) => (a[1].maxWidth || 1 / 0) - (b[1].maxWidth || 1 / 0)));
|
|
3399
|
+
for (const [name, bp] of maxWidthBreakpoints) if (width <= (bp.maxWidth || 1 / 0)) return {
|
|
3400
|
+
name: name,
|
|
3401
|
+
params: bp.params
|
|
3402
|
+
};
|
|
3403
|
+
// Fallback to first available breakpoint
|
|
3404
|
+
const entries = Object.entries(breakpoints);
|
|
3405
|
+
if (0 === entries.length)
|
|
3406
|
+
// Ultimate fallback - return sensible defaults
|
|
3407
|
+
return {
|
|
3408
|
+
name: "desktop",
|
|
3409
|
+
params: {
|
|
3410
|
+
distortionOctaves: 5,
|
|
3411
|
+
displacementScale: 1,
|
|
3412
|
+
blurAmount: 1
|
|
3413
|
+
}
|
|
3414
|
+
};
|
|
3415
|
+
const firstEntry = entries[0];
|
|
3416
|
+
if (!firstEntry) return {
|
|
3417
|
+
name: "desktop",
|
|
3418
|
+
params: {
|
|
3419
|
+
distortionOctaves: 5,
|
|
3420
|
+
displacementScale: 1,
|
|
3421
|
+
blurAmount: 1
|
|
3422
|
+
}
|
|
3423
|
+
};
|
|
3424
|
+
const [fallbackName, fallbackBreakpoint] = firstEntry;
|
|
3425
|
+
return {
|
|
3426
|
+
name: fallbackName,
|
|
3427
|
+
params: fallbackBreakpoint.params
|
|
3428
|
+
};
|
|
3429
|
+
})(width, breakpointsRef.current);
|
|
3430
|
+
// Determine current breakpoint
|
|
3431
|
+
setCurrentBreakpoint(name);
|
|
3432
|
+
// Merge base params with breakpoint params
|
|
3433
|
+
let mergedParams = ((baseParams, breakpointParams) => {
|
|
3434
|
+
const result = {
|
|
3435
|
+
...baseParams
|
|
3436
|
+
}, scaleProperties = [ "displacementScale", "blurAmount", "saturation", "aberrationIntensity", "animationSpeed", "chromaticIntensity" ];
|
|
3437
|
+
// Apply scaling for specific properties
|
|
3438
|
+
for (const prop of scaleProperties) void 0 !== breakpointParams[prop] && void 0 !== baseParams[prop] && (result[prop] = baseParams[prop] * breakpointParams[prop]);
|
|
3439
|
+
// Override properties that should be set directly (not scaled)
|
|
3440
|
+
const overrideProperties = [ "distortionOctaves", "distortionLacunarity", "distortionGain" ];
|
|
3441
|
+
for (const prop of overrideProperties) void 0 !== breakpointParams[prop] && (result[prop] = breakpointParams[prop]);
|
|
3442
|
+
return result;
|
|
3443
|
+
})(baseParamsRef.current, breakpointParams);
|
|
3444
|
+
// Apply performance adjustments if enabled
|
|
3445
|
+
if (enablePerformanceAdjustment) {
|
|
3446
|
+
const tier = (() => {
|
|
3447
|
+
// Check if we're in a browser environment
|
|
3448
|
+
if ("undefined" == typeof window || "undefined" == typeof navigator) return "high"; // Default to high for SSR
|
|
3449
|
+
// Device Memory API (Chrome, Edge, Opera)
|
|
3450
|
+
// Returns RAM in GB: 0.25, 0.5, 1, 2, 4, 8
|
|
3451
|
+
const deviceMemory = navigator.deviceMemory || 4, hardwareConcurrency = navigator.hardwareConcurrency || 4;
|
|
3452
|
+
// Hardware Concurrency API (logical CPU cores)
|
|
3453
|
+
// Low-end: ≤2GB RAM OR ≤2 CPU cores
|
|
3454
|
+
return deviceMemory <= 2 || hardwareConcurrency <= 2 ? "low" :
|
|
3455
|
+
// High-end: ≥4GB RAM AND ≥4 CPU cores
|
|
3456
|
+
deviceMemory >= 4 && hardwareConcurrency >= 4 ? "high" : "medium";
|
|
3457
|
+
})();
|
|
3458
|
+
setPerformanceTier(tier), mergedParams = ((baseParams, performanceTier) => {
|
|
3459
|
+
if ("high" === performanceTier) return baseParams;
|
|
3460
|
+
// No adjustment needed
|
|
3461
|
+
const multiplier = "low" === performanceTier ? .7 : .85;
|
|
3462
|
+
return {
|
|
3463
|
+
...baseParams,
|
|
3464
|
+
distortionOctaves: Math.max(2, Math.round((baseParams.distortionOctaves || 5) * multiplier)),
|
|
3465
|
+
displacementScale: (baseParams.displacementScale || 1) * multiplier,
|
|
3466
|
+
blurAmount: (baseParams.blurAmount || 1) * multiplier,
|
|
3467
|
+
animationSpeed: (baseParams.animationSpeed || 1) * multiplier,
|
|
3468
|
+
chromaticIntensity: (baseParams.chromaticIntensity || 1) * multiplier
|
|
3469
|
+
};
|
|
3470
|
+
})(mergedParams, tier);
|
|
3471
|
+
}
|
|
3472
|
+
setResponsiveParams(mergedParams);
|
|
3473
|
+
}), [ enabled, enablePerformanceAdjustment, debug ]), debouncedCalculate = (func => {
|
|
3474
|
+
const timeoutRef = useRef(null);
|
|
3475
|
+
return useEffect((() => () => {
|
|
3476
|
+
timeoutRef.current && clearTimeout(timeoutRef.current);
|
|
3477
|
+
}), []), useCallback(((...args) => {
|
|
3478
|
+
timeoutRef.current && clearTimeout(timeoutRef.current), timeoutRef.current = setTimeout((() => {
|
|
3479
|
+
func(...args);
|
|
3480
|
+
}), 200);
|
|
3481
|
+
}), [ func, 200 ]);
|
|
3482
|
+
})(calculateParams);
|
|
3483
|
+
/**
|
|
3484
|
+
* Debounced parameter calculation for resize events
|
|
3485
|
+
*/
|
|
3486
|
+
/**
|
|
3487
|
+
* Handle window resize
|
|
3488
|
+
*/
|
|
3489
|
+
return useEffect((() => {
|
|
3490
|
+
if (enabled)
|
|
3491
|
+
// Cleanup
|
|
3492
|
+
// Initial calculation
|
|
3493
|
+
return calculateParams(),
|
|
3494
|
+
// Listen for resize events
|
|
3495
|
+
window.addEventListener("resize", debouncedCalculate), () => {
|
|
3496
|
+
window.removeEventListener("resize", debouncedCalculate);
|
|
3497
|
+
};
|
|
3498
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3499
|
+
}), [ enabled ]), {
|
|
3500
|
+
responsiveParams: responsiveParams,
|
|
3501
|
+
currentBreakpoint: currentBreakpoint,
|
|
3502
|
+
performanceTier: performanceTier,
|
|
3503
|
+
isActive: isActive,
|
|
3504
|
+
recalculate: useCallback((() => {
|
|
3505
|
+
calculateParams();
|
|
3506
|
+
}), [ calculateParams ])
|
|
3507
|
+
};
|
|
3508
|
+
}
|
|
3509
|
+
|
|
3510
|
+
/**
|
|
3511
|
+
* Utility function to get default breakpoints
|
|
3512
|
+
* Useful for documentation and debugging
|
|
3513
|
+
*/ function getDefaultBreakpoints() {
|
|
3514
|
+
return {
|
|
3515
|
+
...DEFAULT_BREAKPOINTS
|
|
3516
|
+
};
|
|
3517
|
+
}
|
|
3518
|
+
|
|
3519
|
+
/**
|
|
3520
|
+
* Utility function to create custom breakpoints
|
|
3521
|
+
*
|
|
3522
|
+
* @param customBreakpoints Partial breakpoint overrides
|
|
3523
|
+
* @returns Complete breakpoint configuration
|
|
3524
|
+
*/ function createBreakpoints$1(customBreakpoints) {
|
|
3525
|
+
return {
|
|
3526
|
+
...DEFAULT_BREAKPOINTS,
|
|
3527
|
+
...customBreakpoints
|
|
3528
|
+
};
|
|
3529
|
+
}
|
|
3530
|
+
|
|
3531
|
+
/**
|
|
3532
|
+
* Get GPU memory info if available (Chrome DevTools only)
|
|
3533
|
+
*/
|
|
3534
|
+
/**
|
|
3535
|
+
* Performance Monitor Hook
|
|
3536
|
+
*
|
|
3537
|
+
* Real-time performance tracking with automatic quality scaling.
|
|
3538
|
+
* Monitors FPS, frame time, and GPU memory to optimize glass effects.
|
|
3539
|
+
*
|
|
3540
|
+
* Features:
|
|
3541
|
+
* - Real-time FPS measurement
|
|
3542
|
+
* - Frame timing analysis
|
|
3543
|
+
* - Automatic quality scaling
|
|
3544
|
+
* - Debug overlay option
|
|
3545
|
+
* - Manual override capability
|
|
3546
|
+
*
|
|
3547
|
+
* @example
|
|
3548
|
+
* ```typescript
|
|
3549
|
+
* const { metrics, recommendedQuality, setQualityLevel } = usePerformanceMonitor({
|
|
3550
|
+
* targetFps: 60,
|
|
3551
|
+
* minFps: 45,
|
|
3552
|
+
* debug: true,
|
|
3553
|
+
* });
|
|
3554
|
+
* ```
|
|
3555
|
+
*
|
|
3556
|
+
* @param config Monitor configuration
|
|
3557
|
+
* @returns Performance metrics and controls
|
|
3558
|
+
*/
|
|
3559
|
+
function usePerformanceMonitor(config = {}) {
|
|
3560
|
+
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] = useState({
|
|
3561
|
+
fps: 0,
|
|
3562
|
+
frameTime: 0,
|
|
3563
|
+
gpuMemory: null,
|
|
3564
|
+
qualityLevel: "medium",
|
|
3565
|
+
timestamp: 0,
|
|
3566
|
+
isAutoScaling: !0,
|
|
3567
|
+
lowFpsCount: 0
|
|
3568
|
+
}), [manualOverride, setManualOverride] = useState(!1), [isEnabled, setIsEnabled] = useState(enabled), frameCountRef = useRef(0), lastFpsUpdateRef = useRef(0), lastFrameTimeRef = useRef(0), animationFrameRef = useRef(null), lowFpsCountRef = useRef(0), highFpsCountRef = useRef(0), qualityLevelRef = useRef("medium"), updateMetrics = useCallback((newMetrics => {
|
|
3569
|
+
setMetrics((prev => ({
|
|
3570
|
+
...prev,
|
|
3571
|
+
...newMetrics,
|
|
3572
|
+
timestamp: performance.now()
|
|
3573
|
+
})));
|
|
3574
|
+
}), []), applyAutoScaling = useCallback((currentFps => {
|
|
3575
|
+
if (manualOverride) return;
|
|
3576
|
+
const currentQuality = qualityLevelRef.current;
|
|
3577
|
+
// Check for low FPS
|
|
3578
|
+
if (currentFps < minFps) lowFpsCountRef.current++, highFpsCountRef.current = 0,
|
|
3579
|
+
// Scale down after N consecutive low-FPS frames
|
|
3580
|
+
lowFpsCountRef.current >= lowFpsFrames && "low" !== currentQuality && (qualityLevelRef.current = "low",
|
|
3581
|
+
updateMetrics({
|
|
3582
|
+
qualityLevel: "low",
|
|
3583
|
+
lowFpsCount: lowFpsCountRef.current
|
|
3584
|
+
})); else if (currentFps >= scaleUpThreshold) {
|
|
3585
|
+
// Scale up after N consecutive high-FPS frames
|
|
3586
|
+
if (highFpsCountRef.current++, lowFpsCountRef.current = 0, highFpsCountRef.current >= highFpsFrames) {
|
|
3587
|
+
const newQuality = "low" === currentQuality ? "medium" : "high";
|
|
3588
|
+
qualityLevelRef.current = newQuality, updateMetrics({
|
|
3589
|
+
qualityLevel: newQuality,
|
|
3590
|
+
lowFpsCount: 0
|
|
3591
|
+
}), highFpsCountRef.current = 0;
|
|
3592
|
+
}
|
|
3593
|
+
} else
|
|
3594
|
+
// FPS in normal range, reset counters
|
|
3595
|
+
lowFpsCountRef.current = 0, highFpsCountRef.current = 0;
|
|
3596
|
+
}), [ manualOverride, minFps, scaleUpThreshold, lowFpsFrames, highFpsFrames, debug, updateMetrics ]), measureFrame = useCallback((currentTime => {
|
|
3597
|
+
if (!isEnabled) return;
|
|
3598
|
+
frameCountRef.current++;
|
|
3599
|
+
// Calculate frame time
|
|
3600
|
+
const frameTime = currentTime - lastFrameTimeRef.current;
|
|
3601
|
+
// Update FPS every 100ms for responsiveness
|
|
3602
|
+
if (lastFrameTimeRef.current = currentTime, currentTime - lastFpsUpdateRef.current >= 100) {
|
|
3603
|
+
const elapsed = currentTime - lastFpsUpdateRef.current, fps = Math.round(1e3 * frameCountRef.current / elapsed);
|
|
3604
|
+
// Apply auto-scaling
|
|
3605
|
+
applyAutoScaling(fps), updateMetrics({
|
|
3606
|
+
fps: fps,
|
|
3607
|
+
frameTime: frameTime,
|
|
3608
|
+
qualityLevel: qualityLevelRef.current,
|
|
3609
|
+
lowFpsCount: lowFpsCountRef.current
|
|
3610
|
+
}),
|
|
3611
|
+
// Reset for next measurement period
|
|
3612
|
+
frameCountRef.current = 0, lastFpsUpdateRef.current = currentTime;
|
|
3613
|
+
}
|
|
3614
|
+
// Continue measurement loop
|
|
3615
|
+
animationFrameRef.current = requestAnimationFrame(measureFrame);
|
|
3616
|
+
}), [ isEnabled, applyAutoScaling, updateMetrics ]);
|
|
3617
|
+
/**
|
|
3618
|
+
* Initialize GPU memory tracking
|
|
3619
|
+
*/
|
|
3620
|
+
useEffect((() => {
|
|
3621
|
+
if (!isEnabled || "undefined" == typeof window) return;
|
|
3622
|
+
let mounted = !0;
|
|
3623
|
+
return (async () => {
|
|
3624
|
+
const memory = await new Promise((resolve => {
|
|
3625
|
+
// Check for WebGL debug renderer info
|
|
3626
|
+
if ("undefined" != typeof window && "undefined" != typeof document) try {
|
|
3627
|
+
const canvas = document.createElement("canvas"), gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
|
|
3628
|
+
if (gl) {
|
|
3629
|
+
const debugInfo = gl.getExtension("WEBGL_debug_renderer_info");
|
|
3630
|
+
if (debugInfo) {
|
|
3631
|
+
var _context, _context2, _context3;
|
|
3632
|
+
// Note: Actual memory info is not directly available via WebGL
|
|
3633
|
+
// We estimate based on renderer
|
|
3634
|
+
const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
|
|
3635
|
+
// Rough estimation based on renderer type
|
|
3636
|
+
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));
|
|
3637
|
+
}
|
|
3638
|
+
}
|
|
3639
|
+
} catch (e) {
|
|
3640
|
+
// WebGL not available or error occurred
|
|
3641
|
+
}
|
|
3642
|
+
resolve(null);
|
|
3643
|
+
}));
|
|
3644
|
+
mounted && updateMetrics({
|
|
3645
|
+
gpuMemory: memory
|
|
3646
|
+
});
|
|
3647
|
+
})(), () => {
|
|
3648
|
+
mounted = !1;
|
|
3649
|
+
};
|
|
3650
|
+
}), [ isEnabled, updateMetrics ]),
|
|
3651
|
+
/**
|
|
3652
|
+
* Start/stop monitoring based on enabled state
|
|
3653
|
+
*/
|
|
3654
|
+
useEffect((() => {
|
|
3655
|
+
if (isEnabled)
|
|
3656
|
+
// Cleanup
|
|
3657
|
+
// Initialize
|
|
3658
|
+
return lastFpsUpdateRef.current = performance.now(), lastFrameTimeRef.current = performance.now(),
|
|
3659
|
+
animationFrameRef.current = requestAnimationFrame(measureFrame), () => {
|
|
3660
|
+
null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
|
|
3661
|
+
animationFrameRef.current = null);
|
|
3662
|
+
};
|
|
3663
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3664
|
+
null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
|
|
3665
|
+
animationFrameRef.current = null);
|
|
3666
|
+
}), [ isEnabled ]);
|
|
3667
|
+
// measureFrame is stable via useCallback, avoid re-creating RAF loop
|
|
3668
|
+
/**
|
|
3669
|
+
* Manually set quality level (disables auto-scaling)
|
|
3670
|
+
*/
|
|
3671
|
+
const setQualityLevel = useCallback((level => {
|
|
3672
|
+
setManualOverride(!0), qualityLevelRef.current = level, updateMetrics({
|
|
3673
|
+
qualityLevel: level,
|
|
3674
|
+
isAutoScaling: !1
|
|
3675
|
+
});
|
|
3676
|
+
}), [ updateMetrics, debug ]), resetAutoScaling = useCallback((() => {
|
|
3677
|
+
setManualOverride(!1), lowFpsCountRef.current = 0, highFpsCountRef.current = 0,
|
|
3678
|
+
updateMetrics({
|
|
3679
|
+
isAutoScaling: !0,
|
|
3680
|
+
lowFpsCount: 0
|
|
3681
|
+
});
|
|
3682
|
+
}), [ updateMetrics, debug ]), toggleMonitoring = useCallback((() => {
|
|
3683
|
+
setIsEnabled((prev => !prev));
|
|
3684
|
+
}), []);
|
|
3685
|
+
/**
|
|
3686
|
+
* Reset to auto-scaling mode
|
|
3687
|
+
*/ var fps, currentQuality;
|
|
3688
|
+
return {
|
|
3689
|
+
metrics: metrics,
|
|
3690
|
+
recommendedQuality: (fps = metrics.fps, currentQuality = metrics.qualityLevel, fps >= 58 ? "high" : fps >= 45 ? "high" === currentQuality ? "high" : "medium" : "low"),
|
|
3691
|
+
isUnderperforming: metrics.fps < minFps,
|
|
3692
|
+
setQualityLevel: setQualityLevel,
|
|
3693
|
+
resetAutoScaling: resetAutoScaling,
|
|
3694
|
+
toggleMonitoring: toggleMonitoring
|
|
3695
|
+
};
|
|
3696
|
+
}
|
|
3697
|
+
|
|
3698
|
+
/**
|
|
3699
|
+
* Debug Overlay Component (Optional)
|
|
3700
|
+
*
|
|
3701
|
+
* Shows real-time performance metrics on screen.
|
|
3702
|
+
* Only rendered when showOverlay is enabled.
|
|
3703
|
+
*/ function PerformanceOverlay({metrics: metrics}) {
|
|
3704
|
+
return null;
|
|
3705
|
+
// Performance overlay removed - will be implemented as separate component
|
|
3706
|
+
}
|
|
3707
|
+
|
|
3708
|
+
/**
|
|
3709
|
+
* Utility to get quality multipliers for glass parameters
|
|
3710
|
+
*/ function getQualityMultipliers(quality) {
|
|
3711
|
+
switch (quality) {
|
|
3712
|
+
case "low":
|
|
3713
|
+
return {
|
|
3714
|
+
distortionOctaves: 2,
|
|
3715
|
+
displacementScale: .6,
|
|
3716
|
+
blurAmount: .7,
|
|
3717
|
+
animationSpeed: .8,
|
|
3718
|
+
chromaticIntensity: .5
|
|
3719
|
+
};
|
|
3720
|
+
|
|
3721
|
+
case "medium":
|
|
3722
|
+
return {
|
|
3723
|
+
distortionOctaves: 4,
|
|
3724
|
+
displacementScale: .85,
|
|
3725
|
+
blurAmount: .9,
|
|
3726
|
+
animationSpeed: .95,
|
|
3727
|
+
chromaticIntensity: .75
|
|
3728
|
+
};
|
|
3729
|
+
|
|
3730
|
+
case "high":
|
|
3731
|
+
return {
|
|
3732
|
+
distortionOctaves: 5,
|
|
3733
|
+
displacementScale: 1,
|
|
3734
|
+
blurAmount: 1,
|
|
3735
|
+
animationSpeed: 1,
|
|
3736
|
+
chromaticIntensity: 1
|
|
3737
|
+
};
|
|
3738
|
+
}
|
|
3739
|
+
}
|
|
3740
|
+
|
|
3741
|
+
/**
|
|
3742
|
+
* PerformanceDashboard - Real-time performance monitoring overlay
|
|
3743
|
+
*
|
|
3744
|
+
* Displays:
|
|
3745
|
+
* - Current FPS with color coding
|
|
3746
|
+
* - Frame time statistics
|
|
3747
|
+
* - Quality level indicator
|
|
3748
|
+
* - GPU memory usage (if available)
|
|
3749
|
+
* - Auto-scaling status
|
|
3750
|
+
*/ const PerformanceDashboard = ({metrics: metrics, isVisible: isVisible = !0, onClose: onClose}) => {
|
|
3751
|
+
// Get color for FPS display
|
|
3752
|
+
const getFpsColor = fps => fps >= 58 ? "#4ade80" : // Green - good
|
|
3753
|
+
fps >= 45 ? "#fbbf24" : "#ef4444" // Red - critical
|
|
3754
|
+
, dashboardStyle = useMemo((() => ({
|
|
3755
|
+
position: "fixed",
|
|
3756
|
+
top: "16px",
|
|
3757
|
+
right: "16px",
|
|
3758
|
+
padding: "12px 16px",
|
|
3759
|
+
backgroundColor: "rgba(17, 24, 39, 0.95)",
|
|
3760
|
+
borderRadius: "8px",
|
|
3761
|
+
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
|
|
3762
|
+
fontFamily: "monospace",
|
|
3763
|
+
fontSize: "12px",
|
|
3764
|
+
color: "#fff",
|
|
3765
|
+
zIndex: 9999,
|
|
3766
|
+
minWidth: "200px",
|
|
3767
|
+
backdropFilter: "blur(8px)",
|
|
3768
|
+
border: "1px solid rgba(255, 255, 255, 0.1)",
|
|
3769
|
+
transition: "opacity 0.3s ease",
|
|
3770
|
+
opacity: isVisible ? 1 : 0,
|
|
3771
|
+
pointerEvents: isVisible ? "auto" : "none"
|
|
3772
|
+
})), [ isVisible ]), headerStyle = useMemo((() => ({
|
|
3773
|
+
display: "flex",
|
|
3774
|
+
justifyContent: "space-between",
|
|
3775
|
+
alignItems: "center",
|
|
3776
|
+
marginBottom: "8px",
|
|
3777
|
+
paddingBottom: "8px",
|
|
3778
|
+
borderBottom: "1px solid rgba(255, 255, 255, 0.1)"
|
|
3779
|
+
})), []), titleStyle = useMemo((() => ({
|
|
3780
|
+
fontWeight: "bold",
|
|
3781
|
+
fontSize: "13px",
|
|
3782
|
+
color: "#fff"
|
|
3783
|
+
})), []), closeButtonStyle = useMemo((() => ({
|
|
3784
|
+
background: "transparent",
|
|
3785
|
+
border: "none",
|
|
3786
|
+
color: "#9ca3af",
|
|
3787
|
+
cursor: "pointer",
|
|
3788
|
+
fontSize: "16px",
|
|
3789
|
+
padding: "0",
|
|
3790
|
+
lineHeight: "1"
|
|
3791
|
+
})), []), metricRowStyle = useMemo((() => ({
|
|
3792
|
+
display: "flex",
|
|
3793
|
+
justifyContent: "space-between",
|
|
3794
|
+
alignItems: "center",
|
|
3795
|
+
marginBottom: "6px"
|
|
3796
|
+
})), []), labelStyle = useMemo((() => ({
|
|
3797
|
+
color: "#9ca3af",
|
|
3798
|
+
marginRight: "12px"
|
|
3799
|
+
})), []), valueStyle = useMemo((() => ({
|
|
3800
|
+
fontWeight: "bold"
|
|
3801
|
+
})), []);
|
|
3802
|
+
// Get quality level badge color
|
|
3803
|
+
return isVisible ? jsxs("div", {
|
|
3804
|
+
style: dashboardStyle,
|
|
3805
|
+
children: [ jsxs("div", {
|
|
3806
|
+
style: headerStyle,
|
|
3807
|
+
children: [ jsx("span", {
|
|
3808
|
+
style: titleStyle,
|
|
3809
|
+
children: "Performance Monitor"
|
|
3810
|
+
}), onClose && jsx("button", {
|
|
3811
|
+
style: closeButtonStyle,
|
|
3812
|
+
onClick: onClose,
|
|
3813
|
+
"aria-label": "Close performance dashboard",
|
|
3814
|
+
children: "×"
|
|
3815
|
+
}) ]
|
|
3816
|
+
}), jsxs("div", {
|
|
3817
|
+
style: metricRowStyle,
|
|
3818
|
+
children: [ jsx("span", {
|
|
3819
|
+
style: labelStyle,
|
|
3820
|
+
children: "FPS"
|
|
3821
|
+
}), jsx("span", {
|
|
3822
|
+
style: {
|
|
3823
|
+
...valueStyle,
|
|
3824
|
+
color: getFpsColor(metrics.fps)
|
|
3825
|
+
},
|
|
3826
|
+
children: Math.round(metrics.fps)
|
|
3827
|
+
}) ]
|
|
3828
|
+
}), jsxs("div", {
|
|
3829
|
+
style: metricRowStyle,
|
|
3830
|
+
children: [ jsx("span", {
|
|
3831
|
+
style: labelStyle,
|
|
3832
|
+
children: "Frame Time"
|
|
3833
|
+
}), jsxs("span", {
|
|
3834
|
+
style: valueStyle,
|
|
3835
|
+
children: [ metrics.frameTime.toFixed(2), "ms" ]
|
|
3836
|
+
}) ]
|
|
3837
|
+
}), jsxs("div", {
|
|
3838
|
+
style: metricRowStyle,
|
|
3839
|
+
children: [ jsx("span", {
|
|
3840
|
+
style: labelStyle,
|
|
3841
|
+
children: "Quality"
|
|
3842
|
+
}), jsx("span", {
|
|
3843
|
+
style: {
|
|
3844
|
+
...valueStyle,
|
|
3845
|
+
color: (quality => {
|
|
3846
|
+
switch (quality) {
|
|
3847
|
+
case "high":
|
|
3848
|
+
return "#4ade80";
|
|
3849
|
+
|
|
3850
|
+
case "medium":
|
|
3851
|
+
return "#fbbf24";
|
|
3852
|
+
|
|
3853
|
+
case "low":
|
|
3854
|
+
return "#ef4444";
|
|
3855
|
+
|
|
3856
|
+
default:
|
|
3857
|
+
return "#9ca3af";
|
|
3858
|
+
}
|
|
3859
|
+
})(metrics.qualityLevel),
|
|
3860
|
+
textTransform: "uppercase",
|
|
3861
|
+
fontSize: "11px"
|
|
3862
|
+
},
|
|
3863
|
+
children: metrics.qualityLevel
|
|
3864
|
+
}) ]
|
|
3865
|
+
}), metrics.gpuMemory && jsxs("div", {
|
|
3866
|
+
style: metricRowStyle,
|
|
3867
|
+
children: [ jsx("span", {
|
|
3868
|
+
style: labelStyle,
|
|
3869
|
+
children: "GPU Memory"
|
|
3870
|
+
}), jsxs("span", {
|
|
3871
|
+
style: valueStyle,
|
|
3872
|
+
children: [ "~", Math.round(metrics.gpuMemory / 1024), "MB" ]
|
|
3873
|
+
}) ]
|
|
3874
|
+
}), metrics.isAutoScaling && jsx("div", {
|
|
3875
|
+
style: {
|
|
3876
|
+
marginTop: "8px",
|
|
3877
|
+
paddingTop: "8px",
|
|
3878
|
+
borderTop: "1px solid rgba(255, 255, 255, 0.1)",
|
|
3879
|
+
fontSize: "10px",
|
|
3880
|
+
color: "#6b7280",
|
|
3881
|
+
textAlign: "center"
|
|
3882
|
+
},
|
|
3883
|
+
children: "Auto-scaling active"
|
|
3884
|
+
}), jsxs("div", {
|
|
3885
|
+
style: {
|
|
3886
|
+
marginTop: "8px",
|
|
3887
|
+
paddingTop: "8px",
|
|
3888
|
+
borderTop: "1px solid rgba(255, 255, 255, 0.1)",
|
|
3889
|
+
display: "flex",
|
|
3890
|
+
alignItems: "center",
|
|
3891
|
+
gap: "6px"
|
|
3892
|
+
},
|
|
3893
|
+
children: [ jsx("div", {
|
|
3894
|
+
style: {
|
|
3895
|
+
width: "8px",
|
|
3896
|
+
height: "8px",
|
|
3897
|
+
borderRadius: "50%",
|
|
3898
|
+
backgroundColor: getFpsColor(metrics.fps),
|
|
3899
|
+
animation: metrics.fps < 45 ? "pulse 1s infinite" : "none"
|
|
3900
|
+
}
|
|
3901
|
+
}), jsx("span", {
|
|
3902
|
+
style: {
|
|
3903
|
+
fontSize: "10px",
|
|
3904
|
+
color: metrics.fps >= 58 ? "#4ade80" : metrics.fps >= 45 ? "#fbbf24" : "#ef4444"
|
|
3905
|
+
},
|
|
3906
|
+
children: metrics.fps >= 58 ? "Optimal" : metrics.fps >= 45 ? "Warning" : "Critical"
|
|
3907
|
+
}) ]
|
|
3908
|
+
}) ]
|
|
3909
|
+
}) : null;
|
|
3910
|
+
};
|
|
3911
|
+
|
|
3912
|
+
// Add pulse animation for critical FPS
|
|
3913
|
+
if ("undefined" != typeof document) {
|
|
3914
|
+
const styleSheet = document.createElement("style");
|
|
3915
|
+
styleSheet.textContent = "\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n ",
|
|
3916
|
+
document.head.appendChild(styleSheet);
|
|
3917
|
+
}
|
|
3918
|
+
|
|
3919
|
+
/**
|
|
3920
|
+
* Mobile optimization presets
|
|
3921
|
+
*
|
|
3922
|
+
* These presets adjust glass effect parameters based on device performance tier
|
|
3923
|
+
* to ensure smooth animations and responsive interactions.
|
|
3924
|
+
*/
|
|
3925
|
+
/**
|
|
3926
|
+
* Performance preset - Maximum FPS, reduced quality
|
|
3927
|
+
* Best for low-end devices or when battery saving is priority
|
|
3928
|
+
*/ const PERFORMANCE_PRESET = {
|
|
3929
|
+
distortionOctaves: 2,
|
|
3930
|
+
// Minimal FBM layers
|
|
3931
|
+
displacementScale: 50,
|
|
3932
|
+
// Subtle displacement
|
|
3933
|
+
blurAmount: 5,
|
|
3934
|
+
// Light blur
|
|
3935
|
+
saturation: 80,
|
|
3936
|
+
// Reduced saturation
|
|
3937
|
+
aberrationIntensity: .3,
|
|
3938
|
+
// Minimal chromatic aberration
|
|
3939
|
+
animationSpeed: .8,
|
|
3940
|
+
// Slightly slower for performance
|
|
3941
|
+
chromaticIntensity: .3,
|
|
3942
|
+
// Low chromatic effect
|
|
3943
|
+
distortionLacunarity: 1.5,
|
|
3944
|
+
// Simpler noise pattern
|
|
3945
|
+
distortionGain: .3
|
|
3946
|
+
}, BALANCED_PRESET = {
|
|
3947
|
+
distortionOctaves: 3,
|
|
3948
|
+
// Moderate FBM layers
|
|
3949
|
+
displacementScale: 75,
|
|
3950
|
+
// Medium displacement
|
|
3951
|
+
blurAmount: 8,
|
|
3952
|
+
// Moderate blur
|
|
3953
|
+
saturation: 90,
|
|
3954
|
+
// Near-full saturation
|
|
3955
|
+
aberrationIntensity: .5,
|
|
3956
|
+
// Moderate chromatic aberration
|
|
3957
|
+
animationSpeed: 1,
|
|
3958
|
+
// Normal speed
|
|
3959
|
+
chromaticIntensity: .5,
|
|
3960
|
+
// Moderate chromatic effect
|
|
3961
|
+
distortionLacunarity: 2,
|
|
3962
|
+
// Standard noise pattern
|
|
3963
|
+
distortionGain: .4
|
|
3964
|
+
}, QUALITY_PRESET = {
|
|
3965
|
+
distortionOctaves: 4,
|
|
3966
|
+
// More FBM layers for detail
|
|
3967
|
+
displacementScale: 100,
|
|
3968
|
+
// Stronger displacement
|
|
3969
|
+
blurAmount: 12,
|
|
3970
|
+
// Smoother blur
|
|
3971
|
+
saturation: 100,
|
|
3972
|
+
// Full saturation
|
|
3973
|
+
aberrationIntensity: .7,
|
|
3974
|
+
// Pronounced chromatic aberration
|
|
3975
|
+
animationSpeed: 1.2,
|
|
3976
|
+
// Slightly faster for drama
|
|
3977
|
+
chromaticIntensity: .7,
|
|
3978
|
+
// Strong chromatic effect
|
|
3979
|
+
distortionLacunarity: 2.2,
|
|
3980
|
+
// Richer noise pattern
|
|
3981
|
+
distortionGain: .5
|
|
3982
|
+
};
|
|
3983
|
+
|
|
3984
|
+
/**
|
|
3985
|
+
* Balanced preset - Good quality with reasonable performance
|
|
3986
|
+
* Default preset for most mobile devices
|
|
3987
|
+
*/
|
|
3988
|
+
/**
|
|
3989
|
+
* Get preset by name
|
|
3990
|
+
*/
|
|
3991
|
+
function getDevicePreset(presetName) {
|
|
3992
|
+
switch (presetName) {
|
|
3993
|
+
case "performance":
|
|
3994
|
+
return PERFORMANCE_PRESET;
|
|
3995
|
+
|
|
3996
|
+
case "balanced":
|
|
3997
|
+
default:
|
|
3998
|
+
return BALANCED_PRESET;
|
|
3999
|
+
|
|
4000
|
+
case "quality":
|
|
4001
|
+
return QUALITY_PRESET;
|
|
4002
|
+
}
|
|
4003
|
+
}
|
|
4004
|
+
|
|
4005
|
+
/**
|
|
4006
|
+
* Mobile-optimized responsive breakpoints
|
|
4007
|
+
* Automatically applies appropriate presets based on viewport size
|
|
4008
|
+
*/ const MOBILE_OPTIMIZED_BREAKPOINTS = {
|
|
4009
|
+
/** Desktop - Full quality */
|
|
4010
|
+
desktop: {
|
|
4011
|
+
minWidth: 1024,
|
|
4012
|
+
params: {
|
|
4013
|
+
distortionOctaves: 6,
|
|
4014
|
+
displacementScale: 150,
|
|
4015
|
+
blurAmount: 15,
|
|
4016
|
+
saturation: 100,
|
|
4017
|
+
aberrationIntensity: 1,
|
|
4018
|
+
animationSpeed: 1,
|
|
4019
|
+
chromaticIntensity: 1,
|
|
4020
|
+
distortionLacunarity: 2.5,
|
|
4021
|
+
distortionGain: .6
|
|
4022
|
+
}
|
|
4023
|
+
},
|
|
4024
|
+
/** Laptop - High quality */
|
|
4025
|
+
laptop: {
|
|
4026
|
+
minWidth: 768,
|
|
4027
|
+
params: {
|
|
4028
|
+
...QUALITY_PRESET,
|
|
4029
|
+
distortionOctaves: 5,
|
|
4030
|
+
displacementScale: 120
|
|
4031
|
+
}
|
|
4032
|
+
},
|
|
4033
|
+
/** Tablet - Balanced quality */
|
|
4034
|
+
tablet: {
|
|
4035
|
+
minWidth: 640,
|
|
4036
|
+
params: {
|
|
4037
|
+
...BALANCED_PRESET,
|
|
4038
|
+
distortionOctaves: 4,
|
|
4039
|
+
displacementScale: 90
|
|
4040
|
+
}
|
|
4041
|
+
},
|
|
4042
|
+
/** Mobile - Performance optimized */
|
|
4043
|
+
mobile: {
|
|
4044
|
+
maxWidth: 639,
|
|
4045
|
+
params: {
|
|
4046
|
+
...PERFORMANCE_PRESET,
|
|
4047
|
+
distortionOctaves: 3,
|
|
4048
|
+
displacementScale: 75,
|
|
4049
|
+
blurAmount: 6
|
|
4050
|
+
}
|
|
4051
|
+
},
|
|
4052
|
+
/** Small mobile - Maximum performance */
|
|
4053
|
+
mobileSmall: {
|
|
4054
|
+
maxWidth: 375,
|
|
4055
|
+
params: {
|
|
4056
|
+
...PERFORMANCE_PRESET,
|
|
4057
|
+
distortionOctaves: 2,
|
|
4058
|
+
displacementScale: 50,
|
|
4059
|
+
blurAmount: 4,
|
|
4060
|
+
saturation: 70
|
|
4061
|
+
}
|
|
4062
|
+
}
|
|
4063
|
+
};
|
|
4064
|
+
|
|
4065
|
+
/**
|
|
4066
|
+
* Get mobile-optimized parameters for current viewport
|
|
4067
|
+
* Can be used standalone or with useResponsiveGlass hook
|
|
4068
|
+
*/ function getMobileOptimizedParams(viewportWidth) {
|
|
4069
|
+
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;
|
|
4070
|
+
}
|
|
4071
|
+
|
|
4072
|
+
/**
|
|
4073
|
+
* Device detection utilities
|
|
4074
|
+
*/ const DeviceDetector = {
|
|
4075
|
+
/** Check if device is mobile */
|
|
4076
|
+
isMobile: () => "undefined" != typeof window && /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
|
|
4077
|
+
/** Check if device is tablet */
|
|
4078
|
+
isTablet() {
|
|
4079
|
+
if ("undefined" == typeof window) return !1;
|
|
4080
|
+
const width = window.innerWidth;
|
|
4081
|
+
return width >= 640 && width < 1024 && this.isMobile();
|
|
4082
|
+
},
|
|
4083
|
+
/** Get recommended preset based on device type */
|
|
4084
|
+
getRecommendedPreset() {
|
|
4085
|
+
return this.isMobile() ? this.isTablet() ? "balanced" : "performance" : "quality";
|
|
4086
|
+
},
|
|
4087
|
+
/** Get device pixel ratio */
|
|
4088
|
+
getPixelRatio: () => "undefined" == typeof window ? 1 : window.devicePixelRatio || 1,
|
|
4089
|
+
/** Check if device has touch support */
|
|
4090
|
+
hasTouchSupport: () => "undefined" != typeof window && ("ontouchstart" in window || navigator.maxTouchPoints > 0)
|
|
4091
|
+
};
|
|
4092
|
+
|
|
3042
4093
|
/**
|
|
3043
4094
|
* AtomixGlass - A high-performance glass morphism component with liquid distortion effects
|
|
3044
4095
|
*
|
|
@@ -3053,6 +4104,8 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3053
4104
|
* - Focus ring support for keyboard navigation
|
|
3054
4105
|
* - Responsive breakpoints for mobile optimization
|
|
3055
4106
|
* - Enhanced ARIA attributes for screen readers
|
|
4107
|
+
* - Time-based animation system with FBM distortion
|
|
4108
|
+
* - Device preset optimization for performance/quality balance
|
|
3056
4109
|
*
|
|
3057
4110
|
* Design System Compliance:
|
|
3058
4111
|
* - Uses design tokens for opacity, spacing, and colors
|
|
@@ -3109,8 +4162,14 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3109
4162
|
* <AtomixGlass overLight="auto" debugOverLight={true}>
|
|
3110
4163
|
* <div>Content with debug logging enabled</div>
|
|
3111
4164
|
* </AtomixGlass>
|
|
3112
|
-
|
|
3113
|
-
|
|
4165
|
+
*
|
|
4166
|
+
* @example
|
|
4167
|
+
* // Performance-optimized for mobile devices
|
|
4168
|
+
* <AtomixGlass devicePreset="performance" disableResponsiveBreakpoints={false}>
|
|
4169
|
+
* <div>Mobile-optimized glass effect</div>
|
|
4170
|
+
* </AtomixGlass>
|
|
4171
|
+
*/ 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}) {
|
|
4172
|
+
const glassRef = useRef(null), contentRef = 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({
|
|
3114
4173
|
glassRef: glassRef,
|
|
3115
4174
|
contentRef: contentRef,
|
|
3116
4175
|
borderRadius: borderRadius,
|
|
@@ -3123,7 +4182,6 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3123
4182
|
withoutEffects: withoutEffects,
|
|
3124
4183
|
elasticity: elasticity,
|
|
3125
4184
|
onClick: onClick,
|
|
3126
|
-
debugBorderRadius: debugBorderRadius,
|
|
3127
4185
|
debugOverLight: debugOverLight,
|
|
3128
4186
|
debugPerformance: debugPerformance,
|
|
3129
4187
|
children: children,
|
|
@@ -3131,8 +4189,49 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3131
4189
|
saturation: saturation,
|
|
3132
4190
|
withLiquidBlur: withLiquidBlur,
|
|
3133
4191
|
padding: padding,
|
|
3134
|
-
style: style
|
|
3135
|
-
|
|
4192
|
+
style: style,
|
|
4193
|
+
isFixedOrSticky: isFixedOrSticky,
|
|
4194
|
+
// Phase 1: Animation System props
|
|
4195
|
+
withTimeAnimation: withTimeAnimation,
|
|
4196
|
+
animationSpeed: animationSpeed,
|
|
4197
|
+
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
4198
|
+
distortionOctaves: distortionOctaves,
|
|
4199
|
+
distortionLacunarity: distortionLacunarity,
|
|
4200
|
+
distortionGain: distortionGain,
|
|
4201
|
+
distortionQuality: distortionQuality
|
|
4202
|
+
});
|
|
4203
|
+
// Re-calculate only when devicePreset changes
|
|
4204
|
+
// Responsive breakpoint system - automatically adjusts parameters based on viewport
|
|
4205
|
+
useResponsiveGlass({
|
|
4206
|
+
baseParams: {
|
|
4207
|
+
...useMemo((() => getDevicePreset(devicePreset)), [ devicePreset ]),
|
|
4208
|
+
distortionOctaves: Math.round((displacementScale || ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE) / 25),
|
|
4209
|
+
displacementScale: displacementScale || ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE,
|
|
4210
|
+
blurAmount: blurAmount || ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT,
|
|
4211
|
+
saturation: saturation || ATOMIX_GLASS.DEFAULTS.SATURATION,
|
|
4212
|
+
aberrationIntensity: aberrationIntensity || ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY,
|
|
4213
|
+
animationSpeed: 1,
|
|
4214
|
+
chromaticIntensity: aberrationIntensity || ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY
|
|
4215
|
+
},
|
|
4216
|
+
breakpoints: MOBILE_OPTIMIZED_BREAKPOINTS,
|
|
4217
|
+
enabled: !disableResponsiveBreakpoints && "undefined" != typeof window,
|
|
4218
|
+
// Enable unless disabled
|
|
4219
|
+
debug: !1
|
|
4220
|
+
});
|
|
4221
|
+
// Performance monitoring - tracks FPS, frame time, memory usage
|
|
4222
|
+
const {metrics: performanceMetrics, recommendedQuality: recommendedQuality, isUnderperforming: isUnderperforming, setQualityLevel: setQualityLevel, toggleMonitoring: toggleMonitoring} = usePerformanceMonitor({
|
|
4223
|
+
enabled: !1,
|
|
4224
|
+
// We'll toggle manually based on prop
|
|
4225
|
+
debug: !1,
|
|
4226
|
+
showOverlay: !1
|
|
4227
|
+
});
|
|
4228
|
+
// Auto-start performance monitoring if enabled (only in development)
|
|
4229
|
+
React.useEffect((() => {
|
|
4230
|
+
"development" === process.env.NODE_ENV && window?.enablePerformanceMonitoring && toggleMonitoring();
|
|
4231
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
4232
|
+
}), []);
|
|
4233
|
+
// Only run once on mount
|
|
4234
|
+
const isOverLight = useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, rootLayoutStyle = useMemo((() => {
|
|
3136
4235
|
if (!isFixedOrSticky) return {};
|
|
3137
4236
|
const {position: p, top: t, left: l, right: r, bottom: b} = restStyle;
|
|
3138
4237
|
return {
|
|
@@ -3152,7 +4251,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3152
4251
|
bottom: b
|
|
3153
4252
|
}
|
|
3154
4253
|
};
|
|
3155
|
-
}), [ isFixedOrSticky, restStyle ])
|
|
4254
|
+
}), [ isFixedOrSticky, restStyle ]);
|
|
4255
|
+
// Calculate base style with transforms
|
|
4256
|
+
// When layout is hoisted to the root, strip those props from the container
|
|
4257
|
+
useMemo((() => {
|
|
3156
4258
|
if (isFixedOrSticky) {
|
|
3157
4259
|
const {position: _p, top: _t, left: _l, right: _r, bottom: _b, ...visualStyle} = restStyle;
|
|
3158
4260
|
return {
|
|
@@ -3168,18 +4270,20 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3168
4270
|
transform: transformStyle
|
|
3169
4271
|
}
|
|
3170
4272
|
};
|
|
3171
|
-
}), [ isFixedOrSticky, restStyle, effectiveWithoutEffects, transformStyle ])
|
|
4273
|
+
}), [ isFixedOrSticky, restStyle, effectiveWithoutEffects, transformStyle ]);
|
|
4274
|
+
// Build className with state modifiers
|
|
4275
|
+
const componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveWithoutEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className ].filter(Boolean).join(" "), positionStyles = useMemo((() => ({
|
|
3172
4276
|
position: isFixedOrSticky ? "absolute" : restStyle.position || "absolute",
|
|
3173
4277
|
top: isFixedOrSticky ? 0 : restStyle.top || 0,
|
|
3174
4278
|
left: isFixedOrSticky ? 0 : restStyle.left || 0
|
|
3175
4279
|
})), [ isFixedOrSticky, restStyle.position, restStyle.top, restStyle.left ]), adjustedSize = useMemo((() => {
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
};
|
|
4280
|
+
// Keep a reference to positionStyles to avoid unused-variable lint,
|
|
4281
|
+
// but sizing is driven by explicit width/height or measured size.
|
|
4282
|
+
positionStyles.position;
|
|
4283
|
+
const resolveLength = (value, measured) => void 0 !== value ? "number" == typeof value ? `${value}px` : value : measured > 0 ? `${measured}px` : "100%", effectiveWidth = width ?? restStyle.width, effectiveHeight = height ?? restStyle.height;
|
|
3180
4284
|
return {
|
|
3181
|
-
width:
|
|
3182
|
-
height:
|
|
4285
|
+
width: resolveLength(effectiveWidth, glassSize.width),
|
|
4286
|
+
height: resolveLength(effectiveHeight, glassSize.height)
|
|
3183
4287
|
};
|
|
3184
4288
|
}), [ width, height, restStyle.width, restStyle.height, positionStyles.position, glassSize.width, glassSize.height ]), gradientValues = useMemo((() => {
|
|
3185
4289
|
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
|
|
@@ -3228,9 +4332,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3228
4332
|
},
|
|
3229
4333
|
"--atomix-glass-radius": `${effectiveBorderRadius}px`,
|
|
3230
4334
|
"--atomix-glass-transform": transformStyle || "none",
|
|
3231
|
-
|
|
3232
|
-
"--atomix-glass-
|
|
3233
|
-
"--atomix-glass-
|
|
4335
|
+
// Internal decorative layers are positioned relative to the root;
|
|
4336
|
+
"--atomix-glass-position": rootLayoutStyle.position,
|
|
4337
|
+
"--atomix-glass-top": `${isFixedOrSticky ? rootLayoutStyle.top : 0}px`,
|
|
4338
|
+
"--atomix-glass-left": `${isFixedOrSticky ? rootLayoutStyle.left : 0}px`,
|
|
3234
4339
|
"--atomix-glass-width": adjustedSize.width,
|
|
3235
4340
|
"--atomix-glass-height": adjustedSize.height,
|
|
3236
4341
|
"--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.09375rem)",
|
|
@@ -3250,10 +4355,12 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3250
4355
|
"--atomix-glass-overlay-highlight-opacity": opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
|
|
3251
4356
|
"--atomix-glass-overlay-highlight-bg": `radial-gradient(circle at ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_X}% ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_Y}%, rgba(255, 255, 255, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.WHITE_OPACITY}) 0%, transparent ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.STOP}%)`
|
|
3252
4357
|
};
|
|
3253
|
-
}), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle,
|
|
4358
|
+
}), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, adjustedSize, isOverLight, overLightConfig.borderOpacity, customZIndex, rootLayoutStyle, isFixedOrSticky ]), renderBackgroundLayer = layerType => jsx("div", {
|
|
3254
4359
|
className: [ ATOMIX_GLASS.BACKGROUND_LAYER_CLASS, "dark" === layerType ? ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS, isOverLight ? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS ].filter(Boolean).join(" ")
|
|
3255
4360
|
});
|
|
3256
|
-
|
|
4361
|
+
// Calculate position and size styles for internal layers
|
|
4362
|
+
// When root is fixed/sticky, internal layers use absolute (relative to root)
|
|
4363
|
+
return jsxs("div", {
|
|
3257
4364
|
...rest,
|
|
3258
4365
|
className: componentClassName,
|
|
3259
4366
|
style: {
|
|
@@ -3270,7 +4377,12 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3270
4377
|
ref: glassRef,
|
|
3271
4378
|
contentRef: contentRef,
|
|
3272
4379
|
className: className,
|
|
3273
|
-
style:
|
|
4380
|
+
style: {
|
|
4381
|
+
...restStyle,
|
|
4382
|
+
...!isFixedOrSticky && {
|
|
4383
|
+
position: "relative"
|
|
4384
|
+
}
|
|
4385
|
+
},
|
|
3274
4386
|
borderRadius: effectiveBorderRadius,
|
|
3275
4387
|
displacementScale: effectiveWithoutEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
|
|
3276
4388
|
blurAmount: effectiveWithoutEffects ? 0 : blurAmount,
|
|
@@ -3301,11 +4413,19 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3301
4413
|
},
|
|
3302
4414
|
onClick: onClick,
|
|
3303
4415
|
mode: mode,
|
|
3304
|
-
transform: baseStyle.transform,
|
|
3305
4416
|
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
3306
4417
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
3307
4418
|
shaderVariant: shaderVariant,
|
|
3308
4419
|
withLiquidBlur: withLiquidBlur,
|
|
4420
|
+
// Phase 1: Animation System props
|
|
4421
|
+
shaderTime: getShaderTime(),
|
|
4422
|
+
withTimeAnimation: withTimeAnimation,
|
|
4423
|
+
animationSpeed: animationSpeed,
|
|
4424
|
+
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
4425
|
+
distortionOctaves: distortionOctaves,
|
|
4426
|
+
distortionLacunarity: distortionLacunarity,
|
|
4427
|
+
distortionGain: distortionGain,
|
|
4428
|
+
distortionQuality: distortionQuality,
|
|
3309
4429
|
children: children
|
|
3310
4430
|
}), Boolean(onClick) && jsxs(Fragment, {
|
|
3311
4431
|
children: [ jsx("div", {
|
|
@@ -3329,6 +4449,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3329
4449
|
}), jsx("span", {
|
|
3330
4450
|
className: ATOMIX_GLASS.BORDER_2_CLASS
|
|
3331
4451
|
}) ]
|
|
4452
|
+
}), debugPerformance && performanceMetrics && jsx(PerformanceDashboard, {
|
|
4453
|
+
metrics: performanceMetrics,
|
|
4454
|
+
isVisible: !0,
|
|
4455
|
+
onClose: () => {}
|
|
3332
4456
|
}) ]
|
|
3333
4457
|
});
|
|
3334
4458
|
}
|
|
@@ -3395,16 +4519,14 @@ const AccordionBody = forwardRef((({children: children, className: className =
|
|
|
3395
4519
|
|
|
3396
4520
|
AccordionBody.displayName = "AccordionBody";
|
|
3397
4521
|
|
|
3398
|
-
const AccordionImpl = memo((({title: title, children: children, defaultOpen: defaultOpen = !1, isOpen: controlledOpen, onOpenChange: onOpenChange,
|
|
4522
|
+
const AccordionImpl = 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}) => {
|
|
3399
4523
|
// Generate unique IDs for accessibility
|
|
3400
4524
|
const instanceId = useId(), buttonId = `accordion-header-${instanceId}`, panelId = `accordion-panel-${instanceId}`, {state: state, toggle: toggle, updatePanelHeight: updatePanelHeight, panelRef: panelRef, contentRef: contentRef, generateClassNames: generateClassNames, generateHeaderClassNames: generateHeaderClassNames} = useAccordion({
|
|
3401
4525
|
defaultOpen: defaultOpen,
|
|
3402
4526
|
disabled: disabled,
|
|
3403
4527
|
iconPosition: iconPosition,
|
|
3404
4528
|
isOpen: controlledOpen,
|
|
3405
|
-
onOpenChange: onOpenChange
|
|
3406
|
-
onOpen: onOpen,
|
|
3407
|
-
onClose: onClose
|
|
4529
|
+
onOpenChange: onOpenChange
|
|
3408
4530
|
}), headerClassNames = generateHeaderClassNames(), panelClassNames = ACCORDION.SELECTORS.PANEL.replace(".", ""), hasCompoundComponents = React.Children.toArray(children).some((child => {
|
|
3409
4531
|
var _context;
|
|
3410
4532
|
|
|
@@ -3785,7 +4907,9 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
3785
4907
|
return this.canvasDPI;
|
|
3786
4908
|
}
|
|
3787
4909
|
},
|
|
3788
|
-
|
|
4910
|
+
createFBMEngine: createFBMEngine,
|
|
4911
|
+
fragmentShaders: fragmentShaders,
|
|
4912
|
+
liquidGlassWithTime: liquidGlassWithTime
|
|
3789
4913
|
}, Symbol.toStringTag, {
|
|
3790
4914
|
value: "Module"
|
|
3791
4915
|
})), sizeMap = {
|
|
@@ -3814,7 +4938,7 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
3814
4938
|
|
|
3815
4939
|
Icon.displayName = "Icon";
|
|
3816
4940
|
|
|
3817
|
-
const Avatar = memo((({src: src, alt: alt = "
|
|
4941
|
+
const Avatar = 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}) => {
|
|
3818
4942
|
const [imageError, setImageError] = useState(!1), avatarClasses = [ AVATAR.CLASSES.BASE, "md" !== size && `c-avatar--${size}`, circle && AVATAR.CLASSES.CIRCLE, disabled && "is-disabled", className ].filter(Boolean).join(" ");
|
|
3819
4943
|
return jsx("div", {
|
|
3820
4944
|
className: avatarClasses,
|
|
@@ -4287,7 +5411,7 @@ class ThemeNaming {
|
|
|
4287
5411
|
ThemeNaming.prefix = "atomix";
|
|
4288
5412
|
|
|
4289
5413
|
const Button = React.memo( 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) => {
|
|
4290
|
-
const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href
|
|
5414
|
+
const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href), iconElement = iconName ? jsx(Icon, {
|
|
4291
5415
|
name: iconName,
|
|
4292
5416
|
size: iconSize
|
|
4293
5417
|
}) : 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 = useCallback((event => {
|
|
@@ -4343,8 +5467,8 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
|
|
|
4343
5467
|
...buttonProps,
|
|
4344
5468
|
ref: ref,
|
|
4345
5469
|
// linkComponent usually forwards ref to anchor
|
|
4346
|
-
href: href,
|
|
4347
|
-
to: href,
|
|
5470
|
+
href: isDisabled ? void 0 : href,
|
|
5471
|
+
to: isDisabled ? void 0 : href,
|
|
4348
5472
|
target: target,
|
|
4349
5473
|
rel: "_blank" === target ? "noopener noreferrer" : void 0
|
|
4350
5474
|
};
|
|
@@ -4357,7 +5481,7 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
|
|
|
4357
5481
|
content = jsx("a", {
|
|
4358
5482
|
...buttonProps,
|
|
4359
5483
|
ref: ref,
|
|
4360
|
-
href: href,
|
|
5484
|
+
href: isDisabled ? void 0 : href,
|
|
4361
5485
|
target: target,
|
|
4362
5486
|
rel: "_blank" === target ? "noopener noreferrer" : void 0,
|
|
4363
5487
|
children: buttonContent
|
|
@@ -4636,7 +5760,7 @@ row: row = !1, flat: flat = !1,
|
|
|
4636
5760
|
// States
|
|
4637
5761
|
active: active = !1, disabled: disabled = !1, loading: loading = !1, selected: selected = !1, interactive: interactive = !1,
|
|
4638
5762
|
// Content
|
|
4639
|
-
header: header, image: image, imageAlt: imageAlt = "", title: title, text: text, actions: actions, icon: icon, footer: footer, children: children,
|
|
5763
|
+
header: header, image: image, imageAlt: imageAlt = "Card image", title: title, text: text, actions: actions, icon: icon, footer: footer, children: children,
|
|
4640
5764
|
// Interaction
|
|
4641
5765
|
onClick: onClick, onHover: onHover, onFocus: onFocus, href: href, target: target,
|
|
4642
5766
|
// Custom Link
|
|
@@ -4827,50 +5951,50 @@ Card.Header = CardHeader, Card.Body = CardBody, Card.Footer = CardFooter;
|
|
|
4827
5951
|
* @param options - Configuration options for the card
|
|
4828
5952
|
* @returns Card state and handlers
|
|
4829
5953
|
*/
|
|
4830
|
-
const
|
|
4831
|
-
const {
|
|
4832
|
-
flipEffect
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
}
|
|
4873
|
-
|
|
5954
|
+
const ElevationCard = ({elevationClass: elevationClass = "is-elevated", className: className = "", style: style, children: children, onClick: onClick, ...props}) => {
|
|
5955
|
+
const {getCardProps: getCardProps} = ((options = {}) => {
|
|
5956
|
+
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 = useRef(null), frontRef = useRef(null), backRef = useRef(null), [isFlipped, setIsFlipped] = useState(!1), [isElevated, setIsElevated] = useState(!1), [isFocused, setIsFocused] = useState(!1), [isHovered, setIsHovered] = useState(!1), handleClick = useCallback((event => {
|
|
5957
|
+
flipEffect && "click" === flipTrigger && setIsFlipped((prev => !prev)), onClick && onClick(event);
|
|
5958
|
+
}), [ flipEffect, flipTrigger, onClick ]), handleKeyDown = useCallback((event => {
|
|
5959
|
+
"Enter" !== event.key && " " !== event.key || (event.preventDefault(), flipEffect && "click" === flipTrigger && setIsFlipped((prev => !prev)),
|
|
5960
|
+
onClick && onClick(event));
|
|
5961
|
+
}), [ flipEffect, flipTrigger, onClick ]), handleMouseEnter = useCallback((() => {
|
|
5962
|
+
setIsHovered(!0), elevationEffect && setIsElevated(!0), flipEffect && "hover" === flipTrigger && setIsFlipped(!0);
|
|
5963
|
+
}), [ elevationEffect, flipEffect, flipTrigger ]), handleMouseLeave = useCallback((() => {
|
|
5964
|
+
setIsHovered(!1), elevationEffect && setIsElevated(!1), flipEffect && "hover" === flipTrigger && setIsFlipped(!1);
|
|
5965
|
+
}), [ elevationEffect, flipEffect, flipTrigger ]), handleFocus = useCallback((() => {
|
|
5966
|
+
setIsFocused(!0);
|
|
5967
|
+
}), []), handleBlur = useCallback((() => {
|
|
5968
|
+
setIsFocused(!1);
|
|
5969
|
+
}), []), getCardProps = useCallback((() => ({
|
|
5970
|
+
className: [ CARD.CLASSES.BASE, isElevated ? elevationClass : "", isFlipped ? CARD.CLASSES.FLIPPED : "", isFocused && focusEffect ? CARD.CLASSES.FOCUSED : "", clickable ? CARD.CLASSES.CLICKABLE : "" ].filter(Boolean).join(" "),
|
|
5971
|
+
ref: cardRef,
|
|
5972
|
+
tabxwIndex: clickable || flipEffect ? 0 : -1,
|
|
5973
|
+
role: clickable ? "button" : void 0,
|
|
5974
|
+
onMouseEnter: handleMouseEnter,
|
|
5975
|
+
onMouseLeave: handleMouseLeave,
|
|
5976
|
+
onFocus: handleFocus,
|
|
5977
|
+
onBlur: handleBlur,
|
|
5978
|
+
onClick: handleClick,
|
|
5979
|
+
onKeyDown: handleKeyDown
|
|
5980
|
+
})), [ isElevated, isFlipped, isFocused, elevationClass, focusEffect, clickable, handleMouseEnter, handleMouseLeave, handleFocus, handleBlur, handleClick, handleKeyDown, flipEffect ]);
|
|
5981
|
+
return {
|
|
5982
|
+
cardRef: cardRef,
|
|
5983
|
+
frontRef: frontRef,
|
|
5984
|
+
backRef: backRef,
|
|
5985
|
+
isFlipped: isFlipped,
|
|
5986
|
+
isElevated: isElevated,
|
|
5987
|
+
isFocused: isFocused,
|
|
5988
|
+
isHovered: isHovered,
|
|
5989
|
+
handleClick: handleClick,
|
|
5990
|
+
handleKeyDown: handleKeyDown,
|
|
5991
|
+
handleMouseEnter: handleMouseEnter,
|
|
5992
|
+
handleMouseLeave: handleMouseLeave,
|
|
5993
|
+
handleFocus: handleFocus,
|
|
5994
|
+
handleBlur: handleBlur,
|
|
5995
|
+
getCardProps: getCardProps
|
|
5996
|
+
};
|
|
5997
|
+
})({
|
|
4874
5998
|
elevationEffect: !0,
|
|
4875
5999
|
elevationClass: elevationClass,
|
|
4876
6000
|
clickable: Boolean(onClick),
|
|
@@ -9251,216 +10375,13 @@ function getRowId$1(row, rowKey) {
|
|
|
9251
10375
|
|
|
9252
10376
|
/**
|
|
9253
10377
|
* Hook for managing DataTable state and behavior
|
|
9254
|
-
*/
|
|
9255
|
-
// Sort state
|
|
9256
|
-
const [sortConfig, setSortConfig] = useState(initialSortConfig || null), [currentPage, setCurrentPage] = useState(1), [searchQuery, setSearchQuery] = useState(""), [internalSelectedRowIds, setInternalSelectedRowIds] = useState([]), selectedRowIds = controlledSelectedRowIds ?? internalSelectedRowIds, [columnOrder, setColumnOrder] = useState((() => columns.map((col => col.key)))), [columnVisibility, setColumnVisibility] = useState((() => {
|
|
9257
|
-
const visibility = {};
|
|
9258
|
-
return columns.forEach((col => {
|
|
9259
|
-
visibility[col.key] = !1 !== col.visible;
|
|
9260
|
-
})), visibility;
|
|
9261
|
-
})), [columnFilterValues, setColumnFilterValues] = useState({});
|
|
9262
|
-
// Pagination state
|
|
9263
|
-
// Update column order when columns prop changes
|
|
9264
|
-
useEffect((() => {
|
|
9265
|
-
const newOrder = columns.map((col => col.key)), currentOrderSet = new Set(columnOrder), newOrderSet = new Set(newOrder);
|
|
9266
|
-
// Only update if there are actual differences
|
|
9267
|
-
newOrder.length === columnOrder.length && newOrder.every((key => currentOrderSet.has(key))) && columnOrder.every((key => newOrderSet.has(key))) || setColumnOrder(newOrder);
|
|
9268
|
-
}), [ columns ]),
|
|
9269
|
-
// Update column visibility when columns prop changes
|
|
9270
|
-
useEffect((() => {
|
|
9271
|
-
setColumnVisibility((prev => {
|
|
9272
|
-
const updated = {
|
|
9273
|
-
...prev
|
|
9274
|
-
};
|
|
9275
|
-
return columns.forEach((col => {
|
|
9276
|
-
col.key in updated || (updated[col.key] = !1 !== col.visible);
|
|
9277
|
-
})), updated;
|
|
9278
|
-
}));
|
|
9279
|
-
}), [ columns ]);
|
|
9280
|
-
// Visible columns based on order and visibility
|
|
9281
|
-
const visibleColumns = useMemo((() => columnOrder.map((key => columns.find((col => col.key === key)))).filter((col => void 0 !== col && !1 !== columnVisibility[col.key]))), [ columns, columnOrder, columnVisibility ]), handleSort = useCallback((key => {
|
|
9282
|
-
if (!sortable) return;
|
|
9283
|
-
let direction = "asc";
|
|
9284
|
-
sortConfig && sortConfig.key === key && "asc" === sortConfig.direction && (direction = "desc");
|
|
9285
|
-
const newSortConfig = {
|
|
9286
|
-
key: key,
|
|
9287
|
-
direction: direction
|
|
9288
|
-
};
|
|
9289
|
-
setSortConfig(newSortConfig), onSort && onSort(newSortConfig);
|
|
9290
|
-
}), [ sortable, sortConfig, onSort ]), handlePageChange = useCallback((page => {
|
|
9291
|
-
page < 1 || setCurrentPage(page);
|
|
9292
|
-
}), []), handleSearch = useCallback((query => {
|
|
9293
|
-
setSearchQuery(query), setCurrentPage(1);
|
|
9294
|
-
} // Reset to first page when searching
|
|
9295
|
-
), []), handleColumnFilterChange = useCallback(((columnKey, value) => {
|
|
9296
|
-
setColumnFilterValues((prev => ({
|
|
9297
|
-
...prev,
|
|
9298
|
-
[columnKey]: value
|
|
9299
|
-
}))), setCurrentPage(1);
|
|
9300
|
-
} // Reset to first page when filtering
|
|
9301
|
-
), []), clearColumnFilters = useCallback((() => {
|
|
9302
|
-
setColumnFilterValues({}), setCurrentPage(1);
|
|
9303
|
-
}), []), activeColumnFilters = useMemo((() => columnFilters ? Object.entries(columnFilterValues).filter((([, value]) => null != value && "" !== value)).map((([columnKey, value]) => {
|
|
9304
|
-
const column = columns.find((col => col.key === columnKey));
|
|
9305
|
-
return column && column.filterable ? {
|
|
9306
|
-
key: columnKey,
|
|
9307
|
-
value: value,
|
|
9308
|
-
lowercaseValue: "string" == typeof value ? value.toLowerCase() : String(value).toLowerCase(),
|
|
9309
|
-
column: column
|
|
9310
|
-
} : null;
|
|
9311
|
-
})).filter((f => null !== f)) : []), [ columnFilters, columnFilterValues, columns ]), filteredData = useMemo((() => {
|
|
9312
|
-
if (!searchQuery && 0 === activeColumnFilters.length) return data;
|
|
9313
|
-
const lowercaseQuery = searchQuery ? searchQuery.toLowerCase() : "";
|
|
9314
|
-
return data.filter((row => {
|
|
9315
|
-
// Apply global search
|
|
9316
|
-
if (searchQuery && !visibleColumns.some((column => {
|
|
9317
|
-
var _context;
|
|
9318
|
-
const value = row[column.key];
|
|
9319
|
-
return null != value && _includesInstanceProperty(_context = String(value).toLowerCase()).call(_context, lowercaseQuery);
|
|
9320
|
-
}))) return !1;
|
|
9321
|
-
// Apply column-specific filters
|
|
9322
|
-
for (let i = 0; i < activeColumnFilters.length; i++) {
|
|
9323
|
-
const filter = activeColumnFilters[i];
|
|
9324
|
-
if (!filter) continue;
|
|
9325
|
-
const {key: key, value: value, lowercaseValue: lowercaseValue, column: column} = filter, cellValue = row[key];
|
|
9326
|
-
if (null == cellValue) return !1;
|
|
9327
|
-
// Use custom filter function if provided
|
|
9328
|
-
var _context2;
|
|
9329
|
-
// Default text filter
|
|
9330
|
-
if (column.filterFunction) {
|
|
9331
|
-
if (!column.filterFunction(cellValue, value)) return !1;
|
|
9332
|
-
} else if (!_includesInstanceProperty(_context2 = String(cellValue).toLowerCase()).call(_context2, lowercaseValue)) return !1;
|
|
9333
|
-
}
|
|
9334
|
-
return !0;
|
|
9335
|
-
}));
|
|
9336
|
-
}), [ data, visibleColumns, searchQuery, activeColumnFilters ]), sortedData = useMemo((() => sortConfig && sortable ? [ ...filteredData ].sort(((a, b) => {
|
|
9337
|
-
const aValue = a[sortConfig.key], bValue = b[sortConfig.key];
|
|
9338
|
-
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;
|
|
9339
|
-
})) : filteredData), [ filteredData, sortConfig, sortable ]), paginatedData = useMemo((() => {
|
|
9340
|
-
if (!paginated) return sortedData;
|
|
9341
|
-
const startIndex = (currentPage - 1) * pageSize;
|
|
9342
|
-
return sortedData.slice(startIndex, startIndex + pageSize);
|
|
9343
|
-
}), [ sortedData, paginated, currentPage, pageSize ]), totalPages = useMemo((() => paginated ? Math.max(1, Math.ceil(sortedData.length / pageSize)) : 1), [ sortedData.length, paginated, pageSize ]), selectedRows = useMemo((() => "none" === selectionMode || 0 === selectedRowIds.length ? [] : sortedData.filter((row => _includesInstanceProperty(selectedRowIds).call(selectedRowIds, getRowId$1(row, rowKey))))), [ sortedData, selectedRowIds, selectionMode, rowKey ]), handleRowSelect = useCallback(((rowId, selected) => {
|
|
9344
|
-
if ("none" === selectionMode) return;
|
|
9345
|
-
let newSelectedIds;
|
|
9346
|
-
if (newSelectedIds = "single" === selectionMode ? selected ? [ rowId ] : [] :
|
|
9347
|
-
// multiple
|
|
9348
|
-
selected ? [ ...selectedRowIds, rowId ] : selectedRowIds.filter((id => id !== rowId)),
|
|
9349
|
-
controlledSelectedRowIds || setInternalSelectedRowIds(newSelectedIds), onSelectionChange) {
|
|
9350
|
-
const selectedRowsData = sortedData.filter((row => _includesInstanceProperty(newSelectedIds).call(newSelectedIds, getRowId$1(row, rowKey))));
|
|
9351
|
-
onSelectionChange(selectedRowsData, newSelectedIds);
|
|
9352
|
-
}
|
|
9353
|
-
}), [ selectionMode, selectedRowIds, controlledSelectedRowIds, onSelectionChange, sortedData, rowKey ]), handleSelectAll = useCallback((selected => {
|
|
9354
|
-
if ("multiple" !== selectionMode) return;
|
|
9355
|
-
const newSelectedIds = selected ? paginatedData.map((row => getRowId$1(row, rowKey))) : [];
|
|
9356
|
-
if (controlledSelectedRowIds || setInternalSelectedRowIds(newSelectedIds), onSelectionChange) {
|
|
9357
|
-
const selectedRowsData = sortedData.filter((row => _includesInstanceProperty(newSelectedIds).call(newSelectedIds, getRowId$1(row, rowKey))));
|
|
9358
|
-
onSelectionChange(selectedRowsData, newSelectedIds);
|
|
9359
|
-
}
|
|
9360
|
-
}), [ selectionMode, paginatedData, sortedData, controlledSelectedRowIds, onSelectionChange, rowKey ]), isAllSelected = useMemo((() => "multiple" === selectionMode && 0 !== paginatedData.length && paginatedData.every((row => _includesInstanceProperty(selectedRowIds).call(selectedRowIds, getRowId$1(row, rowKey))))), [ selectionMode, paginatedData, selectedRowIds, rowKey ]), isIndeterminate = useMemo((() => {
|
|
9361
|
-
if ("multiple" !== selectionMode || 0 === paginatedData.length) return !1;
|
|
9362
|
-
const selectedCount = paginatedData.filter((row => _includesInstanceProperty(selectedRowIds).call(selectedRowIds, getRowId$1(row, rowKey)))).length;
|
|
9363
|
-
return selectedCount > 0 && selectedCount < paginatedData.length;
|
|
9364
|
-
}), [ selectionMode, paginatedData, selectedRowIds, rowKey ]), handleColumnVisibilityToggle = useCallback((columnKey => {
|
|
9365
|
-
setColumnVisibility((prev => {
|
|
9366
|
-
const updated = {
|
|
9367
|
-
...prev,
|
|
9368
|
-
[columnKey]: !prev[columnKey]
|
|
9369
|
-
};
|
|
9370
|
-
if (onColumnVisibilityChange) {
|
|
9371
|
-
const visibleKeys = Object.entries(updated).filter((([, visible]) => visible)).map((([key]) => key));
|
|
9372
|
-
onColumnVisibilityChange(visibleKeys);
|
|
9373
|
-
}
|
|
9374
|
-
return updated;
|
|
9375
|
-
}));
|
|
9376
|
-
}), [ onColumnVisibilityChange ]);
|
|
9377
|
-
// Handle sorting
|
|
9378
|
-
// Handle column reorder
|
|
9379
|
-
return useCallback(((fromIndex, toIndex) => {
|
|
9380
|
-
const newOrder = [ ...columnOrder ], [removed] = newOrder.splice(fromIndex, 1);
|
|
9381
|
-
removed && (newOrder.splice(toIndex, 0, removed), setColumnOrder(newOrder), onColumnReorder && onColumnReorder(newOrder));
|
|
9382
|
-
}), [ columnOrder, onColumnReorder ]),
|
|
9383
|
-
// Reset to first page when data changes
|
|
9384
|
-
useEffect((() => {
|
|
9385
|
-
setCurrentPage(1);
|
|
9386
|
-
}), [ data ]),
|
|
9387
|
-
// Reset current page if it's out of bounds
|
|
9388
|
-
useEffect((() => {
|
|
9389
|
-
currentPage > totalPages && totalPages > 0 && setCurrentPage(Math.max(1, totalPages));
|
|
9390
|
-
}), [ currentPage, totalPages ]), {
|
|
9391
|
-
displayData: paginatedData,
|
|
9392
|
-
sortConfig: sortConfig,
|
|
9393
|
-
currentPage: currentPage,
|
|
9394
|
-
totalPages: totalPages,
|
|
9395
|
-
handleSort: handleSort,
|
|
9396
|
-
handlePageChange: handlePageChange,
|
|
9397
|
-
handleSearch: handleSearch,
|
|
9398
|
-
selectedRowIds: selectedRowIds,
|
|
9399
|
-
selectedRows: selectedRows,
|
|
9400
|
-
handleRowSelect: handleRowSelect,
|
|
9401
|
-
handleSelectAll: handleSelectAll,
|
|
9402
|
-
isAllSelected: isAllSelected,
|
|
9403
|
-
isIndeterminate: isIndeterminate,
|
|
9404
|
-
columnOrder: columnOrder,
|
|
9405
|
-
visibleColumns: visibleColumns,
|
|
9406
|
-
columnVisibility: columnVisibility,
|
|
9407
|
-
handleColumnVisibilityToggle: handleColumnVisibilityToggle,
|
|
9408
|
-
columnFilterValues: columnFilterValues,
|
|
9409
|
-
handleColumnFilterChange: handleColumnFilterChange,
|
|
9410
|
-
clearColumnFilters: clearColumnFilters
|
|
9411
|
-
};
|
|
9412
|
-
}
|
|
9413
|
-
|
|
9414
|
-
Countdown.displayName = "Countdown";
|
|
10378
|
+
*/ Countdown.displayName = "Countdown";
|
|
9415
10379
|
|
|
9416
|
-
const
|
|
10380
|
+
const range = (start, end) => {
|
|
9417
10381
|
const length = end - start + 1;
|
|
9418
10382
|
return Array.from({
|
|
9419
10383
|
length: length
|
|
9420
10384
|
}, ((_, idx) => idx + start));
|
|
9421
|
-
}, usePagination = ({currentPage: currentPage, totalPages: totalPages, siblingCount: siblingCount = 1, onPageChange: onPageChange}) => {
|
|
9422
|
-
const paginationRange = useMemo((() => {
|
|
9423
|
-
// siblingCount + firstPage + lastPage + currentPage + 2*DOTS
|
|
9424
|
-
/*
|
|
9425
|
-
Case 1: If the number of pages is less than the page numbers we want to show in our
|
|
9426
|
-
paginationComponent, we return the range [1..totalPages]
|
|
9427
|
-
*/
|
|
9428
|
-
if (siblingCount + 5 >= totalPages) return range(1, totalPages);
|
|
9429
|
-
const leftSiblingIndex = Math.max(currentPage - siblingCount, 1), rightSiblingIndex = Math.min(currentPage + siblingCount, totalPages), shouldShowLeftDots = leftSiblingIndex > 2, shouldShowRightDots = rightSiblingIndex < totalPages - 2, lastPageIndex = totalPages;
|
|
9430
|
-
/*
|
|
9431
|
-
Case 2: No left dots to show, but rights dots to be shown
|
|
9432
|
-
*/
|
|
9433
|
-
return !shouldShowLeftDots && shouldShowRightDots ? [ ...range(1, 3 + 2 * siblingCount), "...", totalPages ] :
|
|
9434
|
-
/*
|
|
9435
|
-
Case 3: No right dots to show, but left dots to be shown
|
|
9436
|
-
*/
|
|
9437
|
-
shouldShowLeftDots && !shouldShowRightDots ? [ 1, "...", ...range(totalPages - (3 + 2 * siblingCount) + 1, totalPages) ] :
|
|
9438
|
-
/*
|
|
9439
|
-
Case 4: Both left and right dots to be shown
|
|
9440
|
-
*/
|
|
9441
|
-
shouldShowLeftDots && shouldShowRightDots ? [ 1, "...", ...range(leftSiblingIndex, rightSiblingIndex), "...", lastPageIndex ] : [];
|
|
9442
|
-
}), [ totalPages, siblingCount, currentPage ]), goToPage = page => {
|
|
9443
|
-
page >= 1 && page <= totalPages && page !== currentPage && onPageChange(page);
|
|
9444
|
-
};
|
|
9445
|
-
return {
|
|
9446
|
-
paginationRange: paginationRange,
|
|
9447
|
-
currentPage: currentPage,
|
|
9448
|
-
totalPages: totalPages,
|
|
9449
|
-
goToPage: goToPage,
|
|
9450
|
-
nextPage: () => {
|
|
9451
|
-
goToPage(currentPage + 1);
|
|
9452
|
-
},
|
|
9453
|
-
prevPage: () => {
|
|
9454
|
-
goToPage(currentPage - 1);
|
|
9455
|
-
},
|
|
9456
|
-
firstPage: () => {
|
|
9457
|
-
goToPage(1);
|
|
9458
|
-
},
|
|
9459
|
-
lastPage: () => {
|
|
9460
|
-
goToPage(totalPages);
|
|
9461
|
-
},
|
|
9462
|
-
DOTS: "..."
|
|
9463
|
-
};
|
|
9464
10385
|
}, PaginationNavButton = memo((({type: type, onClick: onClick, disabled: disabled, label: label, iconName: iconName}) => jsx("li", {
|
|
9465
10386
|
className: `c-pagination__item c-pagination__item--${type} ${disabled ? "is-disabled" : ""}`,
|
|
9466
10387
|
"aria-disabled": disabled,
|
|
@@ -9477,7 +10398,50 @@ const DOTS = "...", range = (start, end) => {
|
|
|
9477
10398
|
})
|
|
9478
10399
|
})
|
|
9479
10400
|
}))), Pagination = 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}) => {
|
|
9480
|
-
const {paginationRange: paginationRange, goToPage: goToPage, nextPage: nextPage, prevPage: prevPage, firstPage: firstPage, lastPage: lastPage} =
|
|
10401
|
+
const {paginationRange: paginationRange, goToPage: goToPage, nextPage: nextPage, prevPage: prevPage, firstPage: firstPage, lastPage: lastPage} = (({currentPage: currentPage, totalPages: totalPages, siblingCount: siblingCount = 1, onPageChange: onPageChange}) => {
|
|
10402
|
+
const paginationRange = useMemo((() => {
|
|
10403
|
+
// siblingCount + firstPage + lastPage + currentPage + 2*DOTS
|
|
10404
|
+
/*
|
|
10405
|
+
Case 1: If the number of pages is less than the page numbers we want to show in our
|
|
10406
|
+
paginationComponent, we return the range [1..totalPages]
|
|
10407
|
+
*/
|
|
10408
|
+
if (siblingCount + 5 >= totalPages) return range(1, totalPages);
|
|
10409
|
+
const leftSiblingIndex = Math.max(currentPage - siblingCount, 1), rightSiblingIndex = Math.min(currentPage + siblingCount, totalPages), shouldShowLeftDots = leftSiblingIndex > 2, shouldShowRightDots = rightSiblingIndex < totalPages - 2, lastPageIndex = totalPages;
|
|
10410
|
+
/*
|
|
10411
|
+
Case 2: No left dots to show, but rights dots to be shown
|
|
10412
|
+
*/
|
|
10413
|
+
return !shouldShowLeftDots && shouldShowRightDots ? [ ...range(1, 3 + 2 * siblingCount), "...", totalPages ] :
|
|
10414
|
+
/*
|
|
10415
|
+
Case 3: No right dots to show, but left dots to be shown
|
|
10416
|
+
*/
|
|
10417
|
+
shouldShowLeftDots && !shouldShowRightDots ? [ 1, "...", ...range(totalPages - (3 + 2 * siblingCount) + 1, totalPages) ] :
|
|
10418
|
+
/*
|
|
10419
|
+
Case 4: Both left and right dots to be shown
|
|
10420
|
+
*/
|
|
10421
|
+
shouldShowLeftDots && shouldShowRightDots ? [ 1, "...", ...range(leftSiblingIndex, rightSiblingIndex), "...", lastPageIndex ] : [];
|
|
10422
|
+
}), [ totalPages, siblingCount, currentPage ]), goToPage = page => {
|
|
10423
|
+
page >= 1 && page <= totalPages && page !== currentPage && onPageChange(page);
|
|
10424
|
+
};
|
|
10425
|
+
return {
|
|
10426
|
+
paginationRange: paginationRange,
|
|
10427
|
+
currentPage: currentPage,
|
|
10428
|
+
totalPages: totalPages,
|
|
10429
|
+
goToPage: goToPage,
|
|
10430
|
+
nextPage: () => {
|
|
10431
|
+
goToPage(currentPage + 1);
|
|
10432
|
+
},
|
|
10433
|
+
prevPage: () => {
|
|
10434
|
+
goToPage(currentPage - 1);
|
|
10435
|
+
},
|
|
10436
|
+
firstPage: () => {
|
|
10437
|
+
goToPage(1);
|
|
10438
|
+
},
|
|
10439
|
+
lastPage: () => {
|
|
10440
|
+
goToPage(totalPages);
|
|
10441
|
+
},
|
|
10442
|
+
DOTS: "..."
|
|
10443
|
+
};
|
|
10444
|
+
})({
|
|
9481
10445
|
currentPage: currentPage,
|
|
9482
10446
|
totalPages: totalPages,
|
|
9483
10447
|
siblingCount: siblingCount,
|
|
@@ -9689,14 +10653,13 @@ const DropdownContext = createContext({
|
|
|
9689
10653
|
id: "",
|
|
9690
10654
|
trigger: "click"
|
|
9691
10655
|
}), DropdownMenu = forwardRef((({children: children, className: className = "", ...props}, ref) => {
|
|
9692
|
-
const {glass: glass} = useContext(DropdownStyleContext);
|
|
9693
|
-
|
|
9694
|
-
// Wait, the original code wrapped <ul> in Context Provider.
|
|
9695
|
-
// And applied glass wrapper around <ul>.
|
|
9696
|
-
// If we use Compound Component, DropdownMenu should be the list.
|
|
9697
|
-
return jsx("ul", {
|
|
10656
|
+
const {glass: glass} = useContext(DropdownStyleContext), {id: id} = useContext(DropdownContext);
|
|
10657
|
+
return jsx("ul", {
|
|
9698
10658
|
ref: ref,
|
|
10659
|
+
id: `${id}-menu`,
|
|
9699
10660
|
className: `c-dropdown__menu ${glass ? "c-dropdown__menu--glass" : ""} ${className}`.trim(),
|
|
10661
|
+
role: "menu",
|
|
10662
|
+
"aria-labelledby": `${id}-trigger`,
|
|
9700
10663
|
...props,
|
|
9701
10664
|
children: children
|
|
9702
10665
|
});
|
|
@@ -9705,14 +10668,23 @@ const DropdownContext = createContext({
|
|
|
9705
10668
|
// Compound Components
|
|
9706
10669
|
DropdownMenu.displayName = "DropdownMenu";
|
|
9707
10670
|
|
|
9708
|
-
const DropdownTrigger = forwardRef((({children: children, className: className = "", onClick: onClick, onKeyDown: onKeyDown, ...props}, ref) =>
|
|
9709
|
-
|
|
9710
|
-
|
|
9711
|
-
|
|
9712
|
-
|
|
9713
|
-
|
|
9714
|
-
|
|
9715
|
-
|
|
10671
|
+
const DropdownTrigger = forwardRef((({children: children, className: className = "", onClick: onClick, onKeyDown: onKeyDown, ...props}, ref) => {
|
|
10672
|
+
const {isOpen: isOpen, id: id} = useContext(DropdownContext);
|
|
10673
|
+
return jsx("div", {
|
|
10674
|
+
ref: ref,
|
|
10675
|
+
id: `${id}-trigger`,
|
|
10676
|
+
className: `c-dropdown__toggle ${className}`.trim(),
|
|
10677
|
+
onClick: onClick,
|
|
10678
|
+
onKeyDown: onKeyDown,
|
|
10679
|
+
"aria-haspopup": "true",
|
|
10680
|
+
"aria-expanded": isOpen,
|
|
10681
|
+
"aria-controls": `${id}-menu`,
|
|
10682
|
+
tabIndex: 0,
|
|
10683
|
+
role: "button",
|
|
10684
|
+
...props,
|
|
10685
|
+
children: children
|
|
10686
|
+
});
|
|
10687
|
+
}));
|
|
9716
10688
|
|
|
9717
10689
|
DropdownTrigger.displayName = "DropdownTrigger";
|
|
9718
10690
|
|
|
@@ -9952,7 +10924,165 @@ Dropdown.Item = DropdownItem, Dropdown.Divider = DropdownDivider, Dropdown.Heade
|
|
|
9952
10924
|
* ```
|
|
9953
10925
|
*/
|
|
9954
10926
|
const DataTable = 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}) => {
|
|
9955
|
-
const tableRef = useRef(null), headerRef = useRef(null), [resizingColumn, setResizingColumn] = useState(null), [columnWidths, setColumnWidths] = useState({}), [dragStartIndex, setDragStartIndex] = useState(null), [dragOverIndex, setDragOverIndex] = 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} =
|
|
10927
|
+
const tableRef = useRef(null), headerRef = useRef(null), [resizingColumn, setResizingColumn] = useState(null), [columnWidths, setColumnWidths] = useState({}), [dragStartIndex, setDragStartIndex] = useState(null), [dragOverIndex, setDragOverIndex] = 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}) {
|
|
10928
|
+
// Sort state
|
|
10929
|
+
const [sortConfig, setSortConfig] = useState(initialSortConfig || null), [currentPage, setCurrentPage] = useState(1), [searchQuery, setSearchQuery] = useState(""), [internalSelectedRowIds, setInternalSelectedRowIds] = useState([]), selectedRowIds = controlledSelectedRowIds ?? internalSelectedRowIds, [columnOrder, setColumnOrder] = useState((() => columns.map((col => col.key)))), [columnVisibility, setColumnVisibility] = useState((() => {
|
|
10930
|
+
const visibility = {};
|
|
10931
|
+
return columns.forEach((col => {
|
|
10932
|
+
visibility[col.key] = !1 !== col.visible;
|
|
10933
|
+
})), visibility;
|
|
10934
|
+
})), [columnFilterValues, setColumnFilterValues] = useState({});
|
|
10935
|
+
// Pagination state
|
|
10936
|
+
// Update column order when columns prop changes
|
|
10937
|
+
useEffect((() => {
|
|
10938
|
+
const newOrder = columns.map((col => col.key)), currentOrderSet = new Set(columnOrder), newOrderSet = new Set(newOrder);
|
|
10939
|
+
// Only update if there are actual differences
|
|
10940
|
+
newOrder.length === columnOrder.length && newOrder.every((key => currentOrderSet.has(key))) && columnOrder.every((key => newOrderSet.has(key))) || setColumnOrder(newOrder);
|
|
10941
|
+
}), [ columns ]),
|
|
10942
|
+
// Update column visibility when columns prop changes
|
|
10943
|
+
useEffect((() => {
|
|
10944
|
+
setColumnVisibility((prev => {
|
|
10945
|
+
const updated = {
|
|
10946
|
+
...prev
|
|
10947
|
+
};
|
|
10948
|
+
return columns.forEach((col => {
|
|
10949
|
+
col.key in updated || (updated[col.key] = !1 !== col.visible);
|
|
10950
|
+
})), updated;
|
|
10951
|
+
}));
|
|
10952
|
+
}), [ columns ]);
|
|
10953
|
+
// Visible columns based on order and visibility
|
|
10954
|
+
const visibleColumns = useMemo((() => columnOrder.map((key => columns.find((col => col.key === key)))).filter((col => void 0 !== col && !1 !== columnVisibility[col.key]))), [ columns, columnOrder, columnVisibility ]), handleSort = useCallback((key => {
|
|
10955
|
+
if (!sortable) return;
|
|
10956
|
+
let direction = "asc";
|
|
10957
|
+
sortConfig && sortConfig.key === key && "asc" === sortConfig.direction && (direction = "desc");
|
|
10958
|
+
const newSortConfig = {
|
|
10959
|
+
key: key,
|
|
10960
|
+
direction: direction
|
|
10961
|
+
};
|
|
10962
|
+
setSortConfig(newSortConfig), onSort && onSort(newSortConfig);
|
|
10963
|
+
}), [ sortable, sortConfig, onSort ]), handlePageChange = useCallback((page => {
|
|
10964
|
+
page < 1 || setCurrentPage(page);
|
|
10965
|
+
}), []), handleSearch = useCallback((query => {
|
|
10966
|
+
setSearchQuery(query), setCurrentPage(1);
|
|
10967
|
+
} // Reset to first page when searching
|
|
10968
|
+
), []), handleColumnFilterChange = useCallback(((columnKey, value) => {
|
|
10969
|
+
setColumnFilterValues((prev => ({
|
|
10970
|
+
...prev,
|
|
10971
|
+
[columnKey]: value
|
|
10972
|
+
}))), setCurrentPage(1);
|
|
10973
|
+
} // Reset to first page when filtering
|
|
10974
|
+
), []), clearColumnFilters = useCallback((() => {
|
|
10975
|
+
setColumnFilterValues({}), setCurrentPage(1);
|
|
10976
|
+
}), []), activeColumnFilters = useMemo((() => columnFilters ? Object.entries(columnFilterValues).filter((([, value]) => null != value && "" !== value)).map((([columnKey, value]) => {
|
|
10977
|
+
const column = columns.find((col => col.key === columnKey));
|
|
10978
|
+
return column && column.filterable ? {
|
|
10979
|
+
key: columnKey,
|
|
10980
|
+
value: value,
|
|
10981
|
+
lowercaseValue: "string" == typeof value ? value.toLowerCase() : String(value).toLowerCase(),
|
|
10982
|
+
column: column
|
|
10983
|
+
} : null;
|
|
10984
|
+
})).filter((f => null !== f)) : []), [ columnFilters, columnFilterValues, columns ]), filteredData = useMemo((() => {
|
|
10985
|
+
if (!searchQuery && 0 === activeColumnFilters.length) return data;
|
|
10986
|
+
const lowercaseQuery = searchQuery ? searchQuery.toLowerCase() : "";
|
|
10987
|
+
return data.filter((row => {
|
|
10988
|
+
// Apply global search
|
|
10989
|
+
if (searchQuery && !visibleColumns.some((column => {
|
|
10990
|
+
var _context;
|
|
10991
|
+
const value = row[column.key];
|
|
10992
|
+
return null != value && _includesInstanceProperty(_context = String(value).toLowerCase()).call(_context, lowercaseQuery);
|
|
10993
|
+
}))) return !1;
|
|
10994
|
+
// Apply column-specific filters
|
|
10995
|
+
for (let i = 0; i < activeColumnFilters.length; i++) {
|
|
10996
|
+
const filter = activeColumnFilters[i];
|
|
10997
|
+
if (!filter) continue;
|
|
10998
|
+
const {key: key, value: value, lowercaseValue: lowercaseValue, column: column} = filter, cellValue = row[key];
|
|
10999
|
+
if (null == cellValue) return !1;
|
|
11000
|
+
// Use custom filter function if provided
|
|
11001
|
+
var _context2;
|
|
11002
|
+
// Default text filter
|
|
11003
|
+
if (column.filterFunction) {
|
|
11004
|
+
if (!column.filterFunction(cellValue, value)) return !1;
|
|
11005
|
+
} else if (!_includesInstanceProperty(_context2 = String(cellValue).toLowerCase()).call(_context2, lowercaseValue)) return !1;
|
|
11006
|
+
}
|
|
11007
|
+
return !0;
|
|
11008
|
+
}));
|
|
11009
|
+
}), [ data, visibleColumns, searchQuery, activeColumnFilters ]), sortedData = useMemo((() => sortConfig && sortable ? [ ...filteredData ].sort(((a, b) => {
|
|
11010
|
+
const aValue = a[sortConfig.key], bValue = b[sortConfig.key];
|
|
11011
|
+
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;
|
|
11012
|
+
})) : filteredData), [ filteredData, sortConfig, sortable ]), paginatedData = useMemo((() => {
|
|
11013
|
+
if (!paginated) return sortedData;
|
|
11014
|
+
const startIndex = (currentPage - 1) * pageSize;
|
|
11015
|
+
return sortedData.slice(startIndex, startIndex + pageSize);
|
|
11016
|
+
}), [ sortedData, paginated, currentPage, pageSize ]), totalPages = useMemo((() => paginated ? Math.max(1, Math.ceil(sortedData.length / pageSize)) : 1), [ sortedData.length, paginated, pageSize ]), selectedRows = useMemo((() => "none" === selectionMode || 0 === selectedRowIds.length ? [] : sortedData.filter((row => _includesInstanceProperty(selectedRowIds).call(selectedRowIds, getRowId$1(row, rowKey))))), [ sortedData, selectedRowIds, selectionMode, rowKey ]), handleRowSelect = useCallback(((rowId, selected) => {
|
|
11017
|
+
if ("none" === selectionMode) return;
|
|
11018
|
+
let newSelectedIds;
|
|
11019
|
+
if (newSelectedIds = "single" === selectionMode ? selected ? [ rowId ] : [] :
|
|
11020
|
+
// multiple
|
|
11021
|
+
selected ? [ ...selectedRowIds, rowId ] : selectedRowIds.filter((id => id !== rowId)),
|
|
11022
|
+
controlledSelectedRowIds || setInternalSelectedRowIds(newSelectedIds), onSelectionChange) {
|
|
11023
|
+
const selectedRowsData = sortedData.filter((row => _includesInstanceProperty(newSelectedIds).call(newSelectedIds, getRowId$1(row, rowKey))));
|
|
11024
|
+
onSelectionChange(selectedRowsData, newSelectedIds);
|
|
11025
|
+
}
|
|
11026
|
+
}), [ selectionMode, selectedRowIds, controlledSelectedRowIds, onSelectionChange, sortedData, rowKey ]), handleSelectAll = useCallback((selected => {
|
|
11027
|
+
if ("multiple" !== selectionMode) return;
|
|
11028
|
+
const newSelectedIds = selected ? paginatedData.map((row => getRowId$1(row, rowKey))) : [];
|
|
11029
|
+
if (controlledSelectedRowIds || setInternalSelectedRowIds(newSelectedIds), onSelectionChange) {
|
|
11030
|
+
const selectedRowsData = sortedData.filter((row => _includesInstanceProperty(newSelectedIds).call(newSelectedIds, getRowId$1(row, rowKey))));
|
|
11031
|
+
onSelectionChange(selectedRowsData, newSelectedIds);
|
|
11032
|
+
}
|
|
11033
|
+
}), [ selectionMode, paginatedData, sortedData, controlledSelectedRowIds, onSelectionChange, rowKey ]), isAllSelected = useMemo((() => "multiple" === selectionMode && 0 !== paginatedData.length && paginatedData.every((row => _includesInstanceProperty(selectedRowIds).call(selectedRowIds, getRowId$1(row, rowKey))))), [ selectionMode, paginatedData, selectedRowIds, rowKey ]), isIndeterminate = useMemo((() => {
|
|
11034
|
+
if ("multiple" !== selectionMode || 0 === paginatedData.length) return !1;
|
|
11035
|
+
const selectedCount = paginatedData.filter((row => _includesInstanceProperty(selectedRowIds).call(selectedRowIds, getRowId$1(row, rowKey)))).length;
|
|
11036
|
+
return selectedCount > 0 && selectedCount < paginatedData.length;
|
|
11037
|
+
}), [ selectionMode, paginatedData, selectedRowIds, rowKey ]), handleColumnVisibilityToggle = useCallback((columnKey => {
|
|
11038
|
+
setColumnVisibility((prev => {
|
|
11039
|
+
const updated = {
|
|
11040
|
+
...prev,
|
|
11041
|
+
[columnKey]: !prev[columnKey]
|
|
11042
|
+
};
|
|
11043
|
+
if (onColumnVisibilityChange) {
|
|
11044
|
+
const visibleKeys = Object.entries(updated).filter((([, visible]) => visible)).map((([key]) => key));
|
|
11045
|
+
onColumnVisibilityChange(visibleKeys);
|
|
11046
|
+
}
|
|
11047
|
+
return updated;
|
|
11048
|
+
}));
|
|
11049
|
+
}), [ onColumnVisibilityChange ]);
|
|
11050
|
+
// Handle sorting
|
|
11051
|
+
// Handle column reorder
|
|
11052
|
+
return useCallback(((fromIndex, toIndex) => {
|
|
11053
|
+
const newOrder = [ ...columnOrder ], [removed] = newOrder.splice(fromIndex, 1);
|
|
11054
|
+
removed && (newOrder.splice(toIndex, 0, removed), setColumnOrder(newOrder), onColumnReorder && onColumnReorder(newOrder));
|
|
11055
|
+
}), [ columnOrder, onColumnReorder ]),
|
|
11056
|
+
// Reset to first page when data changes
|
|
11057
|
+
useEffect((() => {
|
|
11058
|
+
setCurrentPage(1);
|
|
11059
|
+
}), [ data ]),
|
|
11060
|
+
// Reset current page if it's out of bounds
|
|
11061
|
+
useEffect((() => {
|
|
11062
|
+
currentPage > totalPages && totalPages > 0 && setCurrentPage(Math.max(1, totalPages));
|
|
11063
|
+
}), [ currentPage, totalPages ]), {
|
|
11064
|
+
displayData: paginatedData,
|
|
11065
|
+
sortConfig: sortConfig,
|
|
11066
|
+
currentPage: currentPage,
|
|
11067
|
+
totalPages: totalPages,
|
|
11068
|
+
handleSort: handleSort,
|
|
11069
|
+
handlePageChange: handlePageChange,
|
|
11070
|
+
handleSearch: handleSearch,
|
|
11071
|
+
selectedRowIds: selectedRowIds,
|
|
11072
|
+
selectedRows: selectedRows,
|
|
11073
|
+
handleRowSelect: handleRowSelect,
|
|
11074
|
+
handleSelectAll: handleSelectAll,
|
|
11075
|
+
isAllSelected: isAllSelected,
|
|
11076
|
+
isIndeterminate: isIndeterminate,
|
|
11077
|
+
columnOrder: columnOrder,
|
|
11078
|
+
visibleColumns: visibleColumns,
|
|
11079
|
+
columnVisibility: columnVisibility,
|
|
11080
|
+
handleColumnVisibilityToggle: handleColumnVisibilityToggle,
|
|
11081
|
+
columnFilterValues: columnFilterValues,
|
|
11082
|
+
handleColumnFilterChange: handleColumnFilterChange,
|
|
11083
|
+
clearColumnFilters: clearColumnFilters
|
|
11084
|
+
};
|
|
11085
|
+
}({
|
|
9956
11086
|
data: data,
|
|
9957
11087
|
columns: columns,
|
|
9958
11088
|
sortable: sortable,
|
|
@@ -12306,297 +13436,6 @@ function useTodo(initialProps) {
|
|
|
12306
13436
|
};
|
|
12307
13437
|
}
|
|
12308
13438
|
|
|
12309
|
-
/**
|
|
12310
|
-
* Breadcrumb state and functionality
|
|
12311
|
-
* @param initialOptions - Initial breadcrumb options
|
|
12312
|
-
* @returns Breadcrumb state and methods
|
|
12313
|
-
*/ function useBreadcrumb(initialOptions) {
|
|
12314
|
-
return {
|
|
12315
|
-
defaultOptions: {
|
|
12316
|
-
items: [],
|
|
12317
|
-
divider: BREADCRUMB.DEFAULTS.DIVIDER,
|
|
12318
|
-
className: "",
|
|
12319
|
-
"aria-label": "Breadcrumb",
|
|
12320
|
-
...initialOptions
|
|
12321
|
-
},
|
|
12322
|
-
generateBreadcrumbClass: options => {
|
|
12323
|
-
const {className: className = ""} = options;
|
|
12324
|
-
return [ BREADCRUMB.CLASSES.BASE, className ].filter(Boolean).join(" ").trim();
|
|
12325
|
-
},
|
|
12326
|
-
generateItemClass: (item, isLast) => [ BREADCRUMB.CLASSES.ITEM, item.active || isLast ? BREADCRUMB.CLASSES.ACTIVE : "" ].filter(Boolean).join(" ").trim(),
|
|
12327
|
-
isItemLink: (item, isLast) => Boolean(item.href && !item.active && !isLast),
|
|
12328
|
-
parseItemsFromJson: jsonString => {
|
|
12329
|
-
try {
|
|
12330
|
-
return JSON.parse(jsonString);
|
|
12331
|
-
} catch (error) {
|
|
12332
|
-
return console.error("Error parsing breadcrumb items:", error), [];
|
|
12333
|
-
}
|
|
12334
|
-
}
|
|
12335
|
-
};
|
|
12336
|
-
}
|
|
12337
|
-
|
|
12338
|
-
/**
|
|
12339
|
-
* Hook for managing modal state
|
|
12340
|
-
*/ function useModal$1({isOpen: isOpenProp, onOpenChange: onOpenChange, onOpen: onOpen, onClose: onClose} = {}) {
|
|
12341
|
-
// For uncontrolled usage
|
|
12342
|
-
const [isOpenState, setIsOpenState] = useState(!1), isControlled = void 0 !== isOpenProp, isOpen = isControlled ? !!isOpenProp : isOpenState;
|
|
12343
|
-
// Determine if we're in controlled or uncontrolled mode
|
|
12344
|
-
// Update internal state when prop changes (for controlled mode)
|
|
12345
|
-
useEffect((() => {
|
|
12346
|
-
isControlled && setIsOpenState(!!isOpenProp);
|
|
12347
|
-
}), [ isOpenProp, isControlled ]);
|
|
12348
|
-
const updateOpen = useCallback((nextIsOpen => {
|
|
12349
|
-
// For uncontrolled mode, update internal state
|
|
12350
|
-
isControlled || setIsOpenState(nextIsOpen),
|
|
12351
|
-
// Call the change handler in either mode
|
|
12352
|
-
onOpenChange && onOpenChange(nextIsOpen),
|
|
12353
|
-
// Call the specific handler
|
|
12354
|
-
nextIsOpen && onOpen ? onOpen() : !nextIsOpen && onClose && onClose();
|
|
12355
|
-
}), [ isControlled, onOpenChange, onOpen, onClose ]), open = useCallback((() => {
|
|
12356
|
-
updateOpen(!0);
|
|
12357
|
-
}), [ updateOpen ]), close = useCallback((() => {
|
|
12358
|
-
updateOpen(!1);
|
|
12359
|
-
}), [ updateOpen ]), toggle = useCallback((() => {
|
|
12360
|
-
updateOpen(!isOpen);
|
|
12361
|
-
}), [ isOpen, updateOpen ]);
|
|
12362
|
-
return {
|
|
12363
|
-
isOpen: isOpen,
|
|
12364
|
-
open: open,
|
|
12365
|
-
close: close,
|
|
12366
|
-
toggle: toggle
|
|
12367
|
-
};
|
|
12368
|
-
}
|
|
12369
|
-
|
|
12370
|
-
function useSlider(options) {
|
|
12371
|
-
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 = useRef(null), wrapperRef = useRef(null), repositioningRef = useRef(!1), autoplayRef = useRef(null), [autoplayRunning, setAutoplayRunning] = useState(!1), sliderStateRef = useRef({
|
|
12372
|
-
isTransitioning: !1,
|
|
12373
|
-
loop: loop,
|
|
12374
|
-
slides: slides,
|
|
12375
|
-
slidesToShow: slidesToShow,
|
|
12376
|
-
speed: speed,
|
|
12377
|
-
onSlideChange: onSlideChange
|
|
12378
|
-
}), [realIndex, setRealIndex] = useState(initialSlide), [internalIndex, setInternalIndex] = useState(0), [isTransitioning, setIsTransitioning] = useState(!1), [containerSize, setContainerSize] = useState(0), [touching, setTouching] = useState(!1), [touchStart, setTouchStart] = useState(0), [dragOffset, setDragOffset] = useState(0), slideWidth = useMemo((() => 0 === containerSize ? 0 : (containerSize - spaceBetween * (slidesToShow - 1)) / slidesToShow), [ containerSize, spaceBetween, slidesToShow ]), allSlides = useMemo((() => loop && 0 !== slides.length ? [ ...slides.map(((slide, i) => ({
|
|
12379
|
-
...slide,
|
|
12380
|
-
id: `set1-${slide.id || i}`
|
|
12381
|
-
}))), ...slides.map(((slide, i) => ({
|
|
12382
|
-
...slide,
|
|
12383
|
-
id: `set2-${slide.id || i}`
|
|
12384
|
-
}))), ...slides.map(((slide, i) => ({
|
|
12385
|
-
...slide,
|
|
12386
|
-
id: `set3-${slide.id || i}`
|
|
12387
|
-
}))) ] : slides), [ slides, loop ]), loopedSlides = slides.length, translateValue = useMemo((() => 0 === slideWidth ? 0 : -internalIndex * slideWidth + dragOffset), [ slideWidth, internalIndex, dragOffset ]);
|
|
12388
|
-
// Update the ref whenever the relevant state/props change
|
|
12389
|
-
useEffect((() => {
|
|
12390
|
-
sliderStateRef.current = {
|
|
12391
|
-
isTransitioning: isTransitioning,
|
|
12392
|
-
loop: loop,
|
|
12393
|
-
slides: slides,
|
|
12394
|
-
slidesToShow: slidesToShow,
|
|
12395
|
-
speed: speed,
|
|
12396
|
-
onSlideChange: onSlideChange
|
|
12397
|
-
};
|
|
12398
|
-
}), [ isTransitioning, loop, slides, slidesToShow, speed, onSlideChange ]),
|
|
12399
|
-
// Autoplay effect
|
|
12400
|
-
useEffect((() => {
|
|
12401
|
-
if (!autoplay) return autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12402
|
-
autoplayRef.current = null), void setAutoplayRunning(!1);
|
|
12403
|
-
const autoplayParams = "boolean" == typeof autoplay ? {
|
|
12404
|
-
delay: 3e3
|
|
12405
|
-
} : autoplay, {delay: delay = 3e3, pauseOnMouseEnter: pauseOnMouseEnter = !1, disableOnInteraction: disableOnInteraction = !1, reverseDirection: reverseDirection = !1} = autoplayParams;
|
|
12406
|
-
// Clear any existing interval
|
|
12407
|
-
autoplayRef.current && clearInterval(autoplayRef.current),
|
|
12408
|
-
// Create new interval
|
|
12409
|
-
autoplayRef.current = setInterval((() => {
|
|
12410
|
-
// Use ref to get the latest state without resetting the interval
|
|
12411
|
-
const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
|
|
12412
|
-
// We need to use a functional update to get the latest values
|
|
12413
|
-
setRealIndex((prevRealIndex => {
|
|
12414
|
-
if (currentIsTransitioning) return prevRealIndex;
|
|
12415
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12416
|
-
let nextIndex;
|
|
12417
|
-
// Trigger the slide change
|
|
12418
|
-
if (disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12419
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
|
|
12420
|
-
reverseDirection) {
|
|
12421
|
-
// For reverse direction, we would go to previous slide
|
|
12422
|
-
const prevIndex = currentLoop ? 0 === prevRealIndex ? currentSlides.length - 1 : prevRealIndex - 1 : Math.max(prevRealIndex - 1, 0);
|
|
12423
|
-
return setInternalIndex(currentLoop ? currentSlides.length + prevIndex : prevIndex),
|
|
12424
|
-
setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
|
|
12425
|
-
setIsTransitioning(!1), currentOnSlideChange?.(prevIndex);
|
|
12426
|
-
}), currentSpeed), prevIndex;
|
|
12427
|
-
}
|
|
12428
|
-
// Normal direction
|
|
12429
|
-
return setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex),
|
|
12430
|
-
setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
|
|
12431
|
-
setIsTransitioning(!1), currentOnSlideChange?.(nextIndex),
|
|
12432
|
-
// Reposition after transition ends for looped sliders
|
|
12433
|
-
currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
|
|
12434
|
-
setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
|
|
12435
|
-
repositioningRef.current = !1;
|
|
12436
|
-
}), 0));
|
|
12437
|
-
}), currentSpeed), nextIndex;
|
|
12438
|
-
}));
|
|
12439
|
-
}), delay), setAutoplayRunning(!0);
|
|
12440
|
-
// Handle pause on mouse enter/leave if enabled
|
|
12441
|
-
let containerElement = null;
|
|
12442
|
-
const handleMouseEnter = () => {
|
|
12443
|
-
autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null,
|
|
12444
|
-
setAutoplayRunning(!1));
|
|
12445
|
-
}, handleMouseLeave = () => {
|
|
12446
|
-
// Restart autoplay
|
|
12447
|
-
autoplayRef.current && clearInterval(autoplayRef.current), autoplayRef.current = setInterval((() => {
|
|
12448
|
-
const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
|
|
12449
|
-
setRealIndex((prevRealIndex => {
|
|
12450
|
-
if (currentIsTransitioning) return prevRealIndex;
|
|
12451
|
-
let nextIndex;
|
|
12452
|
-
return nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
|
|
12453
|
-
setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex), setIsTransitioning(!0),
|
|
12454
|
-
setDragOffset(0), setTimeout((() => {
|
|
12455
|
-
setIsTransitioning(!1), currentOnSlideChange?.(nextIndex), currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
|
|
12456
|
-
setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
|
|
12457
|
-
repositioningRef.current = !1;
|
|
12458
|
-
}), 0));
|
|
12459
|
-
}), currentSpeed), nextIndex;
|
|
12460
|
-
}));
|
|
12461
|
-
}), delay), setAutoplayRunning(!0);
|
|
12462
|
-
};
|
|
12463
|
-
// Cleanup
|
|
12464
|
-
return pauseOnMouseEnter && containerRef.current && (containerElement = containerRef.current,
|
|
12465
|
-
containerElement.addEventListener("mouseenter", handleMouseEnter), containerElement.addEventListener("mouseleave", handleMouseLeave)),
|
|
12466
|
-
() => {
|
|
12467
|
-
autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null),
|
|
12468
|
-
containerElement && (containerElement.removeEventListener("mouseenter", handleMouseEnter),
|
|
12469
|
-
containerElement.removeEventListener("mouseleave", handleMouseLeave)), setAutoplayRunning(!1);
|
|
12470
|
-
};
|
|
12471
|
-
}), [ autoplay, repositioningRef ]),
|
|
12472
|
-
// Initialize
|
|
12473
|
-
useEffect((() => {
|
|
12474
|
-
setInternalIndex(loop ? slides.length + initialSlide : initialSlide);
|
|
12475
|
-
}), [ loop, slides.length, initialSlide ]), useEffect((() => {
|
|
12476
|
-
const updateSize = () => {
|
|
12477
|
-
if (containerRef.current) {
|
|
12478
|
-
const size = "horizontal" === direction ? containerRef.current.offsetWidth : containerRef.current.offsetHeight;
|
|
12479
|
-
setContainerSize(size);
|
|
12480
|
-
}
|
|
12481
|
-
};
|
|
12482
|
-
return updateSize(), window.addEventListener("resize", updateSize), () => window.removeEventListener("resize", updateSize);
|
|
12483
|
-
}), [ direction ]);
|
|
12484
|
-
const slideNext = useCallback((() => {
|
|
12485
|
-
if (!isTransitioning) if (
|
|
12486
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12487
|
-
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12488
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), loop) {
|
|
12489
|
-
const nextRealIndex = (realIndex + 1) % slides.length, nextInternalIndex = internalIndex + 1;
|
|
12490
|
-
setRealIndex(nextRealIndex), setInternalIndex(nextInternalIndex), setIsTransitioning(!0),
|
|
12491
|
-
setDragOffset(0), setTimeout((() => {
|
|
12492
|
-
setIsTransitioning(!1), onSlideChange?.(nextRealIndex),
|
|
12493
|
-
// Reposition after transition ends
|
|
12494
|
-
nextInternalIndex >= 2 * slides.length && (repositioningRef.current = !0, setInternalIndex(slides.length + nextRealIndex),
|
|
12495
|
-
setTimeout((() => {
|
|
12496
|
-
repositioningRef.current = !1;
|
|
12497
|
-
}), 0));
|
|
12498
|
-
}), speed);
|
|
12499
|
-
} else {
|
|
12500
|
-
const nextIndex = Math.min(realIndex + 1, slides.length - slidesToShow);
|
|
12501
|
-
setRealIndex(nextIndex), setInternalIndex(nextIndex), setIsTransitioning(!0), setDragOffset(0),
|
|
12502
|
-
setTimeout((() => {
|
|
12503
|
-
setIsTransitioning(!1), onSlideChange?.(nextIndex);
|
|
12504
|
-
}), speed);
|
|
12505
|
-
}
|
|
12506
|
-
}), [ realIndex, internalIndex, slides.length, slidesToShow, loop, isTransitioning, speed, onSlideChange, allSlides.length, loopedSlides, autoplay ]), slidePrev = useCallback((() => {
|
|
12507
|
-
if (!isTransitioning) if (
|
|
12508
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12509
|
-
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12510
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), loop) {
|
|
12511
|
-
const prevRealIndex = 0 === realIndex ? slides.length - 1 : realIndex - 1, prevInternalIndex = internalIndex - 1;
|
|
12512
|
-
setRealIndex(prevRealIndex), setInternalIndex(prevInternalIndex), setIsTransitioning(!0),
|
|
12513
|
-
setDragOffset(0), setTimeout((() => {
|
|
12514
|
-
setIsTransitioning(!1), onSlideChange?.(prevRealIndex),
|
|
12515
|
-
// Reposition after transition ends
|
|
12516
|
-
prevInternalIndex < slides.length && (repositioningRef.current = !0, setInternalIndex(slides.length + prevRealIndex),
|
|
12517
|
-
setTimeout((() => {
|
|
12518
|
-
repositioningRef.current = !1;
|
|
12519
|
-
}), 0));
|
|
12520
|
-
}), speed);
|
|
12521
|
-
} else {
|
|
12522
|
-
const prevIndex = Math.max(realIndex - 1, 0);
|
|
12523
|
-
setRealIndex(prevIndex), setInternalIndex(prevIndex), setIsTransitioning(!0), setDragOffset(0),
|
|
12524
|
-
setTimeout((() => {
|
|
12525
|
-
setIsTransitioning(!1), onSlideChange?.(prevIndex);
|
|
12526
|
-
}), speed);
|
|
12527
|
-
}
|
|
12528
|
-
}), [ realIndex, internalIndex, slides.length, loop, isTransitioning, speed, onSlideChange, allSlides.length, loopedSlides, autoplay ]), goToSlide = useCallback((index => {
|
|
12529
|
-
isTransitioning || index === realIndex || (
|
|
12530
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12531
|
-
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12532
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), setIsTransitioning(!0), setDragOffset(0),
|
|
12533
|
-
setRealIndex(index), setInternalIndex(loop ? slides.length + index : index), setTimeout((() => {
|
|
12534
|
-
setIsTransitioning(!1), onSlideChange?.(index);
|
|
12535
|
-
}), speed));
|
|
12536
|
-
}), [ realIndex, isTransitioning, speed, onSlideChange, loop, loopedSlides, autoplay ]), handleTouchStart = useCallback((e => {
|
|
12537
|
-
if (!allowTouchMove) return;
|
|
12538
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12539
|
-
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12540
|
-
autoplayRef.current = null, setAutoplayRunning(!1));
|
|
12541
|
-
const client = "horizontal" === direction ? "touches" in e ? e.touches[0]?.clientX || 0 : e.clientX : "touches" in e ? e.touches[0]?.clientY || 0 : e.clientY;
|
|
12542
|
-
setTouchStart(client), setTouching(!0), setDragOffset(0);
|
|
12543
|
-
}), [ allowTouchMove, direction, autoplay ]), handleTouchMove = useCallback((e => {
|
|
12544
|
-
if (!touching || !allowTouchMove) return;
|
|
12545
|
-
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;
|
|
12546
|
-
Math.abs(diff) > 10 && (e.preventDefault(), setDragOffset(.5 * -diff));
|
|
12547
|
-
}), [ touching, touchStart, allowTouchMove, direction ]), handleTouchEnd = useCallback((e => {
|
|
12548
|
-
if (!touching || !allowTouchMove) return;
|
|
12549
|
-
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;
|
|
12550
|
-
setTouching(!1), setDragOffset(0), Math.abs(diff) > threshold && (diff > 0 ? slideNext() : slidePrev());
|
|
12551
|
-
}), [ touching, touchStart, threshold, slideNext, slidePrev, allowTouchMove, direction ]), canSlideNext = loop || realIndex < slides.length - slidesToShow, canSlidePrev = loop || realIndex > 0;
|
|
12552
|
-
return {
|
|
12553
|
-
activeIndex: realIndex,
|
|
12554
|
-
realIndex: realIndex,
|
|
12555
|
-
previousIndex: realIndex,
|
|
12556
|
-
isBeginning: !loop && 0 === realIndex,
|
|
12557
|
-
isEnd: !loop && realIndex >= slides.length - slidesToShow,
|
|
12558
|
-
progress: slides.length > 0 ? realIndex / (slides.length - 1) : 0,
|
|
12559
|
-
autoplayRunning: autoplayRunning,
|
|
12560
|
-
transitioning: isTransitioning,
|
|
12561
|
-
touching: touching,
|
|
12562
|
-
translate: translateValue,
|
|
12563
|
-
slidesPerView: slidesToShow,
|
|
12564
|
-
slidesCount: slides.length,
|
|
12565
|
-
isLocked: !1,
|
|
12566
|
-
destroyed: !1,
|
|
12567
|
-
size: containerSize,
|
|
12568
|
-
touches: {
|
|
12569
|
-
startX: 0,
|
|
12570
|
-
startY: 0,
|
|
12571
|
-
currentX: 0,
|
|
12572
|
-
currentY: 0,
|
|
12573
|
-
diff: 0
|
|
12574
|
-
},
|
|
12575
|
-
allowSlideNext: canSlideNext,
|
|
12576
|
-
allowSlidePrev: canSlidePrev,
|
|
12577
|
-
allowTouchMove: allowTouchMove,
|
|
12578
|
-
animating: isTransitioning,
|
|
12579
|
-
enabled: !0,
|
|
12580
|
-
initialized: !0,
|
|
12581
|
-
slideNext: slideNext,
|
|
12582
|
-
slidePrev: slidePrev,
|
|
12583
|
-
goToSlide: goToSlide,
|
|
12584
|
-
canSlideNext: canSlideNext,
|
|
12585
|
-
canSlidePrev: canSlidePrev,
|
|
12586
|
-
containerRef: containerRef,
|
|
12587
|
-
wrapperRef: wrapperRef,
|
|
12588
|
-
handleTouchStart: handleTouchStart,
|
|
12589
|
-
handleTouchMove: handleTouchMove,
|
|
12590
|
-
handleTouchEnd: handleTouchEnd,
|
|
12591
|
-
allSlides: allSlides,
|
|
12592
|
-
translateValue: translateValue,
|
|
12593
|
-
slideWidth: slideWidth,
|
|
12594
|
-
currentSlidesToShow: slidesToShow,
|
|
12595
|
-
loopedSlides: loopedSlides,
|
|
12596
|
-
repositioningRef: repositioningRef
|
|
12597
|
-
};
|
|
12598
|
-
}
|
|
12599
|
-
|
|
12600
13439
|
/**
|
|
12601
13440
|
* Simplified hook for chart data processing
|
|
12602
13441
|
*/ function useChartData(data) {
|
|
@@ -12697,37 +13536,44 @@ function useSlider(options) {
|
|
|
12697
13536
|
// Accordion composables
|
|
12698
13537
|
const composablesImport = Object.freeze( Object.defineProperty({
|
|
12699
13538
|
__proto__: null,
|
|
12700
|
-
|
|
13539
|
+
BALANCED_PRESET: BALANCED_PRESET,
|
|
13540
|
+
DEFAULT_BREAKPOINTS: DEFAULT_BREAKPOINTS,
|
|
13541
|
+
DeviceDetector: DeviceDetector,
|
|
13542
|
+
MOBILE_OPTIMIZED_BREAKPOINTS: MOBILE_OPTIMIZED_BREAKPOINTS,
|
|
13543
|
+
PERFORMANCE_PRESET: PERFORMANCE_PRESET,
|
|
13544
|
+
PerformanceOverlay: PerformanceOverlay,
|
|
13545
|
+
QUALITY_PRESET: QUALITY_PRESET,
|
|
13546
|
+
createBreakpoints: createBreakpoints$1,
|
|
13547
|
+
getDefaultBreakpoints: getDefaultBreakpoints,
|
|
13548
|
+
getDevicePreset: getDevicePreset,
|
|
13549
|
+
getMobileOptimizedParams: getMobileOptimizedParams,
|
|
13550
|
+
getQualityMultipliers: getQualityMultipliers,
|
|
12701
13551
|
useAccordion: useAccordion,
|
|
12702
13552
|
useAtomixGlass: useAtomixGlass,
|
|
12703
13553
|
useBadge: useBadge,
|
|
12704
13554
|
useBarChart: useBarChart,
|
|
12705
13555
|
useBlock: useBlock,
|
|
12706
|
-
useBreadcrumb: useBreadcrumb,
|
|
12707
|
-
useCard: useCard,
|
|
12708
13556
|
useChartData: useChartData,
|
|
12709
13557
|
useChartInteraction: useChartInteraction,
|
|
12710
13558
|
useChartScale: useChartScale,
|
|
12711
|
-
useDataTable: useDataTable,
|
|
12712
13559
|
useEdgePanel: useEdgePanel,
|
|
12713
13560
|
useForm: useForm,
|
|
12714
13561
|
useFormGroup: useFormGroup,
|
|
12715
13562
|
useHero: useHero,
|
|
12716
13563
|
useInput: useInput,
|
|
12717
13564
|
useLineChart: useLineChart,
|
|
12718
|
-
useModal: useModal$1,
|
|
12719
13565
|
useNav: useNav,
|
|
12720
13566
|
useNavDropdown: useNavDropdown,
|
|
12721
13567
|
useNavItem: useNavItem,
|
|
12722
13568
|
useNavbar: useNavbar,
|
|
12723
|
-
|
|
13569
|
+
usePerformanceMonitor: usePerformanceMonitor,
|
|
12724
13570
|
usePieChart: usePieChart,
|
|
12725
13571
|
useRadio: useRadio,
|
|
13572
|
+
useResponsiveGlass: useResponsiveGlass,
|
|
12726
13573
|
useRiver: useRiver,
|
|
12727
13574
|
useSelect: useSelect,
|
|
12728
13575
|
useSideMenu: useSideMenu,
|
|
12729
13576
|
useSideMenuItem: useSideMenuItem,
|
|
12730
|
-
useSlider: useSlider,
|
|
12731
13577
|
useSpinner: useSpinner,
|
|
12732
13578
|
useTextarea: useTextarea,
|
|
12733
13579
|
useTodo: useTodo
|
|
@@ -12818,7 +13664,10 @@ const Select = memo((({options: options, value: value, onChange: onChange, onBl
|
|
|
12818
13664
|
};
|
|
12819
13665
|
}), []);
|
|
12820
13666
|
// Toggle dropdown
|
|
12821
|
-
const
|
|
13667
|
+
const handleToggle = () => {
|
|
13668
|
+
disabled || (!isOpen && bodyRef.current && panelRef.current ? bodyRef.current.style.height = `${panelRef.current.clientHeight}px` : bodyRef.current && (bodyRef.current.style.height = "0px"),
|
|
13669
|
+
setIsOpen(!isOpen));
|
|
13670
|
+
}, handleItemClick = useCallback((option => {
|
|
12822
13671
|
if (setSelectedLabel(option.label), setIsOpen(!1), bodyRef.current && (bodyRef.current.style.height = "0px"),
|
|
12823
13672
|
nativeSelectRef.current && (nativeSelectRef.current.value = option.value), onChange) {
|
|
12824
13673
|
// Create a synthetic event
|
|
@@ -12862,7 +13711,15 @@ const Select = memo((({options: options, value: value, onChange: onChange, onBl
|
|
|
12862
13711
|
"aria-describedby": ariaDescribedBy,
|
|
12863
13712
|
"aria-invalid": invalid,
|
|
12864
13713
|
style: {
|
|
12865
|
-
|
|
13714
|
+
position: "absolute",
|
|
13715
|
+
width: "1px",
|
|
13716
|
+
height: "1px",
|
|
13717
|
+
padding: "0",
|
|
13718
|
+
margin: "-1px",
|
|
13719
|
+
overflow: "hidden",
|
|
13720
|
+
clip: "rect(0, 0, 0, 0)",
|
|
13721
|
+
whiteSpace: "nowrap",
|
|
13722
|
+
border: "0"
|
|
12866
13723
|
},
|
|
12867
13724
|
children: [ placeholder && jsx("option", {
|
|
12868
13725
|
value: "",
|
|
@@ -12875,11 +13732,29 @@ const Select = memo((({options: options, value: value, onChange: onChange, onBl
|
|
|
12875
13732
|
}, option.value))) ]
|
|
12876
13733
|
}), jsx("div", {
|
|
12877
13734
|
className: SELECT.CLASSES.SELECTED,
|
|
12878
|
-
onClick:
|
|
12879
|
-
|
|
12880
|
-
|
|
13735
|
+
onClick: handleToggle,
|
|
13736
|
+
onKeyDown: event => {
|
|
13737
|
+
if (!disabled) switch (event.key) {
|
|
13738
|
+
case "Enter":
|
|
13739
|
+
case " ":
|
|
13740
|
+
event.preventDefault(), handleToggle();
|
|
13741
|
+
break;
|
|
13742
|
+
|
|
13743
|
+
case "Escape":
|
|
13744
|
+
isOpen && (event.preventDefault(), setIsOpen(!1), bodyRef.current && (bodyRef.current.style.height = "0px"));
|
|
13745
|
+
break;
|
|
13746
|
+
|
|
13747
|
+
case "ArrowDown":
|
|
13748
|
+
case "ArrowUp":
|
|
13749
|
+
isOpen || (event.preventDefault(), handleToggle());
|
|
13750
|
+
}
|
|
12881
13751
|
},
|
|
12882
13752
|
"aria-disabled": disabled,
|
|
13753
|
+
tabIndex: disabled ? -1 : 0,
|
|
13754
|
+
role: "combobox",
|
|
13755
|
+
"aria-haspopup": "listbox",
|
|
13756
|
+
"aria-expanded": isOpen,
|
|
13757
|
+
"aria-controls": id ? `${id}-listbox` : void 0,
|
|
12883
13758
|
children: selectedLabel
|
|
12884
13759
|
}), jsx("i", {
|
|
12885
13760
|
className: `${SELECT.CLASSES.ICON_CARET} ${SELECT.CLASSES.TOGGLE_ICON}`
|
|
@@ -12894,10 +13769,16 @@ const Select = memo((({options: options, value: value, onChange: onChange, onBl
|
|
|
12894
13769
|
ref: panelRef,
|
|
12895
13770
|
children: jsx("ul", {
|
|
12896
13771
|
className: SELECT.CLASSES.SELECT_ITEMS,
|
|
13772
|
+
role: "listbox",
|
|
13773
|
+
id: id ? `${id}-listbox` : void 0,
|
|
13774
|
+
"aria-labelledby": id,
|
|
12897
13775
|
children: hasOptionsProp ? options.map(((option, index) => jsx("li", {
|
|
12898
13776
|
className: SELECT.CLASSES.SELECT_ITEM,
|
|
12899
13777
|
"data-value": option.value,
|
|
12900
13778
|
onClick: () => !option.disabled && handleItemClick(option),
|
|
13779
|
+
role: "option",
|
|
13780
|
+
"aria-selected": value === option.value,
|
|
13781
|
+
"aria-disabled": option.disabled,
|
|
12901
13782
|
children: jsxs("label", {
|
|
12902
13783
|
htmlFor: `SelectItem${index}`,
|
|
12903
13784
|
className: "c-checkbox",
|
|
@@ -14433,7 +15314,45 @@ const ModalImpl = memo((({children: children, isOpen: isOpen = !1, onOpenChange
|
|
|
14433
15314
|
onOpenChange: onOpenChange,
|
|
14434
15315
|
onClose: onClose,
|
|
14435
15316
|
onOpen: onOpen
|
|
14436
|
-
})
|
|
15317
|
+
}), contentRef =
|
|
15318
|
+
/**
|
|
15319
|
+
* Hook to trap focus within an element
|
|
15320
|
+
*/
|
|
15321
|
+
function(isOpen) {
|
|
15322
|
+
const containerRef = useRef(null), previouslyFocusedElement = useRef(null), getFocusableElements = 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 => {
|
|
15323
|
+
// Check if visible
|
|
15324
|
+
const style = window.getComputedStyle(el);
|
|
15325
|
+
return "none" !== style.display && "hidden" !== style.visibility;
|
|
15326
|
+
})) : []), []), handleKeyDown = useCallback((event => {
|
|
15327
|
+
if ("Tab" !== event.key) return;
|
|
15328
|
+
const focusableElements = getFocusableElements();
|
|
15329
|
+
if (0 === focusableElements.length) return;
|
|
15330
|
+
const firstElement = focusableElements[0], lastElement = focusableElements[focusableElements.length - 1];
|
|
15331
|
+
event.shiftKey ?
|
|
15332
|
+
// Shift + Tab
|
|
15333
|
+
document.activeElement === firstElement && (event.preventDefault(), lastElement.focus()) :
|
|
15334
|
+
// Tab
|
|
15335
|
+
document.activeElement === lastElement && (event.preventDefault(), firstElement.focus());
|
|
15336
|
+
}), [ getFocusableElements ]);
|
|
15337
|
+
return useEffect((() => {
|
|
15338
|
+
if (isOpen) {
|
|
15339
|
+
previouslyFocusedElement.current = document.activeElement;
|
|
15340
|
+
const focusableElements = getFocusableElements();
|
|
15341
|
+
if (focusableElements.length > 0 && focusableElements[0]) {
|
|
15342
|
+
// Delay focus slightly to ensure element is rendered
|
|
15343
|
+
const firstEl = focusableElements[0];
|
|
15344
|
+
setTimeout((() => {
|
|
15345
|
+
firstEl.focus();
|
|
15346
|
+
}), 0);
|
|
15347
|
+
}
|
|
15348
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
15349
|
+
} else previouslyFocusedElement.current && previouslyFocusedElement.current.focus(),
|
|
15350
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
15351
|
+
return () => {
|
|
15352
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
15353
|
+
};
|
|
15354
|
+
}), [ isOpen, getFocusableElements, handleKeyDown ]), containerRef;
|
|
15355
|
+
}(isOpenState), instanceId = useId(), titleId = `modal-title-${instanceId}`, descId = `modal-desc-${instanceId}`;
|
|
14437
15356
|
// Handle keyboard events for Escape key
|
|
14438
15357
|
useEffect((() => {
|
|
14439
15358
|
if (!keyboard) return;
|
|
@@ -14451,15 +15370,19 @@ const ModalImpl = memo((({children: children, isOpen: isOpen = !1, onOpenChange
|
|
|
14451
15370
|
return React.isValidElement(child) && _includesInstanceProperty(_context = [ "ModalHeader", "ModalBody", "ModalFooter" ]).call(_context, child.type.displayName);
|
|
14452
15371
|
})), modalContent = jsx("div", {
|
|
14453
15372
|
className: "c-modal__content",
|
|
15373
|
+
ref: contentRef,
|
|
14454
15374
|
children: hasCompoundComponents ? React.Children.map(children, (child => React.isValidElement(child) && "ModalHeader" === child.type.displayName ? React.cloneElement(child, {
|
|
14455
|
-
onClose: child.props.onClose || close
|
|
15375
|
+
onClose: child.props.onClose || close,
|
|
15376
|
+
id: titleId
|
|
14456
15377
|
}) : child)) : jsxs(Fragment, {
|
|
14457
15378
|
children: [ (title || closeButton) && jsx(ModalHeader, {
|
|
15379
|
+
id: titleId,
|
|
14458
15380
|
title: title,
|
|
14459
15381
|
subtitle: subtitle,
|
|
14460
15382
|
closeButton: closeButton,
|
|
14461
15383
|
onClose: close
|
|
14462
15384
|
}), jsx(ModalBody, {
|
|
15385
|
+
id: descId,
|
|
14463
15386
|
children: children
|
|
14464
15387
|
}), footer && jsx(ModalFooter, {
|
|
14465
15388
|
children: footer
|
|
@@ -14477,6 +15400,8 @@ const ModalImpl = memo((({children: children, isOpen: isOpen = !1, onOpenChange
|
|
|
14477
15400
|
role: "dialog",
|
|
14478
15401
|
"aria-modal": "true",
|
|
14479
15402
|
"aria-hidden": !isOpenState,
|
|
15403
|
+
"aria-labelledby": titleId,
|
|
15404
|
+
"aria-describedby": descId,
|
|
14480
15405
|
...props,
|
|
14481
15406
|
children: [ jsx("div", {
|
|
14482
15407
|
ref: backdropRef,
|
|
@@ -14723,7 +15648,27 @@ const Navbar = forwardRef((({brand: brand, children: children, variant: variant
|
|
|
14723
15648
|
return window.addEventListener("resize", handleResize), () => {
|
|
14724
15649
|
window.removeEventListener("resize", handleResize);
|
|
14725
15650
|
};
|
|
14726
|
-
}), [ collapsible, expanded, onToggle ])
|
|
15651
|
+
}), [ collapsible, expanded, onToggle ]),
|
|
15652
|
+
// Handle Escape key to close mobile menu
|
|
15653
|
+
useEffect((() => {
|
|
15654
|
+
if (!navbarExpanded || !closeOnEscape) return;
|
|
15655
|
+
const handleEscapeKey = event => {
|
|
15656
|
+
"Escape" === event.key && ("function" == typeof onToggle ? onToggle(!1) : setNavbarExpanded(!1));
|
|
15657
|
+
};
|
|
15658
|
+
return document.addEventListener("keydown", handleEscapeKey), () => {
|
|
15659
|
+
document.removeEventListener("keydown", handleEscapeKey);
|
|
15660
|
+
};
|
|
15661
|
+
}), [ navbarExpanded, closeOnEscape, onToggle ]),
|
|
15662
|
+
// Handle outside click to close mobile menu
|
|
15663
|
+
useEffect((() => {
|
|
15664
|
+
if (!navbarExpanded || !closeOnOutsideClick) return;
|
|
15665
|
+
const handleClickOutside = event => {
|
|
15666
|
+
!collapseRef.current || collapseRef.current.contains(event.target) || event.target.closest(".c-navbar__toggler") || ("function" == typeof onToggle ? onToggle(!1) : setNavbarExpanded(!1));
|
|
15667
|
+
};
|
|
15668
|
+
return document.addEventListener("mousedown", handleClickOutside), () => {
|
|
15669
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
15670
|
+
};
|
|
15671
|
+
}), [ navbarExpanded, closeOnOutsideClick, onToggle ]);
|
|
14727
15672
|
// Generate the navbar class
|
|
14728
15673
|
const navbarClass = generateNavbarClass({
|
|
14729
15674
|
position: position,
|
|
@@ -17315,7 +18260,235 @@ const SectionIntro = ({title: title, label: label, text: text, actions: actions,
|
|
|
17315
18260
|
SectionIntro.displayName = "SectionIntro";
|
|
17316
18261
|
|
|
17317
18262
|
const Slider = forwardRef(((props, ref) => {
|
|
17318
|
-
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 =
|
|
18263
|
+
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) {
|
|
18264
|
+
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 = useRef(null), wrapperRef = useRef(null), repositioningRef = useRef(!1), autoplayRef = useRef(null), [autoplayRunning, setAutoplayRunning] = useState(!1), sliderStateRef = useRef({
|
|
18265
|
+
isTransitioning: !1,
|
|
18266
|
+
loop: loop,
|
|
18267
|
+
slides: slides,
|
|
18268
|
+
slidesToShow: slidesToShow,
|
|
18269
|
+
speed: speed,
|
|
18270
|
+
onSlideChange: onSlideChange
|
|
18271
|
+
}), [realIndex, setRealIndex] = useState(initialSlide), [internalIndex, setInternalIndex] = useState(0), [isTransitioning, setIsTransitioning] = useState(!1), [containerSize, setContainerSize] = useState(0), [touching, setTouching] = useState(!1), [touchStart, setTouchStart] = useState(0), [dragOffset, setDragOffset] = useState(0), slideWidth = useMemo((() => 0 === containerSize ? 0 : (containerSize - spaceBetween * (slidesToShow - 1)) / slidesToShow), [ containerSize, spaceBetween, slidesToShow ]), allSlides = useMemo((() => loop && 0 !== slides.length ? [ ...slides.map(((slide, i) => ({
|
|
18272
|
+
...slide,
|
|
18273
|
+
id: `set1-${slide.id || i}`
|
|
18274
|
+
}))), ...slides.map(((slide, i) => ({
|
|
18275
|
+
...slide,
|
|
18276
|
+
id: `set2-${slide.id || i}`
|
|
18277
|
+
}))), ...slides.map(((slide, i) => ({
|
|
18278
|
+
...slide,
|
|
18279
|
+
id: `set3-${slide.id || i}`
|
|
18280
|
+
}))) ] : slides), [ slides, loop ]), loopedSlides = slides.length, translateValue = useMemo((() => 0 === slideWidth ? 0 : -internalIndex * slideWidth + dragOffset), [ slideWidth, internalIndex, dragOffset ]);
|
|
18281
|
+
// Update the ref whenever the relevant state/props change
|
|
18282
|
+
useEffect((() => {
|
|
18283
|
+
sliderStateRef.current = {
|
|
18284
|
+
isTransitioning: isTransitioning,
|
|
18285
|
+
loop: loop,
|
|
18286
|
+
slides: slides,
|
|
18287
|
+
slidesToShow: slidesToShow,
|
|
18288
|
+
speed: speed,
|
|
18289
|
+
onSlideChange: onSlideChange
|
|
18290
|
+
};
|
|
18291
|
+
}), [ isTransitioning, loop, slides, slidesToShow, speed, onSlideChange ]),
|
|
18292
|
+
// Autoplay effect
|
|
18293
|
+
useEffect((() => {
|
|
18294
|
+
if (!autoplay) return autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
18295
|
+
autoplayRef.current = null), void setAutoplayRunning(!1);
|
|
18296
|
+
const autoplayParams = "boolean" == typeof autoplay ? {
|
|
18297
|
+
delay: 3e3
|
|
18298
|
+
} : autoplay, {delay: delay = 3e3, pauseOnMouseEnter: pauseOnMouseEnter = !1, disableOnInteraction: disableOnInteraction = !1, reverseDirection: reverseDirection = !1} = autoplayParams;
|
|
18299
|
+
// Clear any existing interval
|
|
18300
|
+
autoplayRef.current && clearInterval(autoplayRef.current),
|
|
18301
|
+
// Create new interval
|
|
18302
|
+
autoplayRef.current = setInterval((() => {
|
|
18303
|
+
// Use ref to get the latest state without resetting the interval
|
|
18304
|
+
const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
|
|
18305
|
+
// We need to use a functional update to get the latest values
|
|
18306
|
+
setRealIndex((prevRealIndex => {
|
|
18307
|
+
if (currentIsTransitioning) return prevRealIndex;
|
|
18308
|
+
// Stop autoplay on interaction if disableOnInteraction is true
|
|
18309
|
+
let nextIndex;
|
|
18310
|
+
// Trigger the slide change
|
|
18311
|
+
if (disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
18312
|
+
autoplayRef.current = null, setAutoplayRunning(!1)), nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
|
|
18313
|
+
reverseDirection) {
|
|
18314
|
+
// For reverse direction, we would go to previous slide
|
|
18315
|
+
const prevIndex = currentLoop ? 0 === prevRealIndex ? currentSlides.length - 1 : prevRealIndex - 1 : Math.max(prevRealIndex - 1, 0);
|
|
18316
|
+
return setInternalIndex(currentLoop ? currentSlides.length + prevIndex : prevIndex),
|
|
18317
|
+
setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
|
|
18318
|
+
setIsTransitioning(!1), currentOnSlideChange?.(prevIndex);
|
|
18319
|
+
}), currentSpeed), prevIndex;
|
|
18320
|
+
}
|
|
18321
|
+
// Normal direction
|
|
18322
|
+
return setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex),
|
|
18323
|
+
setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
|
|
18324
|
+
setIsTransitioning(!1), currentOnSlideChange?.(nextIndex),
|
|
18325
|
+
// Reposition after transition ends for looped sliders
|
|
18326
|
+
currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
|
|
18327
|
+
setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
|
|
18328
|
+
repositioningRef.current = !1;
|
|
18329
|
+
}), 0));
|
|
18330
|
+
}), currentSpeed), nextIndex;
|
|
18331
|
+
}));
|
|
18332
|
+
}), delay), setAutoplayRunning(!0);
|
|
18333
|
+
// Handle pause on mouse enter/leave if enabled
|
|
18334
|
+
let containerElement = null;
|
|
18335
|
+
const handleMouseEnter = () => {
|
|
18336
|
+
autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null,
|
|
18337
|
+
setAutoplayRunning(!1));
|
|
18338
|
+
}, handleMouseLeave = () => {
|
|
18339
|
+
// Restart autoplay
|
|
18340
|
+
autoplayRef.current && clearInterval(autoplayRef.current), autoplayRef.current = setInterval((() => {
|
|
18341
|
+
const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
|
|
18342
|
+
setRealIndex((prevRealIndex => {
|
|
18343
|
+
if (currentIsTransitioning) return prevRealIndex;
|
|
18344
|
+
let nextIndex;
|
|
18345
|
+
return nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
|
|
18346
|
+
setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex), setIsTransitioning(!0),
|
|
18347
|
+
setDragOffset(0), setTimeout((() => {
|
|
18348
|
+
setIsTransitioning(!1), currentOnSlideChange?.(nextIndex), currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
|
|
18349
|
+
setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
|
|
18350
|
+
repositioningRef.current = !1;
|
|
18351
|
+
}), 0));
|
|
18352
|
+
}), currentSpeed), nextIndex;
|
|
18353
|
+
}));
|
|
18354
|
+
}), delay), setAutoplayRunning(!0);
|
|
18355
|
+
};
|
|
18356
|
+
// Cleanup
|
|
18357
|
+
return pauseOnMouseEnter && containerRef.current && (containerElement = containerRef.current,
|
|
18358
|
+
containerElement.addEventListener("mouseenter", handleMouseEnter), containerElement.addEventListener("mouseleave", handleMouseLeave)),
|
|
18359
|
+
() => {
|
|
18360
|
+
autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null),
|
|
18361
|
+
containerElement && (containerElement.removeEventListener("mouseenter", handleMouseEnter),
|
|
18362
|
+
containerElement.removeEventListener("mouseleave", handleMouseLeave)), setAutoplayRunning(!1);
|
|
18363
|
+
};
|
|
18364
|
+
}), [ autoplay, repositioningRef ]),
|
|
18365
|
+
// Initialize
|
|
18366
|
+
useEffect((() => {
|
|
18367
|
+
setInternalIndex(loop ? slides.length + initialSlide : initialSlide);
|
|
18368
|
+
}), [ loop, slides.length, initialSlide ]), useEffect((() => {
|
|
18369
|
+
const updateSize = () => {
|
|
18370
|
+
if (containerRef.current) {
|
|
18371
|
+
const size = "horizontal" === direction ? containerRef.current.offsetWidth : containerRef.current.offsetHeight;
|
|
18372
|
+
setContainerSize(size);
|
|
18373
|
+
}
|
|
18374
|
+
};
|
|
18375
|
+
return updateSize(), window.addEventListener("resize", updateSize), () => window.removeEventListener("resize", updateSize);
|
|
18376
|
+
}), [ direction ]);
|
|
18377
|
+
const slideNext = useCallback((() => {
|
|
18378
|
+
if (!isTransitioning) if (
|
|
18379
|
+
// Stop autoplay on interaction if disableOnInteraction is true
|
|
18380
|
+
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
18381
|
+
autoplayRef.current = null, setAutoplayRunning(!1)), loop) {
|
|
18382
|
+
const nextRealIndex = (realIndex + 1) % slides.length, nextInternalIndex = internalIndex + 1;
|
|
18383
|
+
setRealIndex(nextRealIndex), setInternalIndex(nextInternalIndex), setIsTransitioning(!0),
|
|
18384
|
+
setDragOffset(0), setTimeout((() => {
|
|
18385
|
+
setIsTransitioning(!1), onSlideChange?.(nextRealIndex),
|
|
18386
|
+
// Reposition after transition ends
|
|
18387
|
+
nextInternalIndex >= 2 * slides.length && (repositioningRef.current = !0, setInternalIndex(slides.length + nextRealIndex),
|
|
18388
|
+
setTimeout((() => {
|
|
18389
|
+
repositioningRef.current = !1;
|
|
18390
|
+
}), 0));
|
|
18391
|
+
}), speed);
|
|
18392
|
+
} else {
|
|
18393
|
+
const nextIndex = Math.min(realIndex + 1, slides.length - slidesToShow);
|
|
18394
|
+
setRealIndex(nextIndex), setInternalIndex(nextIndex), setIsTransitioning(!0), setDragOffset(0),
|
|
18395
|
+
setTimeout((() => {
|
|
18396
|
+
setIsTransitioning(!1), onSlideChange?.(nextIndex);
|
|
18397
|
+
}), speed);
|
|
18398
|
+
}
|
|
18399
|
+
}), [ realIndex, internalIndex, slides.length, slidesToShow, loop, isTransitioning, speed, onSlideChange, allSlides.length, loopedSlides, autoplay ]), slidePrev = useCallback((() => {
|
|
18400
|
+
if (!isTransitioning) if (
|
|
18401
|
+
// Stop autoplay on interaction if disableOnInteraction is true
|
|
18402
|
+
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
18403
|
+
autoplayRef.current = null, setAutoplayRunning(!1)), loop) {
|
|
18404
|
+
const prevRealIndex = 0 === realIndex ? slides.length - 1 : realIndex - 1, prevInternalIndex = internalIndex - 1;
|
|
18405
|
+
setRealIndex(prevRealIndex), setInternalIndex(prevInternalIndex), setIsTransitioning(!0),
|
|
18406
|
+
setDragOffset(0), setTimeout((() => {
|
|
18407
|
+
setIsTransitioning(!1), onSlideChange?.(prevRealIndex),
|
|
18408
|
+
// Reposition after transition ends
|
|
18409
|
+
prevInternalIndex < slides.length && (repositioningRef.current = !0, setInternalIndex(slides.length + prevRealIndex),
|
|
18410
|
+
setTimeout((() => {
|
|
18411
|
+
repositioningRef.current = !1;
|
|
18412
|
+
}), 0));
|
|
18413
|
+
}), speed);
|
|
18414
|
+
} else {
|
|
18415
|
+
const prevIndex = Math.max(realIndex - 1, 0);
|
|
18416
|
+
setRealIndex(prevIndex), setInternalIndex(prevIndex), setIsTransitioning(!0), setDragOffset(0),
|
|
18417
|
+
setTimeout((() => {
|
|
18418
|
+
setIsTransitioning(!1), onSlideChange?.(prevIndex);
|
|
18419
|
+
}), speed);
|
|
18420
|
+
}
|
|
18421
|
+
}), [ realIndex, internalIndex, slides.length, loop, isTransitioning, speed, onSlideChange, allSlides.length, loopedSlides, autoplay ]), goToSlide = useCallback((index => {
|
|
18422
|
+
isTransitioning || index === realIndex || (
|
|
18423
|
+
// Stop autoplay on interaction if disableOnInteraction is true
|
|
18424
|
+
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
18425
|
+
autoplayRef.current = null, setAutoplayRunning(!1)), setIsTransitioning(!0), setDragOffset(0),
|
|
18426
|
+
setRealIndex(index), setInternalIndex(loop ? slides.length + index : index), setTimeout((() => {
|
|
18427
|
+
setIsTransitioning(!1), onSlideChange?.(index);
|
|
18428
|
+
}), speed));
|
|
18429
|
+
}), [ realIndex, isTransitioning, speed, onSlideChange, loop, loopedSlides, autoplay ]), handleTouchStart = useCallback((e => {
|
|
18430
|
+
if (!allowTouchMove) return;
|
|
18431
|
+
// Stop autoplay on interaction if disableOnInteraction is true
|
|
18432
|
+
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
18433
|
+
autoplayRef.current = null, setAutoplayRunning(!1));
|
|
18434
|
+
const client = "horizontal" === direction ? "touches" in e ? e.touches[0]?.clientX || 0 : e.clientX : "touches" in e ? e.touches[0]?.clientY || 0 : e.clientY;
|
|
18435
|
+
setTouchStart(client), setTouching(!0), setDragOffset(0);
|
|
18436
|
+
}), [ allowTouchMove, direction, autoplay ]), handleTouchMove = useCallback((e => {
|
|
18437
|
+
if (!touching || !allowTouchMove) return;
|
|
18438
|
+
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;
|
|
18439
|
+
Math.abs(diff) > 10 && (e.preventDefault(), setDragOffset(.5 * -diff));
|
|
18440
|
+
}), [ touching, touchStart, allowTouchMove, direction ]), handleTouchEnd = useCallback((e => {
|
|
18441
|
+
if (!touching || !allowTouchMove) return;
|
|
18442
|
+
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;
|
|
18443
|
+
setTouching(!1), setDragOffset(0), Math.abs(diff) > threshold && (diff > 0 ? slideNext() : slidePrev());
|
|
18444
|
+
}), [ touching, touchStart, threshold, slideNext, slidePrev, allowTouchMove, direction ]), canSlideNext = loop || realIndex < slides.length - slidesToShow, canSlidePrev = loop || realIndex > 0;
|
|
18445
|
+
return {
|
|
18446
|
+
activeIndex: realIndex,
|
|
18447
|
+
realIndex: realIndex,
|
|
18448
|
+
previousIndex: realIndex,
|
|
18449
|
+
isBeginning: !loop && 0 === realIndex,
|
|
18450
|
+
isEnd: !loop && realIndex >= slides.length - slidesToShow,
|
|
18451
|
+
progress: slides.length > 0 ? realIndex / (slides.length - 1) : 0,
|
|
18452
|
+
autoplayRunning: autoplayRunning,
|
|
18453
|
+
transitioning: isTransitioning,
|
|
18454
|
+
touching: touching,
|
|
18455
|
+
translate: translateValue,
|
|
18456
|
+
slidesPerView: slidesToShow,
|
|
18457
|
+
slidesCount: slides.length,
|
|
18458
|
+
isLocked: !1,
|
|
18459
|
+
destroyed: !1,
|
|
18460
|
+
size: containerSize,
|
|
18461
|
+
touches: {
|
|
18462
|
+
startX: 0,
|
|
18463
|
+
startY: 0,
|
|
18464
|
+
currentX: 0,
|
|
18465
|
+
currentY: 0,
|
|
18466
|
+
diff: 0
|
|
18467
|
+
},
|
|
18468
|
+
allowSlideNext: canSlideNext,
|
|
18469
|
+
allowSlidePrev: canSlidePrev,
|
|
18470
|
+
allowTouchMove: allowTouchMove,
|
|
18471
|
+
animating: isTransitioning,
|
|
18472
|
+
enabled: !0,
|
|
18473
|
+
initialized: !0,
|
|
18474
|
+
slideNext: slideNext,
|
|
18475
|
+
slidePrev: slidePrev,
|
|
18476
|
+
goToSlide: goToSlide,
|
|
18477
|
+
canSlideNext: canSlideNext,
|
|
18478
|
+
canSlidePrev: canSlidePrev,
|
|
18479
|
+
containerRef: containerRef,
|
|
18480
|
+
wrapperRef: wrapperRef,
|
|
18481
|
+
handleTouchStart: handleTouchStart,
|
|
18482
|
+
handleTouchMove: handleTouchMove,
|
|
18483
|
+
handleTouchEnd: handleTouchEnd,
|
|
18484
|
+
allSlides: allSlides,
|
|
18485
|
+
translateValue: translateValue,
|
|
18486
|
+
slideWidth: slideWidth,
|
|
18487
|
+
currentSlidesToShow: slidesToShow,
|
|
18488
|
+
loopedSlides: loopedSlides,
|
|
18489
|
+
repositioningRef: repositioningRef
|
|
18490
|
+
};
|
|
18491
|
+
}({
|
|
17319
18492
|
slides: validSlides,
|
|
17320
18493
|
slidesToShow: slidesToShow,
|
|
17321
18494
|
spaceBetween: spaceBetween,
|
|
@@ -17342,7 +18515,8 @@ const Slider = forwardRef(((props, ref) => {
|
|
|
17342
18515
|
})
|
|
17343
18516
|
});
|
|
17344
18517
|
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(" ");
|
|
17345
|
-
|
|
18518
|
+
// Keyboard navigation
|
|
18519
|
+
return jsxs("div", {
|
|
17346
18520
|
ref: ref || containerRef,
|
|
17347
18521
|
className: containerClasses,
|
|
17348
18522
|
style: {
|
|
@@ -17360,9 +18534,32 @@ const Slider = forwardRef(((props, ref) => {
|
|
|
17360
18534
|
onMouseMove: handleTouchMove,
|
|
17361
18535
|
onMouseUp: handleTouchEnd,
|
|
17362
18536
|
onMouseLeave: handleTouchEnd,
|
|
18537
|
+
onKeyDown: event => {
|
|
18538
|
+
switch (event.key) {
|
|
18539
|
+
case "ArrowLeft":
|
|
18540
|
+
"horizontal" === direction && (event.preventDefault(), slidePrev());
|
|
18541
|
+
break;
|
|
18542
|
+
|
|
18543
|
+
case "ArrowRight":
|
|
18544
|
+
"horizontal" === direction && (event.preventDefault(), slideNext());
|
|
18545
|
+
break;
|
|
18546
|
+
|
|
18547
|
+
case "ArrowUp":
|
|
18548
|
+
"vertical" === direction && (event.preventDefault(), slidePrev());
|
|
18549
|
+
break;
|
|
18550
|
+
|
|
18551
|
+
case "ArrowDown":
|
|
18552
|
+
"vertical" === direction && (event.preventDefault(), slideNext());
|
|
18553
|
+
}
|
|
18554
|
+
},
|
|
18555
|
+
role: "region",
|
|
18556
|
+
"aria-roledescription": "carousel",
|
|
18557
|
+
"aria-label": rest["aria-label"] || "Image slider",
|
|
18558
|
+
tabIndex: 0,
|
|
17363
18559
|
children: [ jsx("div", {
|
|
17364
18560
|
ref: wrapperRef,
|
|
17365
18561
|
className: "c-slider__wrapper",
|
|
18562
|
+
"aria-live": autoplay ? "off" : "polite",
|
|
17366
18563
|
style: {
|
|
17367
18564
|
display: "flex",
|
|
17368
18565
|
flexDirection: "vertical" === direction ? "column" : "row",
|
|
@@ -17540,15 +18737,24 @@ Steps.displayName = "Steps", Steps.Item = StepsItem, Steps.Step = StepsItem;
|
|
|
17540
18737
|
// Context for compound usage
|
|
17541
18738
|
const TabsContext = createContext({
|
|
17542
18739
|
currentTab: 0,
|
|
17543
|
-
handleTabClick: () => {}
|
|
17544
|
-
|
|
17545
|
-
|
|
17546
|
-
|
|
17547
|
-
|
|
17548
|
-
|
|
17549
|
-
|
|
17550
|
-
|
|
17551
|
-
|
|
18740
|
+
handleTabClick: () => {},
|
|
18741
|
+
handleKeyDown: () => {},
|
|
18742
|
+
totalTabs: 0
|
|
18743
|
+
}), TabsList = forwardRef((({children: children, className: className = "", onKeyDown: onKeyDown, ...props}, ref) => {
|
|
18744
|
+
const {handleKeyDown: contextHandleKeyDown} = useContext(TabsContext), totalTabs = React.Children.count(children);
|
|
18745
|
+
return jsx("ul", {
|
|
18746
|
+
ref: ref,
|
|
18747
|
+
className: `c-tabs__nav ${className}`.trim(),
|
|
18748
|
+
role: "tablist",
|
|
18749
|
+
onKeyDown: e => {
|
|
18750
|
+
contextHandleKeyDown(e, totalTabs), onKeyDown?.(e);
|
|
18751
|
+
},
|
|
18752
|
+
...props,
|
|
18753
|
+
children: React.Children.map(children, ((child, index) => React.isValidElement(child) ? React.cloneElement(child, {
|
|
18754
|
+
index: index
|
|
18755
|
+
}) : child))
|
|
18756
|
+
});
|
|
18757
|
+
}));
|
|
17552
18758
|
|
|
17553
18759
|
// Compound components
|
|
17554
18760
|
TabsList.displayName = "TabsList";
|
|
@@ -17560,8 +18766,10 @@ const TabsTrigger = forwardRef((({children: children, className: className = ""
|
|
|
17560
18766
|
const isActive = void 0 !== index && currentTab === index;
|
|
17561
18767
|
return jsx("li", {
|
|
17562
18768
|
className: "c-tabs__nav-item",
|
|
18769
|
+
role: "presentation",
|
|
17563
18770
|
children: jsx("button", {
|
|
17564
18771
|
ref: ref,
|
|
18772
|
+
id: `tab-nav-${index}`,
|
|
17565
18773
|
className: `c-tabs__nav-btn ${isActive ? TAB.CLASSES.ACTIVE : ""} ${className}`.trim(),
|
|
17566
18774
|
onClick: e => {
|
|
17567
18775
|
void 0 !== index && handleTabClick(index), onClick?.(e);
|
|
@@ -17570,6 +18778,7 @@ const TabsTrigger = forwardRef((({children: children, className: className = ""
|
|
|
17570
18778
|
role: "tab",
|
|
17571
18779
|
"aria-selected": isActive,
|
|
17572
18780
|
"aria-controls": `tab-panel-${index}`,
|
|
18781
|
+
tabIndex: isActive ? 0 : -1,
|
|
17573
18782
|
type: "button",
|
|
17574
18783
|
...props,
|
|
17575
18784
|
children: children
|
|
@@ -17619,24 +18828,59 @@ TabsPanel.displayName = "TabsPanel";
|
|
|
17619
18828
|
const Tabs = memo((({items: items, activeIndex: activeIndex = TAB.DEFAULTS.ACTIVE_INDEX, onTabChange: onTabChange, className: className = "", style: style, glass: glass, children: children}) => {
|
|
17620
18829
|
const [currentTab, setCurrentTab] = useState(activeIndex), handleTabClick = index => {
|
|
17621
18830
|
setCurrentTab(index), onTabChange && onTabChange(index);
|
|
18831
|
+
}, handleKeyDown = (event, totalTabs) => {
|
|
18832
|
+
let newIndex = currentTab;
|
|
18833
|
+
switch (event.key) {
|
|
18834
|
+
case "ArrowRight":
|
|
18835
|
+
newIndex = (currentTab + 1) % totalTabs;
|
|
18836
|
+
break;
|
|
18837
|
+
|
|
18838
|
+
case "ArrowLeft":
|
|
18839
|
+
newIndex = (currentTab - 1 + totalTabs) % totalTabs;
|
|
18840
|
+
break;
|
|
18841
|
+
|
|
18842
|
+
case "Home":
|
|
18843
|
+
newIndex = 0;
|
|
18844
|
+
break;
|
|
18845
|
+
|
|
18846
|
+
case "End":
|
|
18847
|
+
newIndex = totalTabs - 1;
|
|
18848
|
+
break;
|
|
18849
|
+
|
|
18850
|
+
default:
|
|
18851
|
+
return;
|
|
18852
|
+
}
|
|
18853
|
+
event.preventDefault(), handleTabClick(newIndex),
|
|
18854
|
+
// Focus the newly active tab after it renders
|
|
18855
|
+
setTimeout((() => {
|
|
18856
|
+
const tabElement = document.getElementById(`tab-nav-${newIndex}`);
|
|
18857
|
+
tabElement && tabElement.focus();
|
|
18858
|
+
}), 0);
|
|
17622
18859
|
};
|
|
17623
18860
|
// Handle tab change
|
|
17624
18861
|
// Determine content based on mode (legacy items vs compound children)
|
|
17625
18862
|
let content;
|
|
17626
18863
|
// Use items prop if provided
|
|
17627
|
-
|
|
17628
|
-
|
|
18864
|
+
if (items && items.length > 0)
|
|
18865
|
+
// Legacy mode
|
|
18866
|
+
content = jsxs(Fragment, {
|
|
17629
18867
|
children: [ jsx("ul", {
|
|
17630
18868
|
className: "c-tabs__nav",
|
|
18869
|
+
role: "tablist",
|
|
18870
|
+
onKeyDown: e => handleKeyDown(e, items.length),
|
|
17631
18871
|
children: items.map(((item, index) => jsx("li", {
|
|
17632
18872
|
className: "c-tabs__nav-item",
|
|
18873
|
+
role: "presentation",
|
|
17633
18874
|
children: jsx("button", {
|
|
18875
|
+
id: `tab-nav-${index}`,
|
|
17634
18876
|
className: `c-tabs__nav-btn ${index === currentTab ? TAB.CLASSES.ACTIVE : ""}`,
|
|
17635
18877
|
onClick: () => handleTabClick(index),
|
|
17636
18878
|
"data-tabindex": index,
|
|
17637
18879
|
role: "tab",
|
|
17638
18880
|
"aria-selected": index === currentTab,
|
|
17639
18881
|
"aria-controls": `tab-panel-${index}`,
|
|
18882
|
+
tabIndex: index === currentTab ? 0 : -1,
|
|
18883
|
+
type: "button",
|
|
17640
18884
|
children: item.label
|
|
17641
18885
|
})
|
|
17642
18886
|
}, `tab-nav-${index}`)))
|
|
@@ -17660,13 +18904,19 @@ const Tabs = memo((({items: items, activeIndex: activeIndex = TAB.DEFAULTS.ACTI
|
|
|
17660
18904
|
})
|
|
17661
18905
|
}, `tab-panel-${index}`)))
|
|
17662
18906
|
}) ]
|
|
17663
|
-
})
|
|
17664
|
-
|
|
17665
|
-
|
|
17666
|
-
|
|
17667
|
-
|
|
17668
|
-
|
|
17669
|
-
|
|
18907
|
+
}); else {
|
|
18908
|
+
// Compound mode
|
|
18909
|
+
const tabsList = React.Children.toArray(children).find((child => React.isValidElement(child) && "TabsList" === child.type.displayName)), totalTabsCount = tabsList ? React.Children.count(tabsList.props.children) : 0;
|
|
18910
|
+
content = jsx(TabsContext.Provider, {
|
|
18911
|
+
value: {
|
|
18912
|
+
currentTab: currentTab,
|
|
18913
|
+
handleTabClick: handleTabClick,
|
|
18914
|
+
handleKeyDown: handleKeyDown,
|
|
18915
|
+
totalTabs: totalTabsCount
|
|
18916
|
+
},
|
|
18917
|
+
children: children
|
|
18918
|
+
});
|
|
18919
|
+
}
|
|
17670
18920
|
const wrapper = jsx("div", {
|
|
17671
18921
|
className: `c-tabs js-atomix-tab ${className}`,
|
|
17672
18922
|
style: style,
|
|
@@ -17757,7 +19007,7 @@ const Testimonial = ({quote: quote, author: author, size: size = "", skeleton: s
|
|
|
17757
19007
|
className: "c-testimonial__author",
|
|
17758
19008
|
children: [ author.avatarSrc && jsx("img", {
|
|
17759
19009
|
src: author.avatarSrc,
|
|
17760
|
-
alt: author.avatarAlt ||
|
|
19010
|
+
alt: author.avatarAlt || `${author.name}'s avatar`,
|
|
17761
19011
|
className: "c-testimonial__author-avatar c-avatar c-avatar--xxl c-avatar--circle"
|
|
17762
19012
|
}), jsxs("div", {
|
|
17763
19013
|
className: "c-testimonial__info",
|
|
@@ -18033,7 +19283,17 @@ const Tooltip = memo((({content: content, children: children, position: positio
|
|
|
18033
19283
|
cancelAnimationFrame(rafId), window.removeEventListener("resize", handleUpdate),
|
|
18034
19284
|
window.removeEventListener("scroll", handleUpdate, !0);
|
|
18035
19285
|
};
|
|
18036
|
-
}), [ isVisible, updatePosition ])
|
|
19286
|
+
}), [ isVisible, updatePosition ]),
|
|
19287
|
+
// Handle Escape key to close tooltip
|
|
19288
|
+
useEffect((() => {
|
|
19289
|
+
if (!isVisible) return;
|
|
19290
|
+
const handleKeyDown = event => {
|
|
19291
|
+
"Escape" === event.key && hideTooltip();
|
|
19292
|
+
};
|
|
19293
|
+
return document.addEventListener("keydown", handleKeyDown), () => {
|
|
19294
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
19295
|
+
};
|
|
19296
|
+
}), [ isVisible, hideTooltip ]);
|
|
18037
19297
|
// Setup trigger props
|
|
18038
19298
|
const triggerProps = {
|
|
18039
19299
|
"aria-describedby": isVisible ? tooltipId : void 0
|
|
@@ -18722,9 +19982,15 @@ const VideoPlayer = forwardRef((({src: src, type: type = "video", youtubeId: yo
|
|
|
18722
19982
|
const rect = e.currentTarget.getBoundingClientRect(), percent = (e.clientX - rect.left) / rect.width;
|
|
18723
19983
|
setVolume(percent);
|
|
18724
19984
|
}), [ setVolume ]), handleDownload = useCallback((() => {
|
|
18725
|
-
if (src) {
|
|
18726
|
-
|
|
18727
|
-
|
|
19985
|
+
if (src) try {
|
|
19986
|
+
var _context;
|
|
19987
|
+
const url = new URL(src, window.location.origin);
|
|
19988
|
+
if (_includesInstanceProperty(_context = [ "http:", "https:", "blob:", "data:" ]).call(_context, url.protocol)) {
|
|
19989
|
+
const a = document.createElement("a");
|
|
19990
|
+
a.href = url.href, a.download = "video", a.click();
|
|
19991
|
+
}
|
|
19992
|
+
} catch (e) {
|
|
19993
|
+
// Ignore invalid URLs
|
|
18728
19994
|
}
|
|
18729
19995
|
}), [ src ]), handleShare = useCallback((async () => {
|
|
18730
19996
|
if (navigator.share) try {
|
|
@@ -19301,6 +20567,7 @@ const components = Object.freeze( Object.defineProperty({
|
|
|
19301
20567
|
TODO: TODO,
|
|
19302
20568
|
TOGGLE: TOGGLE,
|
|
19303
20569
|
TOOLTIP: TOOLTIP,
|
|
20570
|
+
TYPEDBUTTON: TYPEDBUTTON,
|
|
19304
20571
|
UPLOAD: UPLOAD,
|
|
19305
20572
|
VIDEO_PLAYER: VIDEO_PLAYER,
|
|
19306
20573
|
sliderConstants: sliderConstants
|
|
@@ -25243,5 +26510,5 @@ const atomix = {
|
|
|
25243
26510
|
types: types
|
|
25244
26511
|
};
|
|
25245
26512
|
|
|
25246
|
-
export { ACCORDION, ATOMIX_GLASS, AVATAR, AVATAR_GROUP, Accordion, AreaChart, AtomixGlass, AtomixLogo, Avatar, AvatarGroup, BADGE, BADGE_CSS_VARS, BLOCK, BREADCRUMB, BUTTON, BUTTON_CSS_VARS, BUTTON_GROUP, Badge, BarChart, Block, Breadcrumb, BubbleChart, Button, ButtonGroup, CALLOUT, CARD, CARD_CSS_VARS, CHART, CHECKBOX_CSS_VARS, CLASS_PREFIX, CODE_SNIPPET, COMPONENT_CSS_VARS, COUNTDOWN, Callout, CandlestickChart, Card, Chart, ChartRenderer, Checkbox, ColorModeToggle, Container, Countdown, DATA_TABLE_CLASSES, DATA_TABLE_SELECTORS, DATEPICKER, DEFAULT_ATOMIX_FONTS,
|
|
26513
|
+
export { ACCORDION, ATOMIX_GLASS, AVATAR, AVATAR_GROUP, Accordion, AreaChart, AtomixGlass, AtomixLogo, Avatar, AvatarGroup, BADGE, BADGE_CSS_VARS, BALANCED_PRESET, BLOCK, BREADCRUMB, BUTTON, BUTTON_CSS_VARS, BUTTON_GROUP, Badge, BarChart, Block, Breadcrumb, BubbleChart, Button, ButtonGroup, CALLOUT, CARD, CARD_CSS_VARS, CHART, CHECKBOX_CSS_VARS, CLASS_PREFIX, CODE_SNIPPET, COMPONENT_CSS_VARS, COUNTDOWN, Callout, CandlestickChart, Card, Chart, ChartRenderer, Checkbox, ColorModeToggle, Container, Countdown, DATA_TABLE_CLASSES, DATA_TABLE_SELECTORS, DATEPICKER, DEFAULT_ATOMIX_FONTS, DEFAULT_BREAKPOINTS, DROPDOWN, DROPDOWN_CSS_VARS, DataTable, DatePicker, DesignTokensCustomizer, DeviceDetector, DonutChart, Dropdown, EDGE_PANEL, EdgePanel, ElevationCard, FOOTER, FORM, FORM_GROUP, Footer, FooterLink, FooterSection, FooterSocialLink, Form, FormGroup, FunnelChart, GaugeChart, Grid, GridCol, HERO, HeatmapChart, Hero, INPUT, INPUT_CSS_VARS, Icon, Input, LIST, LIST_GROUP, LineChart, List, ListGroup, MESSAGES, MOBILE_OPTIMIZED_BREAKPOINTS, MODAL, MODAL_CSS_VARS, MasonryGrid, MasonryGridItem, MegaMenu, MegaMenuColumn, MegaMenuLink, Menu, MenuDivider, MenuItem, Messages, Modal, MultiAxisChart, NAV, NAVBAR, Nav, NavDropdown, NavItem, Navbar, PAGINATION_DEFAULTS, PERFORMANCE_PRESET, PHOTOVIEWER, POPOVER, PROGRESS, PROGRESS_CSS_VARS, Pagination, PerformanceOverlay, PhotoViewer, PieChart, Popover, ProductReview, Progress, QUALITY_PRESET, RADIO, RADIO_CSS_VARS, RATING, RIVER, RTLManager, RadarChart, Radio, Rating, River, Row, SECTION_INTRO, SELECT, SIDE_MENU, SIZES, SLIDER, SPINNER, STEPS, ScatterChart, SectionIntro, Select, SideMenu, SideMenuItem, SideMenuList, Slider, Spinner, Steps, TAB, TABS_CSS_VARS, TESTIMONIAL, TEXTAREA, THEME_COLORS, THEME_NAMING, TODO, TOGGLE, TOOLTIP, TOOLTIP_CSS_VARS, TYPEDBUTTON, Tabs, Testimonial, Textarea, ThemeApplicator, ThemeComparator, ThemeContext, ThemeErrorBoundary, ThemeInspector, ThemeLiveEditor, ThemePreview, ThemeProvider, ThemeValidator, Todo, Toggle, Tooltip, TreemapChart, UPLOAD, Upload, VIDEO_PLAYER, VideoPlayer, WaterfallChart, applyCSSVariables, applyCSSVarsToStyle, applyComponentTheme, applyPartStyles, applyTheme, camelToKebab, clearThemes, composables, constants, createBreakpoints$1 as createBreakpoints, createCSSVarStyle, createDarkVariant, createDebugAttrs, createFontPreloadLink, createPartProps, createSlotComponent, createSlotProps, createTheme, createThemeRegistry, createTokens, cssVarsToStyle, deepMerge, atomix as default, defaultTokens, defineConfig, designTokensToCSSVars, exportTheme, extendTheme, extractComponentName, extractYouTubeId, generateCSSVariableName, generateCSSVariables$1 as generateCSSVariables, generateCSSVariablesForSelector, generateClassName, generateComponentCSSVars, generateFontPreloadTags, generateUUID, getAllThemes, getCSSVariable, getComponentCSSVars, getComponentThemeValue, getDefaultBreakpoints, getDevicePreset, getMobileOptimizedParams, getPartStyles, getQualityMultipliers, getTheme, getThemeApplicator, getThemeCount, getThemeIds, getThemeMetadata, hasCustomization, hasTheme, importTheme, injectCSS$1 as injectCSS, injectTheme, isCSSInjected, isDesignTokens, isSlot, isValidCSSVariableName, isYouTubeUrl, mapSCSSTokensToCSSVars, mergeCSSVars, mergeClassNames, mergeComponentProps, mergePartStyles, mergeSlots, mergeTheme, normalizeThemeTokens, preloadFonts, quickTheme, registerTheme, removeCSS, removeCSSVariables, removeTheme, renderSlot, sliderConstants, supportsDarkMode, theme, themePropertyToCSSVar, themeToCSS, types, unregisterTheme, useAccordion, useAtomixGlass, useBadge, useBarChart, useBlock, useChartData, useChartInteraction, useChartScale, useComponentCustomization, useComponentDefaultProps, useComponentTheme, useEdgePanel, useForm, useFormGroup, useHero, useHistory, useInput, useLineChart, useMergedProps, useNav, useNavDropdown, useNavItem, useNavbar, usePerformanceMonitor, usePieChart, useRadio, useResponsiveGlass, useRiver, useSelect, useSideMenu, useSideMenuItem, useSlot, useSpinner, useTextarea, useTheme, useThemeTokens, useTodo, utils, validateTheme };
|
|
25247
26514
|
//# sourceMappingURL=index.esm.js.map
|