@shohojdhara/atomix 0.4.8 → 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 +148 -120
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.d.ts +33 -0
- package/dist/charts.js +1227 -122
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +33 -10
- package/dist/core.js +1052 -41
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +33 -0
- package/dist/forms.js +2086 -1035
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +42 -1
- package/dist/heavy.js +1620 -600
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +441 -270
- package/dist/index.esm.js +1900 -638
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1935 -670
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +6 -3
- package/scripts/atomix-cli.js +148 -4
- package/scripts/cli/__tests__/basic.test.js +3 -2
- package/scripts/cli/__tests__/clean.test.js +278 -0
- package/scripts/cli/__tests__/component-validator.test.js +433 -0
- package/scripts/cli/__tests__/generator.test.js +613 -0
- package/scripts/cli/__tests__/glass-motion.test.js +256 -0
- package/scripts/cli/__tests__/integration.test.js +719 -108
- package/scripts/cli/__tests__/migrate.test.js +74 -0
- package/scripts/cli/__tests__/security.test.js +206 -0
- package/scripts/cli/__tests__/test-setup.js +3 -1
- package/scripts/cli/__tests__/theme-bridge.test.js +507 -0
- package/scripts/cli/__tests__/token-provider.test.js +361 -0
- package/scripts/cli/__tests__/utils.test.js +5 -5
- package/scripts/cli/commands/benchmark.js +105 -0
- package/scripts/cli/commands/build-theme.js +4 -1
- package/scripts/cli/commands/clean.js +109 -0
- package/scripts/cli/commands/doctor.js +88 -0
- package/scripts/cli/commands/generate.js +135 -14
- package/scripts/cli/commands/init.js +45 -18
- package/scripts/cli/commands/migrate.js +106 -0
- package/scripts/cli/commands/sync-tokens.js +206 -0
- package/scripts/cli/commands/theme-bridge.js +248 -0
- package/scripts/cli/commands/tokens.js +157 -0
- package/scripts/cli/commands/validate.js +194 -0
- package/scripts/cli/internal/ai-engine.js +156 -0
- package/scripts/cli/internal/component-validator.js +443 -0
- package/scripts/cli/internal/config-loader.js +162 -0
- package/scripts/cli/internal/filesystem.js +102 -2
- package/scripts/cli/internal/generator.js +359 -39
- package/scripts/cli/internal/glass-generator.js +398 -0
- package/scripts/cli/internal/hook-generator.js +369 -0
- package/scripts/cli/internal/hooks.js +61 -0
- package/scripts/cli/internal/itcss-generator.js +565 -0
- package/scripts/cli/internal/motion-generator.js +679 -0
- package/scripts/cli/internal/template-engine.js +301 -0
- package/scripts/cli/internal/theme-bridge.js +664 -0
- package/scripts/cli/internal/tokens/engine.js +122 -0
- package/scripts/cli/internal/tokens/provider.js +34 -0
- package/scripts/cli/internal/tokens/providers/figma.js +50 -0
- package/scripts/cli/internal/tokens/providers/style-dictionary.js +48 -0
- package/scripts/cli/internal/tokens/providers/w3c.js +48 -0
- package/scripts/cli/internal/tokens/token-provider.js +443 -0
- package/scripts/cli/internal/tokens/token-validator.js +513 -0
- package/scripts/cli/internal/validator.js +276 -0
- package/scripts/cli/internal/wizard.js +60 -6
- package/scripts/cli/mappings.js +23 -0
- package/scripts/cli/migration-tools.js +164 -94
- package/scripts/cli/plugins/style-dictionary.js +46 -0
- package/scripts/cli/templates/README.md +525 -95
- package/scripts/cli/templates/common-templates.js +40 -14
- package/scripts/cli/templates/components/react-component.ts +282 -0
- package/scripts/cli/templates/config/project-config.ts +112 -0
- package/scripts/cli/templates/hooks/use-component.ts +477 -0
- package/scripts/cli/templates/index.js +19 -4
- package/scripts/cli/templates/index.ts +171 -0
- package/scripts/cli/templates/next-templates.js +72 -0
- package/scripts/cli/templates/react-templates.js +70 -126
- package/scripts/cli/templates/scss-templates.js +35 -35
- package/scripts/cli/templates/stories/storybook-story.ts +241 -0
- package/scripts/cli/templates/styles/scss-component.ts +255 -0
- package/scripts/cli/templates/tests/vitest-test.ts +229 -0
- package/scripts/cli/templates/token-templates.js +337 -1
- package/scripts/cli/templates/tokens/token-generators.ts +1088 -0
- package/scripts/cli/templates/types/component-types.ts +145 -0
- package/scripts/cli/templates/utils/testing-utils.ts +144 -0
- package/scripts/cli/templates/vanilla-templates.js +39 -0
- package/scripts/cli/token-manager.js +8 -2
- package/scripts/cli/utils/cache-manager.js +240 -0
- package/scripts/cli/utils/detector.js +46 -0
- package/scripts/cli/utils/diagnostics.js +289 -0
- package/scripts/cli/utils/error.js +45 -3
- package/scripts/cli/utils/helpers.js +24 -0
- package/scripts/cli/utils/logger.js +1 -1
- package/scripts/cli/utils/security.js +302 -0
- package/scripts/cli/utils/telemetry.js +115 -0
- package/scripts/cli/utils/validation.js +4 -38
- package/scripts/cli/utils.js +46 -0
- package/src/components/Accordion/Accordion.stories.tsx +0 -18
- package/src/components/Accordion/Accordion.test.tsx +0 -17
- package/src/components/Accordion/Accordion.tsx +0 -4
- package/src/components/AtomixGlass/AtomixGlass.tsx +102 -2
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +125 -12
- package/src/components/AtomixGlass/PerformanceDashboard.tsx +219 -0
- package/src/components/AtomixGlass/README.md +25 -10
- package/src/components/AtomixGlass/animation-system.ts +578 -0
- package/src/components/AtomixGlass/shader-utils.ts +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 +144 -5
- package/src/lib/composables/useChartExport.ts +3 -13
- package/src/lib/composables/useDropdown.ts +66 -0
- package/src/lib/composables/useFocusTrap.ts +80 -0
- package/src/lib/composables/usePerformanceMonitor.ts +448 -0
- package/src/lib/composables/useResponsiveGlass.presets.ts +192 -0
- package/src/lib/composables/useResponsiveGlass.ts +441 -0
- package/src/lib/composables/useTooltip.ts +16 -0
- package/src/lib/composables/useTypedButton.ts +66 -0
- package/src/lib/config/index.ts +62 -5
- package/src/lib/constants/components.ts +55 -0
- package/src/lib/theme/devtools/__tests__/useHistory.test.tsx +150 -0
- package/src/lib/theme/tokens/centralized-tokens.ts +120 -0
- package/src/lib/theme/utils/__tests__/domUtils.test.ts +101 -0
- package/src/lib/types/components.ts +37 -11
- package/src/lib/types/glass.ts +35 -0
- package/src/lib/types/index.ts +1 -0
- package/src/lib/utils/displacement-generator.ts +1 -1
- package/src/styles/01-settings/_settings.testtypecheck.scss +53 -0
- package/src/styles/01-settings/_settings.typedbutton.scss +53 -0
- package/src/styles/06-components/_components.testbutton.scss +212 -0
- package/src/styles/06-components/_components.testtypecheck.scss +212 -0
- package/src/styles/06-components/_components.typedbutton.scss +212 -0
- package/src/styles/99-utilities/_index.scss +1 -0
- package/src/styles/99-utilities/_utilities.text.scss +1 -1
- package/src/styles/99-utilities/_utilities.touch-target.scss +36 -0
- package/src/styles/06-components/old.chart.styles.scss +0 -2788
package/dist/index.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",
|
|
@@ -1727,7 +1735,16 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1727
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
1750
|
ACTIVATION_ZONE: 200,
|
|
@@ -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;
|
|
@@ -2197,14 +2250,16 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2197
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 = {
|
|
2198
2251
|
width: 0,
|
|
2199
2252
|
height: 0
|
|
2200
|
-
}, 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) => {
|
|
2201
2256
|
// Generate a stable, deterministic ID for SSR compatibility
|
|
2202
2257
|
// Use a module-level counter that's consistent across server and client
|
|
2203
|
-
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);
|
|
2204
2259
|
// Lazy load shader utilities only when shader mode is needed
|
|
2205
2260
|
useEffect((() => {
|
|
2206
2261
|
"shader" === mode ?
|
|
2207
|
-
// Dynamic import shader utilities
|
|
2262
|
+
// Dynamic import shader utilities with animation support
|
|
2208
2263
|
Promise.resolve().then((() => shaderUtils)).then((shaderUtils => {
|
|
2209
2264
|
shaderUtilsRef.current = {
|
|
2210
2265
|
ShaderDisplacementGenerator: shaderUtils.ShaderDisplacementGenerator,
|
|
@@ -2219,7 +2274,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2219
2274
|
// Generate shader map with debouncing and caching
|
|
2220
2275
|
useEffect((() => {
|
|
2221
2276
|
// Enhanced validation for shader mode
|
|
2222
|
-
if ("shader" === mode && glassSize && validateGlassSize(glassSize)
|
|
2277
|
+
if ("shader" === mode && glassSize && validateGlassSize(glassSize)) {
|
|
2223
2278
|
// Create cache key from size and variant
|
|
2224
2279
|
const cacheKey = `${glassSize.width}x${glassSize.height}-${shaderVariant}`, cachedUrl = (key => {
|
|
2225
2280
|
const entry = sharedShaderCache.get(key);
|
|
@@ -2241,11 +2296,9 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2241
2296
|
width: glassSize.width,
|
|
2242
2297
|
height: glassSize.height,
|
|
2243
2298
|
fragment: selectedShader
|
|
2244
|
-
}),
|
|
2245
|
-
// Defer shader generation with longer delay to avoid blocking
|
|
2246
|
-
setTimeout((() => {
|
|
2299
|
+
}), shaderUpdateTimeoutRef.current = setTimeout((() => {
|
|
2247
2300
|
const url = shaderGeneratorRef.current?.updateShader() || "";
|
|
2248
|
-
((key, url) => {
|
|
2301
|
+
url && ((key, url) => {
|
|
2249
2302
|
// Evict oldest entries if at capacity
|
|
2250
2303
|
if (sharedShaderCache.size >= 15) {
|
|
2251
2304
|
const entries = Array.from(sharedShaderCache.entries());
|
|
@@ -2277,7 +2330,8 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2277
2330
|
// Cleanup function with error handling
|
|
2278
2331
|
return () => {
|
|
2279
2332
|
shaderDebounceTimeoutRef.current && (clearTimeout(shaderDebounceTimeoutRef.current),
|
|
2280
|
-
shaderDebounceTimeoutRef.current = null)
|
|
2333
|
+
shaderDebounceTimeoutRef.current = null), shaderUpdateTimeoutRef.current && (clearTimeout(shaderUpdateTimeoutRef.current),
|
|
2334
|
+
shaderUpdateTimeoutRef.current = null);
|
|
2281
2335
|
try {
|
|
2282
2336
|
shaderGeneratorRef.current?.destroy();
|
|
2283
2337
|
} catch (error) {
|
|
@@ -2286,7 +2340,37 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
2286
2340
|
shaderGeneratorRef.current = null;
|
|
2287
2341
|
}
|
|
2288
2342
|
};
|
|
2289
|
-
}), [ 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 ]);
|
|
2290
2374
|
// Removed forced reflow to avoid layout thrash and potential feedback sizing loops
|
|
2291
2375
|
const [rectCache, setRectCache] = useState(null);
|
|
2292
2376
|
useEffect((() => {
|
|
@@ -2620,12 +2704,144 @@ class {
|
|
|
2620
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)"),
|
|
2621
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)");
|
|
2622
2706
|
}
|
|
2623
|
-
}
|
|
2707
|
+
};
|
|
2624
2708
|
|
|
2625
2709
|
/**
|
|
2626
2710
|
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
2627
2711
|
* to avoid React re-renders on mouse movement.
|
|
2628
|
-
*/
|
|
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) => {
|
|
2629
2845
|
parentElement && backgroundDetectionCache.set(parentElement, {
|
|
2630
2846
|
result: result,
|
|
2631
2847
|
timestamp: Date.now(),
|
|
@@ -2638,7 +2854,9 @@ class {
|
|
|
2638
2854
|
* Composable hook for AtomixGlass component logic
|
|
2639
2855
|
* Manages all state, calculations, and event handlers
|
|
2640
2856
|
*/
|
|
2641
|
-
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
|
|
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}) {
|
|
2642
2860
|
// State
|
|
2643
2861
|
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), cachedRectRef = useRef(null), internalGlobalMousePositionRef = useRef({
|
|
2644
2862
|
x: 0,
|
|
@@ -2652,7 +2870,47 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2652
2870
|
}), targetGlobalMousePositionRef = useRef({
|
|
2653
2871
|
x: 0,
|
|
2654
2872
|
y: 0
|
|
2655
|
-
}), 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}) {
|
|
2656
2914
|
const [glassSize, setGlassSize] = useState({
|
|
2657
2915
|
width: 270,
|
|
2658
2916
|
height: 69
|
|
@@ -2711,7 +2969,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2711
2969
|
glassRef: glassRef,
|
|
2712
2970
|
effectiveBorderRadius: effectiveBorderRadius,
|
|
2713
2971
|
cachedRectRef: cachedRectRef
|
|
2714
|
-
}),
|
|
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
|
+
*/
|
|
2715
2976
|
// Extract border-radius from children
|
|
2716
2977
|
useEffect((() => {
|
|
2717
2978
|
const extractRadius = () => {
|
|
@@ -2914,6 +3175,8 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2914
3175
|
lerpActiveRef.current = !0;
|
|
2915
3176
|
const LERP_T = CONSTANTS.LERP_FACTOR, tick = () => {
|
|
2916
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);
|
|
2917
3180
|
const cur = internalMouseOffsetRef.current, tgt = targetMouseOffsetRef.current, dx = tgt.x - cur.x, dy = tgt.y - cur.y;
|
|
2918
3181
|
// If we're close enough, snap and park
|
|
2919
3182
|
if (Math.abs(dx) < .05 && Math.abs(dy) < .05) internalMouseOffsetRef.current = {
|
|
@@ -2922,17 +3185,17 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
2922
3185
|
...targetGlobalMousePositionRef.current
|
|
2923
3186
|
}; else {
|
|
2924
3187
|
internalMouseOffsetRef.current = {
|
|
2925
|
-
x: lerp(cur.x, tgt.x, LERP_T),
|
|
2926
|
-
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)
|
|
2927
3190
|
};
|
|
2928
3191
|
const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
|
|
2929
3192
|
internalGlobalMousePositionRef.current = {
|
|
2930
|
-
x: lerp(curG.x, tgtG.x, LERP_T),
|
|
2931
|
-
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)
|
|
2932
3195
|
};
|
|
2933
3196
|
}
|
|
2934
3197
|
// Imperative style update with the smoothed values
|
|
2935
|
-
updateAtomixGlassStyles(wrapperRef
|
|
3198
|
+
updateAtomixGlassStyles(wrapperRef.current, glassRef.current, {
|
|
2936
3199
|
mouseOffset: internalMouseOffsetRef.current,
|
|
2937
3200
|
globalMousePosition: internalGlobalMousePositionRef.current,
|
|
2938
3201
|
glassSize: glassSize,
|
|
@@ -3023,6 +3286,8 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3023
3286
|
// This is now static (refs or props) unless prop changes
|
|
3024
3287
|
overLightConfig: overLightConfig,
|
|
3025
3288
|
transformStyle: transformStyle,
|
|
3289
|
+
getShaderTime: getShaderTime,
|
|
3290
|
+
applyTimeBasedDistortion: applyTimeBasedDistortion,
|
|
3026
3291
|
handleMouseEnter: handleMouseEnter,
|
|
3027
3292
|
handleMouseLeave: handleMouseLeave,
|
|
3028
3293
|
handleMouseDown: handleMouseDown,
|
|
@@ -3031,6 +3296,800 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3031
3296
|
};
|
|
3032
3297
|
}
|
|
3033
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
|
+
|
|
3034
4093
|
/**
|
|
3035
4094
|
* AtomixGlass - A high-performance glass morphism component with liquid distortion effects
|
|
3036
4095
|
*
|
|
@@ -3045,6 +4104,8 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3045
4104
|
* - Focus ring support for keyboard navigation
|
|
3046
4105
|
* - Responsive breakpoints for mobile optimization
|
|
3047
4106
|
* - Enhanced ARIA attributes for screen readers
|
|
4107
|
+
* - Time-based animation system with FBM distortion
|
|
4108
|
+
* - Device preset optimization for performance/quality balance
|
|
3048
4109
|
*
|
|
3049
4110
|
* Design System Compliance:
|
|
3050
4111
|
* - Uses design tokens for opacity, spacing, and colors
|
|
@@ -3101,8 +4162,14 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3101
4162
|
* <AtomixGlass overLight="auto" debugOverLight={true}>
|
|
3102
4163
|
* <div>Content with debug logging enabled</div>
|
|
3103
4164
|
* </AtomixGlass>
|
|
3104
|
-
|
|
3105
|
-
|
|
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({
|
|
3106
4173
|
glassRef: glassRef,
|
|
3107
4174
|
contentRef: contentRef,
|
|
3108
4175
|
borderRadius: borderRadius,
|
|
@@ -3115,7 +4182,6 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3115
4182
|
withoutEffects: withoutEffects,
|
|
3116
4183
|
elasticity: elasticity,
|
|
3117
4184
|
onClick: onClick,
|
|
3118
|
-
debugBorderRadius: debugBorderRadius,
|
|
3119
4185
|
debugOverLight: debugOverLight,
|
|
3120
4186
|
debugPerformance: debugPerformance,
|
|
3121
4187
|
children: children,
|
|
@@ -3124,8 +4190,48 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3124
4190
|
withLiquidBlur: withLiquidBlur,
|
|
3125
4191
|
padding: padding,
|
|
3126
4192
|
style: style,
|
|
3127
|
-
isFixedOrSticky: isFixedOrSticky
|
|
3128
|
-
|
|
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((() => {
|
|
3129
4235
|
if (!isFixedOrSticky) return {};
|
|
3130
4236
|
const {position: p, top: t, left: l, right: r, bottom: b} = restStyle;
|
|
3131
4237
|
return {
|
|
@@ -3311,6 +4417,15 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3311
4417
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
3312
4418
|
shaderVariant: shaderVariant,
|
|
3313
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,
|
|
3314
4429
|
children: children
|
|
3315
4430
|
}), Boolean(onClick) && jsxs(Fragment, {
|
|
3316
4431
|
children: [ jsx("div", {
|
|
@@ -3334,6 +4449,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
3334
4449
|
}), jsx("span", {
|
|
3335
4450
|
className: ATOMIX_GLASS.BORDER_2_CLASS
|
|
3336
4451
|
}) ]
|
|
4452
|
+
}), debugPerformance && performanceMetrics && jsx(PerformanceDashboard, {
|
|
4453
|
+
metrics: performanceMetrics,
|
|
4454
|
+
isVisible: !0,
|
|
4455
|
+
onClose: () => {}
|
|
3337
4456
|
}) ]
|
|
3338
4457
|
});
|
|
3339
4458
|
}
|
|
@@ -3400,16 +4519,14 @@ const AccordionBody = forwardRef((({children: children, className: className =
|
|
|
3400
4519
|
|
|
3401
4520
|
AccordionBody.displayName = "AccordionBody";
|
|
3402
4521
|
|
|
3403
|
-
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}) => {
|
|
3404
4523
|
// Generate unique IDs for accessibility
|
|
3405
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({
|
|
3406
4525
|
defaultOpen: defaultOpen,
|
|
3407
4526
|
disabled: disabled,
|
|
3408
4527
|
iconPosition: iconPosition,
|
|
3409
4528
|
isOpen: controlledOpen,
|
|
3410
|
-
onOpenChange: onOpenChange
|
|
3411
|
-
onOpen: onOpen,
|
|
3412
|
-
onClose: onClose
|
|
4529
|
+
onOpenChange: onOpenChange
|
|
3413
4530
|
}), headerClassNames = generateHeaderClassNames(), panelClassNames = ACCORDION.SELECTORS.PANEL.replace(".", ""), hasCompoundComponents = React.Children.toArray(children).some((child => {
|
|
3414
4531
|
var _context;
|
|
3415
4532
|
|
|
@@ -3790,7 +4907,9 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
3790
4907
|
return this.canvasDPI;
|
|
3791
4908
|
}
|
|
3792
4909
|
},
|
|
3793
|
-
|
|
4910
|
+
createFBMEngine: createFBMEngine,
|
|
4911
|
+
fragmentShaders: fragmentShaders,
|
|
4912
|
+
liquidGlassWithTime: liquidGlassWithTime
|
|
3794
4913
|
}, Symbol.toStringTag, {
|
|
3795
4914
|
value: "Module"
|
|
3796
4915
|
})), sizeMap = {
|
|
@@ -3819,7 +4938,7 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
3819
4938
|
|
|
3820
4939
|
Icon.displayName = "Icon";
|
|
3821
4940
|
|
|
3822
|
-
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}) => {
|
|
3823
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(" ");
|
|
3824
4943
|
return jsx("div", {
|
|
3825
4944
|
className: avatarClasses,
|
|
@@ -4292,7 +5411,7 @@ class ThemeNaming {
|
|
|
4292
5411
|
ThemeNaming.prefix = "atomix";
|
|
4293
5412
|
|
|
4294
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) => {
|
|
4295
|
-
const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href
|
|
5414
|
+
const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href), iconElement = iconName ? jsx(Icon, {
|
|
4296
5415
|
name: iconName,
|
|
4297
5416
|
size: iconSize
|
|
4298
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 => {
|
|
@@ -4348,8 +5467,8 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
|
|
|
4348
5467
|
...buttonProps,
|
|
4349
5468
|
ref: ref,
|
|
4350
5469
|
// linkComponent usually forwards ref to anchor
|
|
4351
|
-
href: href,
|
|
4352
|
-
to: href,
|
|
5470
|
+
href: isDisabled ? void 0 : href,
|
|
5471
|
+
to: isDisabled ? void 0 : href,
|
|
4353
5472
|
target: target,
|
|
4354
5473
|
rel: "_blank" === target ? "noopener noreferrer" : void 0
|
|
4355
5474
|
};
|
|
@@ -4362,7 +5481,7 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
|
|
|
4362
5481
|
content = jsx("a", {
|
|
4363
5482
|
...buttonProps,
|
|
4364
5483
|
ref: ref,
|
|
4365
|
-
href: href,
|
|
5484
|
+
href: isDisabled ? void 0 : href,
|
|
4366
5485
|
target: target,
|
|
4367
5486
|
rel: "_blank" === target ? "noopener noreferrer" : void 0,
|
|
4368
5487
|
children: buttonContent
|
|
@@ -4641,7 +5760,7 @@ row: row = !1, flat: flat = !1,
|
|
|
4641
5760
|
// States
|
|
4642
5761
|
active: active = !1, disabled: disabled = !1, loading: loading = !1, selected: selected = !1, interactive: interactive = !1,
|
|
4643
5762
|
// Content
|
|
4644
|
-
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,
|
|
4645
5764
|
// Interaction
|
|
4646
5765
|
onClick: onClick, onHover: onHover, onFocus: onFocus, href: href, target: target,
|
|
4647
5766
|
// Custom Link
|
|
@@ -4832,50 +5951,50 @@ Card.Header = CardHeader, Card.Body = CardBody, Card.Footer = CardFooter;
|
|
|
4832
5951
|
* @param options - Configuration options for the card
|
|
4833
5952
|
* @returns Card state and handlers
|
|
4834
5953
|
*/
|
|
4835
|
-
const
|
|
4836
|
-
const {
|
|
4837
|
-
flipEffect
|
|
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
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
}
|
|
4878
|
-
|
|
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
|
+
})({
|
|
4879
5998
|
elevationEffect: !0,
|
|
4880
5999
|
elevationClass: elevationClass,
|
|
4881
6000
|
clickable: Boolean(onClick),
|
|
@@ -9256,216 +10375,13 @@ function getRowId$1(row, rowKey) {
|
|
|
9256
10375
|
|
|
9257
10376
|
/**
|
|
9258
10377
|
* Hook for managing DataTable state and behavior
|
|
9259
|
-
*/
|
|
9260
|
-
// Sort state
|
|
9261
|
-
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((() => {
|
|
9262
|
-
const visibility = {};
|
|
9263
|
-
return columns.forEach((col => {
|
|
9264
|
-
visibility[col.key] = !1 !== col.visible;
|
|
9265
|
-
})), visibility;
|
|
9266
|
-
})), [columnFilterValues, setColumnFilterValues] = useState({});
|
|
9267
|
-
// Pagination state
|
|
9268
|
-
// Update column order when columns prop changes
|
|
9269
|
-
useEffect((() => {
|
|
9270
|
-
const newOrder = columns.map((col => col.key)), currentOrderSet = new Set(columnOrder), newOrderSet = new Set(newOrder);
|
|
9271
|
-
// Only update if there are actual differences
|
|
9272
|
-
newOrder.length === columnOrder.length && newOrder.every((key => currentOrderSet.has(key))) && columnOrder.every((key => newOrderSet.has(key))) || setColumnOrder(newOrder);
|
|
9273
|
-
}), [ columns ]),
|
|
9274
|
-
// Update column visibility when columns prop changes
|
|
9275
|
-
useEffect((() => {
|
|
9276
|
-
setColumnVisibility((prev => {
|
|
9277
|
-
const updated = {
|
|
9278
|
-
...prev
|
|
9279
|
-
};
|
|
9280
|
-
return columns.forEach((col => {
|
|
9281
|
-
col.key in updated || (updated[col.key] = !1 !== col.visible);
|
|
9282
|
-
})), updated;
|
|
9283
|
-
}));
|
|
9284
|
-
}), [ columns ]);
|
|
9285
|
-
// Visible columns based on order and visibility
|
|
9286
|
-
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 => {
|
|
9287
|
-
if (!sortable) return;
|
|
9288
|
-
let direction = "asc";
|
|
9289
|
-
sortConfig && sortConfig.key === key && "asc" === sortConfig.direction && (direction = "desc");
|
|
9290
|
-
const newSortConfig = {
|
|
9291
|
-
key: key,
|
|
9292
|
-
direction: direction
|
|
9293
|
-
};
|
|
9294
|
-
setSortConfig(newSortConfig), onSort && onSort(newSortConfig);
|
|
9295
|
-
}), [ sortable, sortConfig, onSort ]), handlePageChange = useCallback((page => {
|
|
9296
|
-
page < 1 || setCurrentPage(page);
|
|
9297
|
-
}), []), handleSearch = useCallback((query => {
|
|
9298
|
-
setSearchQuery(query), setCurrentPage(1);
|
|
9299
|
-
} // Reset to first page when searching
|
|
9300
|
-
), []), handleColumnFilterChange = useCallback(((columnKey, value) => {
|
|
9301
|
-
setColumnFilterValues((prev => ({
|
|
9302
|
-
...prev,
|
|
9303
|
-
[columnKey]: value
|
|
9304
|
-
}))), setCurrentPage(1);
|
|
9305
|
-
} // Reset to first page when filtering
|
|
9306
|
-
), []), clearColumnFilters = useCallback((() => {
|
|
9307
|
-
setColumnFilterValues({}), setCurrentPage(1);
|
|
9308
|
-
}), []), activeColumnFilters = useMemo((() => columnFilters ? Object.entries(columnFilterValues).filter((([, value]) => null != value && "" !== value)).map((([columnKey, value]) => {
|
|
9309
|
-
const column = columns.find((col => col.key === columnKey));
|
|
9310
|
-
return column && column.filterable ? {
|
|
9311
|
-
key: columnKey,
|
|
9312
|
-
value: value,
|
|
9313
|
-
lowercaseValue: "string" == typeof value ? value.toLowerCase() : String(value).toLowerCase(),
|
|
9314
|
-
column: column
|
|
9315
|
-
} : null;
|
|
9316
|
-
})).filter((f => null !== f)) : []), [ columnFilters, columnFilterValues, columns ]), filteredData = useMemo((() => {
|
|
9317
|
-
if (!searchQuery && 0 === activeColumnFilters.length) return data;
|
|
9318
|
-
const lowercaseQuery = searchQuery ? searchQuery.toLowerCase() : "";
|
|
9319
|
-
return data.filter((row => {
|
|
9320
|
-
// Apply global search
|
|
9321
|
-
if (searchQuery && !visibleColumns.some((column => {
|
|
9322
|
-
var _context;
|
|
9323
|
-
const value = row[column.key];
|
|
9324
|
-
return null != value && _includesInstanceProperty(_context = String(value).toLowerCase()).call(_context, lowercaseQuery);
|
|
9325
|
-
}))) return !1;
|
|
9326
|
-
// Apply column-specific filters
|
|
9327
|
-
for (let i = 0; i < activeColumnFilters.length; i++) {
|
|
9328
|
-
const filter = activeColumnFilters[i];
|
|
9329
|
-
if (!filter) continue;
|
|
9330
|
-
const {key: key, value: value, lowercaseValue: lowercaseValue, column: column} = filter, cellValue = row[key];
|
|
9331
|
-
if (null == cellValue) return !1;
|
|
9332
|
-
// Use custom filter function if provided
|
|
9333
|
-
var _context2;
|
|
9334
|
-
// Default text filter
|
|
9335
|
-
if (column.filterFunction) {
|
|
9336
|
-
if (!column.filterFunction(cellValue, value)) return !1;
|
|
9337
|
-
} else if (!_includesInstanceProperty(_context2 = String(cellValue).toLowerCase()).call(_context2, lowercaseValue)) return !1;
|
|
9338
|
-
}
|
|
9339
|
-
return !0;
|
|
9340
|
-
}));
|
|
9341
|
-
}), [ data, visibleColumns, searchQuery, activeColumnFilters ]), sortedData = useMemo((() => sortConfig && sortable ? [ ...filteredData ].sort(((a, b) => {
|
|
9342
|
-
const aValue = a[sortConfig.key], bValue = b[sortConfig.key];
|
|
9343
|
-
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;
|
|
9344
|
-
})) : filteredData), [ filteredData, sortConfig, sortable ]), paginatedData = useMemo((() => {
|
|
9345
|
-
if (!paginated) return sortedData;
|
|
9346
|
-
const startIndex = (currentPage - 1) * pageSize;
|
|
9347
|
-
return sortedData.slice(startIndex, startIndex + pageSize);
|
|
9348
|
-
}), [ 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) => {
|
|
9349
|
-
if ("none" === selectionMode) return;
|
|
9350
|
-
let newSelectedIds;
|
|
9351
|
-
if (newSelectedIds = "single" === selectionMode ? selected ? [ rowId ] : [] :
|
|
9352
|
-
// multiple
|
|
9353
|
-
selected ? [ ...selectedRowIds, rowId ] : selectedRowIds.filter((id => id !== rowId)),
|
|
9354
|
-
controlledSelectedRowIds || setInternalSelectedRowIds(newSelectedIds), onSelectionChange) {
|
|
9355
|
-
const selectedRowsData = sortedData.filter((row => _includesInstanceProperty(newSelectedIds).call(newSelectedIds, getRowId$1(row, rowKey))));
|
|
9356
|
-
onSelectionChange(selectedRowsData, newSelectedIds);
|
|
9357
|
-
}
|
|
9358
|
-
}), [ selectionMode, selectedRowIds, controlledSelectedRowIds, onSelectionChange, sortedData, rowKey ]), handleSelectAll = useCallback((selected => {
|
|
9359
|
-
if ("multiple" !== selectionMode) return;
|
|
9360
|
-
const newSelectedIds = selected ? paginatedData.map((row => getRowId$1(row, rowKey))) : [];
|
|
9361
|
-
if (controlledSelectedRowIds || setInternalSelectedRowIds(newSelectedIds), onSelectionChange) {
|
|
9362
|
-
const selectedRowsData = sortedData.filter((row => _includesInstanceProperty(newSelectedIds).call(newSelectedIds, getRowId$1(row, rowKey))));
|
|
9363
|
-
onSelectionChange(selectedRowsData, newSelectedIds);
|
|
9364
|
-
}
|
|
9365
|
-
}), [ 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((() => {
|
|
9366
|
-
if ("multiple" !== selectionMode || 0 === paginatedData.length) return !1;
|
|
9367
|
-
const selectedCount = paginatedData.filter((row => _includesInstanceProperty(selectedRowIds).call(selectedRowIds, getRowId$1(row, rowKey)))).length;
|
|
9368
|
-
return selectedCount > 0 && selectedCount < paginatedData.length;
|
|
9369
|
-
}), [ selectionMode, paginatedData, selectedRowIds, rowKey ]), handleColumnVisibilityToggle = useCallback((columnKey => {
|
|
9370
|
-
setColumnVisibility((prev => {
|
|
9371
|
-
const updated = {
|
|
9372
|
-
...prev,
|
|
9373
|
-
[columnKey]: !prev[columnKey]
|
|
9374
|
-
};
|
|
9375
|
-
if (onColumnVisibilityChange) {
|
|
9376
|
-
const visibleKeys = Object.entries(updated).filter((([, visible]) => visible)).map((([key]) => key));
|
|
9377
|
-
onColumnVisibilityChange(visibleKeys);
|
|
9378
|
-
}
|
|
9379
|
-
return updated;
|
|
9380
|
-
}));
|
|
9381
|
-
}), [ onColumnVisibilityChange ]);
|
|
9382
|
-
// Handle sorting
|
|
9383
|
-
// Handle column reorder
|
|
9384
|
-
return useCallback(((fromIndex, toIndex) => {
|
|
9385
|
-
const newOrder = [ ...columnOrder ], [removed] = newOrder.splice(fromIndex, 1);
|
|
9386
|
-
removed && (newOrder.splice(toIndex, 0, removed), setColumnOrder(newOrder), onColumnReorder && onColumnReorder(newOrder));
|
|
9387
|
-
}), [ columnOrder, onColumnReorder ]),
|
|
9388
|
-
// Reset to first page when data changes
|
|
9389
|
-
useEffect((() => {
|
|
9390
|
-
setCurrentPage(1);
|
|
9391
|
-
}), [ data ]),
|
|
9392
|
-
// Reset current page if it's out of bounds
|
|
9393
|
-
useEffect((() => {
|
|
9394
|
-
currentPage > totalPages && totalPages > 0 && setCurrentPage(Math.max(1, totalPages));
|
|
9395
|
-
}), [ currentPage, totalPages ]), {
|
|
9396
|
-
displayData: paginatedData,
|
|
9397
|
-
sortConfig: sortConfig,
|
|
9398
|
-
currentPage: currentPage,
|
|
9399
|
-
totalPages: totalPages,
|
|
9400
|
-
handleSort: handleSort,
|
|
9401
|
-
handlePageChange: handlePageChange,
|
|
9402
|
-
handleSearch: handleSearch,
|
|
9403
|
-
selectedRowIds: selectedRowIds,
|
|
9404
|
-
selectedRows: selectedRows,
|
|
9405
|
-
handleRowSelect: handleRowSelect,
|
|
9406
|
-
handleSelectAll: handleSelectAll,
|
|
9407
|
-
isAllSelected: isAllSelected,
|
|
9408
|
-
isIndeterminate: isIndeterminate,
|
|
9409
|
-
columnOrder: columnOrder,
|
|
9410
|
-
visibleColumns: visibleColumns,
|
|
9411
|
-
columnVisibility: columnVisibility,
|
|
9412
|
-
handleColumnVisibilityToggle: handleColumnVisibilityToggle,
|
|
9413
|
-
columnFilterValues: columnFilterValues,
|
|
9414
|
-
handleColumnFilterChange: handleColumnFilterChange,
|
|
9415
|
-
clearColumnFilters: clearColumnFilters
|
|
9416
|
-
};
|
|
9417
|
-
}
|
|
10378
|
+
*/ Countdown.displayName = "Countdown";
|
|
9418
10379
|
|
|
9419
|
-
|
|
9420
|
-
|
|
9421
|
-
const DOTS = "...", range = (start, end) => {
|
|
10380
|
+
const range = (start, end) => {
|
|
9422
10381
|
const length = end - start + 1;
|
|
9423
10382
|
return Array.from({
|
|
9424
10383
|
length: length
|
|
9425
10384
|
}, ((_, idx) => idx + start));
|
|
9426
|
-
}, usePagination = ({currentPage: currentPage, totalPages: totalPages, siblingCount: siblingCount = 1, onPageChange: onPageChange}) => {
|
|
9427
|
-
const paginationRange = useMemo((() => {
|
|
9428
|
-
// siblingCount + firstPage + lastPage + currentPage + 2*DOTS
|
|
9429
|
-
/*
|
|
9430
|
-
Case 1: If the number of pages is less than the page numbers we want to show in our
|
|
9431
|
-
paginationComponent, we return the range [1..totalPages]
|
|
9432
|
-
*/
|
|
9433
|
-
if (siblingCount + 5 >= totalPages) return range(1, totalPages);
|
|
9434
|
-
const leftSiblingIndex = Math.max(currentPage - siblingCount, 1), rightSiblingIndex = Math.min(currentPage + siblingCount, totalPages), shouldShowLeftDots = leftSiblingIndex > 2, shouldShowRightDots = rightSiblingIndex < totalPages - 2, lastPageIndex = totalPages;
|
|
9435
|
-
/*
|
|
9436
|
-
Case 2: No left dots to show, but rights dots to be shown
|
|
9437
|
-
*/
|
|
9438
|
-
return !shouldShowLeftDots && shouldShowRightDots ? [ ...range(1, 3 + 2 * siblingCount), "...", totalPages ] :
|
|
9439
|
-
/*
|
|
9440
|
-
Case 3: No right dots to show, but left dots to be shown
|
|
9441
|
-
*/
|
|
9442
|
-
shouldShowLeftDots && !shouldShowRightDots ? [ 1, "...", ...range(totalPages - (3 + 2 * siblingCount) + 1, totalPages) ] :
|
|
9443
|
-
/*
|
|
9444
|
-
Case 4: Both left and right dots to be shown
|
|
9445
|
-
*/
|
|
9446
|
-
shouldShowLeftDots && shouldShowRightDots ? [ 1, "...", ...range(leftSiblingIndex, rightSiblingIndex), "...", lastPageIndex ] : [];
|
|
9447
|
-
}), [ totalPages, siblingCount, currentPage ]), goToPage = page => {
|
|
9448
|
-
page >= 1 && page <= totalPages && page !== currentPage && onPageChange(page);
|
|
9449
|
-
};
|
|
9450
|
-
return {
|
|
9451
|
-
paginationRange: paginationRange,
|
|
9452
|
-
currentPage: currentPage,
|
|
9453
|
-
totalPages: totalPages,
|
|
9454
|
-
goToPage: goToPage,
|
|
9455
|
-
nextPage: () => {
|
|
9456
|
-
goToPage(currentPage + 1);
|
|
9457
|
-
},
|
|
9458
|
-
prevPage: () => {
|
|
9459
|
-
goToPage(currentPage - 1);
|
|
9460
|
-
},
|
|
9461
|
-
firstPage: () => {
|
|
9462
|
-
goToPage(1);
|
|
9463
|
-
},
|
|
9464
|
-
lastPage: () => {
|
|
9465
|
-
goToPage(totalPages);
|
|
9466
|
-
},
|
|
9467
|
-
DOTS: "..."
|
|
9468
|
-
};
|
|
9469
10385
|
}, PaginationNavButton = memo((({type: type, onClick: onClick, disabled: disabled, label: label, iconName: iconName}) => jsx("li", {
|
|
9470
10386
|
className: `c-pagination__item c-pagination__item--${type} ${disabled ? "is-disabled" : ""}`,
|
|
9471
10387
|
"aria-disabled": disabled,
|
|
@@ -9482,7 +10398,50 @@ const DOTS = "...", range = (start, end) => {
|
|
|
9482
10398
|
})
|
|
9483
10399
|
})
|
|
9484
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}) => {
|
|
9485
|
-
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
|
+
})({
|
|
9486
10445
|
currentPage: currentPage,
|
|
9487
10446
|
totalPages: totalPages,
|
|
9488
10447
|
siblingCount: siblingCount,
|
|
@@ -9694,14 +10653,13 @@ const DropdownContext = createContext({
|
|
|
9694
10653
|
id: "",
|
|
9695
10654
|
trigger: "click"
|
|
9696
10655
|
}), DropdownMenu = forwardRef((({children: children, className: className = "", ...props}, ref) => {
|
|
9697
|
-
const {glass: glass} = useContext(DropdownStyleContext);
|
|
9698
|
-
|
|
9699
|
-
// Wait, the original code wrapped <ul> in Context Provider.
|
|
9700
|
-
// And applied glass wrapper around <ul>.
|
|
9701
|
-
// If we use Compound Component, DropdownMenu should be the list.
|
|
9702
|
-
return jsx("ul", {
|
|
10656
|
+
const {glass: glass} = useContext(DropdownStyleContext), {id: id} = useContext(DropdownContext);
|
|
10657
|
+
return jsx("ul", {
|
|
9703
10658
|
ref: ref,
|
|
10659
|
+
id: `${id}-menu`,
|
|
9704
10660
|
className: `c-dropdown__menu ${glass ? "c-dropdown__menu--glass" : ""} ${className}`.trim(),
|
|
10661
|
+
role: "menu",
|
|
10662
|
+
"aria-labelledby": `${id}-trigger`,
|
|
9705
10663
|
...props,
|
|
9706
10664
|
children: children
|
|
9707
10665
|
});
|
|
@@ -9710,14 +10668,23 @@ const DropdownContext = createContext({
|
|
|
9710
10668
|
// Compound Components
|
|
9711
10669
|
DropdownMenu.displayName = "DropdownMenu";
|
|
9712
10670
|
|
|
9713
|
-
const DropdownTrigger = forwardRef((({children: children, className: className = "", onClick: onClick, onKeyDown: onKeyDown, ...props}, ref) =>
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
|
|
9717
|
-
|
|
9718
|
-
|
|
9719
|
-
|
|
9720
|
-
|
|
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
|
+
}));
|
|
9721
10688
|
|
|
9722
10689
|
DropdownTrigger.displayName = "DropdownTrigger";
|
|
9723
10690
|
|
|
@@ -9957,7 +10924,165 @@ Dropdown.Item = DropdownItem, Dropdown.Divider = DropdownDivider, Dropdown.Heade
|
|
|
9957
10924
|
* ```
|
|
9958
10925
|
*/
|
|
9959
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}) => {
|
|
9960
|
-
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
|
+
}({
|
|
9961
11086
|
data: data,
|
|
9962
11087
|
columns: columns,
|
|
9963
11088
|
sortable: sortable,
|
|
@@ -12311,297 +13436,6 @@ function useTodo(initialProps) {
|
|
|
12311
13436
|
};
|
|
12312
13437
|
}
|
|
12313
13438
|
|
|
12314
|
-
/**
|
|
12315
|
-
* Breadcrumb state and functionality
|
|
12316
|
-
* @param initialOptions - Initial breadcrumb options
|
|
12317
|
-
* @returns Breadcrumb state and methods
|
|
12318
|
-
*/ function useBreadcrumb(initialOptions) {
|
|
12319
|
-
return {
|
|
12320
|
-
defaultOptions: {
|
|
12321
|
-
items: [],
|
|
12322
|
-
divider: BREADCRUMB.DEFAULTS.DIVIDER,
|
|
12323
|
-
className: "",
|
|
12324
|
-
"aria-label": "Breadcrumb",
|
|
12325
|
-
...initialOptions
|
|
12326
|
-
},
|
|
12327
|
-
generateBreadcrumbClass: options => {
|
|
12328
|
-
const {className: className = ""} = options;
|
|
12329
|
-
return [ BREADCRUMB.CLASSES.BASE, className ].filter(Boolean).join(" ").trim();
|
|
12330
|
-
},
|
|
12331
|
-
generateItemClass: (item, isLast) => [ BREADCRUMB.CLASSES.ITEM, item.active || isLast ? BREADCRUMB.CLASSES.ACTIVE : "" ].filter(Boolean).join(" ").trim(),
|
|
12332
|
-
isItemLink: (item, isLast) => Boolean(item.href && !item.active && !isLast),
|
|
12333
|
-
parseItemsFromJson: jsonString => {
|
|
12334
|
-
try {
|
|
12335
|
-
return JSON.parse(jsonString);
|
|
12336
|
-
} catch (error) {
|
|
12337
|
-
return console.error("Error parsing breadcrumb items:", error), [];
|
|
12338
|
-
}
|
|
12339
|
-
}
|
|
12340
|
-
};
|
|
12341
|
-
}
|
|
12342
|
-
|
|
12343
|
-
/**
|
|
12344
|
-
* Hook for managing modal state
|
|
12345
|
-
*/ function useModal$1({isOpen: isOpenProp, onOpenChange: onOpenChange, onOpen: onOpen, onClose: onClose} = {}) {
|
|
12346
|
-
// For uncontrolled usage
|
|
12347
|
-
const [isOpenState, setIsOpenState] = useState(!1), isControlled = void 0 !== isOpenProp, isOpen = isControlled ? !!isOpenProp : isOpenState;
|
|
12348
|
-
// Determine if we're in controlled or uncontrolled mode
|
|
12349
|
-
// Update internal state when prop changes (for controlled mode)
|
|
12350
|
-
useEffect((() => {
|
|
12351
|
-
isControlled && setIsOpenState(!!isOpenProp);
|
|
12352
|
-
}), [ isOpenProp, isControlled ]);
|
|
12353
|
-
const updateOpen = useCallback((nextIsOpen => {
|
|
12354
|
-
// For uncontrolled mode, update internal state
|
|
12355
|
-
isControlled || setIsOpenState(nextIsOpen),
|
|
12356
|
-
// Call the change handler in either mode
|
|
12357
|
-
onOpenChange && onOpenChange(nextIsOpen),
|
|
12358
|
-
// Call the specific handler
|
|
12359
|
-
nextIsOpen && onOpen ? onOpen() : !nextIsOpen && onClose && onClose();
|
|
12360
|
-
}), [ isControlled, onOpenChange, onOpen, onClose ]), open = useCallback((() => {
|
|
12361
|
-
updateOpen(!0);
|
|
12362
|
-
}), [ updateOpen ]), close = useCallback((() => {
|
|
12363
|
-
updateOpen(!1);
|
|
12364
|
-
}), [ updateOpen ]), toggle = useCallback((() => {
|
|
12365
|
-
updateOpen(!isOpen);
|
|
12366
|
-
}), [ isOpen, updateOpen ]);
|
|
12367
|
-
return {
|
|
12368
|
-
isOpen: isOpen,
|
|
12369
|
-
open: open,
|
|
12370
|
-
close: close,
|
|
12371
|
-
toggle: toggle
|
|
12372
|
-
};
|
|
12373
|
-
}
|
|
12374
|
-
|
|
12375
|
-
function useSlider(options) {
|
|
12376
|
-
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({
|
|
12377
|
-
isTransitioning: !1,
|
|
12378
|
-
loop: loop,
|
|
12379
|
-
slides: slides,
|
|
12380
|
-
slidesToShow: slidesToShow,
|
|
12381
|
-
speed: speed,
|
|
12382
|
-
onSlideChange: onSlideChange
|
|
12383
|
-
}), [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) => ({
|
|
12384
|
-
...slide,
|
|
12385
|
-
id: `set1-${slide.id || i}`
|
|
12386
|
-
}))), ...slides.map(((slide, i) => ({
|
|
12387
|
-
...slide,
|
|
12388
|
-
id: `set2-${slide.id || i}`
|
|
12389
|
-
}))), ...slides.map(((slide, i) => ({
|
|
12390
|
-
...slide,
|
|
12391
|
-
id: `set3-${slide.id || i}`
|
|
12392
|
-
}))) ] : slides), [ slides, loop ]), loopedSlides = slides.length, translateValue = useMemo((() => 0 === slideWidth ? 0 : -internalIndex * slideWidth + dragOffset), [ slideWidth, internalIndex, dragOffset ]);
|
|
12393
|
-
// Update the ref whenever the relevant state/props change
|
|
12394
|
-
useEffect((() => {
|
|
12395
|
-
sliderStateRef.current = {
|
|
12396
|
-
isTransitioning: isTransitioning,
|
|
12397
|
-
loop: loop,
|
|
12398
|
-
slides: slides,
|
|
12399
|
-
slidesToShow: slidesToShow,
|
|
12400
|
-
speed: speed,
|
|
12401
|
-
onSlideChange: onSlideChange
|
|
12402
|
-
};
|
|
12403
|
-
}), [ isTransitioning, loop, slides, slidesToShow, speed, onSlideChange ]),
|
|
12404
|
-
// Autoplay effect
|
|
12405
|
-
useEffect((() => {
|
|
12406
|
-
if (!autoplay) return autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12407
|
-
autoplayRef.current = null), void setAutoplayRunning(!1);
|
|
12408
|
-
const autoplayParams = "boolean" == typeof autoplay ? {
|
|
12409
|
-
delay: 3e3
|
|
12410
|
-
} : autoplay, {delay: delay = 3e3, pauseOnMouseEnter: pauseOnMouseEnter = !1, disableOnInteraction: disableOnInteraction = !1, reverseDirection: reverseDirection = !1} = autoplayParams;
|
|
12411
|
-
// Clear any existing interval
|
|
12412
|
-
autoplayRef.current && clearInterval(autoplayRef.current),
|
|
12413
|
-
// Create new interval
|
|
12414
|
-
autoplayRef.current = setInterval((() => {
|
|
12415
|
-
// Use ref to get the latest state without resetting the interval
|
|
12416
|
-
const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
|
|
12417
|
-
// We need to use a functional update to get the latest values
|
|
12418
|
-
setRealIndex((prevRealIndex => {
|
|
12419
|
-
if (currentIsTransitioning) return prevRealIndex;
|
|
12420
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12421
|
-
let nextIndex;
|
|
12422
|
-
// Trigger the slide change
|
|
12423
|
-
if (disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12424
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
|
|
12425
|
-
reverseDirection) {
|
|
12426
|
-
// For reverse direction, we would go to previous slide
|
|
12427
|
-
const prevIndex = currentLoop ? 0 === prevRealIndex ? currentSlides.length - 1 : prevRealIndex - 1 : Math.max(prevRealIndex - 1, 0);
|
|
12428
|
-
return setInternalIndex(currentLoop ? currentSlides.length + prevIndex : prevIndex),
|
|
12429
|
-
setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
|
|
12430
|
-
setIsTransitioning(!1), currentOnSlideChange?.(prevIndex);
|
|
12431
|
-
}), currentSpeed), prevIndex;
|
|
12432
|
-
}
|
|
12433
|
-
// Normal direction
|
|
12434
|
-
return setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex),
|
|
12435
|
-
setIsTransitioning(!0), setDragOffset(0), setTimeout((() => {
|
|
12436
|
-
setIsTransitioning(!1), currentOnSlideChange?.(nextIndex),
|
|
12437
|
-
// Reposition after transition ends for looped sliders
|
|
12438
|
-
currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
|
|
12439
|
-
setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
|
|
12440
|
-
repositioningRef.current = !1;
|
|
12441
|
-
}), 0));
|
|
12442
|
-
}), currentSpeed), nextIndex;
|
|
12443
|
-
}));
|
|
12444
|
-
}), delay), setAutoplayRunning(!0);
|
|
12445
|
-
// Handle pause on mouse enter/leave if enabled
|
|
12446
|
-
let containerElement = null;
|
|
12447
|
-
const handleMouseEnter = () => {
|
|
12448
|
-
autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null,
|
|
12449
|
-
setAutoplayRunning(!1));
|
|
12450
|
-
}, handleMouseLeave = () => {
|
|
12451
|
-
// Restart autoplay
|
|
12452
|
-
autoplayRef.current && clearInterval(autoplayRef.current), autoplayRef.current = setInterval((() => {
|
|
12453
|
-
const {isTransitioning: currentIsTransitioning, loop: currentLoop, slides: currentSlides, slidesToShow: currentSlidesToShow, speed: currentSpeed, onSlideChange: currentOnSlideChange} = sliderStateRef.current;
|
|
12454
|
-
setRealIndex((prevRealIndex => {
|
|
12455
|
-
if (currentIsTransitioning) return prevRealIndex;
|
|
12456
|
-
let nextIndex;
|
|
12457
|
-
return nextIndex = currentLoop ? (prevRealIndex + 1) % currentSlides.length : Math.min(prevRealIndex + 1, currentSlides.length - currentSlidesToShow),
|
|
12458
|
-
setInternalIndex(currentLoop ? currentSlides.length + nextIndex : nextIndex), setIsTransitioning(!0),
|
|
12459
|
-
setDragOffset(0), setTimeout((() => {
|
|
12460
|
-
setIsTransitioning(!1), currentOnSlideChange?.(nextIndex), currentLoop && nextIndex >= 2 * currentSlides.length && (repositioningRef.current = !0,
|
|
12461
|
-
setInternalIndex(currentSlides.length + nextIndex), setTimeout((() => {
|
|
12462
|
-
repositioningRef.current = !1;
|
|
12463
|
-
}), 0));
|
|
12464
|
-
}), currentSpeed), nextIndex;
|
|
12465
|
-
}));
|
|
12466
|
-
}), delay), setAutoplayRunning(!0);
|
|
12467
|
-
};
|
|
12468
|
-
// Cleanup
|
|
12469
|
-
return pauseOnMouseEnter && containerRef.current && (containerElement = containerRef.current,
|
|
12470
|
-
containerElement.addEventListener("mouseenter", handleMouseEnter), containerElement.addEventListener("mouseleave", handleMouseLeave)),
|
|
12471
|
-
() => {
|
|
12472
|
-
autoplayRef.current && (clearInterval(autoplayRef.current), autoplayRef.current = null),
|
|
12473
|
-
containerElement && (containerElement.removeEventListener("mouseenter", handleMouseEnter),
|
|
12474
|
-
containerElement.removeEventListener("mouseleave", handleMouseLeave)), setAutoplayRunning(!1);
|
|
12475
|
-
};
|
|
12476
|
-
}), [ autoplay, repositioningRef ]),
|
|
12477
|
-
// Initialize
|
|
12478
|
-
useEffect((() => {
|
|
12479
|
-
setInternalIndex(loop ? slides.length + initialSlide : initialSlide);
|
|
12480
|
-
}), [ loop, slides.length, initialSlide ]), useEffect((() => {
|
|
12481
|
-
const updateSize = () => {
|
|
12482
|
-
if (containerRef.current) {
|
|
12483
|
-
const size = "horizontal" === direction ? containerRef.current.offsetWidth : containerRef.current.offsetHeight;
|
|
12484
|
-
setContainerSize(size);
|
|
12485
|
-
}
|
|
12486
|
-
};
|
|
12487
|
-
return updateSize(), window.addEventListener("resize", updateSize), () => window.removeEventListener("resize", updateSize);
|
|
12488
|
-
}), [ direction ]);
|
|
12489
|
-
const slideNext = useCallback((() => {
|
|
12490
|
-
if (!isTransitioning) if (
|
|
12491
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12492
|
-
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12493
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), loop) {
|
|
12494
|
-
const nextRealIndex = (realIndex + 1) % slides.length, nextInternalIndex = internalIndex + 1;
|
|
12495
|
-
setRealIndex(nextRealIndex), setInternalIndex(nextInternalIndex), setIsTransitioning(!0),
|
|
12496
|
-
setDragOffset(0), setTimeout((() => {
|
|
12497
|
-
setIsTransitioning(!1), onSlideChange?.(nextRealIndex),
|
|
12498
|
-
// Reposition after transition ends
|
|
12499
|
-
nextInternalIndex >= 2 * slides.length && (repositioningRef.current = !0, setInternalIndex(slides.length + nextRealIndex),
|
|
12500
|
-
setTimeout((() => {
|
|
12501
|
-
repositioningRef.current = !1;
|
|
12502
|
-
}), 0));
|
|
12503
|
-
}), speed);
|
|
12504
|
-
} else {
|
|
12505
|
-
const nextIndex = Math.min(realIndex + 1, slides.length - slidesToShow);
|
|
12506
|
-
setRealIndex(nextIndex), setInternalIndex(nextIndex), setIsTransitioning(!0), setDragOffset(0),
|
|
12507
|
-
setTimeout((() => {
|
|
12508
|
-
setIsTransitioning(!1), onSlideChange?.(nextIndex);
|
|
12509
|
-
}), speed);
|
|
12510
|
-
}
|
|
12511
|
-
}), [ realIndex, internalIndex, slides.length, slidesToShow, loop, isTransitioning, speed, onSlideChange, allSlides.length, loopedSlides, autoplay ]), slidePrev = useCallback((() => {
|
|
12512
|
-
if (!isTransitioning) if (
|
|
12513
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12514
|
-
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12515
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), loop) {
|
|
12516
|
-
const prevRealIndex = 0 === realIndex ? slides.length - 1 : realIndex - 1, prevInternalIndex = internalIndex - 1;
|
|
12517
|
-
setRealIndex(prevRealIndex), setInternalIndex(prevInternalIndex), setIsTransitioning(!0),
|
|
12518
|
-
setDragOffset(0), setTimeout((() => {
|
|
12519
|
-
setIsTransitioning(!1), onSlideChange?.(prevRealIndex),
|
|
12520
|
-
// Reposition after transition ends
|
|
12521
|
-
prevInternalIndex < slides.length && (repositioningRef.current = !0, setInternalIndex(slides.length + prevRealIndex),
|
|
12522
|
-
setTimeout((() => {
|
|
12523
|
-
repositioningRef.current = !1;
|
|
12524
|
-
}), 0));
|
|
12525
|
-
}), speed);
|
|
12526
|
-
} else {
|
|
12527
|
-
const prevIndex = Math.max(realIndex - 1, 0);
|
|
12528
|
-
setRealIndex(prevIndex), setInternalIndex(prevIndex), setIsTransitioning(!0), setDragOffset(0),
|
|
12529
|
-
setTimeout((() => {
|
|
12530
|
-
setIsTransitioning(!1), onSlideChange?.(prevIndex);
|
|
12531
|
-
}), speed);
|
|
12532
|
-
}
|
|
12533
|
-
}), [ realIndex, internalIndex, slides.length, loop, isTransitioning, speed, onSlideChange, allSlides.length, loopedSlides, autoplay ]), goToSlide = useCallback((index => {
|
|
12534
|
-
isTransitioning || index === realIndex || (
|
|
12535
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12536
|
-
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12537
|
-
autoplayRef.current = null, setAutoplayRunning(!1)), setIsTransitioning(!0), setDragOffset(0),
|
|
12538
|
-
setRealIndex(index), setInternalIndex(loop ? slides.length + index : index), setTimeout((() => {
|
|
12539
|
-
setIsTransitioning(!1), onSlideChange?.(index);
|
|
12540
|
-
}), speed));
|
|
12541
|
-
}), [ realIndex, isTransitioning, speed, onSlideChange, loop, loopedSlides, autoplay ]), handleTouchStart = useCallback((e => {
|
|
12542
|
-
if (!allowTouchMove) return;
|
|
12543
|
-
// Stop autoplay on interaction if disableOnInteraction is true
|
|
12544
|
-
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
12545
|
-
autoplayRef.current = null, setAutoplayRunning(!1));
|
|
12546
|
-
const client = "horizontal" === direction ? "touches" in e ? e.touches[0]?.clientX || 0 : e.clientX : "touches" in e ? e.touches[0]?.clientY || 0 : e.clientY;
|
|
12547
|
-
setTouchStart(client), setTouching(!0), setDragOffset(0);
|
|
12548
|
-
}), [ allowTouchMove, direction, autoplay ]), handleTouchMove = useCallback((e => {
|
|
12549
|
-
if (!touching || !allowTouchMove) return;
|
|
12550
|
-
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;
|
|
12551
|
-
Math.abs(diff) > 10 && (e.preventDefault(), setDragOffset(.5 * -diff));
|
|
12552
|
-
}), [ touching, touchStart, allowTouchMove, direction ]), handleTouchEnd = useCallback((e => {
|
|
12553
|
-
if (!touching || !allowTouchMove) return;
|
|
12554
|
-
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;
|
|
12555
|
-
setTouching(!1), setDragOffset(0), Math.abs(diff) > threshold && (diff > 0 ? slideNext() : slidePrev());
|
|
12556
|
-
}), [ touching, touchStart, threshold, slideNext, slidePrev, allowTouchMove, direction ]), canSlideNext = loop || realIndex < slides.length - slidesToShow, canSlidePrev = loop || realIndex > 0;
|
|
12557
|
-
return {
|
|
12558
|
-
activeIndex: realIndex,
|
|
12559
|
-
realIndex: realIndex,
|
|
12560
|
-
previousIndex: realIndex,
|
|
12561
|
-
isBeginning: !loop && 0 === realIndex,
|
|
12562
|
-
isEnd: !loop && realIndex >= slides.length - slidesToShow,
|
|
12563
|
-
progress: slides.length > 0 ? realIndex / (slides.length - 1) : 0,
|
|
12564
|
-
autoplayRunning: autoplayRunning,
|
|
12565
|
-
transitioning: isTransitioning,
|
|
12566
|
-
touching: touching,
|
|
12567
|
-
translate: translateValue,
|
|
12568
|
-
slidesPerView: slidesToShow,
|
|
12569
|
-
slidesCount: slides.length,
|
|
12570
|
-
isLocked: !1,
|
|
12571
|
-
destroyed: !1,
|
|
12572
|
-
size: containerSize,
|
|
12573
|
-
touches: {
|
|
12574
|
-
startX: 0,
|
|
12575
|
-
startY: 0,
|
|
12576
|
-
currentX: 0,
|
|
12577
|
-
currentY: 0,
|
|
12578
|
-
diff: 0
|
|
12579
|
-
},
|
|
12580
|
-
allowSlideNext: canSlideNext,
|
|
12581
|
-
allowSlidePrev: canSlidePrev,
|
|
12582
|
-
allowTouchMove: allowTouchMove,
|
|
12583
|
-
animating: isTransitioning,
|
|
12584
|
-
enabled: !0,
|
|
12585
|
-
initialized: !0,
|
|
12586
|
-
slideNext: slideNext,
|
|
12587
|
-
slidePrev: slidePrev,
|
|
12588
|
-
goToSlide: goToSlide,
|
|
12589
|
-
canSlideNext: canSlideNext,
|
|
12590
|
-
canSlidePrev: canSlidePrev,
|
|
12591
|
-
containerRef: containerRef,
|
|
12592
|
-
wrapperRef: wrapperRef,
|
|
12593
|
-
handleTouchStart: handleTouchStart,
|
|
12594
|
-
handleTouchMove: handleTouchMove,
|
|
12595
|
-
handleTouchEnd: handleTouchEnd,
|
|
12596
|
-
allSlides: allSlides,
|
|
12597
|
-
translateValue: translateValue,
|
|
12598
|
-
slideWidth: slideWidth,
|
|
12599
|
-
currentSlidesToShow: slidesToShow,
|
|
12600
|
-
loopedSlides: loopedSlides,
|
|
12601
|
-
repositioningRef: repositioningRef
|
|
12602
|
-
};
|
|
12603
|
-
}
|
|
12604
|
-
|
|
12605
13439
|
/**
|
|
12606
13440
|
* Simplified hook for chart data processing
|
|
12607
13441
|
*/ function useChartData(data) {
|
|
@@ -12702,37 +13536,44 @@ function useSlider(options) {
|
|
|
12702
13536
|
// Accordion composables
|
|
12703
13537
|
const composablesImport = Object.freeze( Object.defineProperty({
|
|
12704
13538
|
__proto__: null,
|
|
12705
|
-
|
|
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,
|
|
12706
13551
|
useAccordion: useAccordion,
|
|
12707
13552
|
useAtomixGlass: useAtomixGlass,
|
|
12708
13553
|
useBadge: useBadge,
|
|
12709
13554
|
useBarChart: useBarChart,
|
|
12710
13555
|
useBlock: useBlock,
|
|
12711
|
-
useBreadcrumb: useBreadcrumb,
|
|
12712
|
-
useCard: useCard,
|
|
12713
13556
|
useChartData: useChartData,
|
|
12714
13557
|
useChartInteraction: useChartInteraction,
|
|
12715
13558
|
useChartScale: useChartScale,
|
|
12716
|
-
useDataTable: useDataTable,
|
|
12717
13559
|
useEdgePanel: useEdgePanel,
|
|
12718
13560
|
useForm: useForm,
|
|
12719
13561
|
useFormGroup: useFormGroup,
|
|
12720
13562
|
useHero: useHero,
|
|
12721
13563
|
useInput: useInput,
|
|
12722
13564
|
useLineChart: useLineChart,
|
|
12723
|
-
useModal: useModal$1,
|
|
12724
13565
|
useNav: useNav,
|
|
12725
13566
|
useNavDropdown: useNavDropdown,
|
|
12726
13567
|
useNavItem: useNavItem,
|
|
12727
13568
|
useNavbar: useNavbar,
|
|
12728
|
-
|
|
13569
|
+
usePerformanceMonitor: usePerformanceMonitor,
|
|
12729
13570
|
usePieChart: usePieChart,
|
|
12730
13571
|
useRadio: useRadio,
|
|
13572
|
+
useResponsiveGlass: useResponsiveGlass,
|
|
12731
13573
|
useRiver: useRiver,
|
|
12732
13574
|
useSelect: useSelect,
|
|
12733
13575
|
useSideMenu: useSideMenu,
|
|
12734
13576
|
useSideMenuItem: useSideMenuItem,
|
|
12735
|
-
useSlider: useSlider,
|
|
12736
13577
|
useSpinner: useSpinner,
|
|
12737
13578
|
useTextarea: useTextarea,
|
|
12738
13579
|
useTodo: useTodo
|
|
@@ -12823,7 +13664,10 @@ const Select = memo((({options: options, value: value, onChange: onChange, onBl
|
|
|
12823
13664
|
};
|
|
12824
13665
|
}), []);
|
|
12825
13666
|
// Toggle dropdown
|
|
12826
|
-
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 => {
|
|
12827
13671
|
if (setSelectedLabel(option.label), setIsOpen(!1), bodyRef.current && (bodyRef.current.style.height = "0px"),
|
|
12828
13672
|
nativeSelectRef.current && (nativeSelectRef.current.value = option.value), onChange) {
|
|
12829
13673
|
// Create a synthetic event
|
|
@@ -12867,7 +13711,15 @@ const Select = memo((({options: options, value: value, onChange: onChange, onBl
|
|
|
12867
13711
|
"aria-describedby": ariaDescribedBy,
|
|
12868
13712
|
"aria-invalid": invalid,
|
|
12869
13713
|
style: {
|
|
12870
|
-
|
|
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"
|
|
12871
13723
|
},
|
|
12872
13724
|
children: [ placeholder && jsx("option", {
|
|
12873
13725
|
value: "",
|
|
@@ -12880,11 +13732,29 @@ const Select = memo((({options: options, value: value, onChange: onChange, onBl
|
|
|
12880
13732
|
}, option.value))) ]
|
|
12881
13733
|
}), jsx("div", {
|
|
12882
13734
|
className: SELECT.CLASSES.SELECTED,
|
|
12883
|
-
onClick:
|
|
12884
|
-
|
|
12885
|
-
|
|
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
|
+
}
|
|
12886
13751
|
},
|
|
12887
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,
|
|
12888
13758
|
children: selectedLabel
|
|
12889
13759
|
}), jsx("i", {
|
|
12890
13760
|
className: `${SELECT.CLASSES.ICON_CARET} ${SELECT.CLASSES.TOGGLE_ICON}`
|
|
@@ -12899,10 +13769,16 @@ const Select = memo((({options: options, value: value, onChange: onChange, onBl
|
|
|
12899
13769
|
ref: panelRef,
|
|
12900
13770
|
children: jsx("ul", {
|
|
12901
13771
|
className: SELECT.CLASSES.SELECT_ITEMS,
|
|
13772
|
+
role: "listbox",
|
|
13773
|
+
id: id ? `${id}-listbox` : void 0,
|
|
13774
|
+
"aria-labelledby": id,
|
|
12902
13775
|
children: hasOptionsProp ? options.map(((option, index) => jsx("li", {
|
|
12903
13776
|
className: SELECT.CLASSES.SELECT_ITEM,
|
|
12904
13777
|
"data-value": option.value,
|
|
12905
13778
|
onClick: () => !option.disabled && handleItemClick(option),
|
|
13779
|
+
role: "option",
|
|
13780
|
+
"aria-selected": value === option.value,
|
|
13781
|
+
"aria-disabled": option.disabled,
|
|
12906
13782
|
children: jsxs("label", {
|
|
12907
13783
|
htmlFor: `SelectItem${index}`,
|
|
12908
13784
|
className: "c-checkbox",
|
|
@@ -14438,7 +15314,45 @@ const ModalImpl = memo((({children: children, isOpen: isOpen = !1, onOpenChange
|
|
|
14438
15314
|
onOpenChange: onOpenChange,
|
|
14439
15315
|
onClose: onClose,
|
|
14440
15316
|
onOpen: onOpen
|
|
14441
|
-
})
|
|
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}`;
|
|
14442
15356
|
// Handle keyboard events for Escape key
|
|
14443
15357
|
useEffect((() => {
|
|
14444
15358
|
if (!keyboard) return;
|
|
@@ -14456,15 +15370,19 @@ const ModalImpl = memo((({children: children, isOpen: isOpen = !1, onOpenChange
|
|
|
14456
15370
|
return React.isValidElement(child) && _includesInstanceProperty(_context = [ "ModalHeader", "ModalBody", "ModalFooter" ]).call(_context, child.type.displayName);
|
|
14457
15371
|
})), modalContent = jsx("div", {
|
|
14458
15372
|
className: "c-modal__content",
|
|
15373
|
+
ref: contentRef,
|
|
14459
15374
|
children: hasCompoundComponents ? React.Children.map(children, (child => React.isValidElement(child) && "ModalHeader" === child.type.displayName ? React.cloneElement(child, {
|
|
14460
|
-
onClose: child.props.onClose || close
|
|
15375
|
+
onClose: child.props.onClose || close,
|
|
15376
|
+
id: titleId
|
|
14461
15377
|
}) : child)) : jsxs(Fragment, {
|
|
14462
15378
|
children: [ (title || closeButton) && jsx(ModalHeader, {
|
|
15379
|
+
id: titleId,
|
|
14463
15380
|
title: title,
|
|
14464
15381
|
subtitle: subtitle,
|
|
14465
15382
|
closeButton: closeButton,
|
|
14466
15383
|
onClose: close
|
|
14467
15384
|
}), jsx(ModalBody, {
|
|
15385
|
+
id: descId,
|
|
14468
15386
|
children: children
|
|
14469
15387
|
}), footer && jsx(ModalFooter, {
|
|
14470
15388
|
children: footer
|
|
@@ -14482,6 +15400,8 @@ const ModalImpl = memo((({children: children, isOpen: isOpen = !1, onOpenChange
|
|
|
14482
15400
|
role: "dialog",
|
|
14483
15401
|
"aria-modal": "true",
|
|
14484
15402
|
"aria-hidden": !isOpenState,
|
|
15403
|
+
"aria-labelledby": titleId,
|
|
15404
|
+
"aria-describedby": descId,
|
|
14485
15405
|
...props,
|
|
14486
15406
|
children: [ jsx("div", {
|
|
14487
15407
|
ref: backdropRef,
|
|
@@ -14728,7 +15648,27 @@ const Navbar = forwardRef((({brand: brand, children: children, variant: variant
|
|
|
14728
15648
|
return window.addEventListener("resize", handleResize), () => {
|
|
14729
15649
|
window.removeEventListener("resize", handleResize);
|
|
14730
15650
|
};
|
|
14731
|
-
}), [ 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 ]);
|
|
14732
15672
|
// Generate the navbar class
|
|
14733
15673
|
const navbarClass = generateNavbarClass({
|
|
14734
15674
|
position: position,
|
|
@@ -17320,7 +18260,235 @@ const SectionIntro = ({title: title, label: label, text: text, actions: actions,
|
|
|
17320
18260
|
SectionIntro.displayName = "SectionIntro";
|
|
17321
18261
|
|
|
17322
18262
|
const Slider = forwardRef(((props, ref) => {
|
|
17323
|
-
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
|
+
}({
|
|
17324
18492
|
slides: validSlides,
|
|
17325
18493
|
slidesToShow: slidesToShow,
|
|
17326
18494
|
spaceBetween: spaceBetween,
|
|
@@ -17347,7 +18515,8 @@ const Slider = forwardRef(((props, ref) => {
|
|
|
17347
18515
|
})
|
|
17348
18516
|
});
|
|
17349
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(" ");
|
|
17350
|
-
|
|
18518
|
+
// Keyboard navigation
|
|
18519
|
+
return jsxs("div", {
|
|
17351
18520
|
ref: ref || containerRef,
|
|
17352
18521
|
className: containerClasses,
|
|
17353
18522
|
style: {
|
|
@@ -17365,9 +18534,32 @@ const Slider = forwardRef(((props, ref) => {
|
|
|
17365
18534
|
onMouseMove: handleTouchMove,
|
|
17366
18535
|
onMouseUp: handleTouchEnd,
|
|
17367
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,
|
|
17368
18559
|
children: [ jsx("div", {
|
|
17369
18560
|
ref: wrapperRef,
|
|
17370
18561
|
className: "c-slider__wrapper",
|
|
18562
|
+
"aria-live": autoplay ? "off" : "polite",
|
|
17371
18563
|
style: {
|
|
17372
18564
|
display: "flex",
|
|
17373
18565
|
flexDirection: "vertical" === direction ? "column" : "row",
|
|
@@ -17545,15 +18737,24 @@ Steps.displayName = "Steps", Steps.Item = StepsItem, Steps.Step = StepsItem;
|
|
|
17545
18737
|
// Context for compound usage
|
|
17546
18738
|
const TabsContext = createContext({
|
|
17547
18739
|
currentTab: 0,
|
|
17548
|
-
handleTabClick: () => {}
|
|
17549
|
-
|
|
17550
|
-
|
|
17551
|
-
|
|
17552
|
-
|
|
17553
|
-
|
|
17554
|
-
|
|
17555
|
-
|
|
17556
|
-
|
|
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
|
+
}));
|
|
17557
18758
|
|
|
17558
18759
|
// Compound components
|
|
17559
18760
|
TabsList.displayName = "TabsList";
|
|
@@ -17565,8 +18766,10 @@ const TabsTrigger = forwardRef((({children: children, className: className = ""
|
|
|
17565
18766
|
const isActive = void 0 !== index && currentTab === index;
|
|
17566
18767
|
return jsx("li", {
|
|
17567
18768
|
className: "c-tabs__nav-item",
|
|
18769
|
+
role: "presentation",
|
|
17568
18770
|
children: jsx("button", {
|
|
17569
18771
|
ref: ref,
|
|
18772
|
+
id: `tab-nav-${index}`,
|
|
17570
18773
|
className: `c-tabs__nav-btn ${isActive ? TAB.CLASSES.ACTIVE : ""} ${className}`.trim(),
|
|
17571
18774
|
onClick: e => {
|
|
17572
18775
|
void 0 !== index && handleTabClick(index), onClick?.(e);
|
|
@@ -17575,6 +18778,7 @@ const TabsTrigger = forwardRef((({children: children, className: className = ""
|
|
|
17575
18778
|
role: "tab",
|
|
17576
18779
|
"aria-selected": isActive,
|
|
17577
18780
|
"aria-controls": `tab-panel-${index}`,
|
|
18781
|
+
tabIndex: isActive ? 0 : -1,
|
|
17578
18782
|
type: "button",
|
|
17579
18783
|
...props,
|
|
17580
18784
|
children: children
|
|
@@ -17624,24 +18828,59 @@ TabsPanel.displayName = "TabsPanel";
|
|
|
17624
18828
|
const Tabs = memo((({items: items, activeIndex: activeIndex = TAB.DEFAULTS.ACTIVE_INDEX, onTabChange: onTabChange, className: className = "", style: style, glass: glass, children: children}) => {
|
|
17625
18829
|
const [currentTab, setCurrentTab] = useState(activeIndex), handleTabClick = index => {
|
|
17626
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);
|
|
17627
18859
|
};
|
|
17628
18860
|
// Handle tab change
|
|
17629
18861
|
// Determine content based on mode (legacy items vs compound children)
|
|
17630
18862
|
let content;
|
|
17631
18863
|
// Use items prop if provided
|
|
17632
|
-
|
|
17633
|
-
|
|
18864
|
+
if (items && items.length > 0)
|
|
18865
|
+
// Legacy mode
|
|
18866
|
+
content = jsxs(Fragment, {
|
|
17634
18867
|
children: [ jsx("ul", {
|
|
17635
18868
|
className: "c-tabs__nav",
|
|
18869
|
+
role: "tablist",
|
|
18870
|
+
onKeyDown: e => handleKeyDown(e, items.length),
|
|
17636
18871
|
children: items.map(((item, index) => jsx("li", {
|
|
17637
18872
|
className: "c-tabs__nav-item",
|
|
18873
|
+
role: "presentation",
|
|
17638
18874
|
children: jsx("button", {
|
|
18875
|
+
id: `tab-nav-${index}`,
|
|
17639
18876
|
className: `c-tabs__nav-btn ${index === currentTab ? TAB.CLASSES.ACTIVE : ""}`,
|
|
17640
18877
|
onClick: () => handleTabClick(index),
|
|
17641
18878
|
"data-tabindex": index,
|
|
17642
18879
|
role: "tab",
|
|
17643
18880
|
"aria-selected": index === currentTab,
|
|
17644
18881
|
"aria-controls": `tab-panel-${index}`,
|
|
18882
|
+
tabIndex: index === currentTab ? 0 : -1,
|
|
18883
|
+
type: "button",
|
|
17645
18884
|
children: item.label
|
|
17646
18885
|
})
|
|
17647
18886
|
}, `tab-nav-${index}`)))
|
|
@@ -17665,13 +18904,19 @@ const Tabs = memo((({items: items, activeIndex: activeIndex = TAB.DEFAULTS.ACTI
|
|
|
17665
18904
|
})
|
|
17666
18905
|
}, `tab-panel-${index}`)))
|
|
17667
18906
|
}) ]
|
|
17668
|
-
})
|
|
17669
|
-
|
|
17670
|
-
|
|
17671
|
-
|
|
17672
|
-
|
|
17673
|
-
|
|
17674
|
-
|
|
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
|
+
}
|
|
17675
18920
|
const wrapper = jsx("div", {
|
|
17676
18921
|
className: `c-tabs js-atomix-tab ${className}`,
|
|
17677
18922
|
style: style,
|
|
@@ -17762,7 +19007,7 @@ const Testimonial = ({quote: quote, author: author, size: size = "", skeleton: s
|
|
|
17762
19007
|
className: "c-testimonial__author",
|
|
17763
19008
|
children: [ author.avatarSrc && jsx("img", {
|
|
17764
19009
|
src: author.avatarSrc,
|
|
17765
|
-
alt: author.avatarAlt ||
|
|
19010
|
+
alt: author.avatarAlt || `${author.name}'s avatar`,
|
|
17766
19011
|
className: "c-testimonial__author-avatar c-avatar c-avatar--xxl c-avatar--circle"
|
|
17767
19012
|
}), jsxs("div", {
|
|
17768
19013
|
className: "c-testimonial__info",
|
|
@@ -18038,7 +19283,17 @@ const Tooltip = memo((({content: content, children: children, position: positio
|
|
|
18038
19283
|
cancelAnimationFrame(rafId), window.removeEventListener("resize", handleUpdate),
|
|
18039
19284
|
window.removeEventListener("scroll", handleUpdate, !0);
|
|
18040
19285
|
};
|
|
18041
|
-
}), [ 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 ]);
|
|
18042
19297
|
// Setup trigger props
|
|
18043
19298
|
const triggerProps = {
|
|
18044
19299
|
"aria-describedby": isVisible ? tooltipId : void 0
|
|
@@ -18727,9 +19982,15 @@ const VideoPlayer = forwardRef((({src: src, type: type = "video", youtubeId: yo
|
|
|
18727
19982
|
const rect = e.currentTarget.getBoundingClientRect(), percent = (e.clientX - rect.left) / rect.width;
|
|
18728
19983
|
setVolume(percent);
|
|
18729
19984
|
}), [ setVolume ]), handleDownload = useCallback((() => {
|
|
18730
|
-
if (src) {
|
|
18731
|
-
|
|
18732
|
-
|
|
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
|
|
18733
19994
|
}
|
|
18734
19995
|
}), [ src ]), handleShare = useCallback((async () => {
|
|
18735
19996
|
if (navigator.share) try {
|
|
@@ -19306,6 +20567,7 @@ const components = Object.freeze( Object.defineProperty({
|
|
|
19306
20567
|
TODO: TODO,
|
|
19307
20568
|
TOGGLE: TOGGLE,
|
|
19308
20569
|
TOOLTIP: TOOLTIP,
|
|
20570
|
+
TYPEDBUTTON: TYPEDBUTTON,
|
|
19309
20571
|
UPLOAD: UPLOAD,
|
|
19310
20572
|
VIDEO_PLAYER: VIDEO_PLAYER,
|
|
19311
20573
|
sliderConstants: sliderConstants
|
|
@@ -25248,5 +26510,5 @@ const atomix = {
|
|
|
25248
26510
|
types: types
|
|
25249
26511
|
};
|
|
25250
26512
|
|
|
25251
|
-
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 };
|
|
25252
26514
|
//# sourceMappingURL=index.esm.js.map
|