@shohojdhara/atomix 0.5.0 → 0.5.2

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 (168) hide show
  1. package/atomix.config.ts +12 -0
  2. package/build-tools/webpack-loader.js +5 -4
  3. package/dist/atomix.css +230 -83
  4. package/dist/atomix.css.map +1 -1
  5. package/dist/atomix.min.css +1 -1
  6. package/dist/atomix.min.css.map +1 -1
  7. package/dist/build-tools/webpack-loader.js +5 -4
  8. package/dist/charts.d.ts +24 -23
  9. package/dist/charts.js +271 -369
  10. package/dist/charts.js.map +1 -1
  11. package/dist/config.d.ts +624 -0
  12. package/dist/config.js +59 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/core.d.ts +3 -2
  15. package/dist/core.js +342 -382
  16. package/dist/core.js.map +1 -1
  17. package/dist/forms.d.ts +4 -6
  18. package/dist/forms.js +233 -334
  19. package/dist/forms.js.map +1 -1
  20. package/dist/heavy.d.ts +11 -2
  21. package/dist/heavy.js +406 -445
  22. package/dist/heavy.js.map +1 -1
  23. package/dist/index.d.ts +109 -65
  24. package/dist/index.esm.js +654 -748
  25. package/dist/index.esm.js.map +1 -1
  26. package/dist/index.js +621 -717
  27. package/dist/index.js.map +1 -1
  28. package/dist/index.min.js +1 -1
  29. package/dist/index.min.js.map +1 -1
  30. package/dist/layout.js +59 -60
  31. package/dist/layout.js.map +1 -1
  32. package/dist/theme.js +4 -4
  33. package/dist/theme.js.map +1 -1
  34. package/package.json +24 -9
  35. package/scripts/atomix-cli.js +15 -1
  36. package/scripts/cli/__tests__/complexity-utils.test.js +24 -0
  37. package/scripts/cli/__tests__/detector.test.js +50 -0
  38. package/scripts/cli/__tests__/template-engine.test.js +23 -0
  39. package/scripts/cli/__tests__/test-setup.js +1 -133
  40. package/scripts/cli/commands/doctor.js +15 -3
  41. package/scripts/cli/commands/generate.js +113 -51
  42. package/scripts/cli/internal/ai-engine.js +30 -10
  43. package/scripts/cli/internal/complexity-utils.js +60 -0
  44. package/scripts/cli/internal/component-validator.js +49 -16
  45. package/scripts/cli/internal/generator.js +89 -36
  46. package/scripts/cli/internal/hook-generator.js +5 -2
  47. package/scripts/cli/internal/itcss-generator.js +16 -12
  48. package/scripts/cli/templates/next-templates.js +81 -30
  49. package/scripts/cli/templates/storybook-templates.js +12 -2
  50. package/scripts/cli/utils/detector.js +45 -7
  51. package/scripts/cli/utils/diagnostics.js +78 -0
  52. package/scripts/cli/utils/telemetry.js +13 -0
  53. package/src/components/Accordion/Accordion.stories.tsx +4 -0
  54. package/src/components/AtomixGlass/AtomixGlass.tsx +188 -128
  55. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +63 -91
  56. package/src/components/AtomixGlass/PerformanceDashboard.tsx +153 -201
  57. package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +9 -6
  58. package/src/components/AtomixGlass/glass-utils.ts +51 -1
  59. package/src/components/AtomixGlass/stories/AnimationFeatures.stories.tsx +52 -46
  60. package/src/components/AtomixGlass/stories/Examples.stories.tsx +573 -236
  61. package/src/components/AtomixGlass/stories/Playground.stories.tsx +88 -41
  62. package/src/components/AtomixGlass/stories/argTypes.ts +19 -19
  63. package/src/components/AtomixGlass/stories/shared-components.tsx +7 -12
  64. package/src/components/AtomixGlass/stories/types.ts +3 -3
  65. package/src/components/Button/Button.tsx +114 -57
  66. package/src/components/Callout/Callout.tsx +4 -4
  67. package/src/components/Chart/ChartRenderer.tsx +1 -1
  68. package/src/components/Chart/DonutChart.tsx +11 -8
  69. package/src/components/EdgePanel/EdgePanel.tsx +119 -115
  70. package/src/components/Form/Select.tsx +4 -4
  71. package/src/components/List/List.tsx +4 -4
  72. package/src/components/Navigation/SideMenu/SideMenu.tsx +6 -6
  73. package/src/components/PhotoViewer/PhotoViewerImage.tsx +1 -1
  74. package/src/components/ProductReview/ProductReview.tsx +4 -2
  75. package/src/components/Rating/Rating.tsx +4 -2
  76. package/src/components/SectionIntro/SectionIntro.tsx +4 -2
  77. package/src/components/Steps/Steps.tsx +1 -1
  78. package/src/components/Tabs/Tabs.tsx +5 -5
  79. package/src/components/Testimonial/Testimonial.tsx +4 -2
  80. package/src/components/VideoPlayer/VideoPlayer.tsx +4 -2
  81. package/src/layouts/CssGrid/CssGrid.stories.tsx +464 -0
  82. package/src/layouts/CssGrid/CssGrid.tsx +215 -0
  83. package/src/layouts/CssGrid/index.ts +8 -0
  84. package/src/layouts/CssGrid/scripts/CssGrid.js +284 -0
  85. package/src/layouts/CssGrid/scripts/index.js +43 -0
  86. package/src/layouts/Grid/scripts/Container.js +139 -0
  87. package/src/layouts/Grid/scripts/Grid.js +184 -0
  88. package/src/layouts/Grid/scripts/GridCol.js +273 -0
  89. package/src/layouts/Grid/scripts/Row.js +154 -0
  90. package/src/layouts/Grid/scripts/index.js +48 -0
  91. package/src/layouts/MasonryGrid/MasonryGrid.tsx +71 -59
  92. package/src/lib/composables/atomix-glass/useGlassSize.ts +1 -1
  93. package/src/lib/composables/useAccordion.ts +5 -5
  94. package/src/lib/composables/useAtomixGlass.ts +111 -74
  95. package/src/lib/composables/useAtomixGlassStyles.ts +0 -2
  96. package/src/lib/composables/useBarChart.ts +2 -2
  97. package/src/lib/composables/useChart.ts +3 -2
  98. package/src/lib/composables/useChartToolbar.ts +48 -66
  99. package/src/lib/composables/useDataTable.ts +1 -1
  100. package/src/lib/composables/useDatePicker.ts +2 -2
  101. package/src/lib/composables/useEdgePanel.ts +45 -54
  102. package/src/lib/composables/useHeroBackgroundSlider.ts +5 -5
  103. package/src/lib/composables/usePhotoViewer.ts +2 -3
  104. package/src/lib/composables/usePieChart.ts +1 -1
  105. package/src/lib/composables/usePopover.ts +151 -139
  106. package/src/lib/composables/useSideMenu.ts +28 -41
  107. package/src/lib/composables/useSlider.ts +2 -6
  108. package/src/lib/composables/useTooltip.ts +2 -2
  109. package/src/lib/config/index.ts +39 -0
  110. package/src/lib/constants/components.ts +1 -0
  111. package/src/lib/theme/devtools/Comparator.tsx +1 -1
  112. package/src/lib/theme/devtools/Inspector.tsx +1 -1
  113. package/src/lib/theme/devtools/LiveEditor.tsx +1 -1
  114. package/src/lib/theme/runtime/ThemeProvider.tsx +1 -1
  115. package/src/lib/types/components.ts +1 -0
  116. package/src/styles/01-settings/_index.scss +1 -0
  117. package/src/styles/01-settings/_settings.atomix-glass.scss +174 -0
  118. package/src/styles/01-settings/_settings.masonry-grid.scss +42 -6
  119. package/src/styles/02-tools/_tools.glass.scss +6 -0
  120. package/src/styles/05-objects/_objects.masonry-grid.scss +162 -24
  121. package/src/styles/06-components/_components.atomix-glass.scss +160 -99
  122. package/scripts/cli/__tests__/README.md +0 -81
  123. package/scripts/cli/__tests__/basic.test.js +0 -116
  124. package/scripts/cli/__tests__/clean.test.js +0 -278
  125. package/scripts/cli/__tests__/component-generator.test.js +0 -332
  126. package/scripts/cli/__tests__/component-validator.test.js +0 -433
  127. package/scripts/cli/__tests__/generator.test.js +0 -613
  128. package/scripts/cli/__tests__/glass-motion.test.js +0 -256
  129. package/scripts/cli/__tests__/integration.test.js +0 -938
  130. package/scripts/cli/__tests__/migrate.test.js +0 -74
  131. package/scripts/cli/__tests__/security.test.js +0 -206
  132. package/scripts/cli/__tests__/theme-bridge.test.js +0 -507
  133. package/scripts/cli/__tests__/token-manager.test.js +0 -251
  134. package/scripts/cli/__tests__/token-provider.test.js +0 -361
  135. package/scripts/cli/__tests__/utils.test.js +0 -165
  136. package/src/components/AtomixGlass/stories/AnimationTests.stories.tsx +0 -95
  137. package/src/components/AtomixGlass/stories/CardExamples.stories.tsx +0 -212
  138. package/src/components/AtomixGlass/stories/Customization.stories.tsx +0 -131
  139. package/src/components/AtomixGlass/stories/DashboardExamples.stories.tsx +0 -348
  140. package/src/components/AtomixGlass/stories/EcommerceExamples.stories.tsx +0 -410
  141. package/src/components/AtomixGlass/stories/FormExamples.stories.tsx +0 -436
  142. package/src/components/AtomixGlass/stories/HeroExamples.stories.tsx +0 -264
  143. package/src/components/AtomixGlass/stories/InteractivePlayground.stories.tsx +0 -247
  144. package/src/components/AtomixGlass/stories/MobileUIExamples.stories.tsx +0 -418
  145. package/src/components/AtomixGlass/stories/ModalExamples.stories.tsx +0 -402
  146. package/src/components/AtomixGlass/stories/Modes.stories.tsx +0 -1082
  147. package/src/components/AtomixGlass/stories/Overview.stories.tsx +0 -497
  148. package/src/components/AtomixGlass/stories/Performance.stories.tsx +0 -103
  149. package/src/components/AtomixGlass/stories/PresetGallery.stories.tsx +0 -335
  150. package/src/components/AtomixGlass/stories/Shaders.stories.tsx +0 -395
  151. package/src/components/AtomixGlass/stories/WidgetExamples.stories.tsx +0 -441
  152. package/src/components/TypedButton/TypedButton.stories.tsx +0 -59
  153. package/src/components/TypedButton/TypedButton.tsx +0 -39
  154. package/src/components/TypedButton/index.ts +0 -2
  155. package/src/lib/composables/useBreadcrumb.ts +0 -81
  156. package/src/lib/composables/useChartInteractions.ts +0 -123
  157. package/src/lib/composables/useChartPerformance.ts +0 -347
  158. package/src/lib/composables/useDropdown.ts +0 -338
  159. package/src/lib/composables/useModal.ts +0 -110
  160. package/src/lib/composables/useTypedButton.ts +0 -66
  161. package/src/lib/hooks/usePerformanceMonitor.ts +0 -148
  162. package/src/lib/utils/displacement-generator.ts +0 -92
  163. package/src/lib/utils/memoryMonitor.ts +0 -191
  164. package/src/styles/01-settings/_settings.testtypecheck.scss +0 -53
  165. package/src/styles/01-settings/_settings.typedbutton.scss +0 -53
  166. package/src/styles/06-components/_components.testbutton.scss +0 -212
  167. package/src/styles/06-components/_components.testtypecheck.scss +0 -212
  168. package/src/styles/06-components/_components.typedbutton.scss +0 -212
package/dist/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
 
3
- import React, { useState, useRef, useEffect, memo, forwardRef, useMemo, useCallback, useId, Children, isValidElement, cloneElement, createContext, useContext, useImperativeHandle, Component } from "react";
3
+ import React, { useState, useRef, useCallback, useEffect, memo, forwardRef, useId, useMemo, Children, isValidElement, cloneElement, createContext, useContext, useImperativeHandle, Component } from "react";
4
4
 
5
5
  import * as PhosphorIcons from "@phosphor-icons/react";
6
6
 
@@ -1695,6 +1695,7 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
1695
1695
  FILTER_OVERLAY_CLASS: "c-atomix-glass__filter-overlay",
1696
1696
  FILTER_SHADOW_CLASS: "c-atomix-glass__filter-shadow",
1697
1697
  CONTENT_CLASS: "c-atomix-glass__content",
1698
+ BORDER_BACKDROP_CLASS: "c-atomix-glass__border-backdrop",
1698
1699
  BORDER_1_CLASS: "c-atomix-glass__border-1",
1699
1700
  BORDER_2_CLASS: "c-atomix-glass__border-2",
1700
1701
  HOVER_1_CLASS: "c-atomix-glass__hover-1",
@@ -1964,19 +1965,19 @@ function useAccordion(initialProps) {
1964
1965
  disabled: !1,
1965
1966
  iconPosition: "right",
1966
1967
  ...initialProps
1967
- }, isControlled = "boolean" == typeof defaultProps.isOpen, [internalOpen, setInternalOpen] = useState(defaultProps.defaultOpen || !1), isOpen = isControlled ? defaultProps.isOpen : internalOpen, [panelHeight, setPanelHeight] = useState(isOpen ? "auto" : "0px"), panelRef = useRef(null), contentRef = useRef(null), updatePanelHeight = () => {
1968
+ }, isControlled = "boolean" == typeof defaultProps.isOpen, [internalOpen, setInternalOpen] = useState(defaultProps.defaultOpen || !1), isOpen = isControlled ? defaultProps.isOpen : internalOpen, [panelHeight, setPanelHeight] = useState(isOpen ? "auto" : "0px"), panelRef = useRef(null), contentRef = useRef(null), updatePanelHeight = useCallback((() => {
1968
1969
  if (contentRef.current && panelRef.current) {
1969
1970
  const height = isOpen ? `${contentRef.current.clientHeight}px` : "0px";
1970
1971
  panelRef.current.style.setProperty(ACCORDION.CSS_VARS.PANEL_HEIGHT, height), setPanelHeight(height);
1971
1972
  }
1972
- };
1973
+ }), [ isOpen ]);
1973
1974
  // Controlled/uncontrolled open state
1974
1975
  /**
1975
1976
  * Effect to update panel height when open state changes
1976
1977
  */
1977
1978
  return useEffect((() => {
1978
1979
  updatePanelHeight();
1979
- }), [ isOpen ]),
1980
+ }), [ isOpen, updatePanelHeight ]),
1980
1981
  /**
1981
1982
  * Effect to handle window resize and update panel height
1982
1983
  */
@@ -1985,7 +1986,7 @@ function useAccordion(initialProps) {
1985
1986
  isOpen && updatePanelHeight();
1986
1987
  };
1987
1988
  return window.addEventListener("resize", handleResize), () => window.removeEventListener("resize", handleResize);
1988
- }), [ isOpen ]), {
1989
+ }), [ isOpen, updatePanelHeight ]), {
1989
1990
  state: {
1990
1991
  isOpen: isOpen,
1991
1992
  panelHeight: panelHeight
@@ -2097,7 +2098,7 @@ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
2097
2098
  default:
2098
2099
  return console.warn("AtomixGlass: Invalid displacement mode"), displacementMap;
2099
2100
  }
2100
- }, GlassFilterComponent = ({id: id, displacementScale: displacementScale, aberrationIntensity: aberrationIntensity, mode: mode, shaderMapUrl: shaderMapUrl, blurAmount: blurAmount}) => jsx("svg", {
2101
+ }, sharedShaderCache = new Map, GlassFilterComponent = ({id: id, displacementScale: displacementScale, aberrationIntensity: aberrationIntensity, mode: mode, shaderMapUrl: shaderMapUrl, blurAmount: blurAmount}) => jsx("svg", {
2101
2102
  style: {
2102
2103
  position: "absolute",
2103
2104
  width: "100%",
@@ -2238,24 +2239,17 @@ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
2238
2239
  */ GlassFilterComponent.displayName = "GlassFilter";
2239
2240
 
2240
2241
  // Memoize component to prevent unnecessary re-renders
2241
- const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevProps.id === nextProps.id && prevProps.displacementScale === nextProps.displacementScale && prevProps.aberrationIntensity === nextProps.aberrationIntensity && prevProps.mode === nextProps.mode && prevProps.shaderMapUrl === nextProps.shaderMapUrl && prevProps.blurAmount === nextProps.blurAmount));
2242
-
2243
- // Module-level counter for deterministic ID generation
2244
- let idCounter = 0;
2245
-
2246
- // Module-level shared shader cache with LRU eviction
2247
- const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({children: children, className: className = "", style: style, displacementScale: displacementScale = 25, blurAmount: blurAmount = .0625, saturation: saturation = 180, aberrationIntensity: aberrationIntensity = 2, mouseOffset: mouseOffset = {
2242
+ const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevProps.id === nextProps.id && prevProps.displacementScale === nextProps.displacementScale && prevProps.aberrationIntensity === nextProps.aberrationIntensity && prevProps.mode === nextProps.mode && prevProps.shaderMapUrl === nextProps.shaderMapUrl && prevProps.blurAmount === nextProps.blurAmount)), AtomixGlassContainer = forwardRef((({children: children, className: className = "", style: style, displacementScale: displacementScale = 25, blurAmount: blurAmount = .0625, saturation: saturation = 180, aberrationIntensity: aberrationIntensity = 2, mouseOffset: mouseOffset = {
2248
2243
  x: 0,
2249
2244
  y: 0
2250
2245
  }, 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 = {
2251
2246
  width: 0,
2252
2247
  height: 0
2253
- }, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1,
2248
+ }, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, isFixedOrSticky: isFixedOrSticky = !1,
2254
2249
  // Phase 1: Animation System props
2255
2250
  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) => {
2256
- // Generate a stable, deterministic ID for SSR compatibility
2257
- // Use a module-level counter that's consistent across server and client
2258
- const filterId = useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null), shaderUpdateTimeoutRef = useRef(null), animationFrameRef = useRef(null);
2251
+ // React 18 useId — stable, unique, and SSR-safe (no module-level counter)
2252
+ const rawId = useId(), filterId = useMemo((() => `atomix-glass-filter-${rawId.replace(/:/g, "")}`), [ rawId ]), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null), shaderUpdateTimeoutRef = useRef(null), animationFrameRef = useRef(null);
2259
2253
  // Lazy load shader utilities only when shader mode is needed
2260
2254
  useEffect((() => {
2261
2255
  "shader" === mode ?
@@ -2278,9 +2272,7 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
2278
2272
  // Create cache key from size and variant
2279
2273
  const cacheKey = `${glassSize.width}x${glassSize.height}-${shaderVariant}`, cachedUrl = (key => {
2280
2274
  const entry = sharedShaderCache.get(key);
2281
- return entry ? (
2282
- // Update access timestamp for LRU
2283
- entry.timestamp = Date.now(), entry.url) : null;
2275
+ return entry ? (entry.timestamp = Date.now(), entry.url) : null;
2284
2276
  })(cacheKey);
2285
2277
  // Check shared cache first
2286
2278
  if (cachedUrl) return void setShaderMapUrl(cachedUrl);
@@ -2291,29 +2283,24 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
2291
2283
  if (shaderUtilsRef.current) try {
2292
2284
  const {ShaderDisplacementGenerator: ShaderDisplacementGenerator, fragmentShaders: fragmentShaders} = shaderUtilsRef.current;
2293
2285
  shaderGeneratorRef.current?.destroy();
2294
- const selectedShader = fragmentShaders[shaderVariant] || fragmentShaders.liquidGlass;
2286
+ const selectedShader = fragmentShaders[shaderVariant] ?? fragmentShaders.liquidGlass;
2295
2287
  shaderGeneratorRef.current = new ShaderDisplacementGenerator({
2296
2288
  width: glassSize.width,
2297
2289
  height: glassSize.height,
2298
2290
  fragment: selectedShader
2299
2291
  }), shaderUpdateTimeoutRef.current = setTimeout((() => {
2300
- const url = shaderGeneratorRef.current?.updateShader() || "";
2292
+ const url = shaderGeneratorRef.current?.updateShader() ?? "";
2301
2293
  url && ((key, url) => {
2302
- // Evict oldest entries if at capacity
2303
2294
  if (sharedShaderCache.size >= 15) {
2304
2295
  const entries = Array.from(sharedShaderCache.entries());
2305
- // Sort by timestamp (oldest first)
2306
- entries.sort(((a, b) => a[1].timestamp - b[1].timestamp));
2307
- // Remove oldest entry
2308
- const oldestEntry = entries[0];
2309
- oldestEntry && sharedShaderCache.delete(oldestEntry[0]);
2296
+ entries.sort(((a, b) => a[1].timestamp - b[1].timestamp));
2297
+ const oldest = entries[0];
2298
+ oldest && sharedShaderCache.delete(oldest[0]);
2310
2299
  }
2311
2300
  sharedShaderCache.set(key, {
2312
2301
  url: url,
2313
2302
  timestamp: Date.now()
2314
- }),
2315
- // Development mode: log cache size
2316
- "undefined" != typeof process && "production" === process.env?.NODE_ENV || sharedShaderCache.size;
2303
+ }), "undefined" != typeof process && "production" === process.env?.NODE_ENV || sharedShaderCache.size;
2317
2304
  })(cacheKey, url), setShaderMapUrl(url);
2318
2305
  }), 100);
2319
2306
  } catch (error) {
@@ -2382,7 +2369,6 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
2382
2369
  console.warn("AtomixGlassContainer: Error getting element bounds", error), setRectCache(null);
2383
2370
  }
2384
2371
  }), [ ref, glassSize ]);
2385
- // Pre-calculate static multipliers outside useMemo
2386
2372
  const liquidBlur = useMemo((() => {
2387
2373
  const defaultBlur = {
2388
2374
  baseBlur: blurAmount,
@@ -2451,7 +2437,6 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
2451
2437
  }), [ borderRadius, backdropStyle, mouseOffset, overLight, effectiveWithoutEffects, overLightConfig ]);
2452
2438
  return jsx("div", {
2453
2439
  ref: el => {
2454
- // Apply force no-transition
2455
2440
  // Handle forwarded ref
2456
2441
  "function" == typeof ref ? ref(el) : ref && (ref.current = el);
2457
2442
  },
@@ -2493,6 +2478,7 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
2493
2478
  });
2494
2479
  }));
2495
2480
 
2481
+ // ─── Blur multiplier constants (module-level, never change at runtime) ────────
2496
2482
  AtomixGlassContainer.displayName = "AtomixGlassContainer";
2497
2483
 
2498
2484
  // Singleton instance
@@ -2693,8 +2679,6 @@ class {
2693
2679
  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})`;
2694
2680
  // Container variables
2695
2681
  const style = containerElement.style;
2696
- style.setProperty("--atomix-glass-container-width", isFixedOrSticky ? `${glassSize.width}` : "100%"),
2697
- style.setProperty("--atomix-glass-container-height", isFixedOrSticky ? `${glassSize.height}` : "100%"),
2698
2682
  style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
2699
2683
  style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
2700
2684
  // Shadows
@@ -3155,47 +3139,55 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
3155
3139
  return "undefined" == typeof process || process.env, finalConfig;
3156
3140
  }
3157
3141
  return "undefined" == typeof process || process.env, baseConfig;
3158
- }), [ overLight, getEffectiveOverLight, isHovered, isActive, validateConfigValue, debugOverLight ]), transformStyle = useMemo((() => effectiveWithoutEffects || isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)"), [ effectiveWithoutEffects, isActive, onClick ]), updateRectRef = useRef(null), handleGlobalMousePosition = useCallback((globalPos => {
3159
- if (externalGlobalMousePosition && externalMouseOffset) return;
3160
- if (effectiveWithoutEffects) return;
3161
- const container = mouseContainer?.current || glassRef.current;
3162
- if (!container) return;
3163
- // Use cached rect if available, otherwise get new one
3164
- let rect = cachedRectRef.current;
3165
- if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
3166
- cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
3167
- const center = calculateElementCenter(rect);
3168
- // Write raw target — the lerp loop will smoothly pursue it
3169
- targetMouseOffsetRef.current = {
3170
- x: (globalPos.x - center.x) / rect.width * 100,
3171
- y: (globalPos.y - center.y) / rect.height * 100
3172
- }, targetGlobalMousePositionRef.current = globalPos;
3173
- }), [ mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]), startLerpLoop = useCallback((() => {
3142
+ }), [ overLight, getEffectiveOverLight, isHovered, isActive, validateConfigValue, debugOverLight ]), transformStyle = useMemo((() => effectiveWithoutEffects || isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)"), [ effectiveWithoutEffects, isActive, onClick ]), updateRectRef = useRef(null), stopLerpLoop = useCallback((() => {
3143
+ lerpActiveRef.current = !1, null !== lerpRafRef.current && (cancelAnimationFrame(lerpRafRef.current),
3144
+ lerpRafRef.current = null);
3145
+ }), []), startLerpLoop = useCallback((() => {
3174
3146
  if (lerpActiveRef.current) return;
3175
3147
  lerpActiveRef.current = !0;
3176
3148
  const LERP_T = CONSTANTS.LERP_FACTOR, tick = () => {
3177
3149
  if (!lerpActiveRef.current) return;
3178
- // Add ref validity check to prevent memory leaks
3179
- if (!glassRef.current || !wrapperRef?.current) return void (lerpActiveRef.current = !1);
3150
+ if (!glassRef.current) return void (lerpActiveRef.current = !1);
3180
3151
  const cur = internalMouseOffsetRef.current, tgt = targetMouseOffsetRef.current, dx = tgt.x - cur.x, dy = tgt.y - cur.y;
3181
3152
  // If we're close enough, snap and park
3182
- if (Math.abs(dx) < .05 && Math.abs(dy) < .05) internalMouseOffsetRef.current = {
3153
+ if (Math.abs(dx) < .01 && Math.abs(dy) < .01) return internalMouseOffsetRef.current = {
3183
3154
  ...tgt
3184
3155
  }, internalGlobalMousePositionRef.current = {
3185
3156
  ...targetGlobalMousePositionRef.current
3186
- }; else {
3187
- internalMouseOffsetRef.current = {
3188
- x: lerp$1(cur.x, tgt.x, LERP_T),
3189
- y: lerp$1(cur.y, tgt.y, LERP_T)
3190
- };
3191
- const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
3192
- internalGlobalMousePositionRef.current = {
3193
- x: lerp$1(curG.x, tgtG.x, LERP_T),
3194
- y: lerp$1(curG.y, tgtG.y, LERP_T)
3195
- };
3196
- }
3197
- // Imperative style update with the smoothed values
3198
- updateAtomixGlassStyles(wrapperRef.current, glassRef.current, {
3157
+ },
3158
+ // Final update and stop
3159
+ updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
3160
+ mouseOffset: internalMouseOffsetRef.current,
3161
+ globalMousePosition: internalGlobalMousePositionRef.current,
3162
+ glassSize: glassSize,
3163
+ isHovered: isHovered,
3164
+ isActive: isActive,
3165
+ isOverLight: overLightConfig.isOverLight,
3166
+ baseOverLightConfig: overLightConfig,
3167
+ effectiveBorderRadius: effectiveBorderRadius,
3168
+ effectiveWithoutEffects: effectiveWithoutEffects,
3169
+ effectiveReducedMotion: effectiveReducedMotion,
3170
+ elasticity: elasticity,
3171
+ directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
3172
+ onClick: onClick,
3173
+ withLiquidBlur: withLiquidBlur,
3174
+ blurAmount: blurAmount,
3175
+ saturation: saturation,
3176
+ padding: padding,
3177
+ isFixedOrSticky: isFixedOrSticky
3178
+ }), void stopLerpLoop();
3179
+ // Smooth step
3180
+ internalMouseOffsetRef.current = {
3181
+ x: lerp$1(cur.x, tgt.x, LERP_T),
3182
+ y: lerp$1(cur.y, tgt.y, LERP_T)
3183
+ };
3184
+ const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
3185
+ internalGlobalMousePositionRef.current = {
3186
+ x: lerp$1(curG.x, tgtG.x, LERP_T),
3187
+ y: lerp$1(curG.y, tgtG.y, LERP_T)
3188
+ },
3189
+ // Imperative style update
3190
+ updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
3199
3191
  mouseOffset: internalMouseOffsetRef.current,
3200
3192
  globalMousePosition: internalGlobalMousePositionRef.current,
3201
3193
  glassSize: glassSize,
@@ -3218,10 +3210,24 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
3218
3210
  };
3219
3211
  // 0.08 – lower = more viscous
3220
3212
  lerpRafRef.current = requestAnimationFrame(tick);
3221
- }), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding, isFixedOrSticky ]), stopLerpLoop = useCallback((() => {
3222
- lerpActiveRef.current = !1, null !== lerpRafRef.current && (cancelAnimationFrame(lerpRafRef.current),
3223
- lerpRafRef.current = null);
3224
- }), []);
3213
+ }), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding, isFixedOrSticky, stopLerpLoop ]), handleGlobalMousePosition = useCallback((globalPos => {
3214
+ if (externalGlobalMousePosition && externalMouseOffset) return;
3215
+ if (effectiveWithoutEffects) return;
3216
+ const container = mouseContainer?.current || glassRef.current;
3217
+ if (!container) return;
3218
+ // Use cached rect if available, otherwise get new one
3219
+ let rect = cachedRectRef.current;
3220
+ if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
3221
+ cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
3222
+ const center = calculateElementCenter(rect);
3223
+ // Write raw target — the lerp loop will smoothly pursue it
3224
+ targetMouseOffsetRef.current = {
3225
+ x: (globalPos.x - center.x) / rect.width * 100,
3226
+ y: (globalPos.y - center.y) / rect.height * 100
3227
+ }, targetGlobalMousePositionRef.current = globalPos,
3228
+ // Ensure the lerp loop is running to smoothly chase the new target
3229
+ lerpActiveRef.current || startLerpLoop();
3230
+ }), [ mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects, startLerpLoop ]);
3225
3231
  /**
3226
3232
  * Validate and clamp a numeric config value
3227
3233
  */
@@ -3230,7 +3236,7 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
3230
3236
  if (externalGlobalMousePosition && externalMouseOffset) return;
3231
3237
  if (effectiveWithoutEffects) return;
3232
3238
  const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition);
3233
- // Start the lerp loop — it will smoothly chase the target
3239
+ // Initial start
3234
3240
  startLerpLoop();
3235
3241
  const container = mouseContainer?.current || glassRef.current;
3236
3242
  let resizeObserver = null;
@@ -3243,7 +3249,7 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
3243
3249
  unsubscribe(), stopLerpLoop(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
3244
3250
  updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
3245
3251
  };
3246
- }), [ handleGlobalMousePosition, startLerpLoop, stopLerpLoop, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects ]),
3252
+ }), [ externalGlobalMousePosition, externalMouseOffset, effectiveWithoutEffects, handleGlobalMousePosition, startLerpLoop, stopLerpLoop, mouseContainer, glassRef ]),
3247
3253
  // Also call updateStyles on other state changes (hover, active, etc)
3248
3254
  useEffect((() => {
3249
3255
  updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
@@ -3738,183 +3744,146 @@ function usePerformanceMonitor(config = {}) {
3738
3744
  }
3739
3745
  }
3740
3746
 
3747
+ /** Map an FPS value to a semantic color token string. */ const getQualityColor = quality => {
3748
+ switch (quality) {
3749
+ case "high":
3750
+ return "var(--atomix-color-success, #4ade80)";
3751
+
3752
+ case "medium":
3753
+ return "var(--atomix-color-warning, #fbbf24)";
3754
+
3755
+ case "low":
3756
+ return "var(--atomix-color-danger, #ef4444)";
3757
+
3758
+ default:
3759
+ return "#9ca3af";
3760
+ }
3761
+ }, getFpsLabel = fps => fps >= 58 ? "Optimal" : fps >= 45 ? "Warning" : "Critical";
3762
+
3763
+ /** Map a quality level string to a semantic color token string. */
3764
+ // Inject keyframes once
3765
+ if ("undefined" != typeof document) {
3766
+ const styleId = "perf-dashboard-keyframes";
3767
+ if (!document.getElementById(styleId)) {
3768
+ const styleEl = document.createElement("style");
3769
+ styleEl.id = styleId, styleEl.textContent = "\n@keyframes perf-dashboard-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n}\n",
3770
+ document.head.appendChild(styleEl);
3771
+ }
3772
+ }
3773
+
3741
3774
  /**
3742
- * PerformanceDashboard - Real-time performance monitoring overlay
3775
+ * PerformanceDashboard - Real-time performance monitoring overlay.
3743
3776
  *
3744
- * Displays:
3745
- * - Current FPS with color coding
3746
- * - Frame time statistics
3747
- * - Quality level indicator
3748
- * - GPU memory usage (if available)
3749
- * - Auto-scaling status
3750
- */ const PerformanceDashboard = ({metrics: metrics, isVisible: isVisible = !0, onClose: onClose}) => {
3751
- // Get color for FPS display
3752
- const getFpsColor = fps => fps >= 58 ? "#4ade80" : // Green - good
3753
- fps >= 45 ? "#fbbf24" : "#ef4444" // Red - critical
3754
- , dashboardStyle = useMemo((() => ({
3755
- position: "fixed",
3756
- top: "16px",
3757
- right: "16px",
3758
- padding: "12px 16px",
3759
- backgroundColor: "rgba(17, 24, 39, 0.95)",
3760
- borderRadius: "8px",
3761
- boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
3762
- fontFamily: "monospace",
3763
- fontSize: "12px",
3764
- color: "#fff",
3765
- zIndex: 9999,
3766
- minWidth: "200px",
3767
- backdropFilter: "blur(8px)",
3768
- border: "1px solid rgba(255, 255, 255, 0.1)",
3769
- transition: "opacity 0.3s ease",
3770
- opacity: isVisible ? 1 : 0,
3771
- pointerEvents: isVisible ? "auto" : "none"
3772
- })), [ isVisible ]), headerStyle = useMemo((() => ({
3773
- display: "flex",
3774
- justifyContent: "space-between",
3775
- alignItems: "center",
3776
- marginBottom: "8px",
3777
- paddingBottom: "8px",
3778
- borderBottom: "1px solid rgba(255, 255, 255, 0.1)"
3779
- })), []), titleStyle = useMemo((() => ({
3780
- fontWeight: "bold",
3781
- fontSize: "13px",
3782
- color: "#fff"
3783
- })), []), closeButtonStyle = useMemo((() => ({
3784
- background: "transparent",
3785
- border: "none",
3786
- color: "#9ca3af",
3787
- cursor: "pointer",
3788
- fontSize: "16px",
3789
- padding: "0",
3790
- lineHeight: "1"
3791
- })), []), metricRowStyle = useMemo((() => ({
3792
- display: "flex",
3793
- justifyContent: "space-between",
3794
- alignItems: "center",
3795
- marginBottom: "6px"
3796
- })), []), labelStyle = useMemo((() => ({
3797
- color: "#9ca3af",
3798
- marginRight: "12px"
3799
- })), []), valueStyle = useMemo((() => ({
3800
- fontWeight: "bold"
3801
- })), []);
3802
- // Get quality level badge color
3803
- return isVisible ? jsxs("div", {
3804
- style: dashboardStyle,
3777
+ * Displays FPS, frame time, quality level, GPU memory, and auto-scaling status.
3778
+ * Rendered only when `debugPerformance={true}` on the parent `AtomixGlass`.
3779
+ */ const PerformanceDashboard = memo((({metrics: metrics, isVisible: isVisible = !0, onClose: onClose}) => {
3780
+ if (!isVisible) return null;
3781
+ const fpsColor = (fps = metrics.fps) >= 58 ? "var(--atomix-color-success, #4ade80)" : fps >= 45 ? "var(--atomix-color-warning, #fbbf24)" : "var(--atomix-color-danger, #ef4444)";
3782
+ var fps;
3783
+ const isCritical = metrics.fps < 45;
3784
+ return jsxs("div", {
3785
+ className: "c-perf-dashboard u-position-fixed u-top-4 u-end-4 u-p-3 u-px-4 u-text-xs u-font-mono u-text-white u-rounded-md u-border u-border-white-alpha-10 u-shadow-lg",
3786
+ style: {
3787
+ zIndex: 9999,
3788
+ minWidth: "12.5rem",
3789
+ // 200px
3790
+ backgroundColor: "rgba(17, 24, 39, 0.95)",
3791
+ backdropFilter: "blur(8px)",
3792
+ transition: "opacity 0.3s ease"
3793
+ },
3805
3794
  children: [ jsxs("div", {
3806
- style: headerStyle,
3795
+ className: "u-flex u-items-center u-justify-between u-mb-2 u-pb-2 u-border-b u-border-white-alpha-10",
3807
3796
  children: [ jsx("span", {
3808
- style: titleStyle,
3797
+ className: "u-text-sm u-font-bold u-text-white",
3809
3798
  children: "Performance Monitor"
3810
3799
  }), onClose && jsx("button", {
3811
- style: closeButtonStyle,
3800
+ className: "u-bg-transparent u-border-none u-p-0 u-line-height-1 u-text-base u-text-gray-400 u-cursor-pointer hover:u-text-white",
3812
3801
  onClick: onClose,
3813
3802
  "aria-label": "Close performance dashboard",
3803
+ style: {
3804
+ transition: "color 0.2s ease"
3805
+ },
3814
3806
  children: "×"
3815
3807
  }) ]
3816
3808
  }), jsxs("div", {
3817
- style: metricRowStyle,
3809
+ className: "u-flex u-items-center u-justify-between u-mb-1-5",
3818
3810
  children: [ jsx("span", {
3819
- style: labelStyle,
3811
+ className: "u-text-gray-400 u-me-3",
3820
3812
  children: "FPS"
3821
3813
  }), jsx("span", {
3814
+ className: "u-font-bold",
3822
3815
  style: {
3823
- ...valueStyle,
3824
- color: getFpsColor(metrics.fps)
3816
+ color: fpsColor
3825
3817
  },
3826
3818
  children: Math.round(metrics.fps)
3827
3819
  }) ]
3828
3820
  }), jsxs("div", {
3829
- style: metricRowStyle,
3821
+ className: "u-flex u-items-center u-justify-between u-mb-1-5",
3830
3822
  children: [ jsx("span", {
3831
- style: labelStyle,
3823
+ className: "u-text-gray-400 u-me-3",
3832
3824
  children: "Frame Time"
3833
3825
  }), jsxs("span", {
3834
- style: valueStyle,
3826
+ className: "u-font-bold",
3835
3827
  children: [ metrics.frameTime.toFixed(2), "ms" ]
3836
3828
  }) ]
3837
3829
  }), jsxs("div", {
3838
- style: metricRowStyle,
3830
+ className: "u-flex u-items-center u-justify-between u-mb-1-5",
3839
3831
  children: [ jsx("span", {
3840
- style: labelStyle,
3832
+ className: "u-text-gray-400 u-me-3",
3841
3833
  children: "Quality"
3842
3834
  }), jsx("span", {
3835
+ className: "u-font-bold u-text-uppercase",
3843
3836
  style: {
3844
- ...valueStyle,
3845
- color: (quality => {
3846
- switch (quality) {
3847
- case "high":
3848
- return "#4ade80";
3849
-
3850
- case "medium":
3851
- return "#fbbf24";
3852
-
3853
- case "low":
3854
- return "#ef4444";
3855
-
3856
- default:
3857
- return "#9ca3af";
3858
- }
3859
- })(metrics.qualityLevel),
3860
- textTransform: "uppercase",
3861
- fontSize: "11px"
3837
+ fontSize: "0.6875rem",
3838
+ // 11px
3839
+ color: getQualityColor(metrics.qualityLevel)
3862
3840
  },
3863
3841
  children: metrics.qualityLevel
3864
3842
  }) ]
3865
3843
  }), metrics.gpuMemory && jsxs("div", {
3866
- style: metricRowStyle,
3844
+ className: "u-flex u-items-center u-justify-between u-mb-1-5",
3867
3845
  children: [ jsx("span", {
3868
- style: labelStyle,
3846
+ className: "u-text-gray-400 u-me-3",
3869
3847
  children: "GPU Memory"
3870
3848
  }), jsxs("span", {
3871
- style: valueStyle,
3849
+ className: "u-font-bold",
3872
3850
  children: [ "~", Math.round(metrics.gpuMemory / 1024), "MB" ]
3873
3851
  }) ]
3874
3852
  }), metrics.isAutoScaling && jsx("div", {
3853
+ className: "u-mt-2 u-pt-2 u-border-t u-border-white-alpha-10 u-text-center",
3875
3854
  style: {
3876
- marginTop: "8px",
3877
- paddingTop: "8px",
3878
- borderTop: "1px solid rgba(255, 255, 255, 0.1)",
3879
- fontSize: "10px",
3880
- color: "#6b7280",
3881
- textAlign: "center"
3855
+ fontSize: "0.625rem",
3856
+ // 10px
3857
+ color: "#6b7280"
3882
3858
  },
3883
3859
  children: "Auto-scaling active"
3884
3860
  }), jsxs("div", {
3885
- style: {
3886
- marginTop: "8px",
3887
- paddingTop: "8px",
3888
- borderTop: "1px solid rgba(255, 255, 255, 0.1)",
3889
- display: "flex",
3890
- alignItems: "center",
3891
- gap: "6px"
3892
- },
3861
+ className: "u-flex u-items-center u-gap-2 u-mt-2 u-pt-2 u-border-t u-border-white-alpha-10",
3893
3862
  children: [ jsx("div", {
3863
+ className: "u-rounded-full",
3894
3864
  style: {
3895
- width: "8px",
3896
- height: "8px",
3897
- borderRadius: "50%",
3898
- backgroundColor: getFpsColor(metrics.fps),
3899
- animation: metrics.fps < 45 ? "pulse 1s infinite" : "none"
3865
+ width: "0.5rem",
3866
+ height: "0.5rem",
3867
+ flexShrink: 0,
3868
+ backgroundColor: fpsColor,
3869
+ ...isCritical && {
3870
+ animation: "perf-dashboard-pulse 1s infinite"
3871
+ }
3900
3872
  }
3901
3873
  }), jsx("span", {
3874
+ className: "u-text-xs",
3902
3875
  style: {
3903
- fontSize: "10px",
3904
- color: metrics.fps >= 58 ? "#4ade80" : metrics.fps >= 45 ? "#fbbf24" : "#ef4444"
3876
+ fontSize: "0.625rem",
3877
+ // 10px
3878
+ color: fpsColor
3905
3879
  },
3906
- children: metrics.fps >= 58 ? "Optimal" : metrics.fps >= 45 ? "Warning" : "Critical"
3880
+ children: getFpsLabel(metrics.fps)
3907
3881
  }) ]
3908
3882
  }) ]
3909
- }) : null;
3910
- };
3883
+ });
3884
+ }));
3911
3885
 
3912
- // Add pulse animation for critical FPS
3913
- if ("undefined" != typeof document) {
3914
- const styleSheet = document.createElement("style");
3915
- styleSheet.textContent = "\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n ",
3916
- document.head.appendChild(styleSheet);
3917
- }
3886
+ PerformanceDashboard.displayName = "PerformanceDashboard";
3918
3887
 
3919
3888
  /**
3920
3889
  * Mobile optimization presets
@@ -3925,7 +3894,8 @@ if ("undefined" != typeof document) {
3925
3894
  /**
3926
3895
  * Performance preset - Maximum FPS, reduced quality
3927
3896
  * Best for low-end devices or when battery saving is priority
3928
- */ const PERFORMANCE_PRESET = {
3897
+ */
3898
+ const PERFORMANCE_PRESET = {
3929
3899
  distortionOctaves: 2,
3930
3900
  // Minimal FBM layers
3931
3901
  displacementScale: 50,
@@ -4088,90 +4058,21 @@ function getDevicePreset(presetName) {
4088
4058
  getPixelRatio: () => "undefined" == typeof window ? 1 : window.devicePixelRatio || 1,
4089
4059
  /** Check if device has touch support */
4090
4060
  hasTouchSupport: () => "undefined" != typeof window && ("ontouchstart" in window || navigator.maxTouchPoints > 0)
4091
- };
4092
-
4093
- /**
4094
- * AtomixGlass - A high-performance glass morphism component with liquid distortion effects
4095
- *
4096
- * Features:
4097
- * - Hardware-accelerated glass effects with SVG filters
4098
- * - Mouse-responsive liquid distortion
4099
- * - Dynamic border-radius extraction from children CSS properties
4100
- * - Automatic light/dark theme detection via overLight prop
4101
- * - Accessibility and performance optimizations
4102
- * - Multiple displacement modes (standard, polar, prominent, shader)
4103
- * - Design token integration for consistent theming
4104
- * - Focus ring support for keyboard navigation
4105
- * - Responsive breakpoints for mobile optimization
4106
- * - Enhanced ARIA attributes for screen readers
4107
- * - Time-based animation system with FBM distortion
4108
- * - Device preset optimization for performance/quality balance
4109
- *
4110
- * Design System Compliance:
4111
- * - Uses design tokens for opacity, spacing, and colors
4112
- * - Follows BEM methodology for class naming
4113
- * - Implements focus-ring mixin for accessibility
4114
- * - Supports reduced motion and high contrast preferences
4115
- *
4116
- * @example
4117
- * // Basic usage with dynamic border-radius extraction
4118
- * <AtomixGlass>
4119
- * <div style={{ borderRadius: '12px' }}>Content with 12px radius</div>
4120
- * </AtomixGlass>
4121
- *
4122
- * @example
4123
- * // Manual border-radius override
4124
- * <AtomixGlass borderRadius={20}>
4125
- * <div>Content with 20px glass radius</div>
4126
- * </AtomixGlass>
4127
- *
4128
- * @example
4129
- * // Interactive glass with click handler
4130
- * <AtomixGlass onClick={() => console.log('Clicked')} aria-label="Glass card">
4131
- * <div>Clickable content</div>
4132
- * </AtomixGlass>
4133
- *
4134
- * @example
4135
- * // OverLight - Boolean mode (explicit control)
4136
- * <AtomixGlass overLight={true}>
4137
- * <div>Content on light background</div>
4138
- * </AtomixGlass>
4139
- *
4140
- * @example
4141
- * // OverLight - Auto-detection mode
4142
- * <AtomixGlass overLight="auto">
4143
- * <div>Content with auto-detected background</div>
4144
- * </AtomixGlass>
4145
- *
4146
- * @example
4147
- * // OverLight - Object config with custom settings
4148
- * <AtomixGlass
4149
- * overLight={{
4150
- * threshold: 0.8,
4151
- * opacity: 0.6,
4152
- * contrast: 1.8,
4153
- * brightness: 1.0,
4154
- * saturationBoost: 1.5
4155
- * }}
4156
- * >
4157
- * <div>Content with custom overLight config</div>
4158
- * </AtomixGlass>
4159
- *
4160
- * @example
4161
- * // Debug mode for overLight detection
4162
- * <AtomixGlass overLight="auto" debugOverLight={true}>
4163
- * <div>Content with debug logging enabled</div>
4164
- * </AtomixGlass>
4165
- *
4166
- * @example
4167
- * // Performance-optimized for mobile devices
4168
- * <AtomixGlass devicePreset="performance" disableResponsiveBreakpoints={false}>
4169
- * <div>Mobile-optimized glass effect</div>
4170
- * </AtomixGlass>
4171
- */ function AtomixGlass({children: children, displacementScale: displacementScale = ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, aberrationIntensity: aberrationIntensity = ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer = null, className: className = "", padding: padding = ATOMIX_GLASS.DEFAULTS.PADDING, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, style: style = {}, mode: mode = ATOMIX_GLASS.DEFAULTS.MODE, onClick: onClick, shaderVariant: shaderVariant = "liquidGlass", "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, role: role, tabIndex: tabIndex, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, withLiquidBlur: withLiquidBlur = !1, withBorder: withBorder = !0, withOverLightLayers: withOverLightLayers = ATOMIX_GLASS.DEFAULTS.ENABLE_OVER_LIGHT_LAYERS, debugPerformance: debugPerformance = !1, debugOverLight: debugOverLight = !1, height: height, width: width, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", devicePreset: devicePreset = "balanced", disableResponsiveBreakpoints: disableResponsiveBreakpoints = !1, ...rest}) {
4172
- const glassRef = useRef(null), contentRef = useRef(null), {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = "fixed" === restStyle.position || "sticky" === restStyle.position, {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, getShaderTime: getShaderTime, applyTimeBasedDistortion: applyTimeBasedDistortion, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
4061
+ }, AtomixGlassInner = forwardRef((function({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, isFixedOrSticky: propsIsFixedOrSticky, ...rest}, ref) {
4062
+ const glassRef = useRef(null), contentRef = useRef(null), internalWrapperRef = useRef(null), mergedRef = useMemo((() =>
4063
+ // Helper to merge refs
4064
+ function(...refs) {
4065
+ return node => {
4066
+ refs.forEach((ref => {
4067
+ "function" == typeof ref ? ref(node) : null != ref && (ref.current = node);
4068
+ }));
4069
+ };
4070
+ }
4071
+ // Internal implementation with forwardRef
4072
+ (ref, internalWrapperRef)), [ ref ]), {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = propsIsFixedOrSticky || "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, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
4173
4073
  glassRef: glassRef,
4174
4074
  contentRef: contentRef,
4075
+ wrapperRef: internalWrapperRef,
4175
4076
  borderRadius: borderRadius,
4176
4077
  globalMousePosition: externalGlobalMousePosition,
4177
4078
  mouseOffset: externalMouseOffset,
@@ -4200,7 +4101,6 @@ function getDevicePreset(presetName) {
4200
4101
  distortionGain: distortionGain,
4201
4102
  distortionQuality: distortionQuality
4202
4103
  });
4203
- // Re-calculate only when devicePreset changes
4204
4104
  // Responsive breakpoint system - automatically adjusts parameters based on viewport
4205
4105
  useResponsiveGlass({
4206
4106
  baseParams: {
@@ -4215,22 +4115,21 @@ function getDevicePreset(presetName) {
4215
4115
  },
4216
4116
  breakpoints: MOBILE_OPTIMIZED_BREAKPOINTS,
4217
4117
  enabled: !disableResponsiveBreakpoints && "undefined" != typeof window,
4218
- // Enable unless disabled
4219
4118
  debug: !1
4220
4119
  });
4221
4120
  // Performance monitoring - tracks FPS, frame time, memory usage
4222
- const {metrics: performanceMetrics, recommendedQuality: recommendedQuality, isUnderperforming: isUnderperforming, setQualityLevel: setQualityLevel, toggleMonitoring: toggleMonitoring} = usePerformanceMonitor({
4223
- enabled: !1,
4224
- // We'll toggle manually based on prop
4121
+ const {metrics: performanceMetrics, toggleMonitoring: toggleMonitoring} = usePerformanceMonitor({
4122
+ enabled: debugPerformance,
4123
+ // Enable when debugPerformance is true
4225
4124
  debug: !1,
4226
4125
  showOverlay: !1
4227
4126
  });
4228
- // Auto-start performance monitoring if enabled (only in development)
4127
+ // Auto-start performance monitoring when debugPerformance is enabled
4229
4128
  React.useEffect((() => {
4230
- "development" === process.env.NODE_ENV && window?.enablePerformanceMonitoring && toggleMonitoring();
4129
+ debugPerformance && toggleMonitoring();
4231
4130
  // eslint-disable-next-line react-hooks/exhaustive-deps
4232
- }), []);
4233
- // Only run once on mount
4131
+ }), [ debugPerformance ]);
4132
+ // Re-run when debugPerformance changes
4234
4133
  const isOverLight = useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, rootLayoutStyle = useMemo((() => {
4235
4134
  if (!isFixedOrSticky) return {};
4236
4135
  const {position: p, top: t, left: l, right: r, bottom: b} = restStyle;
@@ -4258,34 +4157,30 @@ function getDevicePreset(presetName) {
4258
4157
  if (isFixedOrSticky) {
4259
4158
  const {position: _p, top: _t, left: _l, right: _r, bottom: _b, ...visualStyle} = restStyle;
4260
4159
  return {
4261
- ...visualStyle,
4262
- ...!effectiveWithoutEffects && {
4263
- transform: transformStyle
4264
- }
4160
+ ...visualStyle
4265
4161
  };
4266
4162
  }
4267
4163
  return {
4268
- ...restStyle,
4269
- ...!effectiveWithoutEffects && {
4270
- transform: transformStyle
4271
- }
4164
+ ...restStyle
4272
4165
  };
4273
- }), [ isFixedOrSticky, restStyle, effectiveWithoutEffects, transformStyle ]);
4166
+ }), [ isFixedOrSticky, restStyle ]);
4274
4167
  // Build className with state modifiers
4275
4168
  const componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveWithoutEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className ].filter(Boolean).join(" "), positionStyles = useMemo((() => ({
4276
4169
  position: isFixedOrSticky ? "absolute" : restStyle.position || "absolute",
4277
- top: isFixedOrSticky ? 0 : restStyle.top || 0,
4278
- left: isFixedOrSticky ? 0 : restStyle.left || 0
4279
- })), [ isFixedOrSticky, restStyle.position, restStyle.top, restStyle.left ]), adjustedSize = useMemo((() => {
4170
+ top: isFixedOrSticky ? restStyle.top ?? 0 : 0,
4171
+ left: isFixedOrSticky ? restStyle.left ?? 0 : 0,
4172
+ right: isFixedOrSticky ? restStyle.right ?? "auto" : "auto",
4173
+ bottom: isFixedOrSticky ? restStyle.bottom ?? "auto" : "auto"
4174
+ })), [ isFixedOrSticky, restStyle.position, restStyle.top, restStyle.left, restStyle.right, restStyle.bottom ]), adjustedSize = useMemo((() => {
4280
4175
  // Keep a reference to positionStyles to avoid unused-variable lint,
4281
4176
  // but sizing is driven by explicit width/height or measured size.
4282
4177
  positionStyles.position;
4283
- const resolveLength = (value, measured) => void 0 !== value ? "number" == typeof value ? `${value}px` : value : measured > 0 ? `${measured}px` : "100%", effectiveWidth = width ?? restStyle.width, effectiveHeight = height ?? restStyle.height;
4178
+ const resolveLength = (value, measured) => void 0 !== value && isFixedOrSticky ? "number" == typeof value ? `${value}px` : value : measured > 0 && isFixedOrSticky ? `${measured}px` : "100%", effectiveWidth = width ?? restStyle.width, effectiveHeight = height ?? restStyle.height;
4284
4179
  return {
4285
4180
  width: resolveLength(effectiveWidth, glassSize.width),
4286
4181
  height: resolveLength(effectiveHeight, glassSize.height)
4287
4182
  };
4288
- }), [ width, height, restStyle.width, restStyle.height, positionStyles.position, glassSize.width, glassSize.height ]), gradientValues = useMemo((() => {
4183
+ }), [ width, height, restStyle.width, restStyle.height, positionStyles.position, glassSize.width, glassSize.height, isFixedOrSticky ]), gradientValues = useMemo((() => {
4289
4184
  const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
4290
4185
  return {
4291
4186
  borderGradientAngle: GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER,
@@ -4315,33 +4210,32 @@ function getDevicePreset(presetName) {
4315
4210
  absMx: absMx,
4316
4211
  absMy: absMy
4317
4212
  };
4318
- }), [ mouseOffset.x, mouseOffset.y ]), opacityValues = useMemo((() => {
4319
- const overLightOpacity = overLightConfig.opacity;
4320
- return {
4321
- hover1: isHovered || isActive ? .5 : 0,
4322
- hover2: isActive ? .5 : 0,
4323
- hover3: isHovered ? .4 : isActive ? .8 : 0,
4324
- base: isOverLight ? overLightOpacity || .4 : 0,
4325
- over: isOverLight ? 1.1 * (overLightOpacity || .4) : 0
4326
- };
4327
- }), [ isHovered, isActive, isOverLight, overLightConfig.opacity ]), glassVars = useMemo((() => {
4328
- const whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, {borderGradientAngle: borderGradientAngle, borderStop1: borderStop1, borderStop2: borderStop2, borderOpacities: borderOpacities, hoverPositions: hoverPositions, basePosition: basePosition, mx: mx, my: my, absMx: absMx, absMy: absMy} = gradientValues, configBorderOpacity = overLightConfig?.borderOpacity ?? 1;
4213
+ }), [ mouseOffset.x, mouseOffset.y ]), clampedOverLightOpacity = Math.max(0, Math.min(1, overLightConfig?.opacity ?? .4)), clampedBorderOpacity = Math.max(0, Math.min(1, overLightConfig?.borderOpacity ?? 1)), opacityValues = useMemo((() => ({
4214
+ hover1: isHovered || isActive ? .5 : 0,
4215
+ hover2: isActive ? .5 : 0,
4216
+ hover3: isHovered ? .4 : isActive ? .8 : 0,
4217
+ base: isOverLight ? clampedOverLightOpacity || .4 : 0,
4218
+ over: isOverLight ? 1.1 * (clampedOverLightOpacity || .4) : 0
4219
+ })), [ isHovered, isActive, isOverLight, clampedOverLightOpacity ]), glassVars = useMemo((() => {
4220
+ const whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, {borderGradientAngle: borderGradientAngle, borderStop1: borderStop1, borderStop2: borderStop2, borderOpacities: borderOpacities, hoverPositions: hoverPositions, basePosition: basePosition, mx: mx, my: my, absMx: absMx, absMy: absMy} = gradientValues;
4329
4221
  return {
4330
4222
  ...void 0 !== customZIndex && {
4331
4223
  "--atomix-glass-base-z-index": customZIndex
4332
4224
  },
4333
4225
  "--atomix-glass-radius": `${effectiveBorderRadius}px`,
4334
4226
  "--atomix-glass-transform": transformStyle || "none",
4335
- // Internal decorative layers are positioned relative to the root;
4336
- "--atomix-glass-position": rootLayoutStyle.position,
4337
- "--atomix-glass-top": `${isFixedOrSticky ? rootLayoutStyle.top : 0}px`,
4338
- "--atomix-glass-left": `${isFixedOrSticky ? rootLayoutStyle.left : 0}px`,
4227
+ "--atomix-glass-container-position": `${isFixedOrSticky ? rootLayoutStyle.position : positionStyles.position}`,
4228
+ "--atomix-glass-position": `${isFixedOrSticky ? rootLayoutStyle.position : positionStyles.position}`,
4229
+ "--atomix-glass-top": `${isFixedOrSticky ? restStyle.top ?? 0 : 0}px`,
4230
+ "--atomix-glass-left": `${isFixedOrSticky ? restStyle.left ?? 0 : 0}px`,
4231
+ "--atomix-glass-right": isFixedOrSticky ? restStyle.right ?? "auto" : "auto",
4232
+ "--atomix-glass-bottom": isFixedOrSticky ? restStyle.bottom ?? "auto" : "auto",
4339
4233
  "--atomix-glass-width": adjustedSize.width,
4340
4234
  "--atomix-glass-height": adjustedSize.height,
4341
- "--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.09375rem)",
4235
+ "--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.125rem)",
4342
4236
  "--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay",
4343
- "--atomix-glass-border-gradient-1": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
4344
- "--atomix-glass-border-gradient-2": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[2] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[3] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
4237
+ "--atomix-glass-border-gradient-1": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * clampedBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * clampedBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
4238
+ "--atomix-glass-border-gradient-2": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[2] ?? 1) * clampedBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[3] ?? 1) * clampedBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
4345
4239
  "--atomix-glass-hover-1-opacity": opacityValues.hover1,
4346
4240
  "--atomix-glass-hover-1-gradient": isOverLight ? `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_END}%)` : `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_STOP}%)`,
4347
4241
  "--atomix-glass-hover-2-opacity": opacityValues.hover2,
@@ -4355,13 +4249,14 @@ function getDevicePreset(presetName) {
4355
4249
  "--atomix-glass-overlay-highlight-opacity": opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
4356
4250
  "--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}%)`
4357
4251
  };
4358
- }), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, adjustedSize, isOverLight, overLightConfig.borderOpacity, customZIndex, rootLayoutStyle, isFixedOrSticky ]), renderBackgroundLayer = layerType => jsx("div", {
4252
+ }), [ gradientValues, opacityValues, effectiveBorderRadius, transformStyle, adjustedSize, isOverLight, clampedBorderOpacity, customZIndex, isFixedOrSticky, positionStyles.position, rootLayoutStyle.position, restStyle.top, restStyle.left, restStyle.right, restStyle.bottom ]), renderBackgroundLayer = layerType => jsx("div", {
4359
4253
  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(" ")
4360
4254
  });
4361
4255
  // Calculate position and size styles for internal layers
4362
4256
  // When root is fixed/sticky, internal layers use absolute (relative to root)
4363
4257
  return jsxs("div", {
4364
4258
  ...rest,
4259
+ ref: mergedRef,
4365
4260
  className: componentClassName,
4366
4261
  style: {
4367
4262
  ...glassVars
@@ -4371,17 +4266,14 @@ function getDevicePreset(presetName) {
4371
4266
  "aria-label": ariaLabel,
4372
4267
  "aria-describedby": ariaDescribedBy,
4373
4268
  "aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
4374
- "aria-pressed": !(!onClick || !isActive) || !onClick && void 0,
4269
+ "aria-pressed": void 0,
4375
4270
  onKeyDown: onClick ? handleKeyDown : void 0,
4376
4271
  children: [ jsx(AtomixGlassContainer, {
4377
4272
  ref: glassRef,
4378
4273
  contentRef: contentRef,
4379
4274
  className: className,
4380
4275
  style: {
4381
- ...restStyle,
4382
- ...!isFixedOrSticky && {
4383
- position: "relative"
4384
- }
4276
+ ...restStyle
4385
4277
  },
4386
4278
  borderRadius: effectiveBorderRadius,
4387
4279
  displacementScale: effectiveWithoutEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
@@ -4417,6 +4309,7 @@ function getDevicePreset(presetName) {
4417
4309
  effectiveReducedMotion: effectiveReducedMotion,
4418
4310
  shaderVariant: shaderVariant,
4419
4311
  withLiquidBlur: withLiquidBlur,
4312
+ isFixedOrSticky: isFixedOrSticky,
4420
4313
  // Phase 1: Animation System props
4421
4314
  shaderTime: getShaderTime(),
4422
4315
  withTimeAnimation: withTimeAnimation,
@@ -4445,6 +4338,8 @@ function getDevicePreset(presetName) {
4445
4338
  }) ]
4446
4339
  }), withBorder && jsxs(Fragment, {
4447
4340
  children: [ jsx("span", {
4341
+ className: ATOMIX_GLASS.BORDER_BACKDROP_CLASS
4342
+ }), jsx("span", {
4448
4343
  className: ATOMIX_GLASS.BORDER_1_CLASS
4449
4344
  }), jsx("span", {
4450
4345
  className: ATOMIX_GLASS.BORDER_2_CLASS
@@ -4455,10 +4350,15 @@ function getDevicePreset(presetName) {
4455
4350
  onClose: () => {}
4456
4351
  }) ]
4457
4352
  });
4458
- }
4353
+ }));
4459
4354
 
4460
- // Default icon
4461
- const DefaultIcon = () => jsx("i", {
4355
+ AtomixGlassInner.displayName = "AtomixGlass";
4356
+
4357
+ /**
4358
+ * AtomixGlass - wrapped with React.memo to prevent unnecessary re-renders.
4359
+ * Ref is forwarded to the root `<div>` element.
4360
+ */
4361
+ const AtomixGlass = memo(AtomixGlassInner), DefaultIcon = () => jsx("i", {
4462
4362
  className: "c-accordion__icon",
4463
4363
  "aria-hidden": "true",
4464
4364
  children: jsx("svg", {
@@ -4492,6 +4392,7 @@ const DefaultIcon = () => jsx("i", {
4492
4392
  });
4493
4393
  }));
4494
4394
 
4395
+ // Default icon
4495
4396
  AccordionHeader.displayName = "AccordionHeader";
4496
4397
 
4497
4398
  const AccordionBody = forwardRef((({children: children, className: className = "", panelRef: panelRef, contentRef: contentRef, ...props}, ref) => {
@@ -5410,7 +5311,152 @@ class ThemeNaming {
5410
5311
 
5411
5312
  ThemeNaming.prefix = "atomix";
5412
5313
 
5413
- const Button = React.memo( forwardRef((({label: label, children: children, onClick: onClick, variant: variant = "primary", size: size = "md", disabled: disabled = !1, loading: loading = !1, loadingText: loadingText, icon: icon, iconName: iconName, iconSize: iconSize = "sm", iconPosition: iconPosition = "start", iconOnly: iconOnly = !1, rounded: rounded = !1, fullWidth: fullWidth = !1, block: block = !1, active: active = !1, selected: selected = !1, type: type = "button", className: className = "", as: Component = "button", href: href, target: target, glass: glass, onHover: onHover, onFocus: onFocus, onBlur: onBlur, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, tabIndex: tabIndex, style: style, linkComponent: linkComponent, ...props}, ref) => {
5314
+ var aCallable = aCallable$3, toObject = toObject$2, IndexedObject = indexedObject, lengthOfArrayLike = lengthOfArrayLike$2, $TypeError = TypeError, REDUCE_EMPTY = "Reduce of empty array with no initial value", createMethod = function(IS_RIGHT) {
5315
+ return function(that, callbackfn, argumentsLength, memo) {
5316
+ var O = toObject(that), self = IndexedObject(O), length = lengthOfArrayLike(O);
5317
+ if (aCallable(callbackfn), 0 === length && argumentsLength < 2) throw new $TypeError(REDUCE_EMPTY);
5318
+ var index = IS_RIGHT ? length - 1 : 0, i = IS_RIGHT ? -1 : 1;
5319
+ if (argumentsLength < 2) for (;;) {
5320
+ if (index in self) {
5321
+ memo = self[index], index += i;
5322
+ break;
5323
+ }
5324
+ if (index += i, IS_RIGHT ? index < 0 : length <= index) throw new $TypeError(REDUCE_EMPTY);
5325
+ }
5326
+ for (;IS_RIGHT ? index >= 0 : length > index; index += i) index in self && (memo = callbackfn(memo, self[index], index, O));
5327
+ return memo;
5328
+ };
5329
+ }, arrayReduce = {
5330
+ // `Array.prototype.reduce` method
5331
+ // https://tc39.es/ecma262/#sec-array.prototype.reduce
5332
+ left: createMethod(!1),
5333
+ // `Array.prototype.reduceRight` method
5334
+ // https://tc39.es/ecma262/#sec-array.prototype.reduceright
5335
+ right: createMethod(!0)
5336
+ }, fails = fails$9, globalThis$1 = globalThis_1, userAgent = environmentUserAgent, classof = classofRaw$2, userAgentStartsWith = function(string) {
5337
+ return userAgent.slice(0, string.length) === string;
5338
+ }, environment = userAgentStartsWith("Bun/") ? "BUN" : userAgentStartsWith("Cloudflare-Workers") ? "CLOUDFLARE" : userAgentStartsWith("Deno/") ? "DENO" : userAgentStartsWith("Node.js/") ? "NODE" : globalThis$1.Bun && "string" == typeof Bun.version ? "BUN" : globalThis$1.Deno && "object" == typeof Deno.version ? "DENO" : "process" === classof(globalThis$1.process) ? "NODE" : globalThis$1.window && globalThis$1.document ? "BROWSER" : "REST", $reduce = arrayReduce.left;
5339
+
5340
+ // `Array.prototype.reduce` method
5341
+ // https://tc39.es/ecma262/#sec-array.prototype.reduce
5342
+ _export({
5343
+ target: "Array",
5344
+ proto: !0,
5345
+ forced: !("NODE" === environment) && environmentV8Version > 79 && environmentV8Version < 83 || !function(METHOD_NAME, argument) {
5346
+ var method = [][METHOD_NAME];
5347
+ return !!method && fails((function() {
5348
+ // eslint-disable-next-line no-useless-call -- required for testing
5349
+ method.call(null, argument || function() {
5350
+ return 1;
5351
+ }, 1);
5352
+ }));
5353
+ }("reduce")
5354
+ }, {
5355
+ reduce: function(callbackfn /* , initialValue */) {
5356
+ var length = arguments.length;
5357
+ return $reduce(this, callbackfn, length, length > 1 ? arguments[1] : void 0);
5358
+ }
5359
+ });
5360
+
5361
+ var reduce$3 = getBuiltInPrototypeMethod$3("Array", "reduce"), isPrototypeOf = objectIsPrototypeOf, method = reduce$3, ArrayPrototype = Array.prototype;
5362
+
5363
+ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
5364
+ var own = it.reduce;
5365
+ return it === ArrayPrototype || isPrototypeOf(ArrayPrototype, it) && own === ArrayPrototype.reduce ? method : own;
5366
+ }));
5367
+
5368
+ /**
5369
+ * Render a slot with the given props
5370
+ *
5371
+ * Priority order:
5372
+ * 1. render function
5373
+ * 2. component
5374
+ * 3. children
5375
+ * 4. fallback
5376
+ *
5377
+ * @example
5378
+ * renderSlot(
5379
+ * { render: (props) => <CustomButton {...props} /> },
5380
+ * { onClick: handleClick, children: 'Click me' }
5381
+ * )
5382
+ */ function renderSlot(slot, props, fallback) {
5383
+ // No slot provided, use fallback
5384
+ if (!slot) return fallback;
5385
+ // Slot is a plain React node
5386
+ if ( React.isValidElement(slot) || "string" == typeof slot || "number" == typeof slot) return slot;
5387
+ // Slot is an object with rendering options
5388
+ if ("object" == typeof slot && null !== slot) {
5389
+ const slotObj = slot;
5390
+ // Priority 1: render function
5391
+ if (slotObj.render && "function" == typeof slotObj.render) return slotObj.render(props);
5392
+ // Priority 2: component
5393
+ if (slotObj.component) {
5394
+ const Component = slotObj.component;
5395
+ return jsx(Component, {
5396
+ ...props
5397
+ });
5398
+ }
5399
+ // Priority 3: children
5400
+ if (void 0 !== slotObj.children) return slotObj.children;
5401
+ }
5402
+ // Fallback
5403
+ return fallback;
5404
+ }
5405
+
5406
+ /**
5407
+ * Check if a value is a slot configuration
5408
+ */ function isSlot(value) {
5409
+ return "object" == typeof value && null !== value && ("render" in value || "component" in value || "children" in value);
5410
+ }
5411
+
5412
+ /**
5413
+ * Merge multiple slot configurations
5414
+ * Later slots override earlier ones
5415
+ */ function mergeSlots(...slots) {
5416
+ const filtered = slots.filter((s => void 0 !== s));
5417
+ if (0 !== filtered.length) return 1 === filtered.length ? filtered[0] : _reduceInstanceProperty(filtered).call(filtered, ((acc, slot) => ({
5418
+ ...acc,
5419
+ ...slot
5420
+ })));
5421
+ }
5422
+
5423
+ /**
5424
+ * Create a slot wrapper component
5425
+ *
5426
+ * @example
5427
+ * const ButtonSlot = createSlotComponent<ButtonSlotProps>('button')
5428
+ *
5429
+ * <ButtonSlot slot={customSlot} {...props}>
5430
+ * Default content
5431
+ * </ButtonSlot>
5432
+ */ function createSlotComponent(defaultElement = "div") {
5433
+ return function({slot: slot, children: children, ...props}) {
5434
+ const slotProps = props;
5435
+ return slot ? jsx(Fragment, {
5436
+ children: renderSlot(slot, slotProps, children)
5437
+ }) : jsx(defaultElement, "string" == typeof defaultElement ? {
5438
+ ...props,
5439
+ children: children
5440
+ } : {
5441
+ ...slotProps,
5442
+ children: children
5443
+ });
5444
+ };
5445
+ }
5446
+
5447
+ /**
5448
+ * Utility to create typed slot props
5449
+ */ function createSlotProps(props) {
5450
+ return props;
5451
+ }
5452
+
5453
+ /**
5454
+ * Hook to manage slot rendering
5455
+ */ function useSlot(slot, props, fallback) {
5456
+ return React.useMemo((() => renderSlot(slot, props, fallback)), [ slot, props, fallback ]);
5457
+ }
5458
+
5459
+ const Button = React.memo( forwardRef((({label: label, children: children, onClick: onClick, variant: variant = "primary", size: size = "md", disabled: disabled = !1, loading: loading = !1, loadingText: loadingText, icon: icon, iconName: iconName, iconSize: iconSize = "sm", iconPosition: iconPosition = "start", iconOnly: iconOnly = !1, rounded: rounded = !1, fullWidth: fullWidth = !1, block: block = !1, active: active = !1, selected: selected = !1, type: type = "button", className: className = "", as: Component = "button", href: href, target: target, glass: glass, onHover: onHover, onFocus: onFocus, onBlur: onBlur, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, tabIndex: tabIndex, style: style, linkComponent: linkComponent, slots: slots, ...props}, ref) => {
5414
5460
  const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href), iconElement = iconName ? jsx(Icon, {
5415
5461
  name: iconName,
5416
5462
  size: iconSize
@@ -5426,17 +5472,28 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
5426
5472
  children: [ loading && jsx("span", {
5427
5473
  className: ThemeNaming.bemClass(THEME_NAMING.BUTTON_PREFIX, THEME_NAMING.SPINNER_ELEMENT),
5428
5474
  "aria-hidden": "true",
5429
- children: jsx(Spinner, {
5475
+ children: renderSlot(slots?.spinner, {
5476
+ className: ThemeNaming.bemClass(THEME_NAMING.BUTTON_PREFIX, THEME_NAMING.SPINNER_ELEMENT),
5430
5477
  size: spinnerSize,
5431
5478
  variant: "link" === variant || "string" == typeof variant && variant.startsWith("outline-") ? "primary" : "danger" === variant ? "error" : variant
5432
- })
5479
+ }, jsx(Spinner, {
5480
+ size: spinnerSize,
5481
+ variant: "link" === variant || "string" == typeof variant && variant.startsWith("outline-") ? "primary" : "danger" === variant ? "error" : variant
5482
+ }))
5433
5483
  }), iconElement && !loading && jsx("span", {
5434
5484
  className: ThemeNaming.bemClass(THEME_NAMING.BUTTON_PREFIX, THEME_NAMING.ICON_ELEMENT),
5435
5485
  "aria-hidden": "true",
5436
- children: iconElement
5486
+ children: renderSlot(slots?.icon, {
5487
+ className: ThemeNaming.bemClass(THEME_NAMING.BUTTON_PREFIX, THEME_NAMING.ICON_ELEMENT),
5488
+ children: iconElement,
5489
+ size: iconSize
5490
+ }, iconElement)
5437
5491
  }), !iconOnly && buttonText && jsx("span", {
5438
5492
  className: ThemeNaming.bemClass(THEME_NAMING.BUTTON_PREFIX, THEME_NAMING.LABEL_ELEMENT),
5439
- children: buttonText
5493
+ children: renderSlot(slots?.label, {
5494
+ className: ThemeNaming.bemClass(THEME_NAMING.BUTTON_PREFIX, THEME_NAMING.LABEL_ELEMENT),
5495
+ children: buttonText
5496
+ }, buttonText)
5440
5497
  }) ]
5441
5498
  }), buttonProps = {
5442
5499
  className: buttonClass,
@@ -5453,48 +5510,59 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
5453
5510
  tabIndex: void 0 !== tabIndex ? tabIndex : isDisabled ? -1 : 0,
5454
5511
  style: style,
5455
5512
  ...props
5456
- };
5457
- // Determine if we should render as a link
5458
- // If disabled, we still check href, but we might want to render as button or anchor with aria-disabled
5459
- // The previous logic was Boolean(href && !isDisabled). This meant if disabled, it renders as <button>.
5460
- // This is a safe fallback for disabled links.
5461
- let content;
5462
- // Render as anchor if href is provided
5463
- if (shouldRenderAsLink)
5464
- // Use custom linkComponent if provided (e.g., Next.js Link)
5465
- if (linkComponent) {
5466
- const LinkComp = linkComponent, linkProps = {
5513
+ }, buttonChildren = renderSlot(slots?.root, {
5514
+ className: buttonClass,
5515
+ children: buttonContent,
5516
+ disabled: isDisabled,
5517
+ loading: loading,
5518
+ onClick: handleClickEvent,
5519
+ type: type,
5520
+ "aria-label": safeAriaLabel,
5521
+ "aria-disabled": isDisabled,
5522
+ "aria-busy": loading
5523
+ }, (() => {
5524
+ // Render as anchor if href is provided
5525
+ if (shouldRenderAsLink) {
5526
+ // Use custom linkComponent if provided (e.g., Next.js Link)
5527
+ if (linkComponent) {
5528
+ const LinkComp = linkComponent, linkProps = {
5529
+ ...buttonProps,
5530
+ ref: ref,
5531
+ // linkComponent usually forwards ref to anchor
5532
+ href: isDisabled ? void 0 : href,
5533
+ to: isDisabled ? void 0 : href,
5534
+ target: target,
5535
+ rel: "_blank" === target ? "noopener noreferrer" : void 0
5536
+ };
5537
+ return jsx(LinkComp, {
5538
+ ...linkProps,
5539
+ children: buttonContent
5540
+ });
5541
+ }
5542
+ // Fallback to regular anchor tag
5543
+ return jsx("a", {
5544
+ ...buttonProps,
5545
+ ref: ref,
5546
+ href: isDisabled ? void 0 : href,
5547
+ target: target,
5548
+ rel: "_blank" === target ? "noopener noreferrer" : void 0,
5549
+ children: buttonContent
5550
+ });
5551
+ }
5552
+ // Default button rendering
5553
+ return jsx(Component, {
5467
5554
  ...buttonProps,
5468
5555
  ref: ref,
5469
- // linkComponent usually forwards ref to anchor
5470
- href: isDisabled ? void 0 : href,
5471
- to: isDisabled ? void 0 : href,
5472
- target: target,
5473
- rel: "_blank" === target ? "noopener noreferrer" : void 0
5474
- };
5475
- content = jsx(LinkComp, {
5476
- ...linkProps,
5556
+ type: "button" === Component ? type : void 0,
5557
+ disabled: isDisabled,
5477
5558
  children: buttonContent
5478
5559
  });
5479
- } else
5480
- // Fallback to regular anchor tag
5481
- content = jsx("a", {
5482
- ...buttonProps,
5483
- ref: ref,
5484
- href: isDisabled ? void 0 : href,
5485
- target: target,
5486
- rel: "_blank" === target ? "noopener noreferrer" : void 0,
5487
- children: buttonContent
5488
- }); else
5489
- // Default button rendering
5490
- content = jsx(Component, {
5491
- ...buttonProps,
5492
- ref: ref,
5493
- type: "button" === Component ? type : void 0,
5494
- disabled: isDisabled,
5495
- children: buttonContent
5496
- });
5497
- if (glass) {
5560
+ })());
5561
+ // Determine if we should render as a link
5562
+ // If disabled, we still check href, but we might want to render as button or anchor with aria-disabled
5563
+ // The previous logic was Boolean(href && !isDisabled). This meant if disabled, it renders as <button>.
5564
+ // This is a safe fallback for disabled links.
5565
+ if (glass) {
5498
5566
  // Default glass props
5499
5567
  const defaultGlassProps = {
5500
5568
  displacementScale: 20,
@@ -5507,10 +5575,10 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
5507
5575
  };
5508
5576
  return jsx(AtomixGlass, {
5509
5577
  ...glassProps,
5510
- children: content
5578
+ children: buttonChildren
5511
5579
  });
5512
5580
  }
5513
- return content;
5581
+ return buttonChildren;
5514
5582
  })));
5515
5583
 
5516
5584
  Button.displayName = "Button";
@@ -6022,67 +6090,12 @@ const ElevationCard = ({elevationClass: elevationClass = "is-elevated", classNam
6022
6090
  });
6023
6091
  };
6024
6092
 
6025
- ElevationCard.displayName = "ElevationCard";
6026
-
6027
- var aCallable = aCallable$3, toObject = toObject$2, IndexedObject = indexedObject, lengthOfArrayLike = lengthOfArrayLike$2, $TypeError = TypeError, REDUCE_EMPTY = "Reduce of empty array with no initial value", createMethod = function(IS_RIGHT) {
6028
- return function(that, callbackfn, argumentsLength, memo) {
6029
- var O = toObject(that), self = IndexedObject(O), length = lengthOfArrayLike(O);
6030
- if (aCallable(callbackfn), 0 === length && argumentsLength < 2) throw new $TypeError(REDUCE_EMPTY);
6031
- var index = IS_RIGHT ? length - 1 : 0, i = IS_RIGHT ? -1 : 1;
6032
- if (argumentsLength < 2) for (;;) {
6033
- if (index in self) {
6034
- memo = self[index], index += i;
6035
- break;
6036
- }
6037
- if (index += i, IS_RIGHT ? index < 0 : length <= index) throw new $TypeError(REDUCE_EMPTY);
6038
- }
6039
- for (;IS_RIGHT ? index >= 0 : length > index; index += i) index in self && (memo = callbackfn(memo, self[index], index, O));
6040
- return memo;
6041
- };
6042
- }, arrayReduce = {
6043
- // `Array.prototype.reduce` method
6044
- // https://tc39.es/ecma262/#sec-array.prototype.reduce
6045
- left: createMethod(!1),
6046
- // `Array.prototype.reduceRight` method
6047
- // https://tc39.es/ecma262/#sec-array.prototype.reduceright
6048
- right: createMethod(!0)
6049
- }, fails = fails$9, globalThis$1 = globalThis_1, userAgent = environmentUserAgent, classof = classofRaw$2, userAgentStartsWith = function(string) {
6050
- return userAgent.slice(0, string.length) === string;
6051
- }, environment = userAgentStartsWith("Bun/") ? "BUN" : userAgentStartsWith("Cloudflare-Workers") ? "CLOUDFLARE" : userAgentStartsWith("Deno/") ? "DENO" : userAgentStartsWith("Node.js/") ? "NODE" : globalThis$1.Bun && "string" == typeof Bun.version ? "BUN" : globalThis$1.Deno && "object" == typeof Deno.version ? "DENO" : "process" === classof(globalThis$1.process) ? "NODE" : globalThis$1.window && globalThis$1.document ? "BROWSER" : "REST", $reduce = arrayReduce.left;
6052
-
6053
- // `Array.prototype.reduce` method
6054
- // https://tc39.es/ecma262/#sec-array.prototype.reduce
6055
- _export({
6056
- target: "Array",
6057
- proto: !0,
6058
- forced: !("NODE" === environment) && environmentV8Version > 79 && environmentV8Version < 83 || !function(METHOD_NAME, argument) {
6059
- var method = [][METHOD_NAME];
6060
- return !!method && fails((function() {
6061
- // eslint-disable-next-line no-useless-call -- required for testing
6062
- method.call(null, argument || function() {
6063
- return 1;
6064
- }, 1);
6065
- }));
6066
- }("reduce")
6067
- }, {
6068
- reduce: function(callbackfn /* , initialValue */) {
6069
- var length = arguments.length;
6070
- return $reduce(this, callbackfn, length, length > 1 ? arguments[1] : void 0);
6071
- }
6072
- });
6073
-
6074
- var reduce$3 = getBuiltInPrototypeMethod$3("Array", "reduce"), isPrototypeOf = objectIsPrototypeOf, method = reduce$3, ArrayPrototype = Array.prototype;
6075
-
6076
- const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
6077
- var own = it.reduce;
6078
- return it === ArrayPrototype || isPrototypeOf(ArrayPrototype, it) && own === ArrayPrototype.reduce ? method : own;
6079
- }));
6080
-
6081
6093
  /**
6082
6094
  * Comprehensive chart hook with shared functionality
6083
6095
  * @param initialProps - Initial chart properties
6084
6096
  * @returns Chart state and methods
6085
- */ function useChart(initialProps) {
6097
+ */
6098
+ function useChart(initialProps) {
6086
6099
  const [interactionState, setInteractionState] = useState({
6087
6100
  hoveredPoint: null,
6088
6101
  selectedPoints: [],
@@ -6114,8 +6127,11 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
6114
6127
  }), animationFrameRef = useRef(null);
6115
6128
  // Default chart properties
6116
6129
  // Cleanup animation frame on unmount
6117
- useEffect((() => () => {
6118
- animationFrameRef.current && cancelAnimationFrame(animationFrameRef.current);
6130
+ useEffect((() => {
6131
+ const currentRef = animationFrameRef.current;
6132
+ return () => {
6133
+ currentRef && cancelAnimationFrame(currentRef);
6134
+ };
6119
6135
  }), []);
6120
6136
  /**
6121
6137
  * Point interaction handlers
@@ -6506,7 +6522,9 @@ function getDatasetBounds(data) {
6506
6522
 
6507
6523
  /**
6508
6524
  * Hook for managing chart toolbar state and generating chart-specific configurations
6509
- */ const ChartToolbar = memo( forwardRef((({chartType: chartType = "line", groups: groups = [], enableDefaults: enableDefaults = !0, defaults: defaults = {
6525
+ */ ElevationCard.displayName = "ElevationCard";
6526
+
6527
+ const ChartToolbar = memo( forwardRef((({chartType: chartType = "line", groups: groups = [], enableDefaults: enableDefaults = !0, defaults: defaults = {
6510
6528
  refresh: !0,
6511
6529
  export: !0,
6512
6530
  fullscreen: !0,
@@ -6996,8 +7014,8 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
6996
7014
  }), [ chartType ]), finalDefaults = useMemo((() => ({
6997
7015
  ...getChartDefaults(),
6998
7016
  ...defaults
6999
- })), [ getChartDefaults, defaults ]), enhancedHandlers = {
7000
- onRefresh: useCallback((() => {
7017
+ })), [ getChartDefaults, defaults ]), enhancedHandlers = useMemo((() => ({
7018
+ onRefresh: () => {
7001
7019
  setState((prev => ({
7002
7020
  ...prev,
7003
7021
  isRefreshing: !0
@@ -7007,8 +7025,8 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
7007
7025
  isRefreshing: !1
7008
7026
  })));
7009
7027
  }), 1e3);
7010
- }), [ handlers.onRefresh ]),
7011
- onExport: useCallback((async format => {
7028
+ },
7029
+ onExport: async format => {
7012
7030
  setState((prev => ({
7013
7031
  ...prev,
7014
7032
  isExporting: !0
@@ -7021,70 +7039,70 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
7021
7039
  isExporting: !1
7022
7040
  })));
7023
7041
  }
7024
- }), [ handlers.onExport ]),
7025
- onFullscreen: useCallback((isFullscreen => {
7042
+ },
7043
+ onFullscreen: isFullscreen => {
7026
7044
  setState((prev => ({
7027
7045
  ...prev,
7028
7046
  isFullscreen: isFullscreen
7029
7047
  }))), handlers.onFullscreen?.(isFullscreen);
7030
- }), [ handlers.onFullscreen ]),
7031
- onZoomIn: useCallback((() => {
7048
+ },
7049
+ onZoomIn: () => {
7032
7050
  setState((prev => ({
7033
7051
  ...prev,
7034
7052
  zoomLevel: Math.min(1.2 * prev.zoomLevel, 5)
7035
7053
  }))), handlers.onZoomIn?.();
7036
- }), [ handlers.onZoomIn ]),
7037
- onZoomOut: useCallback((() => {
7054
+ },
7055
+ onZoomOut: () => {
7038
7056
  setState((prev => ({
7039
7057
  ...prev,
7040
7058
  zoomLevel: Math.max(prev.zoomLevel / 1.2, .2)
7041
7059
  }))), handlers.onZoomOut?.();
7042
- }), [ handlers.onZoomOut ]),
7043
- onZoomReset: useCallback((() => {
7060
+ },
7061
+ onZoomReset: () => {
7044
7062
  setState((prev => ({
7045
7063
  ...prev,
7046
7064
  zoomLevel: 1
7047
7065
  }))), handlers.onZoomReset?.();
7048
- }), [ handlers.onZoomReset ]),
7049
- onPanToggle: useCallback((enabled => {
7066
+ },
7067
+ onPanToggle: enabled => {
7050
7068
  setState((prev => ({
7051
7069
  ...prev,
7052
7070
  panEnabled: enabled
7053
7071
  }))), handlers.onPanToggle?.(enabled);
7054
- }), [ handlers.onPanToggle ]),
7055
- onReset: useCallback((() => {
7072
+ },
7073
+ onReset: () => {
7056
7074
  setState((prev => ({
7057
7075
  ...prev,
7058
7076
  zoomLevel: 1,
7059
7077
  panEnabled: !1
7060
7078
  }))), handlers.onReset?.();
7061
- }), [ handlers.onReset ]),
7062
- onGridToggle: useCallback((show => {
7079
+ },
7080
+ onGridToggle: show => {
7063
7081
  setState((prev => ({
7064
7082
  ...prev,
7065
7083
  showGrid: show
7066
7084
  }))), handlers.onGridToggle?.(show);
7067
- }), [ handlers.onGridToggle ]),
7068
- onLegendToggle: useCallback((show => {
7085
+ },
7086
+ onLegendToggle: show => {
7069
7087
  setState((prev => ({
7070
7088
  ...prev,
7071
7089
  showLegend: show
7072
7090
  }))), handlers.onLegendToggle?.(show);
7073
- }), [ handlers.onLegendToggle ]),
7074
- onTooltipsToggle: useCallback((show => {
7091
+ },
7092
+ onTooltipsToggle: show => {
7075
7093
  setState((prev => ({
7076
7094
  ...prev,
7077
7095
  showTooltips: show
7078
7096
  }))), handlers.onTooltipsToggle?.(show);
7079
- }), [ handlers.onTooltipsToggle ]),
7080
- onAnimationsToggle: useCallback((enabled => {
7097
+ },
7098
+ onAnimationsToggle: enabled => {
7081
7099
  setState((prev => ({
7082
7100
  ...prev,
7083
7101
  animationsEnabled: enabled
7084
7102
  }))), handlers.onAnimationsToggle?.(enabled);
7085
- }), [ handlers.onAnimationsToggle ]),
7086
- onSettings: useCallback((() => {}), [])
7087
- }, generateToolbarGroups = useCallback((() => {
7103
+ },
7104
+ onSettings: () => {}
7105
+ })), [ handlers ]), generateToolbarGroups = useCallback((() => {
7088
7106
  const groups = [], dataActions = [];
7089
7107
  // Data actions group
7090
7108
  finalDefaults.refresh && dataActions.push({
@@ -7209,7 +7227,7 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
7209
7227
  actions: customActions
7210
7228
  });
7211
7229
  return groups;
7212
- }), [ chartType, finalDefaults, state, enhancedHandlers, customActions, customGroups ]);
7230
+ }), [ finalDefaults, state, enhancedHandlers, customActions, customGroups ]);
7213
7231
  // Keyboard shortcuts
7214
7232
  return useEffect((() => {
7215
7233
  const handleKeyDown = event => {
@@ -7801,7 +7819,7 @@ const ChartRenderer = memo( forwardRef((({datasets: datasets = [], config: conf
7801
7819
  announcement: announcement,
7802
7820
  focusedPoint: focusedPoint,
7803
7821
  getAccessibleDescription: () => "Chart description"
7804
- })), [ announcement, focusedPoint ]), transform = useMemo((() => chartContext ? `translate(${chartContext.panOffset.x}px, ${chartContext.panOffset.y}px) scale(${chartContext.zoomLevel})` : ""), [ chartContext?.panOffset.x, chartContext?.panOffset.y, chartContext?.zoomLevel ]), chartData = useMemo((() => {
7822
+ })), [ announcement, focusedPoint ]), transform = useMemo((() => chartContext ? `translate(${chartContext.panOffset.x}px, ${chartContext.panOffset.y}px) scale(${chartContext.zoomLevel})` : ""), [ chartContext ]), chartData = useMemo((() => {
7805
7823
  // Return null if dimensions not ready to prevent calculation with invalid dimensions
7806
7824
  if (!isInitialized || 0 === dimensions.width || 0 === dimensions.height) return null;
7807
7825
  const scales = calculateScales(processedData, dimensions.width, dimensions.height, void 0, config);
@@ -8214,7 +8232,7 @@ function useBarChart(datasets, options = {}) {
8214
8232
  opacity: .4
8215
8233
  } ]
8216
8234
  };
8217
- })) : []), [ options.useGradients ]), formatValue = useCallback((value => options.valueFormatter ? options.valueFormatter(value) : value.toString()), [ options.valueFormatter ]);
8235
+ })) : []), [ options.useGradients ]), formatValue = useCallback((value => options.valueFormatter ? options.valueFormatter(value) : value.toString()), [ options ]);
8218
8236
  return {
8219
8237
  // State
8220
8238
  hoveredBar: hoveredBar,
@@ -8240,7 +8258,7 @@ function useBarChart(datasets, options = {}) {
8240
8258
  y: horizontal ? y + height / 2 : y - 5
8241
8259
  };
8242
8260
  }
8243
- }), [ options.dataLabelPosition ]),
8261
+ }), [ options ]),
8244
8262
  // Handlers
8245
8263
  handleBarHover: handleBarHover,
8246
8264
  handleBarLeave: handleBarLeave,
@@ -8549,13 +8567,13 @@ const DonutChart = memo( forwardRef((({datasets: datasets = [], config: config
8549
8567
  roundedCorners: !0
8550
8568
  }, onDataPointClick: onDataPointClick, ...props}, ref) => {
8551
8569
  // Use the first dataset for donut chart
8552
- const dataset = datasets.length > 0 ? datasets[0] : {
8570
+ const dataset = useMemo((() => datasets.length > 0 ? datasets[0] : {
8553
8571
  label: "",
8554
8572
  data: []
8555
- }, chartData = useMemo((() => {
8573
+ }), [ datasets ]), chartData = useMemo((() => {
8556
8574
  if (!dataset?.data?.length) return null;
8557
8575
  // Filter out invalid data points
8558
- const validDataPoints = dataset?.data?.filter((point => "number" == typeof point.value && !isNaN(point.value) && isFinite(point.value) && point.value > 0));
8576
+ const validDataPoints = (dataset?.data || []).filter((point => "number" == typeof point.value && !isNaN(point.value) && isFinite(point.value) && point.value > 0));
8559
8577
  return validDataPoints.length ? {
8560
8578
  validDataPoints: validDataPoints
8561
8579
  } : null;
@@ -9511,7 +9529,7 @@ function usePieChart(data, options = {}) {
9511
9529
  const parts = [];
9512
9530
  return !1 !== options.showLabels && parts.push(slice.label), options.showPercentages && parts.push(`${Math.round(slice.percentage)}%`),
9513
9531
  options.showValues && parts.push(slice.value.toString()), parts.join(" - ");
9514
- }), [ options.labelFormatter, options.showLabels, options.showPercentages, options.showValues ]), getSliceTransform = useCallback(((slice, isHovered) => isHovered && options.enableHoverEffects && options.hoverOffset ? `translate(${Math.cos(slice.midAngle) * options.hoverOffset}, ${Math.sin(slice.midAngle) * options.hoverOffset})` : ""), [ options.enableHoverEffects, options.hoverOffset ]), isSliceSelected = useCallback((index => selectedSlices.has(index)), [ selectedSlices ]);
9532
+ }), [ options ]), getSliceTransform = useCallback(((slice, isHovered) => isHovered && options.enableHoverEffects && options.hoverOffset ? `translate(${Math.cos(slice.midAngle) * options.hoverOffset}, ${Math.sin(slice.midAngle) * options.hoverOffset})` : ""), [ options.enableHoverEffects, options.hoverOffset ]), isSliceSelected = useCallback((index => selectedSlices.has(index)), [ selectedSlices ]);
9515
9533
  return {
9516
9534
  // Data
9517
9535
  processedData: processedData,
@@ -10938,7 +10956,7 @@ const DataTable = memo((({data: data, columns: columns, className: className, s
10938
10956
  const newOrder = columns.map((col => col.key)), currentOrderSet = new Set(columnOrder), newOrderSet = new Set(newOrder);
10939
10957
  // Only update if there are actual differences
10940
10958
  newOrder.length === columnOrder.length && newOrder.every((key => currentOrderSet.has(key))) && columnOrder.every((key => newOrderSet.has(key))) || setColumnOrder(newOrder);
10941
- }), [ columns ]),
10959
+ }), [ columns, columnOrder ]),
10942
10960
  // Update column visibility when columns prop changes
10943
10961
  useEffect((() => {
10944
10962
  setColumnVisibility((prev => {
@@ -11483,7 +11501,7 @@ function formatDate(date, format) {
11483
11501
  /**
11484
11502
  * Check if a date is within a min and max range
11485
11503
  */ function useDatePicker({value: value, onChange: onChange, selectionMode: selectionMode = "single", startDate: startDate, endDate: endDate, onRangeChange: onRangeChange, format: format = "MM/dd/yyyy", minDate: minDate, maxDate: maxDate, inline: inline = !1} = {}) {
11486
- const [isOpen, setIsOpen] = useState(inline), [inputValue, setInputValue] = useState(value ? formatDate(value, format) : ""), [rangeInputValue, setRangeInputValue] = useState(startDate && endDate ? `${formatDate(startDate, format)} - ${formatDate(endDate, format)}` : startDate ? `${formatDate(startDate, format)} - Select end date` : ""), [viewDate, setViewDate] = useState(value || startDate || new Date), [viewMode, setViewMode] = useState("days"), [rangeSelectionState, setRangeSelectionState] = useState(!startDate || startDate && endDate ? "start" : "end"), datePickerRef = useRef(null), inputRef = useRef(null), today = new Date, currentMonth = viewDate.getMonth(), currentYear = viewDate.getFullYear(), daysInMonth = getDaysInMonth(currentYear, currentMonth), firstDayOfMonth = new Date(currentYear, currentMonth, 1).getDay();
11504
+ const [isOpen, setIsOpen] = useState(inline), [inputValue, setInputValue] = useState(value ? formatDate(value, format) : ""), [rangeInputValue, setRangeInputValue] = useState(startDate && endDate ? `${formatDate(startDate, format)} - ${formatDate(endDate, format)}` : startDate ? `${formatDate(startDate, format)} - Select end date` : ""), [viewDate, setViewDate] = useState(value || startDate || new Date), [viewMode, setViewMode] = useState("days"), [rangeSelectionState, setRangeSelectionState] = useState(!startDate || startDate && endDate ? "start" : "end"), datePickerRef = useRef(null), inputRef = useRef(null), today = useMemo((() => new Date), []), currentMonth = viewDate.getMonth(), currentYear = viewDate.getFullYear(), daysInMonth = getDaysInMonth(currentYear, currentMonth), firstDayOfMonth = new Date(currentYear, currentMonth, 1).getDay();
11487
11505
  // Update input value when value or range dates change externally
11488
11506
  useEffect((() => {
11489
11507
  "single" === selectionMode ? setInputValue(value ? formatDate(value, format) : "") : (setRangeInputValue(startDate && endDate ? `${formatDate(startDate, format)} - ${formatDate(endDate, format)}` : startDate ? `${formatDate(startDate, format)} - Select end date` : ""),
@@ -12006,21 +12024,11 @@ const DatePicker = forwardRef((({value: value, onChange: onChange, selectionMod
12006
12024
  * @returns EdgePanel state and methods
12007
12025
  */
12008
12026
  function useEdgePanel(initialProps) {
12009
- // Default EdgePanel properties
12010
- const defaultProps = {
12011
- position: "start",
12012
- mode: "slide",
12013
- isOpen: !1,
12014
- backdrop: !0,
12015
- closeOnBackdropClick: !0,
12016
- closeOnEscape: !0,
12017
- glass: void 0,
12018
- ...initialProps
12019
- }, [isOpen, setIsOpen] = useState(defaultProps.isOpen || !1), containerRef = useRef(null), backdropRef = useRef(null), adjustBodyPadding = useCallback((() => {
12020
- if (!containerRef.current || "push" !== defaultProps.mode) return;
12021
- const {position: position} = defaultProps, size = "top" === position || "bottom" === position ? containerRef.current.clientHeight : containerRef.current.clientWidth;
12027
+ const {position: position = "start", mode: mode = "slide", isOpen: propIsOpen = !1, backdrop: backdrop = !0, closeOnBackdropClick: closeOnBackdropClick = !0, closeOnEscape: closeOnEscape = !0, glass: glass, onOpenChange: onOpenChange, className: className = ""} = initialProps || {}, [isOpen, setIsOpen] = useState(propIsOpen || !1), containerRef = useRef(null), backdropRef = useRef(null), adjustBodyPadding = useCallback((() => {
12028
+ if (!containerRef.current || "push" !== mode) return;
12029
+ const size = "top" === position || "bottom" === position ? containerRef.current.clientHeight : containerRef.current.clientWidth;
12022
12030
  // Map position to CSS padding property
12023
- let paddingProperty;
12031
+ let paddingProperty;
12024
12032
  switch (position) {
12025
12033
  case "start":
12026
12034
  paddingProperty = "paddingLeft";
@@ -12035,9 +12043,8 @@ function useEdgePanel(initialProps) {
12035
12043
  paddingProperty = `padding${position.charAt(0).toUpperCase() + position.slice(1)}`;
12036
12044
  }
12037
12045
  document.body.style[paddingProperty] = `${size}px`, document.body.classList.add("is-pushed");
12038
- }), [ defaultProps.mode, defaultProps.position ]), resetBodyPadding = useCallback((() => {
12039
- if ("push" !== defaultProps.mode) return;
12040
- const {position: position} = defaultProps;
12046
+ }), [ mode, position ]), resetBodyPadding = useCallback((() => {
12047
+ if ("push" !== mode) return;
12041
12048
  // Map position to CSS padding property
12042
12049
  let paddingProperty;
12043
12050
  switch (position) {
@@ -12054,11 +12061,10 @@ function useEdgePanel(initialProps) {
12054
12061
  paddingProperty = `padding${position.charAt(0).toUpperCase() + position.slice(1)}`;
12055
12062
  }
12056
12063
  document.body.style[paddingProperty] = "", document.body.classList.remove("is-pushed");
12057
- }), [ defaultProps.mode, defaultProps.position ]), openPanel = useCallback(((useFadeAnimation = !1) => {
12064
+ }), [ mode, position ]), openPanel = useCallback(((useFadeAnimation = !1) => {
12058
12065
  if (setIsOpen(!0), document.body.classList.add("is-edgepanel-open"), containerRef.current) {
12059
- const {mode: mode} = defaultProps;
12060
12066
  // Only add animation if not in 'none' mode
12061
- if ("none" !== mode) if (useFadeAnimation) {
12067
+ if ("none" !== mode) if (useFadeAnimation) {
12062
12068
  // Add fade animation class
12063
12069
  containerRef.current.classList.add("is-fade-animating"), containerRef.current.offsetHeight;
12064
12070
  // Remove animation class after animation completes
@@ -12078,14 +12084,13 @@ function useEdgePanel(initialProps) {
12078
12084
  // Set transform or opacity based on animation type
12079
12085
  useFadeAnimation ? (containerRef.current.style.opacity = "1", containerRef.current.style.transform = "") : containerRef.current.style.transform = "translate(0)",
12080
12086
  // If push mode, adjust body padding
12081
- "push" === defaultProps.mode && adjustBodyPadding();
12087
+ "push" === mode && adjustBodyPadding();
12082
12088
  }
12083
- defaultProps.onOpenChange && defaultProps.onOpenChange(!0);
12084
- }), [ defaultProps, adjustBodyPadding ]), closePanel = useCallback(((useFadeAnimation = !1) => {
12089
+ onOpenChange && onOpenChange(!0);
12090
+ }), [ mode, adjustBodyPadding, onOpenChange ]), closePanel = useCallback(((useFadeAnimation = !1) => {
12085
12091
  if (containerRef.current) {
12086
- const {position: position, mode: mode} = defaultProps;
12087
12092
  // Only add animation if not in 'none' mode
12088
- if ("none" !== mode) if (useFadeAnimation) {
12093
+ if ("none" !== mode) if (useFadeAnimation) {
12089
12094
  // Add fade out animation class
12090
12095
  containerRef.current.classList.add("is-fade-animating-out");
12091
12096
  // Capture container for setTimeout
@@ -12107,46 +12112,42 @@ function useEdgePanel(initialProps) {
12107
12112
  // Then set transform
12108
12113
  containerRef.current.style.transform = position ? EDGE_PANEL.TRANSFORM_VALUES[position] : "",
12109
12114
  // Reset body padding if push mode
12110
- "push" === defaultProps.mode && resetBodyPadding(), setTimeout((() => {
12111
- setIsOpen(!1), document.body.classList.remove("is-edgepanel-open"), defaultProps.onOpenChange && defaultProps.onOpenChange(!1);
12115
+ "push" === mode && resetBodyPadding(), setTimeout((() => {
12116
+ setIsOpen(!1), document.body.classList.remove("is-edgepanel-open"), onOpenChange && onOpenChange(!1);
12112
12117
  }), "none" === mode ? 0 : EDGE_PANEL.ANIMATION_DURATION);
12113
- } else setIsOpen(!1), document.body.classList.remove("is-edgepanel-open"), defaultProps.onOpenChange && defaultProps.onOpenChange(!1);
12114
- }), [ defaultProps, resetBodyPadding ]), handleEscapeKey = useCallback((event => {
12115
- defaultProps.closeOnEscape && "Escape" === event.key && isOpen && closePanel();
12116
- }), [ closePanel, defaultProps.closeOnEscape, isOpen ]), handleBackdropClick = useCallback((event => {
12117
- defaultProps.closeOnBackdropClick && event.target === event.currentTarget && closePanel();
12118
- }), [ closePanel, defaultProps.closeOnBackdropClick ]);
12118
+ } else setIsOpen(!1), document.body.classList.remove("is-edgepanel-open"), onOpenChange && onOpenChange(!1);
12119
+ }), [ mode, position, onOpenChange, resetBodyPadding ]), handleEscapeKey = useCallback((event => {
12120
+ closeOnEscape && "Escape" === event.key && isOpen && closePanel();
12121
+ }), [ closePanel, closeOnEscape, isOpen ]), handleBackdropClick = useCallback((event => {
12122
+ closeOnBackdropClick && event.target === event.currentTarget && closePanel();
12123
+ }), [ closePanel, closeOnBackdropClick ]);
12119
12124
  /**
12120
12125
  * Set up event listeners for keyboard events
12121
12126
  */
12122
- return useEffect((() => (isOpen && defaultProps.closeOnEscape && document.addEventListener("keydown", handleEscapeKey),
12127
+ return useEffect((() => (isOpen && closeOnEscape && document.addEventListener("keydown", handleEscapeKey),
12123
12128
  () => {
12124
12129
  document.removeEventListener("keydown", handleEscapeKey);
12125
- })), [ isOpen, handleEscapeKey, defaultProps.closeOnEscape ]),
12130
+ })), [ isOpen, handleEscapeKey, closeOnEscape ]),
12126
12131
  /**
12127
12132
  * Set initial transform values
12128
12133
  */
12129
12134
  useEffect((() => {
12130
- if (containerRef.current) {
12131
- const {position: position, mode: mode} = defaultProps;
12132
- isOpen || "slide" !== mode && "push" !== mode || !position || (containerRef.current.style.transform = EDGE_PANEL.TRANSFORM_VALUES[position],
12133
- // Set initial opacity for fade animations
12134
- defaultProps.glass && (containerRef.current.style.opacity = "0"));
12135
- }
12136
- }), [ defaultProps.mode, defaultProps.position, defaultProps.glass, isOpen ]),
12135
+ containerRef.current && (isOpen || "slide" !== mode && "push" !== mode || !position || (containerRef.current.style.transform = EDGE_PANEL.TRANSFORM_VALUES[position],
12136
+ // Set initial opacity for fade animations
12137
+ glass && (containerRef.current.style.opacity = "0")));
12138
+ }), [ mode, position, glass, isOpen ]),
12137
12139
  /**
12138
12140
  * Sync with prop changes
12139
12141
  */
12140
12142
  useEffect((() => {
12141
- void 0 !== defaultProps.isOpen && defaultProps.isOpen !== isOpen && (defaultProps.isOpen ? openPanel(!!defaultProps.glass) : closePanel(!!defaultProps.glass));
12142
- }), [ defaultProps.isOpen, closePanel, isOpen, openPanel, defaultProps.glass ]),
12143
- {
12143
+ void 0 !== propIsOpen && propIsOpen !== isOpen && (propIsOpen ? openPanel(!!glass) : closePanel(!!glass));
12144
+ }), [ propIsOpen, closePanel, isOpen, openPanel, glass ]), {
12144
12145
  isOpen: isOpen,
12145
12146
  containerRef: containerRef,
12146
12147
  backdropRef: backdropRef,
12147
12148
  generateEdgePanelClass: props => {
12148
- const {position: position = defaultProps.position, className: className = "", isOpen: propIsOpen} = props, baseClass = EDGE_PANEL.CLASSES.BASE;
12149
- return `${baseClass} ${position ? `${baseClass}--${position}` : ""} ${propIsOpen ?? isOpen ? EDGE_PANEL.CLASSES.IS_OPEN : ""} ${className}`.trim();
12149
+ const {position: propPosition = position, className: propClassName = className, isOpen: argIsOpen} = props, baseClass = EDGE_PANEL.CLASSES.BASE;
12150
+ return `${baseClass} ${propPosition ? `${baseClass}--${propPosition}` : ""} ${argIsOpen ?? isOpen ? EDGE_PANEL.CLASSES.IS_OPEN : ""} ${propClassName}`.trim();
12150
12151
  },
12151
12152
  openPanel: openPanel,
12152
12153
  closePanel: closePanel,
@@ -12528,7 +12529,7 @@ function useHero(initialProps) {
12528
12529
  * @returns Slider state and methods
12529
12530
  */
12530
12531
  function(config) {
12531
- const {slides: slides, autoplay: autoplay, loop: loop = !0, transition: transition = "fade", transitionDuration: transitionDuration = 1e3} = config, [currentIndex, setCurrentIndex] = useState(0), [isTransitioning, setIsTransitioning] = useState(!1), autoplayRef = useRef(null), isPausedRef = useRef(!1), callbackRef = useRef(), slideRefs = useMemo((() => slides.map((() => React.createRef()))), [ slides.length ]), videoRefs = useMemo((() => slides.map((() => React.createRef()))), [ slides.length ]), handleSlideTransition = useCallback((nextIndex => {
12532
+ const {slides: slides, autoplay: autoplay, loop: loop = !0, transition: transition = "fade", transitionDuration: transitionDuration = 1e3} = config, [currentIndex, setCurrentIndex] = useState(0), [isTransitioning, setIsTransitioning] = useState(!1), autoplayRef = useRef(null), isPausedRef = useRef(!1), callbackRef = useRef(void 0), slideRefs = useMemo((() => slides.map((() => React.createRef()))), [ slides ]), videoRefs = useMemo((() => slides.map((() => React.createRef()))), [ slides ]), handleSlideTransition = useCallback((nextIndex => {
12532
12533
  if (nextIndex === currentIndex || isTransitioning) return;
12533
12534
  if (nextIndex < 0 || nextIndex >= slides.length) return;
12534
12535
  setIsTransitioning(!0),
@@ -12847,22 +12848,15 @@ function useHero(initialProps) {
12847
12848
  * @param initialProps - Initial side menu properties
12848
12849
  * @returns SideMenu state and methods
12849
12850
  */ function useSideMenu(initialProps) {
12850
- // Default side menu properties
12851
- const defaultProps = {
12852
- collapsible: !0,
12853
- collapsibleDesktop: !1,
12854
- defaultCollapsedDesktop: !1,
12855
- isOpen: !1,
12856
- ...initialProps
12857
- }, [isOpenState, setIsOpenState] = useState(void 0 !== defaultProps.defaultCollapsedDesktop ? !defaultProps.defaultCollapsedDesktop : defaultProps.isOpen || !1), wrapperRef = useRef(null), innerRef = useRef(null), sideMenuRef = useRef(null);
12851
+ const {collapsible: collapsible = !0, collapsibleDesktop: collapsibleDesktop = !1, defaultCollapsedDesktop: defaultCollapsedDesktop = !1, isOpen: isOpen, onToggle: onToggle, disabled: disabled = !1} = initialProps || {}, [isOpenState, setIsOpenState] = useState(void 0 !== defaultCollapsedDesktop ? !defaultCollapsedDesktop : isOpen || !1), wrapperRef = useRef(null), innerRef = useRef(null), sideMenuRef = useRef(null);
12858
12852
  // Local open state for when not controlled externally
12859
12853
  // Update local state when external state changes
12860
12854
  useEffect((() => {
12861
- void 0 !== defaultProps.isOpen ? setIsOpenState(defaultProps.isOpen) : void 0 !== defaultProps.defaultCollapsedDesktop && setIsOpenState(!defaultProps.defaultCollapsedDesktop);
12862
- }), [ defaultProps.isOpen, defaultProps.defaultCollapsedDesktop ]),
12855
+ void 0 !== isOpen ? setIsOpenState(isOpen) : void 0 !== defaultCollapsedDesktop && setIsOpenState(!defaultCollapsedDesktop);
12856
+ }), [ isOpen, defaultCollapsedDesktop ]),
12863
12857
  // Set initial height on mount
12864
12858
  useEffect((() => {
12865
- const shouldCollapse = window.innerWidth < 768 ? defaultProps.collapsible : defaultProps.collapsibleDesktop, currentOpen = void 0 !== defaultProps.isOpen ? defaultProps.isOpen : isOpenState;
12859
+ const shouldCollapse = window.innerWidth < 768 ? collapsible : collapsibleDesktop, currentOpen = void 0 !== isOpen ? isOpen : isOpenState;
12866
12860
  if (shouldCollapse && wrapperRef.current && innerRef.current) {
12867
12861
  // Use setTimeout to ensure DOM is fully rendered
12868
12862
  const timeoutId = setTimeout((() => {
@@ -12871,14 +12865,14 @@ function useHero(initialProps) {
12871
12865
  return () => clearTimeout(timeoutId);
12872
12866
  }
12873
12867
  !shouldCollapse && wrapperRef.current && (wrapperRef.current.style.height = "auto");
12874
- }), []), // Only run on mount
12868
+ }), [ collapsible, collapsibleDesktop, isOpen, isOpenState ]),
12875
12869
  // Handle responsive behavior - vertical collapse for both mobile and desktop
12876
12870
  useEffect((() => {
12877
12871
  const handleResize = () => {
12878
- if (window.innerWidth < 768 ? defaultProps.collapsible : defaultProps.collapsibleDesktop) {
12872
+ if (window.innerWidth < 768 ? collapsible : collapsibleDesktop) {
12879
12873
  if (wrapperRef.current && innerRef.current) {
12880
12874
  // Set proper height for vertical animation (both mobile and desktop)
12881
- const currentOpen = void 0 !== defaultProps.isOpen ? defaultProps.isOpen : isOpenState;
12875
+ const currentOpen = void 0 !== isOpen ? isOpen : isOpenState;
12882
12876
  // Use requestAnimationFrame to ensure DOM is ready
12883
12877
  requestAnimationFrame((() => {
12884
12878
  wrapperRef.current && innerRef.current && (wrapperRef.current.style.height = currentOpen ? `${innerRef.current.scrollHeight}px` : "0px");
@@ -12892,12 +12886,12 @@ function useHero(initialProps) {
12892
12886
  return window.addEventListener("resize", handleResize), () => {
12893
12887
  clearTimeout(timeoutId), window.removeEventListener("resize", handleResize);
12894
12888
  };
12895
- }), [ defaultProps.collapsible, defaultProps.collapsibleDesktop, defaultProps.isOpen, defaultProps.onToggle, isOpenState ]),
12889
+ }), [ collapsible, collapsibleDesktop, isOpen, onToggle, isOpenState ]),
12896
12890
  // Update wrapper height when open state changes (both mobile and desktop)
12897
12891
  useEffect((() => {
12898
- const shouldCollapse = window.innerWidth < 768 ? defaultProps.collapsible : defaultProps.collapsibleDesktop;
12892
+ const shouldCollapse = window.innerWidth < 768 ? collapsible : collapsibleDesktop;
12899
12893
  if (shouldCollapse && wrapperRef.current && innerRef.current) {
12900
- const currentOpen = void 0 !== defaultProps.isOpen ? defaultProps.isOpen : isOpenState;
12894
+ const currentOpen = void 0 !== isOpen ? isOpen : isOpenState;
12901
12895
  // Use requestAnimationFrame to ensure DOM is ready
12902
12896
  requestAnimationFrame((() => {
12903
12897
  wrapperRef.current && innerRef.current && (wrapperRef.current.style.height = currentOpen ? `${innerRef.current.scrollHeight}px` : "0px");
@@ -12905,26 +12899,25 @@ function useHero(initialProps) {
12905
12899
  } else !shouldCollapse && wrapperRef.current && (
12906
12900
  // Not collapsible - always show content
12907
12901
  wrapperRef.current.style.height = "auto");
12908
- }), [ defaultProps.isOpen, isOpenState, defaultProps.collapsible, defaultProps.collapsibleDesktop ]);
12902
+ }), [ isOpen, isOpenState, collapsible, collapsibleDesktop ]);
12909
12903
  /**
12910
12904
  * Generate side menu class based on properties
12911
12905
  * @param props - Side menu properties
12912
12906
  * @returns Class string
12913
12907
  */
12914
12908
  const handleToggle = () => {
12915
- if (defaultProps.disabled) return;
12916
- const newState = void 0 !== defaultProps.isOpen ? !defaultProps.isOpen : !isOpenState;
12917
- "function" == typeof defaultProps.onToggle ?
12909
+ if (disabled) return;
12910
+ const newState = void 0 !== isOpen ? !isOpen : !isOpenState;
12911
+ "function" == typeof onToggle ?
12918
12912
  // Controlled component
12919
- defaultProps.onToggle(newState) :
12913
+ onToggle(newState) :
12920
12914
  // Uncontrolled component
12921
12915
  setIsOpenState(newState);
12922
- }, getCurrentOpenState = () => void 0 !== defaultProps.isOpen ? defaultProps.isOpen : isOpenState;
12916
+ }, getCurrentOpenState = () => void 0 !== isOpen ? isOpen : isOpenState;
12923
12917
  /**
12924
12918
  * Generate wrapper class
12925
12919
  * @returns Class string
12926
12920
  */ return {
12927
- defaultProps: defaultProps,
12928
12921
  isOpenState: getCurrentOpenState(),
12929
12922
  wrapperRef: wrapperRef,
12930
12923
  innerRef: innerRef,
@@ -13629,7 +13622,7 @@ SelectOption.displayName = "SelectOption";
13629
13622
  /**
13630
13623
  * Select - A component for dropdown selection
13631
13624
  */
13632
- const Select = memo((({options: options, value: value, onChange: onChange, onBlur: onBlur, onFocus: onFocus, placeholder: placeholder = "Select an option", className: className = "", style: style, disabled: disabled = !1, required: required = !1, id: id, name: name, size: size = "md", invalid: invalid = !1, valid: valid = !1, multiple: multiple = !1, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, glass: glass, children: children}) => {
13625
+ const SelectComponentBase = ({options: options, value: value, onChange: onChange, onBlur: onBlur, onFocus: onFocus, placeholder: placeholder = "Select an option", className: className = "", style: style, disabled: disabled = !1, required: required = !1, id: id, name: name, size: size = "md", invalid: invalid = !1, valid: valid = !1, multiple: multiple = !1, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, glass: glass, children: children}) => {
13633
13626
  const {generateSelectClass: generateSelectClass} = useSelect({
13634
13627
  size: size,
13635
13628
  disabled: disabled,
@@ -13820,7 +13813,7 @@ const Select = memo((({options: options, value: value, onChange: onChange, onBl
13820
13813
  });
13821
13814
  }
13822
13815
  return selectContent;
13823
- }));
13816
+ }, Select = memo(SelectComponentBase);
13824
13817
 
13825
13818
  Select.displayName = "Select", Select.Option = SelectOption;
13826
13819
 
@@ -14387,7 +14380,7 @@ Footer.displayName = "Footer";
14387
14380
  */
14388
14381
  const MasonryGrid = forwardRef((({children: children, className: className = "", xs: xs = 1, sm: sm, md: md, lg: lg, xl: xl, xxl: xxl, gap: gap = 16, animate: animate = !0, imagesLoaded: imagesLoaded = !0, onLayoutComplete: onLayoutComplete, onImageLoad: onImageLoad, ...props}, ref) => {
14389
14382
  // === REFS & STATE ===
14390
- const [columns, setColumns] = useState(xs), [positions, setPositions] = useState([]), [layoutComplete, setLayoutComplete] = useState(!1), [loadingImages, setLoadingImages] = useState(!1), containerRef = useRef(null), columnHeights = useRef([]), imagesLoadedCount = useRef(0), totalImagesCount = useRef(0), imageElements = useRef(new Map);
14383
+ const [columns, setColumns] = useState(xs), [positions, setPositions] = useState([]), [, setLayoutComplete] = useState(!1), [loadingImages, setLoadingImages] = useState(!1), containerRef = useRef(null), columnHeights = useRef([]), imagesLoadedCount = useRef(0), totalImagesCount = useRef(0), imageElements = useRef(new Map);
14391
14384
  useEffect((() => {
14392
14385
  setLoadingImages(!!imagesLoaded);
14393
14386
  }), [ columns, imagesLoaded ]),
@@ -14416,34 +14409,45 @@ const MasonryGrid = forwardRef((({children: children, className: className = ""
14416
14409
  });
14417
14410
  })), setItems(newItems);
14418
14411
  }), [ children ]);
14419
- // === TRACK & MANAGE IMAGES ===
14420
- const handleImageLoad = useCallback((img => {
14421
- if (!imageElements.current.get(img)) {
14422
- // Add loaded class for animation
14423
- if (imageElements.current.set(img, !0), imagesLoadedCount.current += 1, containerRef.current && imagesLoaded) {
14424
- const itemElement = img.closest(".o-masonry-grid > div");
14425
- itemElement && (itemElement.offsetHeight, itemElement.classList.add("o-masonry-grid__item-loaded"),
14426
- itemElement.classList.remove("o-masonry-grid__item-loading"));
14412
+ // === MANAGE ITEM LAYOUT ===
14413
+ const calculateLayout = useCallback((() => {
14414
+ if (!containerRef.current || 0 === items.length) return;
14415
+ const colWidth = (containerRef.current.offsetWidth - gap * (columns - 1)) / columns;
14416
+ columnHeights.current = Array(columns).fill(0);
14417
+ const newPositions = [];
14418
+ items.forEach(((item, index) => {
14419
+ if (item.ref.current) {
14420
+ // Find the shortest column
14421
+ const shortestCol = columnHeights.current.indexOf(Math.min(...columnHeights.current)), left = shortestCol * (colWidth + gap), top = columnHeights.current[shortestCol] ?? 0, height = item.ref.current.offsetHeight;
14422
+ columnHeights.current[shortestCol] = top + height + gap, newPositions[index] = {
14423
+ left: left,
14424
+ top: top,
14425
+ width: colWidth,
14426
+ height: height
14427
+ };
14427
14428
  }
14428
- // Ensure layout is recalculated after DOM paints the item image (prevents overlap on slow/late image loads)
14429
- requestAnimationFrame((() => {
14430
- requestAnimationFrame((() => {
14431
- calculateLayout();
14432
- }));
14433
- })), onImageLoad?.(imagesLoadedCount.current, totalImagesCount.current),
14434
- // If all images have loaded, update loading state and complete layout
14435
- imagesLoadedCount.current >= totalImagesCount.current && totalImagesCount.current > 0 && (setLayoutComplete(!0),
14436
- setLoadingImages(!1), // This ensures the loading class is removed *immediately* after images load
14437
- // Force a double requestAnimationFrame for final layout calculation after all images are loaded (guarantees DOM paint)
14438
- requestAnimationFrame((() => {
14439
- requestAnimationFrame((() => {
14440
- calculateLayout(),
14441
- // As a failsafe, if still present for some render lag, force another setLoadingImages(false)
14442
- setLoadingImages(!1);
14443
- }));
14444
- })), onLayoutComplete?.());
14429
+ })), setPositions(newPositions);
14430
+ }), [ items, columns, gap ]), handleImageLoad = useCallback((img => {
14431
+ if (imageElements.current.get(img)) return;
14432
+ // Add loaded class for animation
14433
+ if (imageElements.current.set(img, !0), imagesLoadedCount.current += 1, containerRef.current && imagesLoaded) {
14434
+ const itemElement = img.closest(".o-masonry-grid > div");
14435
+ itemElement && (itemElement.offsetHeight, itemElement.classList.add("o-masonry-grid__item-loaded"),
14436
+ itemElement.classList.remove("o-masonry-grid__item-loading"));
14445
14437
  }
14446
- }), [ onImageLoad, onLayoutComplete, imagesLoaded ]), trackImages = useCallback((() => {
14438
+ // Schedule layout recalculation after next paint to prevent overlap
14439
+ const scheduleLayoutUpdate = () => {
14440
+ const frameId = requestAnimationFrame((() => {
14441
+ onImageLoad?.(imagesLoadedCount.current, totalImagesCount.current), calculateLayout();
14442
+ }));
14443
+ return () => cancelAnimationFrame(frameId);
14444
+ }, cleanup = scheduleLayoutUpdate();
14445
+ // Clean up previous scheduled updates
14446
+ // If all images have loaded, update loading state and complete layout
14447
+ imagesLoadedCount.current >= totalImagesCount.current && totalImagesCount.current > 0 && (setLayoutComplete(!0),
14448
+ setLoadingImages(!1), setTimeout((() => cleanup()), 0), // Clean up after current execution
14449
+ scheduleLayoutUpdate(), onLayoutComplete?.());
14450
+ }), [ onImageLoad, onLayoutComplete, imagesLoaded, calculateLayout ]), trackImages = useCallback((() => {
14447
14451
  if (!imagesLoaded || !containerRef.current) return;
14448
14452
  imageElements.current.clear(), imagesLoadedCount.current = 0;
14449
14453
  const images = containerRef.current.querySelectorAll("img");
@@ -14462,30 +14466,21 @@ const MasonryGrid = forwardRef((({children: children, className: className = ""
14462
14466
  img.removeEventListener("error", masonryImg._masonryLoadHandler), delete masonryImg._masonryLoadHandler);
14463
14467
  }));
14464
14468
  });
14465
- }), [ imagesLoaded, handleImageLoad, onLayoutComplete ]), calculateLayout = useCallback((() => {
14466
- if (!containerRef.current || 0 === items.length) return;
14467
- const colWidth = (containerRef.current.offsetWidth - gap * (columns - 1)) / columns;
14468
- columnHeights.current = Array(columns).fill(0);
14469
- const newPositions = [];
14470
- items.forEach(((item, index) => {
14471
- if (item.ref.current) {
14472
- // Find the shortest column
14473
- const shortestCol = columnHeights.current.indexOf(Math.min(...columnHeights.current)), left = shortestCol * (colWidth + gap), top = columnHeights.current[shortestCol] ?? 0, height = item.ref.current.offsetHeight;
14474
- columnHeights.current[shortestCol] = top + height + gap, newPositions[index] = {
14475
- left: left,
14476
- top: top,
14477
- width: colWidth,
14478
- height: height
14479
- };
14480
- }
14481
- })), setPositions(newPositions);
14482
- }), [ items, columns, gap ]);
14483
- // === OBSERVE CONTAINER RESIZE ===
14469
+ }), [ imagesLoaded, handleImageLoad, onLayoutComplete ]);
14470
+ // === TRACK & MANAGE IMAGES ===
14471
+ // === OBSERVE CONTAINER RESIZE ===
14484
14472
  useEffect((() => {
14485
14473
  if (!containerRef.current) return;
14486
- let animationFrame = null;
14487
- const observer = new ResizeObserver((() => {
14488
- animationFrame && cancelAnimationFrame(animationFrame), animationFrame = requestAnimationFrame((() => calculateLayout()));
14474
+ let animationFrame = null, lastWidth = 0;
14475
+ const observer = new ResizeObserver((entries => {
14476
+ const entry = entries[0];
14477
+ if (!entry) return;
14478
+ const currentWidth = entry.contentRect.width;
14479
+ // Only recalculate if width actually changed (prevents excessive calculations)
14480
+ Math.abs(currentWidth - lastWidth) > 1 && (animationFrame && cancelAnimationFrame(animationFrame),
14481
+ animationFrame = requestAnimationFrame((() => {
14482
+ calculateLayout(), lastWidth = currentWidth;
14483
+ })));
14489
14484
  }));
14490
14485
  return observer.observe(containerRef.current), () => {
14491
14486
  observer.disconnect(), animationFrame && cancelAnimationFrame(animationFrame);
@@ -14496,24 +14491,21 @@ const MasonryGrid = forwardRef((({children: children, className: className = ""
14496
14491
  setLayoutComplete(!0), void setLoadingImages(!1))
14497
14492
  // Only reset layoutComplete when items or columns change
14498
14493
  ), [ items, columns, calculateLayout, imagesLoaded, trackImages ]),
14499
- // === NEW: Add ResizeObservers to all grid items for bulletproof image+content measurement ===
14494
+ // === ADD RESIZEOBSERVERS TO GRID ITEMS FOR DYNAMIC CONTENT MEASUREMENT ===
14500
14495
  React.useEffect((() => {
14501
- // Clean up old observers if items ever change
14502
14496
  const observers = [];
14497
+ let animationFrame = null;
14498
+ // Debounced layout calculation for item resize events
14499
+ const debouncedCalculateLayout = () => {
14500
+ animationFrame && cancelAnimationFrame(animationFrame), animationFrame = requestAnimationFrame(calculateLayout);
14501
+ };
14503
14502
  return items.forEach((item => {
14504
14503
  if (item.ref.current) {
14505
- const obs = new ResizeObserver((() => {
14506
- // Double rAF: ensures layout only runs after DOM/paint/async renders
14507
- requestAnimationFrame((() => {
14508
- requestAnimationFrame((() => {
14509
- calculateLayout();
14510
- }));
14511
- }));
14512
- }));
14504
+ const obs = new ResizeObserver(debouncedCalculateLayout);
14513
14505
  obs.observe(item.ref.current), observers.push(obs);
14514
14506
  }
14515
14507
  })), () => {
14516
- observers.forEach((obs => obs.disconnect()));
14508
+ observers.forEach((obs => obs.disconnect())), animationFrame && cancelAnimationFrame(animationFrame);
14517
14509
  };
14518
14510
  }), [ items, calculateLayout ]);
14519
14511
  // Ensure loadingImages state resets when items/columns/imagesLoaded change
@@ -15950,12 +15942,12 @@ const SideMenu = forwardRef((({title: title, children: children, menuItems: men
15950
15942
  const index = Number(key);
15951
15943
  index >= currentLength && (delete nestedWrapperRefs.current[index], delete nestedInnerRefs.current[index]);
15952
15944
  })));
15953
- }), [ menuItems?.length ]);
15945
+ }), [ menuItems ]);
15954
15946
  // Helper function to update nested wrapper height
15955
- const updateNestedHeight = (index, isOpen) => {
15947
+ const updateNestedHeight = useCallback(((index, isOpen) => {
15956
15948
  const wrapper = nestedWrapperRefs.current[index], inner = nestedInnerRefs.current[index];
15957
15949
  wrapper && inner && (wrapper.style.height = isOpen ? `${inner.scrollHeight}px` : "0px");
15958
- };
15950
+ }), []);
15959
15951
  // Set initial heights for nested wrappers on mount and when menuItems change
15960
15952
  useEffect((() => {
15961
15953
  if (!menuItems?.length) return;
@@ -15969,7 +15961,7 @@ const SideMenu = forwardRef((({title: title, children: children, menuItems: men
15969
15961
  // Only run when menuItems change, nestedItemStates is read but not in deps to avoid loops
15970
15962
  // eslint-disable-next-line react-hooks/exhaustive-deps
15971
15963
  ;
15972
- }), [ menuItems?.length ]),
15964
+ }), [ menuItems, updateNestedHeight ]),
15973
15965
  // Update nested wrapper heights when state changes
15974
15966
  useEffect((() => {
15975
15967
  if (!menuItems?.length) return;
@@ -15982,7 +15974,7 @@ const SideMenu = forwardRef((({title: title, children: children, menuItems: men
15982
15974
  })), () => {
15983
15975
  frameIds.forEach((id => cancelAnimationFrame(id)));
15984
15976
  };
15985
- }), [ nestedItemStates, menuItems?.length ]);
15977
+ }), [ nestedItemStates, menuItems, updateNestedHeight ]);
15986
15978
  // Combine refs using utility
15987
15979
  const combinedRef = useForkRef(sideMenuRef, ref), sideMenuClass = generateSideMenuClass({
15988
15980
  className: className,
@@ -16869,7 +16861,7 @@ useEffect((() => {
16869
16861
  }
16870
16862
  };
16871
16863
  }));
16872
- }), [ isMounted, currentIndex, calculateBounds, constrainPosition ]), setImagePosition = useCallback((position => {
16864
+ }), [ currentIndex, calculateBounds, constrainPosition ]), setImagePosition = useCallback((position => {
16873
16865
  setImageStates((prev => {
16874
16866
  const currentState = prev[currentIndex] || {
16875
16867
  zoomLevel: 1,
@@ -16919,7 +16911,7 @@ useEffect((() => {
16919
16911
  }
16920
16912
  };
16921
16913
  }));
16922
- }), [ isMounted, currentIndex, calculateBounds, constrainPosition ]), handleWheel = useCallback((event => {
16914
+ }), [ currentIndex, calculateBounds, constrainPosition ]), handleWheel = useCallback((event => {
16923
16915
  var _context;
16924
16916
  if (!isMounted || !event || !event.currentTarget) return;
16925
16917
  // Additional safety check for the target element
@@ -17276,7 +17268,7 @@ useEffect((() => {
17276
17268
  }
17277
17269
  return prev;
17278
17270
  }));
17279
- }), [ isMounted, enableGestures, isDragging, startDragPosition, currentIndex, constrainPosition, calculateBounds ]), handleTouchEnd = useCallback((() => {
17271
+ }), [ enableGestures, isDragging, startDragPosition, currentIndex, constrainPosition, calculateBounds ]), handleTouchEnd = useCallback((() => {
17280
17272
  setIsDragging(!1), lastDistanceRef.current = null, lastMidpointRef.current = null;
17281
17273
  }), []), currentState = imageStates[currentIndex] || {
17282
17274
  zoomLevel: 1,
@@ -17480,9 +17472,9 @@ const PopoverContext = createContext({
17480
17472
  triggerType: "click"
17481
17473
  }), Popover = ({content: content, position: position = "top", trigger: trigger = "click", className: className = "", style: style, delay: delay = 0, offset: offset = 12, defaultOpen: defaultOpen = !1, isOpen: controlledIsOpen, onOpenChange: onOpenChange, closeOnClickOutside: closeOnClickOutside = !0, closeOnEscape: closeOnEscape = !0, id: id, children: children, glass: glass}) => {
17482
17474
  const {isOpen: isOpen, setIsOpen: setIsOpen, triggerRef: triggerRef, popoverRef: popoverRef, arrowRef: arrowRef, popoverId: popoverId, currentPosition: currentPosition, updatePosition: updatePosition} = (({position: position = "top", trigger: trigger = "click", offset: offset = 12, delay: delay = 0, defaultOpen: defaultOpen = !1, isOpen: controlledIsOpen, onOpenChange: onOpenChange, closeOnClickOutside: closeOnClickOutside = !0, closeOnEscape: closeOnEscape = !0, id: id}) => {
17483
- const [isOpen, setIsOpenState] = useState(defaultOpen), [currentPosition, setCurrentPosition] = useState("auto" === position ? "top" : position), triggerRef = useRef(null), popoverRef = useRef(null), arrowRef = useRef(null), timeoutRef = useRef(null), popoverId = id || `popover-${Math.random().toString(36).slice(2, 11)}`, isControlled = void 0 !== controlledIsOpen, isOpenState = isControlled ? controlledIsOpen : isOpen, setIsOpen = newIsOpen => {
17475
+ const [isOpen, setIsOpenState] = useState(defaultOpen), [currentPosition, setCurrentPosition] = useState("auto" === position ? "top" : position), triggerRef = useRef(null), popoverRef = useRef(null), arrowRef = useRef(null), timeoutRef = useRef(null), popoverId = id || `popover-${Math.random().toString(36).slice(2, 11)}`, isControlled = void 0 !== controlledIsOpen, isOpenState = isControlled ? controlledIsOpen : isOpen, setIsOpen = useCallback((newIsOpen => {
17484
17476
  isControlled || setIsOpenState(newIsOpen), onOpenChange && onOpenChange(newIsOpen);
17485
- };
17477
+ }), [ isControlled, onOpenChange ]);
17486
17478
  // Handle hover events if trigger is hover
17487
17479
  useEffect((() => {
17488
17480
  if ("hover" !== trigger || !triggerRef.current || !popoverRef.current) return;
@@ -17502,17 +17494,16 @@ const PopoverContext = createContext({
17502
17494
  setIsOpen(!1);
17503
17495
  };
17504
17496
  // Add hover event listeners
17505
- return triggerRef.current.addEventListener("mouseenter", handleTriggerMouseEnter),
17506
- triggerRef.current.addEventListener("mouseleave", handleTriggerMouseLeave), popoverRef.current.addEventListener("mouseenter", handlePopoverMouseEnter),
17507
- popoverRef.current.addEventListener("mouseleave", handlePopoverMouseLeave), () => {
17508
- triggerRef.current && (triggerRef.current.removeEventListener("mouseenter", handleTriggerMouseEnter),
17509
- triggerRef.current.removeEventListener("mouseleave", handleTriggerMouseLeave)),
17510
- popoverRef.current && (popoverRef.current.removeEventListener("mouseenter", handlePopoverMouseEnter),
17511
- popoverRef.current.removeEventListener("mouseleave", handlePopoverMouseLeave)),
17512
- null !== timeoutRef.current && window.clearTimeout(timeoutRef.current);
17497
+ triggerRef.current.addEventListener("mouseenter", handleTriggerMouseEnter), triggerRef.current.addEventListener("mouseleave", handleTriggerMouseLeave),
17498
+ popoverRef.current.addEventListener("mouseenter", handlePopoverMouseEnter), popoverRef.current.addEventListener("mouseleave", handlePopoverMouseLeave);
17499
+ const currentTrigger = triggerRef.current, currentPopover = popoverRef.current;
17500
+ return () => {
17501
+ currentTrigger && (currentTrigger.removeEventListener("mouseenter", handleTriggerMouseEnter),
17502
+ currentTrigger.removeEventListener("mouseleave", handleTriggerMouseLeave)), currentPopover && (currentPopover.removeEventListener("mouseenter", handlePopoverMouseEnter),
17503
+ currentPopover.removeEventListener("mouseleave", handlePopoverMouseLeave)), null !== timeoutRef.current && window.clearTimeout(timeoutRef.current);
17513
17504
  };
17514
- }), [ trigger, delay, isOpenState ]);
17515
- const updatePosition = event => {
17505
+ }), [ trigger, delay, isOpenState, setIsOpen ]);
17506
+ const updatePosition = useCallback((event => {
17516
17507
  if (!triggerRef.current || !popoverRef.current) return;
17517
17508
  const triggerRect = triggerRef.current.getBoundingClientRect(), popoverRect = popoverRef.current.getBoundingClientRect(), viewportWidth = window.innerWidth, viewportHeight = window.innerHeight, isNearViewportEdge = triggerRect.top < 50 || triggerRect.bottom > viewportHeight - 50 || triggerRect.left < 50 || triggerRect.right > viewportWidth - 50;
17518
17509
  // If this is a scroll update and trigger isn't near edges, skip repositioning
@@ -17573,9 +17564,9 @@ const PopoverContext = createContext({
17573
17564
  // Add scroll position to convert viewport coordinates to absolute position
17574
17565
  const absoluteTop = top + window.scrollY, absoluteLeft = left + window.scrollX;
17575
17566
  // Apply position using absolute positioning to follow when scrolling
17576
- popoverRef.current.style.position = "absolute", popoverRef.current.style.top = `${absoluteTop}px`,
17577
- popoverRef.current.style.left = `${absoluteLeft}px`;
17578
- };
17567
+ popoverRef.current && (popoverRef.current.style.position = "absolute", popoverRef.current.style.top = `${absoluteTop}px`,
17568
+ popoverRef.current.style.left = `${absoluteLeft}px`);
17569
+ }), [ position, offset ]);
17579
17570
  // Position the popover
17580
17571
  return useEffect((() => {
17581
17572
  if (!isOpenState || !triggerRef.current || !popoverRef.current) return;
@@ -17601,7 +17592,7 @@ const PopoverContext = createContext({
17601
17592
  window.removeEventListener("resize", updatePosition), window.removeEventListener("scroll", handleScroll),
17602
17593
  scrollTimeout && clearTimeout(scrollTimeout), clearInterval(intervalId);
17603
17594
  };
17604
- }), [ isOpenState, position, offset ]),
17595
+ }), [ isOpenState, updatePosition ]),
17605
17596
  // Handle click outside to close popover
17606
17597
  useEffect((() => {
17607
17598
  if (!isOpenState || !closeOnClickOutside) return;
@@ -17611,7 +17602,7 @@ const PopoverContext = createContext({
17611
17602
  return document.addEventListener("mousedown", handleClickOutside), () => {
17612
17603
  document.removeEventListener("mousedown", handleClickOutside);
17613
17604
  };
17614
- }), [ isOpenState, closeOnClickOutside ]),
17605
+ }), [ isOpenState, closeOnClickOutside, setIsOpen ]),
17615
17606
  // Handle escape key to close popover
17616
17607
  useEffect((() => {
17617
17608
  if (!isOpenState || !closeOnEscape) return;
@@ -17621,7 +17612,7 @@ const PopoverContext = createContext({
17621
17612
  return document.addEventListener("keydown", handleEscapeKey), () => {
17622
17613
  document.removeEventListener("keydown", handleEscapeKey);
17623
17614
  };
17624
- }), [ isOpenState, closeOnEscape ]),
17615
+ }), [ isOpenState, closeOnEscape, setIsOpen ]),
17625
17616
  // Clean up on unmount
17626
17617
  useEffect((() => () => {
17627
17618
  null !== timeoutRef.current && window.clearTimeout(timeoutRef.current);
@@ -17802,10 +17793,11 @@ const calculateStarValue = (e, starValue, allowHalf) => {
17802
17793
  }), [ readOnly, onChange, allowHalf ]);
17803
17794
  // Use vanilla JS implementation if specified
17804
17795
  useEffect((() => {
17805
- if (useVanillaJS && "undefined" != typeof window && internalRef.current)
17796
+ if (!useVanillaJS || "undefined" == typeof window || !internalRef.current) return;
17797
+ const currentInstance = ratingInstance.current;
17806
17798
  // Cleanup on unmount
17807
- return () => {
17808
- ratingInstance.current && ratingInstance.current.destroy();
17799
+ return () => {
17800
+ currentInstance && currentInstance.destroy();
17809
17801
  };
17810
17802
  }), [ useVanillaJS, valueProp, defaultValue, maxValue, allowHalf, readOnly, size, variant, onChange ]),
17811
17803
  // Update vanilla JS implementation when props change
@@ -17926,10 +17918,11 @@ const ProductReview = ({productName: productName, productImage: productImage, in
17926
17918
  const [rating, setRating] = useState(initialRating), [comment, setComment] = useState(""), [submitted, setSubmitted] = useState(!1), reviewRef = useRef(null), reviewInstance = useRef(null);
17927
17919
  useEffect((() => {
17928
17920
  // Only run on client-side
17929
- if ("undefined" != typeof window && reviewRef.current)
17921
+ if ("undefined" == typeof window || !reviewRef.current) return;
17922
+ const currentInstance = reviewInstance.current;
17930
17923
  // Cleanup on unmount
17931
- return () => {
17932
- reviewInstance.current && reviewInstance.current.destroy();
17924
+ return () => {
17925
+ currentInstance && currentInstance.destroy();
17933
17926
  };
17934
17927
  }), [ productName, productImage, initialRating, maxRating, allowHalf, ratingColor, onSubmit ]);
17935
17928
  const handleSubmit = e => {
@@ -18174,10 +18167,11 @@ const SectionIntro = ({title: title, label: label, text: text, actions: actions,
18174
18167
  const sectionIntroRef = useRef(null), sectionIntroInstance = useRef(null);
18175
18168
  useEffect((() => {
18176
18169
  // Only run on client-side
18177
- if ("undefined" != typeof window && sectionIntroRef.current)
18170
+ if ("undefined" == typeof window || !sectionIntroRef.current) return;
18171
+ const currentInstance = sectionIntroInstance.current;
18178
18172
  // Cleanup on unmount
18179
- return () => {
18180
- sectionIntroInstance.current && sectionIntroInstance.current.destroy();
18173
+ return () => {
18174
+ currentInstance && currentInstance.destroy();
18181
18175
  };
18182
18176
  }), [ alignment, backgroundImageSrc, showOverlay, size, skeleton ]);
18183
18177
  // Determine CSS classes
@@ -18261,7 +18255,7 @@ SectionIntro.displayName = "SectionIntro";
18261
18255
 
18262
18256
  const Slider = forwardRef(((props, ref) => {
18263
18257
  const {slides: slides = [], height: height = 300, width: width = "100%", slidesToShow: slidesToShow = 1, spaceBetween: spaceBetween = 0, loop: loop = !1, initialSlide: initialSlide = 0, direction: direction = "horizontal", speed: speed = 300, allowTouchMove: allowTouchMove = !0, threshold: threshold = 50, grabCursor: grabCursor = !0, autoplay: autoplay, navigation: navigation, pagination: pagination, className: className, style: style, onSlideChange: onSlideChange, ...rest} = props, validSlides = Array.isArray(slides) ? slides : [], slider = function(options) {
18264
- const {slides: rawSlides, slidesToShow: slidesToShow = 1, spaceBetween: spaceBetween = 0, loop: loop = !1, initialSlide: initialSlide = 0, direction: direction = "horizontal", speed: speed = 300, allowTouchMove: allowTouchMove = !0, threshold: threshold = 50, autoplay: autoplay, onSlideChange: onSlideChange} = options, slides = Array.isArray(rawSlides) ? rawSlides : [], containerRef = useRef(null), wrapperRef = useRef(null), repositioningRef = useRef(!1), autoplayRef = useRef(null), [autoplayRunning, setAutoplayRunning] = useState(!1), sliderStateRef = useRef({
18258
+ 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 = useMemo((() => Array.isArray(rawSlides) ? rawSlides : []), [ rawSlides ]), containerRef = useRef(null), wrapperRef = useRef(null), repositioningRef = useRef(!1), autoplayRef = useRef(null), [autoplayRunning, setAutoplayRunning] = useState(!1), sliderStateRef = useRef({
18265
18259
  isTransitioning: !1,
18266
18260
  loop: loop,
18267
18261
  slides: slides,
@@ -18396,7 +18390,7 @@ const Slider = forwardRef(((props, ref) => {
18396
18390
  setIsTransitioning(!1), onSlideChange?.(nextIndex);
18397
18391
  }), speed);
18398
18392
  }
18399
- }), [ realIndex, internalIndex, slides.length, slidesToShow, loop, isTransitioning, speed, onSlideChange, allSlides.length, loopedSlides, autoplay ]), slidePrev = useCallback((() => {
18393
+ }), [ realIndex, internalIndex, slides.length, slidesToShow, loop, isTransitioning, speed, onSlideChange, autoplay ]), slidePrev = useCallback((() => {
18400
18394
  if (!isTransitioning) if (
18401
18395
  // Stop autoplay on interaction if disableOnInteraction is true
18402
18396
  autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
@@ -18418,7 +18412,7 @@ const Slider = forwardRef(((props, ref) => {
18418
18412
  setIsTransitioning(!1), onSlideChange?.(prevIndex);
18419
18413
  }), speed);
18420
18414
  }
18421
- }), [ realIndex, internalIndex, slides.length, loop, isTransitioning, speed, onSlideChange, allSlides.length, loopedSlides, autoplay ]), goToSlide = useCallback((index => {
18415
+ }), [ realIndex, internalIndex, slides.length, loop, isTransitioning, speed, onSlideChange, autoplay ]), goToSlide = useCallback((index => {
18422
18416
  isTransitioning || index === realIndex || (
18423
18417
  // Stop autoplay on interaction if disableOnInteraction is true
18424
18418
  autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
@@ -18426,7 +18420,7 @@ const Slider = forwardRef(((props, ref) => {
18426
18420
  setRealIndex(index), setInternalIndex(loop ? slides.length + index : index), setTimeout((() => {
18427
18421
  setIsTransitioning(!1), onSlideChange?.(index);
18428
18422
  }), speed));
18429
- }), [ realIndex, isTransitioning, speed, onSlideChange, loop, loopedSlides, autoplay ]), handleTouchStart = useCallback((e => {
18423
+ }), [ realIndex, isTransitioning, speed, onSlideChange, loop, slides.length, autoplay ]), handleTouchStart = useCallback((e => {
18430
18424
  if (!allowTouchMove) return;
18431
18425
  // Stop autoplay on interaction if disableOnInteraction is true
18432
18426
  autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
@@ -18681,7 +18675,7 @@ const Steps = ({items: items, activeIndex: activeIndex = 0, vertical: vertical =
18681
18675
  let content;
18682
18676
  useEffect((() => {
18683
18677
  currentStep !== activeIndex && setCurrentStep(activeIndex);
18684
- }), [ activeIndex ]),
18678
+ }), [ activeIndex, currentStep ]),
18685
18679
  // Legacy rendering
18686
18680
  content = items && items.length > 0 ? items.map(((item, index) => jsx(StepsItem, {
18687
18681
  index: index,
@@ -18953,10 +18947,11 @@ const Testimonial = ({quote: quote, author: author, size: size = "", skeleton: s
18953
18947
  const testimonialRef = useRef(null), testimonialInstance = useRef(null);
18954
18948
  useEffect((() => {
18955
18949
  // Only run on client-side
18956
- if ("undefined" != typeof window && testimonialRef.current)
18950
+ if ("undefined" == typeof window || !testimonialRef.current) return;
18951
+ const currentInstance = testimonialInstance.current;
18957
18952
  // Cleanup on unmount
18958
- return () => {
18959
- testimonialInstance.current && testimonialInstance.current.destroy();
18953
+ return () => {
18954
+ currentInstance && currentInstance.destroy();
18960
18955
  };
18961
18956
  }), [ size, skeleton ]);
18962
18957
  // Determine CSS classes
@@ -20097,11 +20092,13 @@ const VideoPlayer = forwardRef((({src: src, type: type = "video", youtubeId: yo
20097
20092
  detectBorderRadius();
20098
20093
  // Create ResizeObserver to watch for style changes
20099
20094
  let resizeObserver = null;
20100
- return "undefined" != typeof ResizeObserver && containerRef.current && (resizeObserver = new ResizeObserver(detectBorderRadius),
20095
+ "undefined" != typeof ResizeObserver && containerRef.current && (resizeObserver = new ResizeObserver(detectBorderRadius),
20101
20096
  resizeObserver.observe(containerRef.current)),
20102
20097
  // Also listen for window resize (in case styles change)
20103
- window.addEventListener("resize", detectBorderRadius), () => {
20104
- window.removeEventListener("resize", detectBorderRadius), resizeObserver && containerRef.current && (resizeObserver.unobserve(containerRef.current),
20098
+ window.addEventListener("resize", detectBorderRadius);
20099
+ const currentContainer = containerRef.current;
20100
+ return () => {
20101
+ window.removeEventListener("resize", detectBorderRadius), resizeObserver && currentContainer && (resizeObserver.unobserve(currentContainer),
20105
20102
  resizeObserver.disconnect());
20106
20103
  };
20107
20104
  }), []);
@@ -22441,7 +22438,7 @@ const logger = getLogger(), ThemeProvider = ({children: children, defaultTheme:
22441
22438
  // If defaultTheme is provided, use it
22442
22439
  return null != defaultTheme ? defaultTheme : "default";
22443
22440
  // Default fallback
22444
- }), [ defaultTheme, enablePersistence, storageKey ]), [currentTheme, setCurrentTheme] = useState((() => "string" == typeof initialDefaultTheme ? initialDefaultTheme : "tokens-theme")), [activeTokens, setActiveTokens] = useState((() => {
22441
+ }), [ defaultTheme, enablePersistence, storageKey, storageAdapter ]), [currentTheme, setCurrentTheme] = useState((() => "string" == typeof initialDefaultTheme ? initialDefaultTheme : "tokens-theme")), [activeTokens, setActiveTokens] = useState((() => {
22445
22442
  // If defaultTheme is DesignTokens, validate and store them
22446
22443
  if (defaultTheme && "string" != typeof defaultTheme) {
22447
22444
  const {tokens: tokens, validation: validation} = validateAndMergeTokens(defaultTheme);
@@ -23742,7 +23739,7 @@ class ThemeValidator {
23742
23739
  *
23743
23740
  * Provides detailed inspection and debugging information for themes
23744
23741
  */ const ThemeInspector = ({theme: theme, showValidation: showValidation = !0, showCSSVariables: showCSSVariables = !0, showStructure: showStructure = !0, className: className, style: style}) => {
23745
- const [activeTab, setActiveTab] = useState("overview"), [expandedSections, setExpandedSections] = useState(new Set([ "palette" ])), [searchQuery, setSearchQuery] = useState(""), [debouncedSearchQuery, setDebouncedSearchQuery] = useState(""), [copiedPath, setCopiedPath] = useState(null), searchTimeoutRef = useRef();
23742
+ const [activeTab, setActiveTab] = useState("overview"), [expandedSections, setExpandedSections] = useState(new Set([ "palette" ])), [searchQuery, setSearchQuery] = useState(""), [debouncedSearchQuery, setDebouncedSearchQuery] = useState(""), [copiedPath, setCopiedPath] = useState(null), searchTimeoutRef = useRef(void 0);
23746
23743
  // Debounce search query
23747
23744
  useEffect((() => (searchTimeoutRef.current && clearTimeout(searchTimeoutRef.current),
23748
23745
  searchTimeoutRef.current = setTimeout((() => {
@@ -24148,7 +24145,7 @@ class ThemeValidator {
24148
24145
  }) ]
24149
24146
  });
24150
24147
  }, ThemeComparator = ({themeA: themeA, themeB: themeB, showOnlyDifferences: showOnlyDifferences = !1, className: className, style: style}) => {
24151
- const [searchQuery, setSearchQuery] = useState(""), [debouncedSearchQuery, setDebouncedSearchQuery] = useState(""), [filterType, setFilterType] = useState("all"), [filterCategory, setFilterCategory] = useState("all"), searchTimeoutRef = useRef();
24148
+ const [searchQuery, setSearchQuery] = useState(""), [debouncedSearchQuery, setDebouncedSearchQuery] = useState(""), [filterType, setFilterType] = useState("all"), [filterCategory, setFilterCategory] = useState("all"), searchTimeoutRef = useRef(void 0);
24152
24149
  // Debounce search query
24153
24150
  useEffect((() => (searchTimeoutRef.current && clearTimeout(searchTimeoutRef.current),
24154
24151
  searchTimeoutRef.current = setTimeout((() => {
@@ -24944,7 +24941,7 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
24944
24941
  } catch (err) {
24945
24942
  setError(err instanceof Error ? err.message : "Invalid JSON");
24946
24943
  }
24947
- }), [ updateTheme ]), jsonUpdateTimeoutRef = useRef();
24944
+ }), [ updateTheme ]), jsonUpdateTimeoutRef = useRef(void 0);
24948
24945
  // Debounced JSON update to history
24949
24946
  useEffect((() => {
24950
24947
  if (!error) {
@@ -26151,97 +26148,6 @@ function getComponentCSSVars(component) {
26151
26148
  } : base : override;
26152
26149
  }
26153
26150
 
26154
- /**
26155
- * Render a slot with the given props
26156
- *
26157
- * Priority order:
26158
- * 1. render function
26159
- * 2. component
26160
- * 3. children
26161
- * 4. fallback
26162
- *
26163
- * @example
26164
- * renderSlot(
26165
- * { render: (props) => <CustomButton {...props} /> },
26166
- * { onClick: handleClick, children: 'Click me' }
26167
- * )
26168
- */ function renderSlot(slot, props, fallback) {
26169
- // No slot provided, use fallback
26170
- if (!slot) return fallback;
26171
- // Slot is a plain React node
26172
- if ( React.isValidElement(slot) || "string" == typeof slot || "number" == typeof slot) return slot;
26173
- // Slot is an object with rendering options
26174
- if ("object" == typeof slot && null !== slot) {
26175
- const slotObj = slot;
26176
- // Priority 1: render function
26177
- if (slotObj.render && "function" == typeof slotObj.render) return slotObj.render(props);
26178
- // Priority 2: component
26179
- if (slotObj.component) {
26180
- const Component = slotObj.component;
26181
- return jsx(Component, {
26182
- ...props
26183
- });
26184
- }
26185
- // Priority 3: children
26186
- if (void 0 !== slotObj.children) return slotObj.children;
26187
- }
26188
- // Fallback
26189
- return fallback;
26190
- }
26191
-
26192
- /**
26193
- * Check if a value is a slot configuration
26194
- */ function isSlot(value) {
26195
- return "object" == typeof value && null !== value && ("render" in value || "component" in value || "children" in value);
26196
- }
26197
-
26198
- /**
26199
- * Merge multiple slot configurations
26200
- * Later slots override earlier ones
26201
- */ function mergeSlots(...slots) {
26202
- const filtered = slots.filter((s => void 0 !== s));
26203
- if (0 !== filtered.length) return 1 === filtered.length ? filtered[0] : _reduceInstanceProperty(filtered).call(filtered, ((acc, slot) => ({
26204
- ...acc,
26205
- ...slot
26206
- })));
26207
- }
26208
-
26209
- /**
26210
- * Create a slot wrapper component
26211
- *
26212
- * @example
26213
- * const ButtonSlot = createSlotComponent<ButtonSlotProps>('button')
26214
- *
26215
- * <ButtonSlot slot={customSlot} {...props}>
26216
- * Default content
26217
- * </ButtonSlot>
26218
- */ function createSlotComponent(defaultElement = "div") {
26219
- return function({slot: slot, children: children, ...props}) {
26220
- const slotProps = props;
26221
- return slot ? jsx(Fragment, {
26222
- children: renderSlot(slot, slotProps, children)
26223
- }) : jsx(defaultElement, "string" == typeof defaultElement ? {
26224
- ...props,
26225
- children: children
26226
- } : {
26227
- ...slotProps,
26228
- children: children
26229
- });
26230
- };
26231
- }
26232
-
26233
- /**
26234
- * Utility to create typed slot props
26235
- */ function createSlotProps(props) {
26236
- return props;
26237
- }
26238
-
26239
- /**
26240
- * Hook to manage slot rendering
26241
- */ function useSlot(slot, props, fallback) {
26242
- return React.useMemo((() => renderSlot(slot, props, fallback)), [ slot, props, fallback ]);
26243
- }
26244
-
26245
26151
  /**
26246
26152
  * Hook to merge theme overrides with component props
26247
26153
  *