@shohojdhara/atomix 0.4.7 → 0.4.9

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