@shohojdhara/atomix 0.3.4 → 0.3.6

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 (237) hide show
  1. package/README.md +101 -199
  2. package/atomix.config.ts +241 -0
  3. package/dist/atomix.css +269 -189
  4. package/dist/atomix.css.map +1 -0
  5. package/dist/atomix.min.css +15179 -11
  6. package/dist/atomix.min.css.map +1 -0
  7. package/dist/charts.d.ts +1929 -0
  8. package/dist/charts.js +6477 -0
  9. package/dist/charts.js.map +1 -0
  10. package/dist/core.d.ts +1289 -0
  11. package/dist/core.js +3373 -0
  12. package/dist/core.js.map +1 -0
  13. package/dist/forms.d.ts +1085 -0
  14. package/dist/forms.js +2466 -0
  15. package/dist/forms.js.map +1 -0
  16. package/dist/heavy.d.ts +636 -0
  17. package/dist/heavy.js +4566 -0
  18. package/dist/heavy.js.map +1 -0
  19. package/dist/index.d.ts +5171 -4792
  20. package/dist/index.esm.js +6098 -4563
  21. package/dist/index.esm.js.map +1 -1
  22. package/dist/index.js +6291 -4747
  23. package/dist/index.js.map +1 -1
  24. package/dist/index.min.js +1 -1
  25. package/dist/index.min.js.map +1 -1
  26. package/dist/layout.d.ts +300 -0
  27. package/dist/layout.js +336 -0
  28. package/dist/layout.js.map +1 -0
  29. package/dist/theme.d.ts +2122 -0
  30. package/dist/theme.js +6084 -0
  31. package/dist/theme.js.map +1 -0
  32. package/package.json +59 -27
  33. package/scripts/atomix-cli.js +544 -16
  34. package/scripts/cli/__tests__/cli-commands.test.js +204 -0
  35. package/scripts/cli/__tests__/utils.test.js +201 -0
  36. package/scripts/cli/__tests__/vitest.config.js +26 -0
  37. package/scripts/cli/interactive-init.js +1 -1
  38. package/scripts/cli/token-manager.js +32 -7
  39. package/scripts/cli/utils.js +347 -0
  40. package/src/components/Accordion/Accordion.stories.tsx +50 -17
  41. package/src/components/Accordion/Accordion.tsx +5 -54
  42. package/src/components/Accordion/index.ts +1 -1
  43. package/src/components/AtomixGlass/AtomixGlass.tsx +65 -31
  44. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +11 -4
  45. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +1 -32
  46. package/src/components/AtomixGlass/stories/Examples.stories.tsx +2 -2
  47. package/src/components/AtomixGlass/stories/shared-components.tsx +0 -31
  48. package/src/components/Avatar/Avatar.stories.tsx +7 -0
  49. package/src/components/Avatar/Avatar.tsx +3 -3
  50. package/src/components/Badge/Badge.stories.tsx +91 -13
  51. package/src/components/Badge/Badge.tsx +3 -3
  52. package/src/components/Block/Block.stories.tsx +7 -23
  53. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +7 -0
  54. package/src/components/Breadcrumb/Breadcrumb.tsx +3 -3
  55. package/src/components/Button/Button.stories.tsx +141 -22
  56. package/src/components/Button/ButtonGroup.stories.tsx +315 -0
  57. package/src/components/Button/ButtonGroup.tsx +67 -0
  58. package/src/components/Button/index.ts +2 -0
  59. package/src/components/Callout/Callout.stories.tsx +8 -6
  60. package/src/components/Card/Card.stories.tsx +82 -28
  61. package/src/components/Card/ElevationCard.tsx +1 -1
  62. package/src/components/Chart/AnimatedChart.tsx +19 -18
  63. package/src/components/Chart/AreaChart.tsx +5 -2
  64. package/src/components/Chart/BarChart.tsx +1 -1
  65. package/src/components/Chart/BubbleChart.tsx +6 -6
  66. package/src/components/Chart/CandlestickChart.tsx +0 -1
  67. package/src/components/Chart/Chart.stories.tsx +5 -7
  68. package/src/components/Chart/Chart.tsx +0 -16
  69. package/src/components/Chart/ChartRenderer.tsx +1 -1
  70. package/src/components/Chart/ChartToolbar.tsx +1 -0
  71. package/src/components/Chart/DonutChart.tsx +0 -1
  72. package/src/components/Chart/FunnelChart.tsx +1 -2
  73. package/src/components/Chart/GaugeChart.tsx +0 -1
  74. package/src/components/Chart/HeatmapChart.tsx +0 -1
  75. package/src/components/Chart/LineChart.tsx +0 -1
  76. package/src/components/Chart/MultiAxisChart.tsx +0 -1
  77. package/src/components/Chart/PieChart.tsx +0 -1
  78. package/src/components/Chart/RadarChart.tsx +19 -13
  79. package/src/components/Chart/ScatterChart.tsx +3 -4
  80. package/src/components/Chart/TreemapChart.tsx +2 -1
  81. package/src/components/Chart/WaterfallChart.tsx +0 -2
  82. package/src/components/Chart/types.ts +12 -2
  83. package/src/components/Chart/utils.ts +4 -3
  84. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +7 -0
  85. package/src/components/DataTable/DataTable.stories.tsx +23 -16
  86. package/src/components/DataTable/DataTable.tsx +3 -3
  87. package/src/components/DatePicker/DatePicker.stories.tsx +27 -19
  88. package/src/components/Dropdown/Dropdown.stories.tsx +11 -19
  89. package/src/components/Dropdown/Dropdown.tsx +12 -9
  90. package/src/components/EdgePanel/EdgePanel.stories.tsx +1 -0
  91. package/src/components/Footer/Footer.stories.tsx +8 -6
  92. package/src/components/Footer/FooterLink.tsx +9 -2
  93. package/src/components/Footer/FooterSection.tsx +3 -3
  94. package/src/components/Form/Checkbox.stories.tsx +7 -0
  95. package/src/components/Form/Checkbox.tsx +3 -3
  96. package/src/components/Form/Form.stories.tsx +7 -0
  97. package/src/components/Form/FormGroup.stories.tsx +9 -1
  98. package/src/components/Form/Input.stories.tsx +69 -16
  99. package/src/components/Form/Input.tsx +4 -2
  100. package/src/components/Form/Radio.stories.tsx +9 -1
  101. package/src/components/Form/Radio.tsx +3 -3
  102. package/src/components/Form/Select.stories.tsx +9 -1
  103. package/src/components/Form/Select.tsx +3 -3
  104. package/src/components/Form/Textarea.stories.tsx +10 -2
  105. package/src/components/Form/Textarea.tsx +4 -2
  106. package/src/components/Hero/Hero.stories.tsx +7 -0
  107. package/src/components/List/List.stories.tsx +10 -3
  108. package/src/components/List/List.tsx +3 -3
  109. package/src/components/List/ListGroup.tsx +3 -1
  110. package/src/components/Messages/Messages.stories.tsx +8 -7
  111. package/src/components/Modal/Modal.stories.tsx +17 -6
  112. package/src/components/Modal/Modal.tsx +3 -3
  113. package/src/components/Navigation/Menu/MegaMenu.tsx +9 -3
  114. package/src/components/Navigation/Menu/Menu.stories.tsx +7 -0
  115. package/src/components/Navigation/Menu/Menu.tsx +9 -3
  116. package/src/components/Navigation/Nav/Nav.stories.tsx +7 -0
  117. package/src/components/Navigation/Navbar/Navbar.stories.tsx +1 -0
  118. package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +1 -1
  119. package/src/components/Pagination/Pagination.stories.tsx +188 -111
  120. package/src/components/Pagination/Pagination.tsx +88 -7
  121. package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -5
  122. package/src/components/PhotoViewer/PhotoViewerImage.tsx +2 -2
  123. package/src/components/Popover/Popover.stories.tsx +191 -115
  124. package/src/components/Popover/Popover.tsx +4 -4
  125. package/src/components/ProductReview/ProductReview.stories.tsx +80 -58
  126. package/src/components/Progress/Progress.stories.tsx +79 -49
  127. package/src/components/Progress/Progress.tsx +6 -2
  128. package/src/components/Rating/Rating.stories.tsx +109 -84
  129. package/src/components/Rating/Rating.tsx +5 -2
  130. package/src/components/River/River.stories.tsx +194 -114
  131. package/src/components/SectionIntro/SectionIntro.stories.tsx +19 -9
  132. package/src/components/Slider/Slider.stories.tsx +7 -0
  133. package/src/components/Slider/Slider.tsx +10 -9
  134. package/src/components/Spinner/Spinner.stories.tsx +15 -11
  135. package/src/components/Spinner/Spinner.tsx +3 -3
  136. package/src/components/Steps/Steps.stories.tsx +132 -98
  137. package/src/components/Tabs/Tabs.stories.tsx +163 -112
  138. package/src/components/Tabs/Tabs.tsx +3 -3
  139. package/src/components/Testimonial/Testimonial.stories.tsx +114 -68
  140. package/src/components/Todo/Todo.stories.tsx +38 -12
  141. package/src/components/Toggle/Toggle.stories.tsx +61 -28
  142. package/src/components/Tooltip/Tooltip.stories.tsx +318 -200
  143. package/src/components/Tooltip/Tooltip.tsx +3 -3
  144. package/src/components/Upload/Upload.stories.tsx +122 -84
  145. package/src/components/VideoPlayer/VideoPlayer.stories.tsx +7 -24
  146. package/src/components/index.ts +6 -2
  147. package/src/layouts/MasonryGrid/MasonryGrid.tsx +2 -2
  148. package/src/lib/composables/useAtomixGlass.ts +2 -3
  149. package/src/lib/composables/useChartPerformance.ts +102 -78
  150. package/src/lib/composables/useChartScale.ts +10 -0
  151. package/src/lib/composables/useHero.ts +9 -2
  152. package/src/lib/composables/useHeroBackgroundSlider.ts +5 -3
  153. package/src/lib/composables/useNavbar.ts +0 -10
  154. package/src/lib/composables/useSideMenu.ts +1 -0
  155. package/src/lib/composables/useVideoPlayer.ts +3 -2
  156. package/src/lib/config/loader.ts +57 -14
  157. package/src/lib/constants/components.ts +10 -0
  158. package/src/lib/hooks/index.ts +0 -1
  159. package/src/lib/hooks/useComponentCustomization.ts +11 -15
  160. package/src/lib/hooks/usePerformanceMonitor.ts +149 -0
  161. package/src/lib/patterns/index.ts +2 -2
  162. package/src/lib/patterns/slots.tsx +2 -2
  163. package/src/lib/theme/README.md +174 -0
  164. package/src/lib/theme/adapters/index.ts +31 -0
  165. package/src/lib/theme/adapters/themeAdapter.ts +287 -0
  166. package/src/lib/theme/config/__tests__/configLoader.test.ts +207 -0
  167. package/src/lib/theme/config/configLoader.ts +254 -0
  168. package/src/lib/theme/config/loader.ts +37 -48
  169. package/src/lib/theme/config/types.ts +2 -2
  170. package/src/lib/theme/config/validator.ts +15 -91
  171. package/src/lib/theme/{constants.ts → constants/constants.ts} +0 -18
  172. package/src/lib/theme/constants/index.ts +8 -0
  173. package/src/lib/theme/core/ThemeRegistry.ts +19 -6
  174. package/src/lib/theme/core/__tests__/createTheme.test.ts +132 -0
  175. package/src/lib/theme/core/composeTheme.ts +155 -0
  176. package/src/lib/theme/core/createTheme.ts +94 -0
  177. package/src/lib/theme/{createTheme.ts → core/createThemeObject.ts} +10 -6
  178. package/src/lib/theme/core/index.ts +5 -19
  179. package/src/lib/theme/devtools/Comparator.tsx +346 -22
  180. package/src/lib/theme/devtools/IMPROVEMENTS.md +139 -38
  181. package/src/lib/theme/devtools/Inspector.tsx +335 -51
  182. package/src/lib/theme/devtools/LiveEditor.tsx +489 -112
  183. package/src/lib/theme/devtools/Preview.tsx +471 -221
  184. package/src/lib/theme/{core → devtools}/ThemeValidator.ts +6 -3
  185. package/src/lib/theme/devtools/index.ts +14 -4
  186. package/src/lib/theme/devtools/useHistory.ts +130 -0
  187. package/src/lib/theme/errors/index.ts +12 -0
  188. package/src/lib/theme/generators/cssFile.ts +79 -0
  189. package/src/lib/theme/generators/generateCSS.ts +89 -0
  190. package/src/lib/theme/{generateCSSVariables.ts → generators/generateCSSVariables.ts} +4 -14
  191. package/src/lib/theme/generators/index.ts +19 -0
  192. package/src/lib/theme/i18n/rtl.ts +7 -7
  193. package/src/lib/theme/index.ts +120 -15
  194. package/src/lib/theme/runtime/ThemeApplicator.ts +53 -95
  195. package/src/lib/theme/{ThemeContext.tsx → runtime/ThemeContext.tsx} +1 -1
  196. package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +4 -4
  197. package/src/lib/theme/runtime/ThemeProvider.tsx +456 -179
  198. package/src/lib/theme/runtime/index.ts +1 -2
  199. package/src/lib/theme/runtime/useTheme.ts +1 -2
  200. package/src/lib/theme/test/testTheme.ts +385 -0
  201. package/src/lib/theme/tokens/index.ts +12 -0
  202. package/src/lib/theme/tokens/tokens.ts +721 -0
  203. package/src/lib/theme/types.ts +6 -42
  204. package/src/lib/theme/{utils.ts → utils/domUtils.ts} +2 -2
  205. package/src/lib/theme/utils/index.ts +11 -0
  206. package/src/lib/theme/utils/injectCSS.ts +90 -0
  207. package/src/lib/theme/utils/themeHelpers.ts +78 -0
  208. package/src/lib/theme/{themeUtils.ts → utils/themeUtils.ts} +1 -1
  209. package/src/lib/theme-tools.ts +8 -9
  210. package/src/lib/types/components.ts +93 -34
  211. package/src/lib/types/partProps.ts +0 -16
  212. package/src/lib/utils/componentUtils.ts +1 -1
  213. package/src/lib/utils/fontPreloader.ts +148 -0
  214. package/src/lib/utils/index.ts +11 -0
  215. package/src/lib/utils/memoryMonitor.ts +189 -0
  216. package/src/styles/01-settings/_settings.design-tokens.scss +4 -1
  217. package/src/styles/01-settings/_settings.fonts.scss +2 -5
  218. package/src/styles/02-tools/_tools.button.scss +66 -79
  219. package/src/styles/06-components/_components.atomix-glass.scss +13 -3
  220. package/src/styles/06-components/_components.navbar.scss +0 -6
  221. package/src/styles/06-components/_components.pagination.scss +88 -0
  222. package/scripts/build-themes.js +0 -208
  223. package/scripts/sync-theme-config.js +0 -309
  224. package/src/components/AtomixGlass/atomixGLass.old.tsx +0 -1263
  225. package/src/lib/theme/composeTheme.ts +0 -370
  226. package/src/lib/theme/core/ThemeCache.ts +0 -283
  227. package/src/lib/theme/core/ThemeEngine.test.ts +0 -146
  228. package/src/lib/theme/core/ThemeEngine.ts +0 -657
  229. package/src/lib/theme/createThemeFromConfig.ts +0 -132
  230. package/src/lib/theme/devtools/CLI.ts +0 -364
  231. package/src/lib/theme/runtime/ThemeManager.test.ts +0 -192
  232. package/src/lib/theme/runtime/ThemeManager.ts +0 -442
  233. package/src/styles/03-generic/_generated-root.css +0 -5
  234. package/src/themes/README.md +0 -442
  235. package/src/themes/themes.config.js +0 -35
  236. /package/src/lib/theme/{cssVariableMapper.ts → adapters/cssVariableMapper.ts} +0 -0
  237. /package/src/lib/theme/{errors.ts → errors/errors.ts} +0 -0
package/dist/forms.js ADDED
@@ -0,0 +1,2466 @@
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+
3
+ import React, { useRef, useEffect, memo, forwardRef, useId, useState, useMemo, useCallback } from "react";
4
+
5
+ // Define checkbox class constants
6
+ const FORM_CLASSES_BASE = "c-form", FORM_CLASSES_DISABLED = "c-form--disabled", FORM_GROUP_CLASSES_BASE = "c-form-group", FORM_GROUP_CLASSES_SMALL = "c-form-group--sm", FORM_GROUP_CLASSES_LARGE = "c-form-group--lg", FORM_GROUP_CLASSES_INVALID = "c-form-group--invalid", FORM_GROUP_CLASSES_VALID = "c-form-group--valid", FORM_GROUP_CLASSES_DISABLED = "c-form-group--disabled", INPUT_CLASSES_BASE = "c-input", INPUT_CLASSES_SMALL = "c-input--sm", INPUT_CLASSES_LARGE = "c-input--lg", INPUT_CLASSES_INVALID = "is-invalid", INPUT_CLASSES_VALID = "is-valid", INPUT_CLASSES_DISABLED = "is-disabled", INPUT_CLASSES_FULL_WIDTH = "c-input--full-width", INPUT_CLASSES_PREFIX_ICON = "c-input--prefix-icon", INPUT_CLASSES_SUFFIX_ICON = "c-input--suffix-icon", INPUT_CLASSES_CLEARABLE = "c-input--clearable", INPUT_CLASSES_WITH_COUNTER = "c-input--with-counter", INPUT_CLASSES_PASSWORD_TOGGLE = "c-input--password-toggle", INPUT_ELEMENTS_WRAPPER = "c-input-wrapper", RADIO_CLASSES_BASE = "c-radio", RADIO_CLASSES_INVALID = "is-error", RADIO_CLASSES_VALID = "is-valid", RADIO_CLASSES_DISABLED = "is-disabled", SELECT_CLASSES_BASE = "c-select", SELECT_CLASSES_SELECTED = "c-select__selected", SELECT_CLASSES_SELECT_BODY = "c-select__body", SELECT_CLASSES_SELECT_PANEL = "c-select__panel", SELECT_CLASSES_SELECT_ITEMS = "c-select__items", SELECT_CLASSES_SELECT_ITEM = "c-select__item", SELECT_CLASSES_TOGGLE_ICON = "c-select__toggle-icon", SELECT_CLASSES_ICON_CARET = "icon-atomix-caret-down", SELECT_CLASSES_SMALL = "c-select--sm", SELECT_CLASSES_LARGE = "c-select--lg", SELECT_CLASSES_INVALID = "is-invalid", SELECT_CLASSES_VALID = "is-valid", SELECT_CLASSES_DISABLED = "is-disabled", SELECT_CLASSES_IS_OPEN = "is-open", TEXTAREA_CLASSES_BASE = "c-input c-input--textarea", TEXTAREA_CLASSES_SMALL = "c-input--sm", TEXTAREA_CLASSES_LARGE = "c-input--lg", TEXTAREA_CLASSES_INVALID = "is-invalid", TEXTAREA_CLASSES_VALID = "is-valid", TEXTAREA_CLASSES_DISABLED = "is-disabled", ATOMIX_GLASS = {
7
+ BASE_CLASS: "c-atomix-glass",
8
+ CONTAINER_CLASS: "c-atomix-glass__container",
9
+ INNER_CLASS: "c-atomix-glass__inner",
10
+ FILTER_CLASS: "c-atomix-glass__filter",
11
+ FILTER_OVERLAY_CLASS: "c-atomix-glass__filter-overlay",
12
+ FILTER_SHADOW_CLASS: "c-atomix-glass__filter-shadow",
13
+ CONTENT_CLASS: "c-atomix-glass__content",
14
+ BORDER_1_CLASS: "c-atomix-glass__border-1",
15
+ BORDER_2_CLASS: "c-atomix-glass__border-2",
16
+ HOVER_1_CLASS: "c-atomix-glass__hover-1",
17
+ HOVER_2_CLASS: "c-atomix-glass__hover-2",
18
+ HOVER_3_CLASS: "c-atomix-glass__hover-3",
19
+ BASE_LAYER_CLASS: "c-atomix-glass__base",
20
+ OVERLAY_LAYER_CLASS: "c-atomix-glass__overlay",
21
+ OVERLAY_HIGHLIGHT_CLASS: "c-atomix-glass__overlay-highlight",
22
+ BACKGROUND_LAYER_CLASS: "c-atomix-glass__background-layer",
23
+ BACKGROUND_LAYER_DARK_CLASS: "c-atomix-glass__background-layer--dark",
24
+ BACKGROUND_LAYER_BLACK_CLASS: "c-atomix-glass__background-layer--black",
25
+ BACKGROUND_LAYER_OVER_LIGHT_CLASS: "c-atomix-glass__background-layer--over-light",
26
+ BACKGROUND_LAYER_HIDDEN_CLASS: "c-atomix-glass__background-layer--hidden",
27
+ VARIANT_PREFIX: "c-atomix-glass--",
28
+ MODE_PREFIX: "c-atomix-glass--",
29
+ CLASSES: {
30
+ BASE: "c-atomix-glass",
31
+ CONTAINER: "c-atomix-glass__container",
32
+ INNER: "c-atomix-glass__inner",
33
+ FILTER: "c-atomix-glass__filter",
34
+ CONTENT: "c-atomix-glass__content",
35
+ ACTIVE: "active",
36
+ OVER_LIGHT: "c-atomix-glass__container--over-light",
37
+ // Mode variants
38
+ STANDARD: "c-atomix-glass--standard",
39
+ POLAR: "c-atomix-glass--polar",
40
+ PROMINENT: "c-atomix-glass--prominent",
41
+ SHADER: "c-atomix-glass--shader"
42
+ },
43
+ DEFAULTS: {
44
+ DISPLACEMENT_SCALE: 20,
45
+ BLUR_AMOUNT: 1,
46
+ SATURATION: 140,
47
+ ABERRATION_INTENSITY: 2.5,
48
+ ELASTICITY: .05,
49
+ CORNER_RADIUS: 16,
50
+ // Default border-radius matching design system
51
+ PADDING: "0 0",
52
+ MODE: "standard",
53
+ OVER_LIGHT: !1,
54
+ ENABLE_OVER_LIGHT_LAYERS: !0
55
+ },
56
+ CONSTANTS: {
57
+ ACTIVATION_ZONE: 200,
58
+ MIN_BLUR: .1,
59
+ MOUSE_INFLUENCE_DIVISOR: 100,
60
+ EDGE_FADE_PIXELS: 2,
61
+ DEFAULT_CORNER_RADIUS: 16,
62
+ // Fallback value matching design system
63
+ MAX_SIZE: 4096,
64
+ // Maximum width/height for glass size
65
+ // Gradient calculation constants
66
+ GRADIENT: {
67
+ BASE_ANGLE: 135,
68
+ // Base angle for border gradients (degrees)
69
+ ANGLE_MULTIPLIER: 1.2,
70
+ // Multiplier for mouse influence on angle
71
+ BORDER_STOP_1: {
72
+ MIN: 10,
73
+ // Minimum percentage for border stop 1
74
+ BASE: 33,
75
+ // Base percentage for border stop 1
76
+ MULTIPLIER: .3
77
+ },
78
+ BORDER_STOP_2: {
79
+ MAX: 90,
80
+ // Maximum percentage for border stop 2
81
+ BASE: 66,
82
+ // Base percentage for border stop 2
83
+ MULTIPLIER: .4
84
+ },
85
+ BORDER_OPACITY: {
86
+ BASE_1: .12,
87
+ // Base opacity for border gradient 1
88
+ BASE_2: .4,
89
+ // Base opacity for border gradient 2
90
+ BASE_3: .32,
91
+ // Base opacity for border gradient 3
92
+ BASE_4: .6,
93
+ // Base opacity for border gradient 4
94
+ MULTIPLIER_LOW: .008,
95
+ // Low multiplier for mouse influence on opacity
96
+ MULTIPLIER_HIGH: .012
97
+ },
98
+ CENTER_POSITION: 50,
99
+ // Center position percentage (50%)
100
+ HOVER_POSITION: {
101
+ DIVISOR_1: 2,
102
+ // Divisor for hover 1 position calculation
103
+ DIVISOR_2: 1.5,
104
+ // Divisor for hover 2 position calculation
105
+ MULTIPLIER_3: 1
106
+ },
107
+ BASE_LAYER_MULTIPLIER: .5
108
+ },
109
+ // Gradient opacity values for hover effects
110
+ GRADIENT_OPACITY: {
111
+ HOVER_1: {
112
+ BLACK_START: .3,
113
+ // Start opacity for black hover 1
114
+ BLACK_MID: .1,
115
+ // Mid opacity for black hover 1
116
+ BLACK_STOP: 30,
117
+ // Stop percentage for black hover 1
118
+ BLACK_END: 60,
119
+ // End percentage for black hover 1
120
+ WHITE_START: .5,
121
+ // Start opacity for white hover 1
122
+ WHITE_STOP: 50
123
+ },
124
+ HOVER_2: {
125
+ BLACK_START: .4,
126
+ // Start opacity for black hover 2
127
+ BLACK_MID: .15,
128
+ // Mid opacity for black hover 2
129
+ BLACK_STOP: 40,
130
+ // Stop percentage for black hover 2
131
+ BLACK_END: 80,
132
+ // End percentage for black hover 2
133
+ WHITE_START: 1,
134
+ // Start opacity for white hover 2
135
+ WHITE_STOP: 80
136
+ },
137
+ HOVER_3: {
138
+ BLACK_START: .5,
139
+ // Start opacity for black hover 3
140
+ BLACK_MID: .2,
141
+ // Mid opacity for black hover 3
142
+ BLACK_STOP: 50,
143
+ // Stop percentage for black hover 3
144
+ BLACK_END: 100,
145
+ // End percentage for black hover 3
146
+ WHITE_START: 1,
147
+ // Start opacity for white hover 3
148
+ WHITE_STOP: 100
149
+ }
150
+ },
151
+ // Base and overlay gradient constants
152
+ BASE_GRADIENT: {
153
+ ANGLE: 135,
154
+ // Gradient angle in degrees
155
+ BLACK_START_BASE: .15,
156
+ // Base start opacity for black
157
+ BLACK_START_MULTIPLIER: .003,
158
+ // Multiplier for mouse X influence on start
159
+ BLACK_MID_BASE: .1,
160
+ // Base mid opacity for black
161
+ BLACK_MID_MULTIPLIER: .002,
162
+ // Multiplier for mouse Y influence on mid
163
+ BLACK_MID_STOP: 50,
164
+ // Mid stop percentage
165
+ BLACK_END_BASE: .18,
166
+ // Base end opacity for black
167
+ BLACK_END_MULTIPLIER: .004,
168
+ // Multiplier for mouse X influence on end
169
+ WHITE_OPACITY: .1
170
+ },
171
+ OVERLAY_GRADIENT: {
172
+ BLACK_START_BASE: .12,
173
+ // Base start opacity for black overlay
174
+ BLACK_START_MULTIPLIER: .003,
175
+ // Multiplier for mouse X influence on start
176
+ BLACK_MID: .06,
177
+ // Mid opacity for black overlay
178
+ BLACK_MID_STOP: 40,
179
+ // Mid stop percentage
180
+ BLACK_END_BASE: .15,
181
+ // Base end opacity for black overlay
182
+ BLACK_END_MULTIPLIER: .003,
183
+ // Multiplier for mouse Y influence on end
184
+ WHITE_OPACITY: .05
185
+ },
186
+ // Overlay highlight constants
187
+ OVERLAY_HIGHLIGHT: {
188
+ POSITION_X: 20,
189
+ // X position percentage
190
+ POSITION_Y: 20,
191
+ // Y position percentage
192
+ WHITE_OPACITY: .4,
193
+ // White opacity in gradient
194
+ STOP: 60,
195
+ // Stop percentage
196
+ OPACITY_MULTIPLIER: .7
197
+ },
198
+ // Displacement and aberration multipliers
199
+ MULTIPLIERS: {
200
+ SHADER_DISPLACEMENT: .8,
201
+ // Displacement scale multiplier for shader mode
202
+ OVER_LIGHT_DISPLACEMENT: .6,
203
+ // Displacement scale multiplier for over-light mode
204
+ SHADER_ABERRATION: .7
205
+ },
206
+ // Saturation constants
207
+ SATURATION: {
208
+ HIGH_CONTRAST: 200
209
+ }
210
+ }
211
+ }, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
212
+ if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
213
+ const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
214
+ return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
215
+ }, calculateElementCenter = rect => rect ? {
216
+ x: rect.left + rect.width / 2,
217
+ y: rect.top + rect.height / 2
218
+ } : {
219
+ x: 0,
220
+ y: 0
221
+ }, calculateMouseInfluence = mouseOffset => {
222
+ if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
223
+ // More responsive calculation for overlight effects
224
+ const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$1.MOUSE_INFLUENCE_DIVISOR;
225
+ return Math.min(1.5, influence);
226
+ // Cap influence for better control
227
+ }, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$1.MIN_BLUR : Math.max(CONSTANTS$1.MIN_BLUR, Math.min(50, value)), validateGlassSize = size => size && "number" == typeof size.width && "number" == typeof size.height && size.width > 0 && size.height > 0 && size.width <= CONSTANTS$1.MAX_SIZE && size.height <= CONSTANTS$1.MAX_SIZE, parseBorderRadiusValue = value => {
228
+ if ("number" == typeof value) return Math.max(0, value);
229
+ if ("string" != typeof value || !value.trim()) return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
230
+ const trimmedValue = value.trim();
231
+ // Handle px values
232
+ if (trimmedValue.endsWith("px")) {
233
+ const parsed = parseFloat(trimmedValue);
234
+ return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
235
+ }
236
+ // Handle rem values (assume 16px = 1rem)
237
+ if (trimmedValue.endsWith("rem")) {
238
+ const parsed = parseFloat(trimmedValue);
239
+ return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
240
+ }
241
+ // Handle em values (assume 16px = 1em for simplicity)
242
+ if (trimmedValue.endsWith("em")) {
243
+ const parsed = parseFloat(trimmedValue);
244
+ return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
245
+ }
246
+ // Handle percentage (convert to approximate px value, assuming 200px container)
247
+ if (trimmedValue.endsWith("%")) {
248
+ const parsed = parseFloat(trimmedValue);
249
+ return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
250
+ }
251
+ // Handle unitless numbers
252
+ const numValue = parseFloat(trimmedValue);
253
+ return isNaN(numValue) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
254
+ }, extractBorderRadiusFromElement = element => {
255
+ if (!element || !element.props) return null;
256
+ // Check inline styles first (highest priority)
257
+ if (element.props.style) {
258
+ const radiusFromStyle = (style => {
259
+ if (!style) return null;
260
+ // Check various border-radius properties
261
+ const borderRadius = style.borderRadius || style.borderTopLeftRadius || style.borderTopRightRadius || style.borderBottomLeftRadius || style.borderBottomRightRadius;
262
+ return void 0 !== borderRadius ? parseBorderRadiusValue(borderRadius) : null;
263
+ })(element.props.style);
264
+ if (null !== radiusFromStyle && radiusFromStyle > 0) return radiusFromStyle;
265
+ }
266
+ // If element has children, recursively check them
267
+ if (element.props.children) {
268
+ const childRadius = extractBorderRadiusFromChildren(element.props.children);
269
+ if (childRadius > 0 && childRadius !== CONSTANTS$1.DEFAULT_CORNER_RADIUS) return childRadius;
270
+ }
271
+ return null;
272
+ }, extractBorderRadiusFromChildren = children => {
273
+ if (!children) return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
274
+ try {
275
+ const childArray = React.Children.toArray(children);
276
+ for (let i = 0; i < childArray.length; i++) {
277
+ const child = childArray[i];
278
+ if ( React.isValidElement(child)) {
279
+ const radius = extractBorderRadiusFromElement(child);
280
+ if (null !== radius) return radius;
281
+ }
282
+ }
283
+ } catch (error) {
284
+ // Silently handle errors
285
+ }
286
+ return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
287
+ }, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
288
+ switch (mode) {
289
+ case "standard":
290
+ return displacementMap;
291
+
292
+ case "polar":
293
+ return polarDisplacementMap;
294
+
295
+ case "prominent":
296
+ return prominentDisplacementMap;
297
+
298
+ case "shader":
299
+ return shaderMapUrl || displacementMap;
300
+
301
+ default:
302
+ return console.warn("AtomixGlass: Invalid displacement mode"), displacementMap;
303
+ }
304
+ }, GlassFilterComponent = ({id: id, displacementScale: displacementScale, aberrationIntensity: aberrationIntensity, mode: mode, shaderMapUrl: shaderMapUrl, blurAmount: blurAmount}) => jsx("svg", {
305
+ style: {
306
+ position: "absolute",
307
+ width: "100%",
308
+ height: "100%",
309
+ inset: 0
310
+ },
311
+ "aria-hidden": "true",
312
+ suppressHydrationWarning: !0,
313
+ children: jsxs("defs", {
314
+ children: [ jsxs("radialGradient", {
315
+ id: `${id}-edge-mask`,
316
+ cx: "50%",
317
+ cy: "50%",
318
+ r: "50%",
319
+ children: [ jsx("stop", {
320
+ offset: "0%",
321
+ stopColor: "black",
322
+ stopOpacity: "0"
323
+ }), jsx("stop", {
324
+ offset: `${Math.max(30, 80 - 2 * aberrationIntensity)}%`,
325
+ stopColor: "black",
326
+ stopOpacity: "0"
327
+ }), jsx("stop", {
328
+ offset: "100%",
329
+ stopColor: "white",
330
+ stopOpacity: "1"
331
+ }) ]
332
+ }), jsxs("filter", {
333
+ id: id,
334
+ x: "-35%",
335
+ y: "-35%",
336
+ width: "170%",
337
+ height: "170%",
338
+ colorInterpolationFilters: "sRGB",
339
+ children: [ jsx("feImage", {
340
+ id: "feimage",
341
+ x: "0",
342
+ y: "0",
343
+ width: "100%",
344
+ height: "100%",
345
+ result: "DISPLACEMENT_MAP",
346
+ href: getDisplacementMap(mode, "data:image/jpeg;base64,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cUAUAkEkziomgGgkoxZGgxZFQFQlYnQHRdPfj/10KCSCKESCNiVkViPSLpD0h6I0Q0I0A2IoBWBIJIBKBIJoJIJ2R2J0JWBUJ0JUB0XTv479dFZDYiglYigkhEgjZFQjRFQjRFQjQigFYigHYigmgEgmglYlYnQlQlYlQHQlQnQ9P/kf1yVkNiNCNkNiVENiNiViNEViNkVCVgKCViViViSCViSCVgdCViVCViVCdgVCVCdD1D+U/XBWQ2I0I2Q2JUQ2I0JWQ0I2JUQ2JUI2JUI2J0JWJWJWA2R0BWJ0I2JUJ2BUJUJ0P//EABkQAQEBAQEBAAAAAAAAAAAAAAECABEDEP/aAAgBAQABAgB1atWrVq1atWrVq1atWrVq1atWrVq1atWrVq+OrVq1atWrVq1atWrVq1atWrVq1atWrVq1atXxVppppppdWrVq1atWrVq1NNNNNNNNNNNPVWmmmmms6tWrVq1atWpppppppppppppp6q0000uc51atWrVq1ammmmmmmmmmmmmt1Vpppc5znVq1atWrVqaaaaaaaaaaaaaeqtNLnOc51atWrVq1ammmmmmmmmmmmmnqrS5znOc6tWrVq16222mmmmmmlVppp6tKuc5znOrVq1a9TbbbbTTTTTSq000qtLnOc5zq1atWrW0222200000qqqtKqrnOc5zq1atTbbbbbbbbTTTSqqqqqq5znOc6tTTTbbbbbbbbTTTSqqqqrlVznOctNNNtttttttttNNNNKqqqrqznKqrTTTTbbbbbbbbbTTTSqqqqrqznOc5aaaabbbbbbbbbaaaaVVVVVdWc5znVq1NNttttttttttNNKqqqqudWc5znVq16tbbbbbbbbbbTTSqqqq5XVnOc6tWrVrb1tttttttttNNKqqqqrWrK5VWmmm2230bbbbbbaaaXOc5zlVa1KuVVppptttt9G22222mmlzlVznK6tWVVWmmmm2222222222mlznOc5znLWppVVWmmm22222229bTWrOc5znOcq1qaaVpWmm222222229erVqznOc5znKtatStK0rTbTTbbbberXr1as5znOc5aVpppppWlabaabbbb1ta9WrVnOc5znU0rTTTTTTTTTbTTbbbTWvVq1as5znOdTTStNNNNNNNNNtNNtttN6tWvVq1ZznOrU00rTTTTTTTTTTTTTbTWvVq1atWrOc6tTTTStNNNNNNNNNNtNNtNa9WrVq1Z1Z1NNNNNK1q1NNNNNNNNNNNtNatWrVq1atWrU00000rWrVq1atWrVq1alaaa1atWrVq1NNNammmmla1atWrVq1aterVq16tWrVnVqa1NK1qaaaVX/xAAWEAADAAAAAAAAAAAAAAAAAAAhgJD/2gAIAQEAAz8AaExf/8QAGhEBAQEBAQEBAAAAAAAAAAAAAQISEQADEP/aAAgBAgEBAgDx48ePHjx48ePHjx48ePHjx48ePHjx48ePHj86IiIiIiInjx48ePHjx48IiIiIj0oooooooooRERER73ve60UUUUUUVrWiiiiiihERERER73ve97ooooorRWiiiiihKERERER73ve973RRRRWtFFFFFFCIiIiIiPe973ve60UUVrRRRRRRQiIlCIiI973ve973pRRWiiiiiiiiiiiiiiihEe973ve973RRWtFFFFFFFFFFFFFFFFFFa13ve973WitaKKKKKKKKKKKKKKKKKK1rWtd1rutFa1oooooooooooosssooorWta1rWta1rRRRRRRRRRRZZZZZZZZZWta1rWta1rRRRRRRRRZZZZZZZZZZZZe9a1rWta1rWitaKLLLLLLLLLLLLLLLLL3rWta1rWtFbLLLLLLLLLLLLLLLLLLLL3vWta1rWita1ssssssss+hZZZZZZZZe961rWta0Vre97LLLLLLLLLLLPoWWWWWXrWta1oorWta3ssss+hZZZZ9Cyyyyyyyyiita1orWta1ve9llllllllllllllllFFa0VorWta1ve9llllllllllllllllllFFFaK1rWta1rWiyyyyyyyyyyyyiiiiiiitFFa1rWta1oosoosssssoooosoooorRRRWta1rWta0UUUUUWUUUUUUUUUUUVoooorWta1rWtaKKKKKKmiiiiiiiiiiiiiiitd73ve61oSiiipoqaKKKKKKKKKK0UUUVrve973vREREZoSihEooooorRRRRWtd73ve9EREREREoSiiiiitFllllla73ve9ERERERESiiiiiitH0PoWWWWVrXe96IiIiMoiJRRRRRRWjwlFFllllFFd6IiIiIlCUUUUUUUUUePHjx48ePCIiIiIiIiUUUUUUUUUUUePHjx48ePHjx48ePHjx48IiUUUUUUJRRRX//xAAWEQADAAAAAAAAAAAAAAAAAAABYJD/2gAIAQIBAz8AtEV7/8QAFxEBAQEBAAAAAAAAAAAAAAAAAAECEP/aAAgBAwEBAgCtNNNNNNNNNNNNNNNNNNNNNNNNNNNNNcrTTTTTTTTTTTTTTTTTTTTTTTTTTTTTXKrTTTTTTTU000000000000000000001FVpppppqampqaaaaaaaaaaaaaaaaaaaa5Vaaaaampqampqammmmmmmmmmmlaaaaaaiq0001NTU1NTU1NTTTTTTTTTTSqqtNNNcqtNNSyzU1LNTU1NTTTTTTTTTSqqq001ytNLLLLNTU1NTU1NTbbbTTTTTSqqq001ytNLLLLLNTU1NTU3NttttNNNNNKqq001KrSyyyyyzU1NTU3Nzc02220000qqqqrSqqyyyyyzU1NTU3Nzc3NttttNNNKqqqqqqssssss1NTU3Nzc3NzbbbbTTTSqqqqqqrLLLLLNTU1Nzc3Nzc22220000qqqqqqqqssss1NTU3Nzc3NzbbbbbTTSqqqqqqqqqqzU1NTc3Nzc3Nzbc22000qqqqqqqqqqqtTU3Nzc3Nzc3NtzbTTSqqqqrKqqqqqtNNzc23Nzc3Nzc3NTU1KqqqrKqqqqqtNNNNttzc3Nzc3NzU1NLLLLLKqqqqqqqq0022223Nzc3NzU1NSyyyyyyqqqqqqqrTTbbbbc3Nzc3NTU1LLLLLLKsqqqqqqrTTTTbbbc3Nzc1NTUsssssssqqqqqqrTTTTTbbbTc3NTU1NTUsssssqqqqqqqq0000222023NTU1NTUsssssqqqqqqqq000000003NTU1NTU1LLLLLNKrTSqqqqtNNNNNNtNNTU1NSzUssss00qq0qqqqrTTTTTTTTTU1NTUs1LLLNNNKrTTTSqqq00000000001NTU1LNTU0000qtNNNKqqqtNNNNNNNNTU1NTUs1NNNNNKss1NNNK00qtK0000001NNTU0s000000qq000001NKrStNNNNK1NNNNStNNNNNKqtNNNNNNNK0000000rU0000rTTTTTSq00000rTTTTTTTTTTTTTTTTStNNNNKr/xAAUEQEAAAAAAAAAAAAAAAAAAACg/9oACAEDAQM/AAAf/9k=", "data:image/jpeg;base64,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", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAABVXElEQVR4nO19aZasPKxkuE5toffS+1/YR/8AS6GQZAxZd3qvffJQtjEe5AgNQGaN//N/caZxAAAODFyZsnLcnZIGz47UiVVeNeWpWDlmJbhILW8rv7oaYBz4SpWS+ZJKuwofHMeVH8DXoFMjVHpmXFdJpR1zzRipWFUiVYJaIlVCLpynQO0fHRE7uQ5Vg/JUUQl8TfyeoAXGzJyVI1aemVGdSg24WXtEPKYLdWJ0lQ4HHOdnIKdjzLP04eGsZ+4csbeDelukY3XyfVqO6Ts6ciWdGtyIQKOfajAjlXVneAL1HCCYpzGy1O9xn4fDI/RLe6r6YhxkqKECes0BaZBwoFgHXZV4pVBrRufKg4U1LzHckwwSYSrQBy2ANh1RSkXLNWxvU7qcEQPUSM2XOqYjGQTQRQOB3UQVVwT8WauIvzBtsQZpcFlT2tiI9Y3RS25gmlM844DtdOSANkhHNC35KKbALj9AGYFanCrguAe1KVJFBk4lB9Qu7ej71xy4u3DkzNCa3M0C9N3ozgSqYmIMqhzDL/EpRaDL1o9UA9SmYFRtHP2ZGFIpg5oL9JIDdCo36Jhw5LPwOeyYgtII5KLN8yBWiC/ELTGUBsdz6LMxDOsKuFum4Q40WJaj7mBNA2GCQm1WDkL5IKco9Euw1uIInd8r/nTK8jsu0KhGeYF+DHxZB7ccCGcZyjMVHtGaCfBxW/THgXhiB02sLBaOPryNdZjJIA7VLfTNQIX+O7TefrqrrGTbWSwo0WACYtC5YrSyO2OCXN4X8+gtByomLHBfgLvqWWSxRj+Ar7DT1KgOPRMHOoBys+yioMG9D1SiX+Y2K2+NwE0xkkHmKXm1e9Jn7j8C7dZfCogsKRGHC/CqaJDzCvodEdm1y6IAdO38dEwIS8s+j52vSMLD7aD/vGOGZxyIy8jBAFt/IBTLYCAM3ThCuX9ErX8kI4Ds/HRFXpG4PT30Q8oQK9s8+nSXl4OeFRUNyrzBInxGW+RO+a6oFQVnNQeWYQDitUIJL3L/ldZ/hH6cQTAecaBEZObAi/uhjSnQnqVl5YnVzo8gJg5U2C7rUKbBRQrQlfw7sC5TcyGDwFEyGpcgk4VBVqIwtA5njRLlQCXasoPOLQf1sOn6L9Df8U0WntGP8BzgBQe6Uw0TdsIAREpw0aAWNDTNPxsBu9C1PkUInoQGPFBccpCVXTti/iRDifgS3GuSzJhYG8TGC89Y/ZYoH0xw+5EyiI1r9U+d8BD3YUBsuX7m1aK/WvIm+hGeAzB8xx4H+lNra3ANV53q0K/ci45ZZwTUXema0dlFJMATULB2CN5B/D4fynoqKg3KVgTTkS6REUev/q03oYRVLopeme6u6qmeG4A2WKF/xJaz/sshGBH2mAMZtZkDfTCQDQKW6PcLrZ/eCEBufVZbnmlg6UiSgeQXZKg+R1Wpan5NhlyZaKAR6vwjTOBGodckRlH/aNTqDQdipVzuFWv0UzM91aFfxp31123QsPfvOJBwUxQTPRZhwC36Gc1rI1CGuR4q8Norvy5IRpz+EaW3h/X9T8sKQ4k145o4c4aFQP/qr3J4uP5G/dslOxzYDADCXFJxHRJYuw791ObLmv4YB6r6+4C47CQV6wcCtMiFEdBM7KFQ/+UtYCgQteZ3fvr5FEChBXrzGl9FplT/2jlx4x0HkJtVbX4K/Rj4Ps5zBzBwHPPcgWPM9z3P+tTGKq+WsVmu56O1uY4IxfNCm5gWz7XlCVv9TId0XmUcFoefKZaJOT3vnTasOv/rUj1KBeUMi8FLhtfk8HdH/YeehXU9B8Jse9xnlKOpf43+sXgXCL0dyJWdvl/cFMohQTYIRZHqf8AIlOq/EsWVGVXxL/l0k4wY5crBaFhmbtW/OuhLDoSjjbN322eBfu5uE/0AvjEu5cc6HojaHVe9VkL1NJKmv/R3PotwKhzR6n6ZwKnjr1VVRsCWczbgzIg1rNBttucKj4EpGzIIH6Sygx8xII4S601wwARJgC5ug8Y5ZfXf+f0POEDQFHxvoZ/mhtisnJUUv6/ayIESbQUHypZEpJIDmNh9hv5z0hH9PDEQpg9aiNEDMcPEcApRn760MxFF9sE62sIysX55MRCVaxoQfBXoMeNtElsKahm8KtDfcsAHrdAvZwXT79AP4Ju13XEAsWjgQ+/6Zw60UYGxgyrDEQGImQyIGUDndomDOwQQsgWkhLq+dr5+H77dMJ9cexSt9jvJEC/t2KBP7mqMaQGIG9d5AvcC9EqzeAxNEqALVshaHgYDZ/EbSGrvefhr4NZOos+DUQTErVOU0K+OEJyuBwCb6hwINJ8xM0jBsbpwcBVwpT30B5D9eKKej2N7nNiudFeKYJfw7Xygs1djYwXVc2al+K2+C3ylKMDleX6AfngMEFHyjgPCBMksbgq9QT95RDkM8BoUzk/IyFpo3tffHfR/3qBMndYfdw1i41EWk2vRZiIf7KxzJvk8n3AgNCgnRXN+h35u4zEA43vFAah7kx2erqYMEh6g/wxGzU/bCQNMZBX6R5wJQGvEVTwEQJyWsP48Vrb+L5kvJtAwQfAKKRJQcvjL6n8zALhwXIH+lgM+sQ7Z+zXSbY9+4HwOAAIlyKshjXgcAVsvOMC8WgTEmEBk9BvoC/8nhwF0ynoDfDhmIPKgBpRe9wu4R5FD2eKWFGHMLnA5UsvRk6ScQEJtGIIzsSUr2hwAMMpHLHJvO4Gv9/Yh+stogVbxjaj4ESNCDlg/5EBpDXJArAYBdCGKTEmDeyPwLuq9w3co3YI9YXrd4Mg9H037u95YOxoyBqG8U/+4g75mRkC2kq0yC2Dy/GL0w1wgCSJ/EwfwJBgAXYsUBkB9ISPGJYOI/jA3bES9DZoLU9DQ5oYO8TT7YNIgRMCd4ucl96PkmDi0GZ4X9X/VGMhyBiFz7/r/XvTzQq4g+DxR4vsXceCcwYNQGMERksw5GaAOiH1Ho+6XqPdKUswQr+oXxfaSRTInZ2ildyLcqPyi0KyZp6BkENwt7w0Y+nRWM00k0HEgQPY3oh/hXSAQcBGwCwR3uWzzlAP1jVHE52I0ROn/ZEcI05ohruucLYauyyOfrPeHX4qufiD8FbZ0iO/qk74HR8AE/cANLka4F/WGyDQZtQMRNCf0ufGgs2VGLIMfM9BRVe6jnzrRhTRtrJ8ZAzAa4r0gxGLxFtoTDmRH36GXvBSgNgUhQ0APs51nuees+4ubPA06h5wadb3v4l2HzRgxEasHSOznyfJur7hJyzlk7GKCe0SUG4BUm8IhHjK4ugojVcUyPPgR9GufVXHGAKwy470gKTK47ZIXd0JV2ceQN4fCbArAmXkKCNEwQCtC5LOh5BU03QFo6qV9UdxMjW8mNsFtaawvYoAmOXqS+kR0h666iHjDegC9KP7ZldbbMVVuol+oq/mqyJfMGIAxwdqUipkDfMljDiChX8JiVI2NcpRBDAMEHLAGtNLk7hRphD9S20D/BzmwiExYK4FWhLlGhPqNtcYZTsQM40aGPiEeKcNtMPE9UoMA99foj5fXcO+LTQxQFQsOxDbPOAB1yhcWAEimANEEwWkACQPmJW90v2kvkx1nSuizkx0d7s1BD1qsez72eC5HL7Y7cOE47pkSt2ud63UwbQQA10oNlMYfRrlJYyjQUVX+HvSPEANUcbAUlQPS5hEH4Mq+rAxuGFkAsCnAjM4RPH7bHtF+u7oQsd0d4hHhjtym6ionhTifmJnwbASRD4gGE76noZNFkiXwcdLAoW946rygeW1nAdaVmzUy560YgHqgGCAC+uqrD3lDAPqCA6zsCan1PSIUFqBwhED+21zLeZTbPmXKKBeRhU0ViZctkcba4d+RiiOdOuaZM9PwwfeOubGeBenUwUeGTun8jJBh0IMVxIjAjWbhF6FfWM1FigHkuSwCNCUOVnfiOQcU7vJAOpEhBwNoHCHAfaHgZYG4twBBhG/Y6SX0B7VXu586l9HDfI5QeS0f6iVai0yD/OzcR23sACGnQAzmojrnh1ddLH+ErgLu49k36E9w55mE9tXSvlvQI+IVMSyu3gx9xIH75wAo6oFoCuBbjsoC8NLuHSA6qxJcizsWy8yQ+kU6aj6o+m88VTGzQhIXxTrF5dcWYEThTORlCxCUgtRnqnyG/gLuy+L3JaIIerDsSkFHs1A8JtvhAApKrANiVG6uOEKAOzyy6R38gigrsWYJjtimCPVC71W+S0fMx4cAQXRNUTgfPNg5yeJZQSUNCS5Xzg80E6TRSAmREsAW+mVWNu+FYlIFNGu+wWpjiiz794hFa1zeHn3PATSPBawZoimYKwkznJvtRyzhj3CqFOhKyokkXAwqh/tpkqvqs8gwPeiIuUdW2esmtuHe+aCuytSsCI3zwwreMgX6M9w/R/8a7pVHZ42/bVWCciR1oq7OFOJHHEC4HMIBJGdpYQGmIwQ4+q/6JfhdIiLWJHfZg7A3sTLgvrMGXTpozhYPsIKAKwijARuBAv0SxdkMew64Op9rdwswaFHJAriUSuEk+P4S9JcKC2HaZ/oOiFnGACuBvuYAosonRSUBXx0MzCVl9oKX1TOg9PVbga7VPx+z6NHOoUjZCEgkMI/FOyZdHrRBs4dgE3KqdCc2LEAgSbQAliksBoLQHqB/Dfe+iPMLMYCiHDEGkCL7PyBMY9vzWXFgDsTOjJNhaQGC27N0fjpotkol6624PfkYhM6d3yXX5cbes/4gIdAxGwH3jjqXFVHC4muppChjxzsL0HmGn6N/pY/kVFekmq0YwBssQoIo6wy/AxdDdjjQ3hRCvGSupHN+2kRnWX+woM/8aPJ5b8QaqMQpX04t8PQIJwITKp/nktjcAlY3gRVsLjZDAppzdoTYAqhkIsqZFWv0X1LtaCASXsA966CKKnsxwGywCgksj0LZuzv+mgNUAzMFtq9onZ/ixr+JgPId7jF3vd6tCPqwu6gzOykYAcowms/jVc83/i0SiBskbmp5a8g4wMsqAcRrHyzDjPVX6C+BXrs6D90eUUz3MQBu3aHOzi6NQ+YAX3vp+5IDCISBbbnRrPN5NLfS/Y77tCWFtsvOT1QzMm5RRFLA0fOxmtoRslMidsO6iWXPDmR9YfmBwGoFNBr0z/YmTy6KNlmhXwR7awd4/l0MENifUH7rDmXdLxxAGQAkDuR33YY8HJhS0Jvfw5dJbm1FBPLIsyivHU24F1WXt6qMCupRhBUxsSMuuPea6AKp7ufM8EusWATNtPu+0SwzmjmvMRg3Ud7zbNAOUXq36BebrHkR9Z3bk8lwHr5hTkVETevwIOGeCFOGwqVNqDmA4qxYAJApcAtgU2XUCwNKCAriScoq9FhvNRh6oW5kN3SVSg4I9K+l4UI2pu6/EG9yFocnSilYBttTm6WYoyxGkQYuEKtGKPH9Fv0KdymWxKiKNmFIDMDKANGrQeX/gLyX0iw85kBTZA6YRXKDQ8SAz3e1hSK+ay9Z7okGHhgstrncszT6Kh0h75EMyM+Jzo+bgrNltAYB+o0dCEbeJskziZZzwEURJNCJZQn3l+g3nUKN651lmaeaEANkU7CKjAmmbUiwc3u05wCPyA6Pt4nQd8ZyGvI3IB60kQx62eBgvpsNbjey3Ik+qdMfoV+4QIZyyyStfzR24OxfngYcPFX2KS3LAsxAj8IR1O6jv0b8UztAZ3nyVhN+HLfwCwX0UKADNe4x7DzJ9CEHCqOEwh3ikYLuL9E2wilT/KL7MfxUoAFVZlXX7Z+K/i6VgW9tB4gJJrRwS9Rknu0AQz+yQsUlJQZZZQ+59SBpPEB/VEk+HEm1gHtftJnw/Ef547joTEH2f1DjHgnubitMpW1yICI+u0POtMLvCZsFU1oiCIb4BDrzIai6uEOi6vJGFoPupGOK8fCi2gHTEQRxd374WZghnkE/ycCgF2vQSHRKgATYuT37jpA1ztLT4fLoLN49xW8904/j4okpSMWOErULZOMI6Jk5dxxgoq62ivbMVj7oeJ3ijAFXYgCqLzaS4W6dVKIviqJ3DYJkCi53NN3wMWugoTDhPiCe/Z8ZErihgJ9dyXKu7sYn7KV0Faessu5QiC/gXhLDOqTGPPmzhn4cd9sUFJbh1h3qwgDoKX/P544DPjEEC1PsVhJKUA/k7QSPSKDPWirtcfZ6a2sT5hRTyYFsCibckbwgJOfHdpPVv/lFRUhg0OebQqU8aV2y/LU1wOfoFxzzVnbFfNWsCb8KsWkKHHyG+/Nvj/sbDszLiwfDPQfoypCKujFhmUTmx6H5wITo+oc9Jp5YJmsd25IxuTEIbz51u+IIlab+UVoAArQFA5h534UYCYD2lI9HvikUl6Lld+hPmH6A/o8Vv2XmN8LQ02DbFBTuEMk5jjBdl2lAwlOwDQ7YJEETax0hEsHgY5khrMMQD8/rfucNjtRi0OsGSDpcYk6Gg07J3R446C+ZHG4KPPbN6j+ZAmPHrTMZYB/dyKfoz6agqLS8FEnIbRGxz1xvvwoBZvzMFDeIOlYk3KNxh7hPUfzB+bnjAEBzW2+VLF6Oo80zH6yIWCNF2UgHR55Gl0Txzwy7QJeUKDMI8UesOYgVQf3fmoJZuRIza5Y99C9MQaikPdpigvQQ5yY13M+3nSjuKmZTgPBmW9b92AsDwHyAcyCAfskB2ZND5dAsngTXKX7+XJcs0e9ypx0VnVRnynTUGXaBUFqAigO2ZeYLLUxByYHuplCpXD5B/wrxDdxFyDtkUArJr0Mju9ebpiCSp3CHlnzwjq1zKWbvnwxIC6kpF/e5MzpHyifcu9tToX+AGkQmiOg1U6aGAE4D8nbMjcwcCAGAdTVI/XMR144Edyg/h2mEnDFawF18faFB6oHP1m0QJHyv+DNJALAFYEFc1++bgrPVwh3SQUJ70fdGj5IDbENunKBKBAzxQutLMSl+RT93xcwB9Ta5p7MqU/R8XGQT96dPAvP1EdDvb0CQKWjV/ywGjwh3iBcZk5YxUeAF+l+4PRnTDRm0E8p8l7d90HtEt6ZgQQnNpzAA6RFB5gCvgmfHKQuFxTcioAMfoso3gToNEvq9fe55vQdlOlwmvkJMlT8m9Me0AOT2aABgcogG4UgGwVlhlUMpUd4VFTkbDWr0V9r9kQsURmywHuxGKfbY8noZ7khYNxqIR5QJwz49qsj4NiSwEdym0+jCAd8bnnDamQvAS+dHVH4GvRqBCv3cVcB92omwf01ynGUXiJmAcOO/5YCp+Y4MbAFw7Ut2hA7MjSuTrHGJfpbSDwYA3lusl6vC5QD4ZbiT/foscNMjYm8kY51G71wgCOgbDiB1UqSR8vGYLUDn/AR8j3CtEgPpLGiUcp9SupZJi9TYFOT8jGkBDt8+4YAo/nC703BPFiBAPCO+48DUMgF5S/QXyH4Cd8H6I59HGm89CLOdGNDGN6YAfknnAtncxC+yEZ0D0j5xoF4zyVQ9dbPa/ScYATjomRV8yjrn7QnbiTRvS0xyU/MmpsOlBwmFTevj0tZHpEH5USbAw4PAuoj7QuyELQb6dSTtAKpvEf9O8T+H/pmJQfAGDVYe0a0puA0JytujYhY6t6dZdkan4N71PSi/NAKQehBhhGbzyBupfECUrcgZU8ET7jFhGhwhVv/z6vpjQM9MwLUjQdez7slGIHL7l6B/qhIecd/nKaF/pu9Lbcsi0dLg3InsEW2ZgqTCrf86LPZhK9hXJmDisHZCGKy1I1ShX/J8tG3W3kA1ecNkM+Ja3BGaWwB6acfV81T5Jw0yBzQS4CD48LHc+eGQAJMG+TnxmgO00hAMTEHZNiG2aaGfTl11sZgvCc1E2kSV9G9SUdDg0jpRNIj1701B4FeCvrUxK1Roz3qFnsnQ53zU9PKp0Q/igDUGXchDl/vRTD6s1PS9Sd5hGP2fs2LUHCicn0QG9oUCDXiGR5Wn+etKt2mwyAehVUV0Pk+ur+a5/EbYXKqpmQhVvenpNOBi7/ZYnyEaxrzdmcJfm16aSL1Ok5fDHY7XjgZrF6g9hcKVKiWOoZMNC6m8TfN/MDGK6P/4MfbWukAEYIU+bfoxaNAmGchcAwh27/S9uIv7TOhkW7TsG3+Hdkndip+DdOrGIxJTEK1L7N4798oY/gpoQsroj9AHQx8K6zXEOxdIWGQD8Yi6zXm2nNjKHZcEwMKMHHDF9MIFkjxDP+o+Bz8zQVgRVzfS8ZYGt3B/7/MsTgULYCf6ILilQecRga7aiYYj9L0/MTVJ94eTBnGS3eAM6WnBd/5cZ78i+qWrpPtX+xqn6sIHfaWhMZiZA+PwrVMX6L9Wa7AROMgIWOx7jEgDK7L8iQOZ3hf6RQh7bs+aCb7dkRJPoX/m03eC4fldGiw9oh1TENR/Hw3rfsa9vRDL0olMUK90Q/2XdkBqMLtFzNcaK01ba/ip06AagT4mNI0GyQU6vmr1vzACZ7ceGDDxJk+Og/ahpBdIzlEUA3ELYmUJd3GQAGrfXMKZBfTPs9d3goGXNLj1iILPszYF1pOEBDQpWYimRnamkh27UFh3HMBXvHAU/WQjoBPo98BTErvz34xAVP9XTyPQQB+E/efNC8VPedi9UbIJLvlBM4zWQHZgyMIl/1TxiwbpIP4c+mfyt0Hf0YCVt9WXHpE8yrVZhXHkARlfjiJpZdYTSe5Zf2cXqLQMSEf1muCZjgOjXAZN/lT2JfqvhTAKpxa3Cj5efPlSTY9oB0LGdmRMm2AZHp1S7WVFzhf6/g7uoviDBvkh6J+V+jao33jep0GuP0/Ki3GgNp0pEHeIdpQpV6OIVmjCFbdH3KHOBfKar3sXaEAtgG3w4K3lGaJYgz29YpU0oqBCJECNB4EYOfz9z7crGo9gBK4aGwhTl82Mg79igq7JNE7aC0H/igmsy1iAItIN6KvMZ15/HNfy7sxgSYNjVa8ekQTHxbDJHergntOY+pdRPtEJBNT69nDNl6K8NBfCHP8gQj9vahR9nj+L+hBJHrOfZAEQ6+yMN0nBAP7jq6P/k+JgfibA5LndDl+4IL6Be4Z1QG2jTdp6O5Uacz7dBuX8Dg3gjbt6vs7alKYgOP07Lz4Y/JLNDeqn4kDnAhWm4Kt1gQZC+2x8WPrq/3CRNPoFfVygHOT/FBYAV035MHj8d/Wtiv+L4G4fmogEAIfVjIshGg2XGzMzvgtWf6f4fwP0z/TtmGOtC8rf0kBeEJr1OTBgQAsrgimQG0GpcZGyuEkNB+BCQVyA/kvJIG0KtsC4GCcgW0u7EtY+5sKt0WF4c/SbBTDv/IQ+CKlwoF5A94fBMSBGcoHMFJgdAN0A3dX9UyVdecF0konIJ3OjbAMUzYpT1VkfxX8Yy6oKp6SiQWypDGGISzMmW2cKCg7KgDF16Efh/+Rjie/WBfq6Rsle0IDX6N4MmvmCx4Rv9hsZ/ZdkhuPRjce4tL66QJUvhJgJR7IDwQuKd0VBcyh2Y8TMKPK2Td1ZbWBXpWZZv5Rnw8QASBB82AA9ABXWj2hQeUQLU+DFtSO0VDaOdRSwZnAXNGjugYbGkQyDuCdHznTJvoTO6j+gbjhMr7XTq/8DOL7S12KS4kel+0Mb/noAEQ/Uw31awn3X59mHfkS5ZpoGdRBc+0WWQf9woKRBGRgcALlJB531F4HSA+AipfWr5wMCMRzEpXuDAXxFQC8tg3/gQ4DH4j24XYs1Y+QN/84XWF8MR7GgkzE9AJDHn8NfKYIVP+ZOcQYUFg8au1zInGoAbhkaZW5IZSxy5gb6nfkdwDoILvyikie3NKD2ggFW8P70IA2VkyzJpCNGIDhCfGQmkJrvoN+q/xQDLLaTpVHLIeazBIQGWSBiMexjZzX8/c978xugR2EfQG3yBOrNqiB+4/OQ4+SXSJvcM+Lwe9A/03ch+Jg/Zn40u9Q9HEAOG6CKH5ULJLPt0sD0QKCSUt0/M91xHQaAbo9y+zkJ12phXDpmuW+mtSPEstB3Is589RiYdf9pHBj34AbD9aCGwvY9geb78mG9O9BPDYBKegvos35ZE4Py8QsxiAAUg2BA5wYdDeANjlR/9cFUYWKQrbBd3hExC5rVvCnmEugtB77qs6EZqB/EgWRW7RqKVOh+4gCL5er64L9X5gCGRb2V52OZ0gtCpoSwcJlMPZ0Fy6AUTqrxytt6BGHtQ//cEfpCDKK2Xuv7WHlLg/rluTS3cF3/BkS5qqx3C/9HiqVen/dAkRqEZtHzwVjt66B5ysSLtZvWyDI5a6YjJDJk9DsHznZfszyZgAx68YVSEbF92IiSErxYFkUHfamMLYv6mBEhhwx3Euv1dejLaUESKu78okQDVDGAj97QQHZxlfLiTV6RAwXcc2XzGFhUvuRBRgAoXKAs8dGvSkylPA/xo0kYly/EdtIwahwIH/N5/kuYTg+DEb0gRnmuWWyQCOQp9EdqFjpfwj1PQ+q/9YKpfs78rkGoaIAqBqhpcKvsc8qQysgzvCKiv8E0lujvml2TSWbHpxRnm+dvksn1IldxhBAROKiPgxqXfs5BL8nJEwBvE9llJEGsD2N3axzhqArrp6C/jXtL3yrLigndK6JKA9TpngZn3QHMMKCw+1xTKdTC9bcMR6iNOlffJuWzCyQ9yxyCzgPVdGnQMknO/HL4SNFRFOpVk12gAwHHBR9SMaCcb4xyV4x7ymfayzY9gH6F8gIJJfR73FuxeRkOYDEXLk3loKz8on0a9ETKszcxXdqXj6L4Z95gnY8lDRYuEMcA9/vaEDhKcEogqaFOHRzx3CCMDoI10+CIOFZMU+ZImUX7IiX8CayfQv8HVH7K988BULg9K9doxy8q7Xz5iijbH4Q0eJ2IwhLVK4ofxIeEaUX20gXyD2IAUGk45C3pkigLq2FHkY651x0XSHBcAj3EwTN/dcdH6goI0blthGP1Fvo9vlfQf4r7WPz2cKozAmiYkHcotlT4rl2m5ZvSMnUXK+kMPoJwGRCMGtOl4s8ttcHsDfD+VY3x5jXLqbVo9VooGIG0EQEEyQUS6KPzecj5OQ5tbHk5Gj0OWzU7Rfz3BfTLIGoN/T3c24j6jTAsmCD50iCALjw37KBlxAYdDYZfTVMvCTEK4Sr0EYDrDRr1D/qsAgDrVjJxO3XKJRmkkvhgXw0DPU5xMnRvXiUOcN+dS3PMEfmZlz/6jWFAmmlcTtosV08g6TV8QG5cZQLu9/IK1PAyHO6Y0OcPaZ8y9eNkNDSI6chLTWvTuJMyQAAu+0IdB0ojEPKgShrd8zaZOM+tJNtx9jm3Rp4VOgRNwoRp48DCBeIjv+lQAj1nFktoyb+E/pa38zHuLVU/iwIX99V+jwn17f+YlCpSn3pdpYkwQSFr4tIRQkTwvgsU9obYledga3kG/bRA4HIwTNNLGJDNtSmUTRfITw13Zq5myRcy7vnRBrtdTdJWYZl9fa3yP8O9FdNzACSIP2WCSaP6osxlEGRMqt8HTFYhAfpwmBrckSiR1T/ooy4Q0wZhOJ/PT6Hf1zk5YPmI/kOkGX9NbNMFQqzPFmCh+zfA7zMsQHzn7fwk7tOOfKt4EET5ngnsGumgsy1ZbZ5Ctg91JyQdwaLi3mqqaDhzIBsBG8gUvw3hxTiln0ynduAfhpjHHAZYS/ORdlwgyYCKrOOFBh30O0UmOn4RAGiD6qzkH+CeiisXqFPw7u10TFi7Rp3/80T/Z0+RXaCRYNqFAQsXyCGOyJDIK2UgHqziWYpfDh7pN1VNsGPqEfOd1i4QmrOcaiNgxBjpgmYJ198G8bsqv8P9ggNNsXoVQpomO1CAu4Nv5Rq1BmE5C525qH/LGC57C2Aey8oFsr/xKjpBRIrz+YWp4gCGPqo/JugH6KvriQml+i8tgFQiXi711ax9j4CwTUDIFBFw1Sy0RJL54lSqic8B5PSdHXjDhKVB2LEBI/xxLF6lEbULqXzHd4V+txUIjRn67P3rKDKrX5cG7cv0hcJXtOZWHjESOPjBVsmB6bVen6TUwx3SSuXf24DG3a9V/iPcP9L91E/xHACZDPsO0i0TKJm8RqpP1LiaqSIhIAb1Dwe9X0ZksLwf4fX2GeQCiVtlQ+vNjV+f/Hth+V7QBDFwuUDFt/DsOy7zCsxMRnBhBNKXY45ZD34i5s0p80dxX2yQPgdAQ4ZO8UPRf8OEhhJrh6dIWQSMxXhk9d9aAGvJH3i9bZjc/7GZ/Db0n8lfOph24KDiOT12gY6hUD6IKnV4cAQYgBq8T1lcpfEspfqKAyXoOfVvg+IhGXaYUF5IzUbLkWYBokii7neNbpl0S9QulxA5WIkJ/UC2NJc/kszJuSZssKYbQSAa2FVnJShgOKCv1lnjVTAwoilf8mOQ6AoJvsb9Q9BzjbtAGfoLMhQ+0i0WNplwmxh/IrJ0HNkCICI73u70vYn+j+4NG5zfrv7PJI7QuY9sGQ4kL4ho4ICOmv7oER9Gj5lds1Cido3718p+jwa1C3Rb88YspC7zlLboECUyKONan48x090IMqwLVTxC4DY0jT+C/jMFuB/AmP8vYwD8v6SO4AJlGnCD9R4IKx67QxyQZAF+ruyf6P4zLV0gVB4/tKYlw0a+Y0KbxP0Q2Rms+RgzFxMoRBYy8Mawj/Rkln80DY8KxvT+2WKL4s+OzeJTphwKr+Zm2be4fwz6ctdmZeMCoTEFd/TYvwUkl++6QtXaRvRMWguAqezlRhAc+mP2lt0bv60E12R/UP2f6Rj0wMvuh4p3NGlg93+QnJ9jGoHr3N26FnxYpUF/S3xvKvuPFb9VNi5QWXlbM/T81dOGU7SVSP2fuRHrhQbZDjAfRkT/QGyA0CAMVO7WH0xThYVgABcNCgvAt0Er3LvK57MzOfRpoGsCcT71VJ/kfxHoOW24QGXlazJUU5KL9ItF1cVBhVCGQe+nJqyZD47maBBqCyDa6G4tvzNNzMf5TIOgFoBUvnEAIyC+HGIzJl4kF2n4o/mPQL+BeKn8PqgqtPw5v4g5FgKGRSf9jKWmYMLiSJkRM6LmETW98qqczx9MZASMEEMsw2zmEbCp/NtNbFKL+9II9PBdufW/QPHz+fA26MF/Nvmwj35oy+KuaKfPZiNVcudfwe5sGSJgJO1OflG4PYpoH/a0zN+QStn7W9MM9MM5cFANuz3hk/ajswYr3yc9k966339bLGti5agqz5RcIGr0KR+2yVDD/c5zEmXsEEfyfxDVf6LBlSF7Yp0UXSFJ408nC4IB0h/0zQF+hc68doF+Q6BpJSI3ZPQi3e3gkMpHoP8A8VL/nas8RZQfqXI0La+aJxgpFP+UoPqOltFyygjiETQ994z82Dj1N54t6I8l0WMHi0t8HvGaMMnQRAKb43pmpAemIuB9AixrxrpZVwlAvxBzpvJGEAqUy92DwIdHxqFLizY8YkMA9nxM8FLDQbBZD7EhIT9b/m3pNAL8pRl5QnzYEZcpAAfB6YbPbeBrzTBHLNJaUk/VfEb8nYK/rV+5QJ5KhyfVP+DD86QdkCw6X8ibVcdBuAeTxPoRK/EPJn1ddO7XcdBRNq46dp7PJzeFzpmsigi73LbpKhf1dGrpAmEX+qFe+LAxmdtUSCZaT3NR9K5lUvz5WQGSiSjGzUbm70yE8svDoSmb9y8cCI7+HbK7hwO55b2oegIUPlJ31et6ALULhFfWAM2iSbhSs/aSulSLZu0FWT1VZrPANkHcnvEvUIA8+SuxO2TfIONbpcyHo6rJu1aMRxU7KauVlYJ/xIHnpyoXqOtlDf3y1BLUC5bdJ3HEEzxrL4iKhvLubo9n8z79xYmj3ut1IGKC8YGPR+IDd5f1fR7xXSrcy5/2cG4b3LlAuMPpW4Nw2/AmLS1AB/2BFDBk9HdDlDV/YRoJkiNpt8gB1/opkMMsvrgvdDvNB3B/jfW7aTcuEDb08wL6eALqdyGyOFGkpPPDWnGEuhB5zMu9JV7N7e9J8gQgPgcQm1DcEYpbc6B+IvbhDO9r1vU7Z/sGjQu06PETYvzE7SAkt8RQG2B9ZtMLDgx3z+T3IH5gmn9RYr8I8U4o6IlYcIEWNKhi5ZdM+Fl9v9MgNttwgc6047D/lE3oU1b51blGf1eWoayXy0fM/83J3P3z646Wv+YfbxCxL+T1TIaZjb2nfJzAs/SL9P1mm5ULhI2wWFquu1r28Jgdd6bz5vsWkQOjOtVc8Q+kCsYAAvT9C8G5dQJ6tgMfppUi2zm12WCjZfXTiI8GuIU+flh27XAjZiPux9pZIj6UrtS/BP8zjWi05w+WqL7ns/FlOKCxAzsjPprn67P7bfpLvrsTq7RvGfAL0A9y2VN9WSwBPSQDfbiW+/sXU7gHetbMPL8MdzUFBQCg9aebQiKa96HwD6r5p40B3LhAll5YBuwZh3dpaTfHstj1kx8tbw33NycGPeh1UbYD3CzB/VgWf2ySP9js+VWJACWXnw7/66CPm57V+SnbLyzDsvN/PgnuUWn6RbG6DfoDU/pFjfc6+V6ffpAe+UUfpm27eaPI39X8Qyn75aPaqXyLz2JlvvbXeLO/+8KY9lygMr3zi34kNQ76rt8yNFvajVz5T3Ah3/m5boNSDRD/4ZfgHtVSxRGKZ96nn5Lp2362b4P+3JA/kPaGrj2c/a7+CbzvpPL+TAY9atwrSX42/R4h96MkF2jvsj+SRpGrzi562Pwuy1+28B9I4urkU/P8gXtvdq0YnxmEPy3qD1ygP5g+m3NxNcUM/6I8NpO+1xmh6qXf7s3+wfS/kQD/P13pbxDjn57D0gX6Penr+SWfvoL4/9OvSf/gVv4FFuCPTwB/fhv+TPp77mn+ufS/jAB876+awxkF1j/M+O+n9T2A9T2GvQHeXvjn0l9wF2h7lJc3H+hE8e2+xY2R/0k02H4qog0f3XBrns/8+dRv5QcW4E8/wrhJixvY5W2+8k75/wwOlBLertx6nLLf5helt8+sfs4F+u1EWj2SLB/aVw/8DzuTtL68QNb1+relrMJLpT648eYLILcP4H+7N1tN4ln6uXeBXnfy41LLb7GX73ihAP39yzP/VrpF9l1xxyPaPft5+pH3zeJu7lmAd4NtXvWjUtPXFZevNx5czK8H/89Lo8jnV54WxaLx4sIfTO/eL954tfmVC/SzCv4HpWbf3+uLnkfAurwiH14g+0cp0QO3/l3yVDmWxfWIP5YeQf+5X/TqG2FPL/kFdrMAZP+tpULTx3+O4t+Qinbgn3D61yl7+eW/P0sXJGW/tBIPAuVHaWcDXvhFdMnSAuyv5xM1/451S5Wc32I/b/D7L9yLBRjOgcNwn/jwL6VKnQ9UvxVgZ+WXkWKzx/+b8fN0i/5949Bbhm0X6Ndp+ubewkdJfusGMU+ZY2r6TIbuor8/lU6NnDiz6x+GkcYrg1DW9OlemOsWO9Dfswzbvwu03+ypsn8ouPZEAnr9baYj6HsuSsZug151/4JTZEgdMU/nku6X+tTs0T8y+hnhLKR8C/18s3vZrLcAnwB9cfYnTOcR8/yRdvrbZgb3+EuAGOoU/eVAf5rEpTkdPPPyOw6Uv6s3yJsKdPgpeXWiX0P/FveNF7ThAr0DenfqYyPAqXgWln/Glf3+kVjBlLCfxzlI3/9z3j+n+Osv5Y/FGwdyS23D11IlF5+lfTXz2ibcEeOJC/QU6119qvzx/8IStL5VVf8NpfiRZJ7nv/hQ7NbGktYv/7V4uCo7QjnTjbtMNaTL2hc2YdsgNBbgBda7U/1+fKQ87qB49DRwfd9xwNQ/ghH4J/wilmrAcNT3fCxtgjpCPQHUTdpOW+56R4nush1WUIM7F+iRau/qRzpT6qTlRCzdPwGgGrv7GZBd/ksIqj/kP8zFWf+1NGBkjojL7p/fFLo/1hTQ58XH/Gt35kgnRte0q0QP/SXP9lygVx7OSsE/tJ6Fr5+KRxkASAO+UCJgsgwjNJkzrG6S/nWpU8+WJ3xDdH//n9Ts+ota5a/JR8l/qCOakPWhQdiwBpUFeKv13yN+Q1od6vLNHwd6peYd6PNC5QDcIPi/WPw3U/3/b+TfY65dIDIg5X/jpMHK7AeJsC4mIvChHG/bGjx/Elyuc4dFC9CvqVXiLzonZSq0fnKKTovhns+8CyT/ZJfdoZF/auovSI5pOGo579rdWg5vc51tLsmmwDJiCqpp7dnMMlprGrR8QAP93gvacIEqY3rLjWfFoRLmgulgW8ULjewO0uG7wr8VflC9mYIj7eDfhvucxvxYMeSmq+PbSvVgZd/ZhCZT1HHVlCBb4gcp04NGOlLlrolYu0CPEZ9r9rT+/X8LHAXqO88nRAKlvOVfYlmG3ok4EF2gEYiBv8wIMKDFdQGCyz6osaE86P4S99H7z77QFhLihq04sLYGXRA9YsWCD1QVCPADiM81DeiR5MjZ7slAqftzGADQe2+JGwz9I3LALhygMOBO/n9JKgXvTo4pfkI/K/sxyO2JAbFD3HorWZcNzkyNIpptFzJ94hqFfnf4AHx3M35Q+YQDj14s0ZoK/rvuUBLTQYhH9Yqoh7/xNtGIzf6KZPirbl/WwSvxwYmRFH8oyrFRYUWxTNmnPy/lnXqK/kUAUPKhcIF+geLfAn33n1qa1GGvDHzD2fgvgDgIlgaDaRDh/tKR/TUpYjLU8hv/wbnPQbA0QCAAW4MwWGZCrOfEsdxCboEMcmKN9Q1TkCu/u+n+JOilZak2FtaA6/nOT3yDLYNe3J6DT1gNceCwoSf0TxqcsfKwgf42IyAoZDU/oe8t+UYQNyDQq/8Tdf9IA/kE4nzepKj++anOYzKUNamSLMAODe44sKnsc769cCN1+r5oR9+MMZXPgvY7oWIB4HeQxoyYB/78UwL5L5cSpBYWAI5yRIOQmaAZOvIoL/yfAOAdS0p7pAHDZ37Rhgv0CPRydh/3mwQgI7DjBeWPNANxIJgItgCYrwP9JSp/nQijKC1ARL/cAiri4D4UxhzCS9vKq9DInfe/MAsf+0WNC/QJ6KVYQbx7tfCFDT0oc28K2B0i0FsEzDeOxrQYAx4Ej2kK/A25P2cEWIyDgOhv/kz9PYZ/rI2QQW+GVhZAIoFiv+72rgNke+kyJn5MhlSzdIFSzSfKPlyeGzwRIlh5x0xutrAAiOGB0cC8I/dzEOE+QjDwRzigfs4IlUhYRyyOZArEF1o/ETNrMKwIarCfCLXOhD2nKBAD0UeSmfQ19y7QG2Uf8zd+Trak68UPBKVxKKxLuHuDqPgxY99gScztmabgbHPRYA469tzXX5qC9jB0kv/jsObirLQ2hnhX/7G3fBdI7wjhXhYutKXjXjNhJ4/KLEAbcE3tAj0APVoR1HFtlVFL+hZTNeJR3AgKAQDoUQB/7M0fXNA/aXBeI1HBbzYCqlPik9qrJkI/eEHRR+Lwt1D/je5/Z7rPlGEZzo0rUwe+S/Q/JYNbgOLu+x/CvRv3OKAjmBR/8IIMjr0REBr4Uf5jrjU2v3/SgLdn/AlHSJyf4LiDAB21vn2uhoR+MwvBAlBXI47iHEMo8iwskcCKU3RpnzaZgJtiSYbv+0cYC4rv457yXQRcUKJKtZpn6A9tZL/2c8wughfElJjNDgt/zWSbBKfsyneE2nDkp1ISGqbiN01/nY8K3oFNuM83giRcVjLQiHk+OwYg0GAW7K70WNAFe0zAkhhQMsy3QfeVfSzu436h8rNMsyLhVKpwROyVRoBr1AuSxpMJg3ynYEMPvx30+75EX2lfRSoIwSxJJkNGvzwKiDWD+pdbQBqLVymr465t4Ro9ZcJipMosxCB4gft4qsY950uSVNqraLChSfhNZtP916mEQAH3kUCfz7omohtBZkBYXR2/jQOl72EWICI43FGIuBc17zTIjWeNDYE4brGDO+kglzLWtwYBvCWhcusBWe8g3X0j7CnuOX+r8qFyLC6hOZdCbo2AuD3zbKf+gUAGpsHpAh28fNqqEA0zBxDH/iQxXEY4sm5mzQ1E/6dCvBqB3gLocPD2PEPUpZnsNVuvuP50/HGgNuhvmYC2mcxvywV6iftYyZnOJnQCLVNGV2cESs8HVCNt5ELHdhLlpfU5GjYOwK3TRymhX2LfC67xVqbe3km6XzhgcC8tQOH9jzi3bQvgIiRhBlgmrLtBqDt6xYQ56soFeob7Htac6byd8UKgwx/fmkdulTBMTxQ6vsk4LFwgg75lUMmU0e8cmL6T7+WLNOhvFJRwwI0AAr6zEUCqCaeQmiGcygzcR/8RhaEXdX4RN1m7Rim/YsIsFs8BnuJ+S+XnUxX0i8tZ+fUwyi5Q6fkA87dPHrpAJjGz2ozOA6T7R/gWAWtunVaXRiqVaoLUdg4ASvQvXCAnDAJ5rKgZ1JvFQum8VpZEdtztVpu7kSlT3JVe5hdMaJ4DyMTLU2vcz7xLqrMGFR/UKbQ2CUBHygetLwZhbswC/dJ5dO9ppqzpOUNfKAO9VSprDzPuYTKytDlanRlYTXOHxz43YUAVDV+DmnMFH1HpzcW4WS7GiPiaBnYq04AbsGtU2pfKXMNGBKDPAXZwjy2Vj7h59akK+irc3AOHtrOIiGZUXg3sW7909pELNOIQZ9UpfbtNdLWRt+XCZdW6qlND8qQaBJfZw1FM9y5Qbgn2fLIXlOYAomG5IlHNuKUBnVUVURoEE9HCICAUl88BHuGe87fQF52xhv4M72S4/CMRVwPCqb3T5ognzyer/B0XaOTNoGuLMKDcIb4mpyF/VYCCP/ZSgs5+4gK1NIhDhLHixDyblbS1jbeAVjTgsglwxPYlVUqDkPOga7F4G5SKBaCBfOGoKh9B/36smI6YyWjmzE770hQMqh/U4Gx0+T8VMWQnipCgSgO6dq8ZsSaq/0UAgFjswoCQAXWCeSqSkDO368pSqmlgdlWuyeFB03WIleGXhxnONsu3QT9X+dzJLfSpWIOAJzBhyDd5wnG4d4Tk/JQukEB/xHxnBETIbAQOdmHPadi12QgM70drBHmsnnHhFRWyRzolNCh9pELxxwBApsSztcV16sC/TSECXNMg9RYu4Qw838bKNNvaBbrBPeU/hT6iKPMxD201xoFZE/7VhUG8cn4uShw4DuDM/Odtbl0gRq/olOT+pLmXjlS50ugN+pFwP1Bjd+ECXZVf4Sx3nh0hJoOjn2fbLadJB9RRvKFBhfXWL4r5lWuUnwPcQH/Q3x76yoon0L/VLkUi0EuN2ofhiPfKM/M1KfFfywFE9I849IihsO8LK7z0NDTOOixWRJEDALEGCxfIP18FQ9CBPnEgb1Ocep1K4xmKGzQI9Wu/qDMINnOq//b15JVU+RqXm9CP9W0A0F0licGYXSCkm55SnEfJ4GsWyCaMahd1R4e+Dq37RducFzRiYXBGwGdFctBLTBuO8TUzjZXQIoqiHDfVvyv7KBMregdTxKra59l1KNz6RTEvBuG7BtnPQZ/30o658SgbjLlrSxGHWR0OdIh3VIUBJQ2uzxeOA2PaBEb/Acn5UkT9WypB366jkY9jfQJ0TA7ULtBX7wJRZlRk8I3IrheaTFyviuUIGzRIqRTPgOPjFKlHRwNUZ1HnT4PQvwox6O+SJG0YUEI/FhfQLzqM6ZguzbkSw/e1UvKCike/YzpCE99IxHAX6MujhUEZRr8NR9taM2ErRdlm58flMz+7LlDFkKDmG3fItinrps0FrlwgRGJY3TGHVrfyJgBY+UUxv3oOUEOfWj6CPkh2duQeTL2FYp5eWg4Iit1NoQL3durrqrQYAHRVdoFGHNGlMYe4cYSq+Wu+UxaUGVBMi/4uz46vxIF8JJqNNO41ybg1aw7Iwln916Yy1t7eGF28NX0NB6qM+fo5wNrbQVq/ZwT6M5Otp+zuqPKKgDIZ4hn6w22c3wKyysYFunA79f04gP+0mR19UuNqEWQ70kMxmupNqkQX9O4ENBNjoexBoEc81fk/jvvod2W1dZvs+xIYjlRHbPaITFpR5WzRwDcg0aDhSXgZLijdtBO2AfXZNfSlWQP99qxMrEmHZCI35A1Q0JEvDJ+vy+c5pvMzznhgdsgXeyVtnNqNZB8kjbgXcnQQI6HcmtH9zZIbTAM0zcAef6eV1ptSKXg1BWVxiiwEBvs0iJWeAflF8PrLArSrytDPZ19AX9pIPtLAOm+lPVx+4V+/HIXiB98JlUcB5AVl/+fKTEqoMCgGAH1BzOAfHgN3HMiaKIkuxwC1Ci/R/6WNCxcIsR8rNjuYUwO/mWdTkN4cEVY8pgGf6l1P9ov6l+F2oB8RvK6XTV0o/ivPu850ukvBDjD6h2to0f1iGexOqPFhxMY22WP4lSal8PVIk//E/THXYpTgZbIYRyMNQXaucfjOGNc+RZvMAdsg2YVmr7stUBpQSNqaAlMWg68MX7RQGlQ8q2kQ53RWLF+G+zXQlzaaryihc6B0wU9+KTre+UGyA34JKX6kh8GXuOx+aDwG52kOjfjl4NVroeWKopOZOTCmYq6dloTsDHqMIhQeSJ0gkCFsE+Yl9Z7E7aFXQq4tmpUOX4F49ojitVjXz3ne06B9GW4H+lbT14/U7F7xI25AGmWRBJC1F5QeBrtq/3IysC80gY1BR5/RiL2YL0StA/R5Jzgt5E8AvSrtM8W1coHS0wCkvF9FTBhxLzBxv7kdyG7IVL0jNXDxRL8xILi7+1nWz0kWNKC8fiNMQRzzxdlR1U89UUBfigL0igZ6IZo0gXmI80OZ4/A2INCCMBxq6I4QRwsojcBkwmUBpobj74iJFyTTl5xrXxJOaQEwVhBfmYLIASeDbIfp+6UycoAR0A367M2zk5NNgYxwxIcDCvfoKXm9bTPR4Drr8yi/EfYJ9BFBLM1GalDmk+JXt8pFUe2FIR5TvpQxeuTw1xjgt0EpIB7peE1MqDNHH3M7/Vem+UWgxgIM65YzJBlYZrisOhdojOslCAY9Ig0GgT6QATGT9jRl09ZUmFZ3qNzKMjiuAgPvYY8G4SyAgW8W9yPol3IZ3KCS3YoJqZKN/rk9nbh9YhGFZzry04D0QAARyfYZ9JhMAgC+HQRmwpjkiegv9qNcAguKOSCKHxWIY5GxvnaBsttTc28xc1ocZK1T0xv0x/zTmgKRU+kRIVIl1dvQ2h2d/bZ1Lvaghb7VGBf34b7OlzRo5smeD38JGPNfXl8NJkbZOJjiV+8/fsa0A5gGRN+JYCfHthZ0jdXwEioyqBjFHnImYTfAunoRqHOBXM4M/bQ1Y/gU8hZ43oBOvhDI8wk2IfXkEE/BsXcS2wAvaVC/C/QA+lM00vKB4ud8Q4OCWnFEv8s+l2m/koIYB7P/k41ATtfZr6D+Bz335Tuh7h5Fxca2+4KFyFBkW0mp9v7hIK5doOrTmgJQ5dwCTNy38hcH5qw5HwAL9Jfq/8YUbHpED2mQboOmpd5Dn/YptLyDO7dc0GCM1Ceq/KF5h/VE/5V5YgRGytsRZgRs0MgBfrvLKZrBwmnMw8z4wjkTob9A/77693rEIdL+aj4lwmoBfVH/g65CLA7qK7s6nUeEngbSGHIbVKGf9kNYketfKn7rkOR+naJdH3NEm+dyF1xwHAcr9KcoFp9BbUA2BJEGmQOXuLPVTiwIC0myHROIEgAwjrML1KF/iwaW58lVMxakhWe0E3N8QwyIIQGriUemYKYsW+9zYsAmnDkTvxBTrfCZzxO3rb5k7fasaVDOx4rJCFhSGhyhXu4C8adT/9d+D6dB4AC8xn0evguEOMMR/+aVjiLDXhBeuUDB3e+gLzTIkqcFCfR5yQdSSADHYucOSTPV8dkjQqi/fTJQfSHmFvpJKB8qfs93NNg0xPk3D+ntIFQ0OAiFTIYdF8j8n/BCxMxb8O0KjAOV7AgxB0iSg+Upah4O3GcukPW2gD5bHsoU6E9rYRcIJfTvomHPV6bgI48Ik0gAhjwIW0Jf9qbQUohIleLH6C84kDdD1MBc9UE1R+ULWVi8coFGHwYY7ud4w8QtXlDM88QLDpCISnQajgP64fX3XlBkVOh8R+CcSH97EByVsYcEvdvz2hQE2a5pMDPfssJ96ENklER2z4RlpRZtq8opxXX5PNlQWjwgRoAb37lA5vnIbdDLCrMjBIf+Jf16ljGRMDMNMEWRXZdsEBYukOI+9laPy/sYU6VeMeAcQH9HCFKZOWBt9k3BHFEmV9KAngTzUgW4SRY/qfiZOUv0h52TeXIy/DU15urYKVX/I+AewgFDvNCA2UVM8J04/x71rFFtwZiLNWiquzJiA0I/IhOkmXODr6XdKcHQpUPOU/jL+p6LhuOaD5Z/agroknNp4hGE+Nhug773eaCCE8JsoT/SoEP/A6NswQBHBTEeAFkAtwym+CMZ9GsxdhzkCIG+KMwZeObyBPrUbYQjMjk5JkNBv4Ae9ClOkcxHPnZyRtT/E44nOjsOGEjUL7rLg1z80hQAWx4R6M5EGwRn6Pv2UP0C7qGTHad/7i63kXpVVIwY2RShPsnREW9nJzpN9/uNnUmGMVoOuCM0e/PRiQCutxYpGzcSSOH8dOg3zSKgJ+EbqbJ5yVqmxL94c5dEFxwA1RsQz2vXHLAh4jeN8q39px5R+v8Amz6PkGEJd25cttlHv2+Y9LaTEiXEAtRFVv+YW8IcwLQAFvhaKIxAgIFY000SE+ucMWFGcLugRpSPgL5ygQa1tKGNFV6zFPIFRXZpFhyQ+qULNGgILClxDT13dtcjAnCk7wMESJVYR0GSkc8uEa/or2hQot+1V8VJTWPq76Uj5O6K5c1fjwbhyicOwBwhTGuA2gUKmW7OZYaRPcWS0R+4IZ49f1DkmWx2XIkX5E5YBd38UQ4gFHHnAq0ekCGcWpkC29bh0/Nd4NugK+jnmgbuoZ87fY9X6A87ynMImzLzWQqm+0sLENW/XaumIHLgkuxEfLjt80MEGJn8LJmIftHrrRGIed7EAgBohWxVrOwLDpTqnziAseIDRoRvjow3TQGCR/Tt6NnEOsmoKN4xQUw5V67IENEfFJvsTN6koZ6PH63yoIwpFfaClhw4pSxx8DEJMGw2PLMyDc0PKDpZ8btMKvQzvl1f5LxkeBojlNpEUNvhgLcUA5L9ouTzZHcIrPt3TAHmhcAY+HbhUkYVf0WS0RU33Z5cs41+a2mO8uZWHfJZmoIxKWGIB7tDqC0Am4JrA+DFggycDPSGe5KeSonlw0KLfOBiawTiMeNBZHhBi6xA9v4XHOCWKG8NkZA8v3hAVpoC66sxBWfLrQdhshP1xnDjR+gvTy3RbxfKNKBZrwqYzkfMDJkC48agYrgfOovX7nJAjPjkax4d+TPnv1o7fE15XSOLq7SKI7aMRe8zZ+JOBRrQlAvZRhQ+4wD8whv1X4UBgyZQgB6BFR0N4g9jCfofKn4gFN+hX3UbWj4EGvDkyz0SoNPRtX40Be7MMA2G82FMfX/pp2kWLnGbyhcmoCrK5KOEeaXiBIpGYA0SvM3GCPhYoxh3JU9ig4HvlgOAKw6Qb/OYA5iAfmgKAPWIvlmstQgafEuxIwZLWRS8NmuKnTVgGpQaS9MIgLZjESVPrHsozDHAcNxnCyARsFMCvedTThWF9MJiSwtgGcozEwTu4v/I6It0iYoQ1ml9rsFwGed7oN4PK/VK9xfuEOrirSmovhP8SPFLMZ5S9AsN4qlH6LfenA/NzrHhvrALas8+T3xMZs8UD8OxwJ29oBHgbs1glMAzAoxGv4j0gjTE+Zl5GBOQ+MBCExosiMBOyIb3rxyoikYhsIWJLhN4xAUlYhFLU5C+E7xW/HEz9OyLAGCNftmHxAemQZg8XyiwGyqF4PNMMoD8InN+/C4Qef9sDUDQF93vcLlNaeG10JJe8AypBpWS8YHJgCjGXoasTQRtjHj2Nk8F/IADzC4edOkOhVMoznamYPmNsB0vqCFGRjznd9BvG2b7eo3DbeIGB6LGeToETaxsDYgV7vlMMrBBkLs97AVl6Hv/R9zIRWIOx0Wp7iexSOAEBBpA4J5UhtBAYRATOy2ITrwvnBS/rfwxBzoXSEJhd6qKERFBr6aAvxNco3+nmIjxI+hfuD2BEkyDxRYOQp5BP+M+2gEniThCqC1AbQcQQX9HAM4PzpAYd+IiFYsRAwUTat0RZz0oD4Kawx0Oyn3nZ8EB4UOp+/WBMUIRoAvnjrspQP8grMV33A8hRol4zq/gjvps6faMOVyp1eqNnGvm9SPjnvig28CO0KD7/ZapoM8cuDECUf2PMiMrjXxgGrDwC8SXGi0LzSdNeRILjPmNO1SgHArrfQ6AQ4LSLICKiGdpLWYKvjP6RS5YkCEzgeRbN1igfxRnDeg+buUU8XBen/cyuT3BL6zswAFnQnnLfwwyBSi8/0vsh1fUHIgBjHrnSaR8LDIJ96Xul90vJBZ8Zm975SuHhyF+ESPfCEqqveQAOj4g4b4E/dxlJQzt/s3LcLvFxg4UDWTneEuYDLzHwopYGWhAw/GieBcxHHxyD1TsgDJBNqNyfhzoCfc3nk9OIsworuwIsSRN1KVYRhSR98+V5ZREDUPfgACZArUAUfGfvRUcOM9Uqp2vXYQErTuEgiRoY4A1GeRsYwdKiHfoX7u2UjPglZzBSNNgRlma7B+UFx0jIg6gh+r+7AKZnfEMk+EuZSMmchPJi3JBwv2IuB9xu8PW22xtzvGejJ1WjT4HWt8Gbd+KM3lOiCN5/w90fw/6EBmj/w8xN3BPeyD52unvam7Rj1Djp6j9mNzI3m2RTEALO4AY+CZtZJgWF+iUdeHqiBeUZlQXGoGLGAsncKgodnR/lw72/uG+Pky1wzEavKDnHLAls/flCmXUHACWlECYvzW4jwEWRVEqOf8O/TIfqx88KDW++uQLq044HSABmWiwtLOzcenx69F6PuLm6USK5CLiyUs4VEm11ET1liXh1BMTAEYOyG0fkx57Qa5oTJIbHLitQZXXLcO9O4T3MYDY0J9CP2IxRw7zVGEBaG46yXaHg/rnPbsY0llbcpbYqfUjbozAKo2QzxqKi0Gprzkwi6z4RyOWa6qd8zPVLVsAQPU9KsUPtgxvOVDkkTYIfXE2xm4MkIo/g37o5UqJOFZoP6HvE+sdoUDjnAaBtRfowaquNAJs/Q/CFj+D2yaA4N5FkeTGp2ALj5W6ZbHzMrHhwuAygRukOKIFMCWS3SFRH97+Ew5khYW2CDgrtmIA4QY3/gj9oy52wQA3WFkAmipyZZmGQzPYhLvwC+L6W4bdfQL9rRckXC3cdFrO6IolB8reutQ5PwgY6iwAoinIbo8IdtPzWXEguawQSiDQ2GMAFfp+DLDQNO/QT5sU0B83r7UAkw/OyWkK5MJ6u02RTEmxUjEo6N3uqqiRwIgj3aahxSAZklhXDJ00un+Bf/Hpxqw9Zu05SmcBLOMWQDhA9a85gE3dZBxAEQMM8DfCRIJRsrYBP4Z+pGLn/2TFL9A3oNNUR5yYrWiVaNuDWBE3AI2gQfhOmSIe6KcxYrHMdDulApcO1xIIcyVtenZIwVLnCJXBQHtTyECcKXHHAaTLebbZhociLS18I6wlw8LplzZ76L+uFPTzDg2tF0VuiB+85USS0FV1eZsGwZT1nKCfnR+qD/EAyBScSfgQZyoFXrjm19BPmWqYkNzTiZxn5ydbgHNK7Ah1FoDHCJahuYX/jAMg3FtjaJvSHaKfR88K45ehXz2cBvRepKtChmZSWgA7hu1vcOCKzzYSQX9wI6UBGvUvY71wgcqZL4AeEe/VoziviXT/weg/RxELgKggInnUsanIwBxQM/uIAyDcR5rVIQHcHZovw1UaJRcD+ksltM2HcVcpqA2K37Y8Oj+G+LDVwzOB2Otk+wTaXeJGyQdXnKDLQcV8YzGNWcyQiqURkLOcKXpbJp0eWwBceUO8OELHPFs8W6zcocCBVPmAA4i6v4oBQhHeg/4qxG9CP4FSKp0DVF9agEE4GDIlPmudUONdTJguQRB04AOS0wza74kfv0OyMaav3WpKP75U8CO22kZ/7U7gUp+wlRLQER0hsQCwVfcB8ZSOVj7jAKLuv40BqNjEABHuUiy9oGfohxY7C1D47inDbUIAMGkQ1sINlumgUTgqUI8o00DyubiZRl/s4toqvzVy5LC7QCY9CgNGRQPOFM+8KgvAR8TKZxxA8n8iB5ApMVda/YukvRigrdxB/6jQP7x90IIj9iCZeSrQ4MK/wv2lHbCWEe5HAsfV34+gn8eNxVEWn97qodSFkmdXB5F/CA3kUYB4Mri3AOXz4MdvRkArJQ7OYbFd0sQAJtwEoLbNni/El68UM6EZiP1IJjb2iRFJBtFG1hV8ZZ4A1IMXuBslDu6E34SRltJXmTrgjigVm3y+amiF9pwXVbnRPvODJHxcYUDQpgiXe6YKBhB7dmjKU5cXT8RKDthsYxtMtt/EAKWr07XZQf+QY66k9lnxo8+0AYBtf0Z/4rziycSEmLh+npOi2gSqDEN0aVRZqeyL63pyvIPnI065T9iMQB8GlJnaFIg7RNDUykccQKhE6RpVcXD6UvxvQf/VaUWJHBJgkmFQvWTONsECzLNj4n9QD2FuGSUj5Sd23Z2J9QJ97sEpdIv7PIt8ybJmNPU+t6HFQvePuC6+zzi7lTBAM40pKNyh/sboMw4gVDIb12Fx/W9SfzX6i5CXplFzgK9NmWABIjEwfM7OPZkbrQuLYnJd3LOc59kd4muLQIB7i+cKpozq1Kha1tcX6BfPG4J+WnIIiKswoPR/NtHf3hj9lRzAXHvxpfjfhP7UP+9oDou5MWck9pWFjIl/jgQGwhp1pZYyjDK4q/oj91Y6/TV42wajqd/qMKK/eDqb0Z9i36sl1dw7QlUozE5YZsjv4YD5XfELMX0E/CH6pU/xwrUyMWRACdNBf8RT1hsPx4stZ+KpgVSh+HP7SsEXdmBrwOLEiIVVt0ecQPT7cURQImZQG4E1DdwRitrdBh0ZjpED2ET8DgfgfeqtofAvknbQn4JXb7lRI3p3UIet6y9FRm2apLB0TPyr+jfOZJbyGmWInOxUpeBDBFxagNs05G8/gSYx3CXqFTVZo78yAuG1Ajjs1t4/KmXP7hDbotdPxORep05ygp6Hq38c9wX6/dq0OwzxgPsXHOD6mQm8lZpuNrKoUghIl3RpyYStHh6l/d5MBUpRILJA/7guPGblmBk3Anfe/y36S5+HbEbMJLYEDiAQu+OAzbz4cdx36Be4FHCX4ucc4FEqLT4yH+Yo4VSecFhPVazSwaLDW63fpVFml2kj6hXdn319WwXfOeEg8v558BP0lzdGIa5RZMI7DljxW0FcFUtKlBeKq1N0mEYJR+knFSWDiO8L09LhLNknp5cx8Trl9vuUeDpWThtR70jzqcKWWZiv94BwZpwp74eWjlCwMPF4tSRwI5uFoaam4wCkEjHmmcXqn+R9hn7rpGPF1Vk6tRMA8HzuA4CsztMl6kEJD/kSqd9LAYfPYf1mIHZdEICCyhPg0BZUo232woDV8+D+RaB1QFwGCbccQBpXmHYW03eCN0JhNvQZ/aNqXHpEjzmQJlAGACE14W9Atl1rFSVX43o/SUfVx8e9AlPTu1Yl99lhasMR1o8K/WBinN2MJgyo0PYI/aXPs3VjlOa25oAvhyb5Bd7UDfSjqlyjH9XZcOYVB2yqAmhT/zbPRWYw9PNa5KpRFf+STzdJTC2O6cPMyoNOrQV1DBx2OYARrj2o5wMhI/XHSEf4DPno8+QeRrGWYgmxUlaNOKXwneAd9I9U2Xr8He4D9nXqduGCAyVGA+hxXThmfZeB9ADt2SfMGRQ1+eQvSmpAos/DLXJcmNW/QbZ0gc4MRwvZCJhWxobuv7qVUeZxcVNI2rwOf6XN14+jv/V5MsQTvlvQJ4jzTBijD9R/7EG4pIuSHsI1seZ3fvr5BE18koEWWKj/O3HdGgFuhkb3gxV5ZRCQm1VtFnZAdTzNH1Wbr/PPj6EfIWmxQ/82B2RQHnet/nk2XO8XDT+la+c5cAAzQk2J0fEZxI8e+hdErBnXxJkHXyWK4pgOzEEg9sbDG3A6IsEUjm/Rf8RObIZF8ec48OU7/Qn6recEa7ARsP5CgS4p+4HOrbwHBazUfwBPFHGGvjQZcfTAmwjKonKbFS3Wb4dIs8pIyupfFwlHcxcblEbAu91BP7RSLs8hgS5nOCU+4sCs/xIA2eln6H/oArncOu9oWcTEumM37iWr/3iiaUZnM9LkEj+xRmSuf/fpepNKAEv1eVQ0yNpdRtw1Apvoj7hngxBG33eBYoMbDoheGDhgMQAatbpAP/pTDfprtycxoQ0A5jwDCCMlsvo3JoQMdcKrDrhq7vxqkS8jgI4M39hgC/EAsnHI41YAva5NpiCrf/d2CO7ZKUIyAkfUx6bFH4QBdKpEOeM4nwVN8p4D0gmAKwZ4h/7RnNoPfBPc9RKbZz8fnpIVB7SrkOGiQF8Gkg4yDSQk4PY74C5Tc2FwD4bmLTk6uTKuV2lQSobOdkbAmrUqOQ30IAxomNCGwq848IVH6BcZ9U5RkmFoUx49e8u3mVmrf8dPjAG0yBONQJV8mAknoUuJ9RLWi093eTkogAr6R5NnGrAv1BV5uNoIdOgvcc8dpqMGA4jFhgOQtW9z4OsZ+hPuFaZxbYJmXXhnK6hB6FzmNisXRUVJWaygjyYvNBhdO+5xhCHWKWC0JEMcLngXCTFlXh2bHRHZtcviCv0LUzAU7rmBXZgdHqRmjzjwZYU1+iFnIzSv8x3uqfE6AJCeCw7QxOSGVS4O6Bxorv5XYca9laN3PBImlGAfG5/uqplYR3plzjBu5GYIfZZLCtbAL++LtUfeePa3YUC+BJF1ueewlg0OfG2if3HLv7ztYy06p1+BHpkgp6R/bhNQ14e2Tgm5JUotvXOq1gn0NPBKued71nTgrrq47u4DENe/at5CXyBuxYiSwu1pnB8sjED3QIDn0+Oer7plgp4t3Z5tDrTvAt2jP6G5gG/VRvtnPlg2Xj5AmUgMmSoI66Eqp4iDjM9R5Tdp0Hb0KN1duIZ+bmbFGy8oje5GgM6KSbFKvxcUQbwIAJSWPRPUI0qAfsoBeg6wg34beqRT0qDBU6Ea44gLxZ9H58oho4ojVM1s0IcbqGFBmyQ+KVq+Rn9zuTr9ff+q++PaWy9IGkSgG7aYe/ePqBamIBu6xruTznWI5egLDnwxGs4/Ye97bpQhKZJqv7/7GfkgF+rEBGfCVWZCTPnOjwxnPWcyxAqtLMZanXyfSv/Hz46iWQl6ryEc6KdaQ3440BkBh1qeRon4sTqGC2liNQdGdUra0xL+H/kMAsbYr+iHAAAAAElFTkSuQmCC", shaderMapUrl),
347
+ preserveAspectRatio: "xMidYMid slice"
348
+ }), jsx("feColorMatrix", {
349
+ in: "DISPLACEMENT_MAP",
350
+ type: "matrix",
351
+ values: "0.3 0.3 0.3 0 0\n 0.3 0.3 0.3 0 0\n 0.3 0.3 0.3 0 0\n 0 0 0 1 0",
352
+ result: "EDGE_INTENSITY"
353
+ }), jsx("feComponentTransfer", {
354
+ in: "EDGE_INTENSITY",
355
+ result: "EDGE_MASK",
356
+ children: jsx("feFuncA", {
357
+ type: "discrete",
358
+ tableValues: `0 ${.05 * aberrationIntensity} 1`
359
+ })
360
+ }), jsx("feOffset", {
361
+ in: "SourceGraphic",
362
+ dx: "0",
363
+ dy: "0",
364
+ result: "CENTER_ORIGINAL"
365
+ }), jsx("feDisplacementMap", {
366
+ in: "SourceGraphic",
367
+ in2: "DISPLACEMENT_MAP",
368
+ scale: displacementScale * ("shader" === mode ? 1 : -1),
369
+ xChannelSelector: "R",
370
+ yChannelSelector: "B",
371
+ result: "RED_DISPLACED"
372
+ }), jsx("feColorMatrix", {
373
+ in: "RED_DISPLACED",
374
+ type: "matrix",
375
+ values: "1 0 0 0 0\n 0 0 0 0 0\n 0 0 0 0 0\n 0 0 0 1 0",
376
+ result: "RED_CHANNEL"
377
+ }), jsx("feDisplacementMap", {
378
+ in: "SourceGraphic",
379
+ in2: "DISPLACEMENT_MAP",
380
+ scale: displacementScale * (("shader" === mode ? 1 : -1) - .02 * aberrationIntensity),
381
+ xChannelSelector: "R",
382
+ yChannelSelector: "B",
383
+ result: "GREEN_DISPLACED"
384
+ }), jsx("feColorMatrix", {
385
+ in: "GREEN_DISPLACED",
386
+ type: "matrix",
387
+ values: "0 0 0 0 0\n 0 1 0 0 0\n 0 0 0 0 0\n 0 0 0 1 0",
388
+ result: "GREEN_CHANNEL"
389
+ }), jsx("feDisplacementMap", {
390
+ in: "SourceGraphic",
391
+ in2: "DISPLACEMENT_MAP",
392
+ scale: displacementScale * (("shader" === mode ? 1 : -1) - .03 * aberrationIntensity),
393
+ xChannelSelector: "R",
394
+ yChannelSelector: "B",
395
+ result: "BLUE_DISPLACED"
396
+ }), jsx("feColorMatrix", {
397
+ in: "BLUE_DISPLACED",
398
+ type: "matrix",
399
+ values: "0 0 0 0 0\n 0 0 0 0 0\n 0 0 1 0 0\n 0 0 0 1 0",
400
+ result: "BLUE_CHANNEL"
401
+ }), jsx("feBlend", {
402
+ in: "GREEN_CHANNEL",
403
+ in2: "BLUE_CHANNEL",
404
+ mode: "screen",
405
+ result: "GB_COMBINED"
406
+ }), jsx("feBlend", {
407
+ in: "RED_CHANNEL",
408
+ in2: "GB_COMBINED",
409
+ mode: "screen",
410
+ result: "RGB_COMBINED"
411
+ }), jsx("feGaussianBlur", {
412
+ in: "RGB_COMBINED",
413
+ result: "ABERRATED_BLURRED",
414
+ stdDeviation: blurAmount * aberrationIntensity * .05
415
+ }), jsx("feComposite", {
416
+ in: "ABERRATED_BLURRED",
417
+ in2: "EDGE_MASK",
418
+ operator: "in",
419
+ result: "EDGE_ABERRATION"
420
+ }), jsx("feComponentTransfer", {
421
+ in: "EDGE_MASK",
422
+ result: "INVERTED_MASK",
423
+ children: jsx("feFuncA", {
424
+ type: "table",
425
+ tableValues: "1 0"
426
+ })
427
+ }), jsx("feComposite", {
428
+ in: "CENTER_ORIGINAL",
429
+ in2: "INVERTED_MASK",
430
+ operator: "in",
431
+ result: "CENTER_CLEAN"
432
+ }), jsx("feComposite", {
433
+ in: "EDGE_ABERRATION",
434
+ in2: "CENTER_CLEAN",
435
+ operator: "over"
436
+ }) ]
437
+ }) ]
438
+ })
439
+ });
440
+
441
+ /**
442
+ * Checkbox state and functionality
443
+ * @param initialProps - Initial checkbox properties
444
+ * @returns Checkbox state and methods
445
+ */ GlassFilterComponent.displayName = "GlassFilter";
446
+
447
+ // Memoize component to prevent unnecessary re-renders
448
+ 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)), 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 = {
449
+ x: 0,
450
+ y: 0
451
+ }, globalMousePosition: globalMousePosition = {
452
+ x: 0,
453
+ y: 0
454
+ }, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, active: active = !1, isHovered: isHovered = !1, isActive: isActive = !1, overLight: overLight = !1, cornerRadius: cornerRadius = 0, padding: padding = "0 0", glassSize: glassSize = {
455
+ width: 0,
456
+ height: 0
457
+ }, onClick: onClick, mode: mode = "standard", effectiveDisableEffects: effectiveDisableEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", enableLiquidBlur: enableLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
458
+ // Generate a stable, deterministic ID for SSR compatibility
459
+ // React's useId() should produce the same ID on server and client for the same
460
+ // component position in the tree. We use useState to ensure the ID is only
461
+ // generated once and remains stable across renders.
462
+ const baseId = useId(), [filterId] = useState((() => `atomix-glass-filter-${baseId.replace(/:/g, "-").replace(/^[^a-z]/i, "atomix-")}`)), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null);
463
+ // Lazy load shader utilities only when shader mode is needed
464
+ useEffect((() => {
465
+ "shader" === mode ?
466
+ // Dynamic import shader utilities
467
+ Promise.resolve().then((() => shaderUtils)).then((shaderUtils => {
468
+ shaderUtilsRef.current = {
469
+ ShaderDisplacementGenerator: shaderUtils.ShaderDisplacementGenerator,
470
+ fragmentShaders: shaderUtils.fragmentShaders
471
+ };
472
+ })).catch((error => {
473
+ console.warn("AtomixGlassContainer: Error loading shader utilities", error);
474
+ })) :
475
+ // Clear shader utils when not in shader mode to free memory
476
+ shaderUtilsRef.current = null;
477
+ }), [ mode ]),
478
+ // Generate shader map with debouncing and caching
479
+ useEffect((() => {
480
+ // Enhanced validation for shader mode
481
+ if ("shader" === mode && glassSize && validateGlassSize(glassSize) && shaderUtilsRef.current) {
482
+ // Create cache key from size and variant
483
+ const cacheKey = `${glassSize.width}x${glassSize.height}-${shaderVariant}`, cachedUrl = (key => {
484
+ const entry = sharedShaderCache.get(key);
485
+ return entry ? (
486
+ // Update access timestamp for LRU
487
+ entry.timestamp = Date.now(), entry.url) : null;
488
+ })(cacheKey);
489
+ // Check shared cache first
490
+ if (cachedUrl) return void setShaderMapUrl(cachedUrl);
491
+ // Clear any pending debounce
492
+ shaderDebounceTimeoutRef.current && clearTimeout(shaderDebounceTimeoutRef.current);
493
+ // Debounce shader generation to avoid blocking on rapid size changes
494
+ const generateShader = () => {
495
+ if (shaderUtilsRef.current) try {
496
+ const {ShaderDisplacementGenerator: ShaderDisplacementGenerator, fragmentShaders: fragmentShaders} = shaderUtilsRef.current;
497
+ shaderGeneratorRef.current?.destroy();
498
+ const selectedShader = fragmentShaders[shaderVariant] || fragmentShaders.liquidGlass;
499
+ shaderGeneratorRef.current = new ShaderDisplacementGenerator({
500
+ width: glassSize.width,
501
+ height: glassSize.height,
502
+ fragment: selectedShader
503
+ });
504
+ // Use requestIdleCallback if available for non-blocking generation
505
+ const generate = () => {
506
+ const url = shaderGeneratorRef.current?.updateShader() || "";
507
+ ((key, url) => {
508
+ // Evict oldest entries if at capacity
509
+ if (sharedShaderCache.size >= 15) {
510
+ const entries = Array.from(sharedShaderCache.entries());
511
+ // Sort by timestamp (oldest first)
512
+ entries.sort(((a, b) => a[1].timestamp - b[1].timestamp));
513
+ // Remove oldest entry
514
+ const oldestEntry = entries[0];
515
+ oldestEntry && sharedShaderCache.delete(oldestEntry[0]);
516
+ }
517
+ sharedShaderCache.set(key, {
518
+ url: url,
519
+ timestamp: Date.now()
520
+ }),
521
+ // Development mode: log cache size
522
+ "production" !== process.env.NODE_ENV && sharedShaderCache.size;
523
+ })(cacheKey, url), setShaderMapUrl(url);
524
+ };
525
+ "undefined" != typeof requestIdleCallback ? requestIdleCallback(generate, {
526
+ timeout: 1e3
527
+ }) :
528
+ // Fallback to setTimeout for browsers without requestIdleCallback
529
+ setTimeout(generate, 0);
530
+ } catch (error) {
531
+ console.warn("AtomixGlassContainer: Error generating shader map", error), setShaderMapUrl("");
532
+ } else
533
+ // Shader utils not loaded yet, retry after a short delay
534
+ shaderDebounceTimeoutRef.current = setTimeout(generateShader, 100);
535
+ };
536
+ // Debounce with 300ms delay
537
+ shaderDebounceTimeoutRef.current = setTimeout(generateShader, 300);
538
+ } else
539
+ // Not in shader mode, clear URL
540
+ setShaderMapUrl("");
541
+ // Cleanup function with error handling
542
+ return () => {
543
+ shaderDebounceTimeoutRef.current && (clearTimeout(shaderDebounceTimeoutRef.current),
544
+ shaderDebounceTimeoutRef.current = null);
545
+ try {
546
+ shaderGeneratorRef.current?.destroy();
547
+ } catch (error) {
548
+ console.warn("AtomixGlassContainer: Error during shader cleanup", error);
549
+ } finally {
550
+ shaderGeneratorRef.current = null;
551
+ }
552
+ };
553
+ }), [ mode, glassSize, shaderVariant ]);
554
+ // Removed forced reflow to avoid layout thrash and potential feedback sizing loops
555
+ const [rectCache, setRectCache] = useState(null);
556
+ useEffect((() => {
557
+ if (!ref || "function" == typeof ref) return;
558
+ const element = ref.current;
559
+ if (element) try {
560
+ setRectCache(element.getBoundingClientRect());
561
+ } catch (error) {
562
+ console.warn("AtomixGlassContainer: Error getting element bounds", error), setRectCache(null);
563
+ }
564
+ }), [ ref, glassSize ]);
565
+ // Pre-calculate static multipliers outside useMemo
566
+ const liquidBlur = useMemo((() => {
567
+ const defaultBlur = {
568
+ baseBlur: blurAmount,
569
+ edgeBlur: 1.25 * blurAmount,
570
+ centerBlur: 1.1 * blurAmount,
571
+ flowBlur: 1.2 * blurAmount
572
+ };
573
+ // Enhanced validation for liquid blur
574
+ if (!enableLiquidBlur || !rectCache || !globalMousePosition || "number" != typeof globalMousePosition.x || "number" != typeof globalMousePosition.y || isNaN(globalMousePosition.x) || isNaN(globalMousePosition.y)) return defaultBlur;
575
+ try {
576
+ // Cache center and distance calculations
577
+ const center = calculateElementCenter(rectCache), distance = calculateDistance(globalMousePosition, center), maxDistance = Math.sqrt(rectCache.width * rectCache.width + rectCache.height * rectCache.height) / 2, normalizedDistance = Math.min(distance / maxDistance, 1), mouseInfluence = calculateMouseInfluence(mouseOffset), baseBlur = blurAmount + mouseInfluence * blurAmount * .4, edgeBlur = baseBlur * (.8 + .6 * (1.5 * normalizedDistance + .3 * mouseInfluence)), centerBlur = baseBlur * (.3 + .4 * (.3 * (1 - normalizedDistance) + .2 * mouseInfluence)), deltaX = globalMousePosition.x - center.x, deltaY = globalMousePosition.y - center.y, flowDirection = Math.atan2(deltaY, deltaX), flowBlur = baseBlur * (.4 + .6 * (.5 * Math.sin(flowDirection + mouseInfluence * Math.PI) + .5)), stateMultiplier = (isHovered ? 1.2 : 1) * (isActive ? 1.4 : 1);
578
+ return {
579
+ baseBlur: clampBlur(baseBlur * stateMultiplier),
580
+ edgeBlur: clampBlur(edgeBlur * stateMultiplier),
581
+ centerBlur: clampBlur(centerBlur * stateMultiplier),
582
+ flowBlur: clampBlur(flowBlur * stateMultiplier)
583
+ };
584
+ } catch (error) {
585
+ return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
586
+ defaultBlur;
587
+ }
588
+ }), [ enableLiquidBlur, blurAmount, globalMousePosition, mouseOffset, isHovered, isActive, rectCache, style, glassSize ]), backdropStyle = useMemo((() => {
589
+ try {
590
+ const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), validatedBaseBlur = "number" != typeof liquidBlur.baseBlur || isNaN(liquidBlur.baseBlur) ? 0 : liquidBlur.baseBlur, validatedEdgeBlur = "number" != typeof liquidBlur.edgeBlur || isNaN(liquidBlur.edgeBlur) ? 0 : liquidBlur.edgeBlur, validatedCenterBlur = "number" != typeof liquidBlur.centerBlur || isNaN(liquidBlur.centerBlur) ? 0 : liquidBlur.centerBlur, validatedFlowBlur = "number" != typeof liquidBlur.flowBlur || isNaN(liquidBlur.flowBlur) ? 0 : liquidBlur.flowBlur, area = rectCache ? rectCache.width * rectCache.height : 0;
591
+ // Validate blur values before using them
592
+ return !enableLiquidBlur || effectiveReducedMotion || effectiveDisableEffects || area > 18e4 ? {
593
+ backdropFilter: `blur(${clampBlur(Math.max(validatedBaseBlur, .8 * validatedEdgeBlur, 1.1 * validatedCenterBlur, .9 * validatedFlowBlur))}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(1.05) brightness(1.05)`
594
+ } : {
595
+ backdropFilter: `${[ `blur(${validatedBaseBlur}px)`, `blur(${validatedEdgeBlur}px)`, `blur(${validatedCenterBlur}px)`, `blur(${validatedFlowBlur}px)` ].join(" ")} saturate(${Math.min(dynamicSaturation, 200)}%) contrast(1.05) brightness(1.05)`
596
+ };
597
+ // Single-pass fallback: stronger radius to match perceived blur of multi-pass
598
+ } catch (error) {
599
+ return console.warn("AtomixGlassContainer: Error calculating backdrop style", error),
600
+ {
601
+ backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
602
+ };
603
+ }
604
+ }), [ filterId, liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveDisableEffects, enableLiquidBlur ]), containerVars = useMemo((() => {
605
+ try {
606
+ // Safe extraction of mouse offset values
607
+ const mx = mouseOffset && "number" == typeof mouseOffset.x && !isNaN(mouseOffset.x) ? mouseOffset.x : 0, my = mouseOffset && "number" == typeof mouseOffset.y && !isNaN(mouseOffset.y) ? mouseOffset.y : 0;
608
+ return {
609
+ "--atomix-glass-container-width": `${glassSize?.width}`,
610
+ "--atomix-glass-container-height": `${glassSize?.height}`,
611
+ "--atomix-glass-container-padding": padding || "0 0",
612
+ "--atomix-glass-container-radius": `${"number" != typeof cornerRadius || isNaN(cornerRadius) ? 0 : cornerRadius}px`,
613
+ "--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
614
+ "--atomix-glass-container-shadow": overLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${.4 + .002 * mx})`, `inset 0 -1px 0 rgba(0, 0, 0, ${.2 + .001 * Math.abs(my)})`, `inset 0 0 20px rgba(0, 0, 0, ${.08 + .001 * Math.abs(mx + my)})`, `0 2px 12px rgba(0, 0, 0, ${.12 + .002 * Math.abs(my)})` ].join(", ") : "0 0 20px rgba(0, 0, 0, 0.15) inset, 0 4px 8px rgba(0, 0, 0, 0.08) inset",
615
+ "--atomix-glass-container-shadow-opacity": effectiveDisableEffects ? 0 : 1,
616
+ // Background and shadow values use design token-aligned RGB values
617
+ "--atomix-glass-container-bg": overLight ? `linear-gradient(${180 + .5 * mx}deg, rgba(255, 255, 255, 0.1) 0%, transparent 20%, transparent 80%, rgba(0, 0, 0, 0.05) 100%)` : "none",
618
+ "--atomix-glass-container-text-shadow": overLight ? "0px 2px 12px rgba(0, 0, 0, 0)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
619
+ "--atomix-glass-container-box-shadow": overLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0px 12px 40px rgba(0, 0, 0, 0.25)"
620
+ };
621
+ } catch (error) {
622
+ return console.warn("AtomixGlassContainer: Error generating container variables", error),
623
+ {
624
+ "--atomix-glass-container-padding": "0 0",
625
+ "--atomix-glass-container-radius": "0px",
626
+ "--atomix-glass-container-backdrop": "none",
627
+ "--atomix-glass-container-shadow": "none",
628
+ "--atomix-glass-container-shadow-opacity": 1,
629
+ "--atomix-glass-container-bg": "none",
630
+ "--atomix-glass-container-text-shadow": "none"
631
+ };
632
+ }
633
+ }), [ glassSize, padding, cornerRadius, backdropStyle, mouseOffset, overLight, effectiveDisableEffects ]);
634
+ return jsx("div", {
635
+ ref: ref,
636
+ className: `${ATOMIX_GLASS.CONTAINER_CLASS} ${className} ${active ? ATOMIX_GLASS.CLASSES.ACTIVE : ""} ${overLight ? ATOMIX_GLASS.CLASSES.OVER_LIGHT : ""}`,
637
+ style: {
638
+ ...style,
639
+ ...containerVars
640
+ },
641
+ onClick: onClick,
642
+ children: jsxs("div", {
643
+ className: ATOMIX_GLASS.INNER_CLASS,
644
+ style: {
645
+ padding: "var(--atomix-glass-container-padding)",
646
+ boxShadow: "var(--atomix-glass-container-box-shadow)"
647
+ },
648
+ onMouseEnter: onMouseEnter,
649
+ onMouseLeave: onMouseLeave,
650
+ onMouseDown: onMouseDown,
651
+ onMouseUp: onMouseUp,
652
+ children: [ jsxs("div", {
653
+ className: ATOMIX_GLASS.FILTER_CLASS,
654
+ children: [ jsx(GlassFilter, {
655
+ blurAmount: blurAmount,
656
+ mode: mode,
657
+ id: filterId,
658
+ displacementScale: "number" != typeof displacementScale || isNaN(displacementScale) ? 0 : displacementScale,
659
+ aberrationIntensity: "number" != typeof aberrationIntensity || isNaN(aberrationIntensity) ? 0 : aberrationIntensity,
660
+ shaderMapUrl: shaderMapUrl
661
+ }), jsx("div", {
662
+ className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
663
+ suppressHydrationWarning: !0,
664
+ style: {
665
+ filter: `url(#${filterId})`,
666
+ backdropFilter: "var(--atomix-glass-container-backdrop)",
667
+ borderRadius: "var(--atomix-glass-container-radius)"
668
+ }
669
+ }), jsx("div", {
670
+ className: ATOMIX_GLASS.FILTER_SHADOW_CLASS,
671
+ style: {
672
+ boxShadow: "var(--atomix-glass-container-shadow)",
673
+ opacity: "var(--atomix-glass-container-shadow-opacity)",
674
+ background: "var(--atomix-glass-container-bg)",
675
+ borderRadius: "var(--atomix-glass-container-radius)"
676
+ }
677
+ }) ]
678
+ }), jsx("div", {
679
+ ref: contentRef,
680
+ className: ATOMIX_GLASS.CONTENT_CLASS,
681
+ style: {
682
+ position: "relative",
683
+ textShadow: "var(--atomix-glass-container-text-shadow)",
684
+ ...elasticity > 0 ? {
685
+ zIndex: 100
686
+ } : {}
687
+ },
688
+ children: children
689
+ }) ]
690
+ })
691
+ });
692
+ }));
693
+
694
+ // Module-level shared shader cache with LRU eviction
695
+ AtomixGlassContainer.displayName = "AtomixGlassContainer";
696
+
697
+ // Singleton instance
698
+ const globalMouseTracker = new
699
+ /**
700
+ * Global mouse tracker singleton
701
+ * Tracks mouse position at document level and distributes to subscribers
702
+ * Reduces event processing overhead when multiple AtomixGlass instances are present
703
+ */
704
+ class {
705
+ constructor() {
706
+ this.listeners = new Set, this.position = {
707
+ x: 0,
708
+ y: 0
709
+ }, this.rafId = null, this.lastEvent = null, this.isTracking = !1,
710
+ /**
711
+ * Handle mouse move event
712
+ */
713
+ this.handleMouseMove = e => {
714
+ this.lastEvent = e,
715
+ // Use requestAnimationFrame to throttle updates
716
+ null === this.rafId && (this.rafId = requestAnimationFrame((() => {
717
+ this.lastEvent && (this.position = {
718
+ x: this.lastEvent.clientX,
719
+ y: this.lastEvent.clientY
720
+ },
721
+ // Notify all subscribers
722
+ this.listeners.forEach((callback => {
723
+ try {
724
+ callback(this.position);
725
+ } catch (error) {
726
+ console.error("GlobalMouseTracker: Error in subscriber callback", error);
727
+ }
728
+ }))), this.rafId = null;
729
+ })));
730
+ };
731
+ }
732
+ /**
733
+ * Subscribe to mouse position updates
734
+ * @param callback Function to call when mouse position changes
735
+ * @returns Unsubscribe function
736
+ */ subscribe(callback) {
737
+ // Return unsubscribe function
738
+ return this.listeners.add(callback),
739
+ // Start tracking if this is the first subscriber
740
+ 1 === this.listeners.size && this.startTracking(),
741
+ // Immediately notify with current position
742
+ callback(this.position), () => {
743
+ this.unsubscribe(callback);
744
+ };
745
+ }
746
+ /**
747
+ * Unsubscribe from mouse position updates
748
+ */ unsubscribe(callback) {
749
+ this.listeners.delete(callback),
750
+ // Stop tracking if no more subscribers
751
+ 0 === this.listeners.size && this.stopTracking();
752
+ }
753
+ /**
754
+ * Start tracking mouse movement
755
+ */ startTracking() {
756
+ this.isTracking || (this.isTracking = !0,
757
+ // Use document-level listener for global tracking
758
+ document.addEventListener("mousemove", this.handleMouseMove, {
759
+ passive: !0
760
+ }));
761
+ }
762
+ /**
763
+ * Stop tracking mouse movement
764
+ */ stopTracking() {
765
+ this.isTracking && (this.isTracking = !1, document.removeEventListener("mousemove", this.handleMouseMove),
766
+ // Cancel any pending RAF
767
+ null !== this.rafId && (cancelAnimationFrame(this.rafId), this.rafId = null), this.lastEvent = null);
768
+ }
769
+ /**
770
+ * Get current mouse position (synchronous)
771
+ */ getPosition() {
772
+ return {
773
+ ...this.position
774
+ };
775
+ }
776
+ /**
777
+ * Get number of active subscribers (for debugging)
778
+ */ getSubscriberCount() {
779
+ return this.listeners.size;
780
+ }
781
+ }, {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
782
+ parentElement && backgroundDetectionCache.set(parentElement, {
783
+ result: result,
784
+ timestamp: Date.now(),
785
+ config: overLightConfig,
786
+ threshold: threshold
787
+ });
788
+ };
789
+
790
+ /**
791
+ * Composable hook for AtomixGlass component logic
792
+ * Manages all state, calculations, and event handlers
793
+ */
794
+ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadius: cornerRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, disableEffects: disableEffects = !1, elasticity: elasticity = .05, onClick: onClick, debugCornerRadius: debugCornerRadius = !1, debugOverLight: debugOverLight = !1, enablePerformanceMonitoring: enablePerformanceMonitoring = !1, children: children}) {
795
+ // State
796
+ const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), [glassSize, setGlassSize] = useState({
797
+ width: 270,
798
+ height: 69
799
+ }), [internalGlobalMousePosition, setInternalGlobalMousePosition] = useState({
800
+ x: 0,
801
+ y: 0
802
+ }), [internalMouseOffset, setInternalMouseOffset] = useState({
803
+ x: 0,
804
+ y: 0
805
+ }), [dynamicCornerRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), effectiveCornerRadius = useMemo((() => void 0 !== cornerRadius ? Math.max(0, cornerRadius) : Math.max(0, dynamicCornerRadius)), [ cornerRadius, dynamicCornerRadius, debugCornerRadius ]), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveHighContrast = useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveDisableEffects = useMemo((() => disableEffects || effectiveReducedMotion), [ disableEffects, effectiveReducedMotion ]), globalMousePosition = useMemo((() => externalGlobalMousePosition || internalGlobalMousePosition), [ externalGlobalMousePosition, internalGlobalMousePosition ]), mouseOffset = useMemo((() => externalMouseOffset || internalMouseOffset), [ externalMouseOffset, internalMouseOffset ]);
806
+ // Extract border-radius from children
807
+ useEffect((() => {
808
+ const extractRadius = () => {
809
+ try {
810
+ let extractedRadius = null, extractionSource = "default";
811
+ if (contentRef.current) {
812
+ const firstChild = contentRef.current.firstElementChild;
813
+ if (firstChild) {
814
+ const domRadius = (element => {
815
+ if (!element || "undefined" == typeof window) return null;
816
+ try {
817
+ const computedStyles = window.getComputedStyle(element), borderRadius = computedStyles.borderRadius || computedStyles.borderTopLeftRadius || computedStyles.borderTopRightRadius || computedStyles.borderBottomLeftRadius || computedStyles.borderBottomRightRadius;
818
+ if (borderRadius && "0px" !== borderRadius && "auto" !== borderRadius) {
819
+ const parsed = parseBorderRadiusValue(borderRadius);
820
+ return parsed > 0 ? parsed : null;
821
+ }
822
+ return null;
823
+ } catch (error) {
824
+ return null;
825
+ }
826
+ })(firstChild);
827
+ null !== domRadius && domRadius > 0 && (extractedRadius = domRadius, extractionSource = "DOM element");
828
+ }
829
+ }
830
+ if (null === extractedRadius) {
831
+ const childRadius = extractBorderRadiusFromChildren(children);
832
+ childRadius > 0 && childRadius !== CONSTANTS.DEFAULT_CORNER_RADIUS && (extractedRadius = childRadius,
833
+ extractionSource = "React children");
834
+ }
835
+ null !== extractedRadius && extractedRadius > 0 ? setDynamicCornerRadius(extractedRadius) : process.env.NODE_ENV;
836
+ } catch (error) {
837
+ "production" !== process.env.NODE_ENV && debugCornerRadius && console.error("[AtomixGlass] Error extracting corner radius:", error);
838
+ }
839
+ };
840
+ extractRadius();
841
+ const timeoutId = setTimeout(extractRadius, 100);
842
+ return () => clearTimeout(timeoutId);
843
+ }), [ children, debugCornerRadius, contentRef ]),
844
+ // Media query handlers and background detection
845
+ useEffect((() => {
846
+ if (("auto" === overLight || "object" == typeof overLight && null !== overLight) && glassRef.current) {
847
+ const element = glassRef.current, cachedResult = ((parentElement, overLightConfig) => {
848
+ if (!parentElement) return null;
849
+ const cached = backgroundDetectionCache.get(parentElement);
850
+ return cached && ((config1, config2) => {
851
+ // Primitive comparison for boolean and 'auto'
852
+ if ("object" != typeof config1 || null === config1) return config1 === config2;
853
+ // Both must be objects at this point
854
+ if ("object" != typeof config2 || null === config2) return !1;
855
+ const obj1 = config1, obj2 = config2, props = [ "threshold", "opacity", "contrast", "brightness", "saturationBoost" ];
856
+ for (const prop of props) {
857
+ const val1 = obj1[prop], val2 = obj2[prop];
858
+ // If both are undefined, they're equal for this property
859
+ if (void 0 !== val1 || void 0 !== val2) {
860
+ // If one is undefined and the other isn't, they're different
861
+ if (void 0 === val1 || void 0 === val2) return !1;
862
+ // Compare numeric values (handle NaN and floating point precision)
863
+ if ("number" == typeof val1 && "number" == typeof val2) {
864
+ // Use Number.isNaN for proper NaN comparison
865
+ if (Number.isNaN(val1) && Number.isNaN(val2)) continue;
866
+ if (Number.isNaN(val1) || Number.isNaN(val2)) return !1;
867
+ // Compare with small epsilon for floating point numbers
868
+ if (Math.abs(val1 - val2) > Number.EPSILON) return !1;
869
+ } else if (val1 !== val2) return !1;
870
+ }
871
+ }
872
+ return !0;
873
+ })(cached.config, overLightConfig) ? (
874
+ // Update timestamp for LRU-like behavior (though WeakMap doesn't support LRU)
875
+ cached.timestamp = Date.now(), cached.result) : null;
876
+ })(element.parentElement, overLight);
877
+ if (null !== cachedResult) return void setDetectedOverLight(cachedResult);
878
+ const timeoutId = setTimeout((() => {
879
+ try {
880
+ if (!element) return void setDetectedOverLight(!1);
881
+ // Validate window context
882
+ if ("undefined" == typeof window || "function" != typeof window.getComputedStyle) return void setDetectedOverLight(!1);
883
+ let totalLuminance = 0, validSamples = 0, hasValidBackground = !1, currentElement = element.parentElement, depth = 0;
884
+ const maxDepth = 20, maxSamples = 10;
885
+ // Limit traversal depth to prevent infinite loops and performance issues
886
+ for (;currentElement && validSamples < maxSamples && depth < maxDepth; ) {
887
+ try {
888
+ const computedStyle = window.getComputedStyle(currentElement);
889
+ if (!computedStyle) {
890
+ currentElement = currentElement.parentElement, depth++;
891
+ continue;
892
+ }
893
+ const bgColor = computedStyle.backgroundColor, bgImage = computedStyle.backgroundImage;
894
+ // Check for solid color backgrounds
895
+ if (bgColor && "rgba(0, 0, 0, 0)" !== bgColor && "transparent" !== bgColor && "initial" !== bgColor && "none" !== bgColor) {
896
+ const rgb = bgColor.match(/\d+/g);
897
+ if (rgb && rgb.length >= 3) {
898
+ const r = Number(rgb[0]), g = Number(rgb[1]), b = Number(rgb[2]);
899
+ // Validate RGB values are valid numbers
900
+ if (!isNaN(r) && !isNaN(g) && !isNaN(b) && isFinite(r) && isFinite(g) && isFinite(b) && r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255 && (r > 10 || g > 10 || b > 10)) {
901
+ const luminance = (.299 * r + .587 * g + .114 * b) / 255;
902
+ !isNaN(luminance) && isFinite(luminance) && (totalLuminance += luminance, validSamples++,
903
+ hasValidBackground = !0);
904
+ }
905
+ }
906
+ }
907
+ // Check for image backgrounds
908
+ bgImage && "none" !== bgImage && "initial" !== bgImage && (
909
+ // For image backgrounds, assume medium luminance
910
+ totalLuminance += .5, validSamples++, hasValidBackground = !0);
911
+ } catch (styleError) {
912
+ process.env.NODE_ENV;
913
+ }
914
+ // Move to parent element for next iteration
915
+ if (!currentElement) break;
916
+ // Exit loop if currentElement becomes null
917
+ currentElement = currentElement.parentElement, depth++;
918
+ }
919
+ // More conservative detection with better error handling
920
+ if (hasValidBackground && validSamples > 0) {
921
+ const avgLuminance = totalLuminance / validSamples;
922
+ if (!isNaN(avgLuminance) && isFinite(avgLuminance)) {
923
+ let threshold = .7;
924
+ // Conservative threshold for overlight
925
+ // If overLight is an object, use its threshold property with validation
926
+ if ("object" == typeof overLight && null !== overLight) {
927
+ const objConfig = overLight;
928
+ if (void 0 !== objConfig.threshold) {
929
+ const configThreshold = "number" == typeof objConfig.threshold && !isNaN(objConfig.threshold) && isFinite(objConfig.threshold) ? objConfig.threshold : .7;
930
+ threshold = Math.min(.9, Math.max(.1, configThreshold));
931
+ }
932
+ }
933
+ const isOverLightDetected = avgLuminance > threshold;
934
+ // Cache the result in shared cache
935
+ setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
936
+ setDetectedOverLight(isOverLightDetected);
937
+ } else {
938
+ // Invalid luminance calculation, default to false
939
+ const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
940
+ setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
941
+ setDetectedOverLight(result);
942
+ }
943
+ } else {
944
+ // Default to false if no valid background found
945
+ const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
946
+ setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
947
+ setDetectedOverLight(result);
948
+ }
949
+ } catch (error) {
950
+ // Enhanced error logging with context
951
+ "development" === process.env.NODE_ENV && console.warn("AtomixGlass: Error detecting background brightness:", error);
952
+ const result = !1;
953
+ if (element && element.parentElement) {
954
+ const threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
955
+ setCachedBackgroundDetection(element.parentElement, overLight, result, threshold);
956
+ }
957
+ setDetectedOverLight(result);
958
+ }
959
+ }), 150);
960
+ return () => clearTimeout(timeoutId);
961
+ }
962
+ if ("boolean" == typeof overLight &&
963
+ // For boolean values, disable auto-detection
964
+ // Cache is automatically managed by WeakMap (no manual clearing needed)
965
+ setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
966
+ const mediaQueryReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"), mediaQueryHighContrast = window.matchMedia("(prefers-contrast: high)");
967
+ setUserPrefersReducedMotion(mediaQueryReducedMotion.matches), setUserPrefersHighContrast(mediaQueryHighContrast.matches);
968
+ const handleReducedMotionChange = e => {
969
+ setUserPrefersReducedMotion(e.matches);
970
+ }, handleHighContrastChange = e => {
971
+ setUserPrefersHighContrast(e.matches);
972
+ };
973
+ return mediaQueryReducedMotion.addEventListener ? (mediaQueryReducedMotion.addEventListener("change", handleReducedMotionChange),
974
+ mediaQueryHighContrast.addEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.addListener && (mediaQueryReducedMotion.addListener(handleReducedMotionChange),
975
+ mediaQueryHighContrast.addListener(handleHighContrastChange)), () => {
976
+ try {
977
+ mediaQueryReducedMotion.removeEventListener ? (mediaQueryReducedMotion.removeEventListener("change", handleReducedMotionChange),
978
+ mediaQueryHighContrast.removeEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.removeListener && (mediaQueryReducedMotion.removeListener(handleReducedMotionChange),
979
+ mediaQueryHighContrast.removeListener(handleHighContrastChange));
980
+ } catch (cleanupError) {
981
+ console.error("AtomixGlass: Error cleaning up media query listeners:", cleanupError);
982
+ }
983
+ };
984
+ } catch (error) {
985
+ return void console.error("AtomixGlass: Error setting up media queries:", error);
986
+ }
987
+ }), [ overLight, glassRef, debugOverLight ]);
988
+ // Mouse tracking using shared global tracker
989
+ // Cache bounding rect to avoid repeated getBoundingClientRect calls
990
+ const cachedRectRef = useRef(null), updateRectRef = useRef(null), handleGlobalMousePosition = useCallback((globalPos => {
991
+ if (externalGlobalMousePosition && externalMouseOffset)
992
+ // External mouse position provided, skip internal tracking
993
+ return;
994
+ if (effectiveDisableEffects) return;
995
+ const container = mouseContainer?.current || glassRef.current;
996
+ if (!container) return;
997
+ enablePerformanceMonitoring && performance.now();
998
+ // Use cached rect if available, otherwise get new one
999
+ let rect = cachedRectRef.current;
1000
+ if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
1001
+ cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
1002
+ const center = calculateElementCenter(rect), newOffset = {
1003
+ x: (globalPos.x - center.x) / rect.width * 100,
1004
+ y: (globalPos.y - center.y) / rect.height * 100
1005
+ };
1006
+ // Calculate offset relative to this container
1007
+ // React 18 automatically batches these updates
1008
+ setInternalMouseOffset(newOffset), setInternalGlobalMousePosition(globalPos), "production" !== process.env.NODE_ENV && enablePerformanceMonitoring && performance.now();
1009
+ }), [ mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveDisableEffects, enablePerformanceMonitoring ]);
1010
+ // Subscribe to shared mouse tracker
1011
+ useEffect((() => {
1012
+ if (externalGlobalMousePosition && externalMouseOffset)
1013
+ // External mouse position provided, don't subscribe
1014
+ return;
1015
+ if (effectiveDisableEffects)
1016
+ // Effects disabled, don't subscribe
1017
+ return;
1018
+ // Subscribe to shared tracker
1019
+ const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
1020
+ // Update cached rect when container size changes
1021
+ let resizeObserver = null;
1022
+ return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
1023
+ null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
1024
+ const container = mouseContainer?.current || glassRef.current;
1025
+ container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
1026
+ }));
1027
+ })), resizeObserver.observe(container)), () => {
1028
+ unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
1029
+ updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
1030
+ };
1031
+ }), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveDisableEffects ]);
1032
+ // Transform calculations
1033
+ const calculateDirectionalScale = useCallback((() => {
1034
+ if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return "scale(1)";
1035
+ const rect = glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect), deltaX = globalMousePosition.x - center.x, deltaY = globalMousePosition.y - center.y, edgeDistanceX = Math.max(0, Math.abs(deltaX) - glassSize.width / 2), edgeDistanceY = Math.max(0, Math.abs(deltaY) - glassSize.height / 2), edgeDistance = calculateDistance({
1036
+ x: edgeDistanceX,
1037
+ y: edgeDistanceY
1038
+ }, {
1039
+ x: 0,
1040
+ y: 0
1041
+ });
1042
+ if (edgeDistance > CONSTANTS.ACTIVATION_ZONE) return "scale(1)";
1043
+ const fadeInFactor = 1 - edgeDistance / CONSTANTS.ACTIVATION_ZONE, centerDistance = calculateDistance(globalMousePosition, center);
1044
+ if (0 === centerDistance) return "scale(1)";
1045
+ const normalizedX = deltaX / centerDistance, normalizedY = deltaY / centerDistance, stretchIntensity = Math.min(centerDistance / 300, 1) * elasticity * fadeInFactor, scaleX = 1 + Math.abs(normalizedX) * stretchIntensity * .3 - Math.abs(normalizedY) * stretchIntensity * .15, scaleY = 1 + Math.abs(normalizedY) * stretchIntensity * .3 - Math.abs(normalizedX) * stretchIntensity * .15;
1046
+ return `scaleX(${Math.max(.8, scaleX)}) scaleY(${Math.max(.8, scaleY)})`;
1047
+ }), [ globalMousePosition, elasticity, glassSize, glassRef ]), calculateFadeInFactor = useCallback((() => {
1048
+ if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return 0;
1049
+ const rect = glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect), edgeDistanceX = Math.max(0, Math.abs(globalMousePosition.x - center.x) - glassSize.width / 2), edgeDistanceY = Math.max(0, Math.abs(globalMousePosition.y - center.y) - glassSize.height / 2), edgeDistance = calculateDistance({
1050
+ x: edgeDistanceX,
1051
+ y: edgeDistanceY
1052
+ }, {
1053
+ x: 0,
1054
+ y: 0
1055
+ });
1056
+ return edgeDistance > CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / CONSTANTS.ACTIVATION_ZONE;
1057
+ }), [ globalMousePosition, glassSize, glassRef ]), calculateElasticTranslation = useCallback((() => {
1058
+ if (!glassRef.current) return {
1059
+ x: 0,
1060
+ y: 0
1061
+ };
1062
+ const fadeInFactor = calculateFadeInFactor(), rect = glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect);
1063
+ return {
1064
+ x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
1065
+ y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
1066
+ };
1067
+ }), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() => effectiveDisableEffects ? {
1068
+ x: 0,
1069
+ y: 0
1070
+ } : calculateElasticTranslation()), [ calculateElasticTranslation, effectiveDisableEffects ]), directionalScale = useMemo((() => effectiveDisableEffects ? "scale(1)" : calculateDirectionalScale()), [ calculateDirectionalScale, effectiveDisableEffects ]), transformStyle = useMemo((() => effectiveDisableEffects ? isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)" : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? "scale(0.96)" : directionalScale}`), [ elasticTranslation, isActive, onClick, directionalScale, effectiveDisableEffects ]);
1071
+ // Size management
1072
+ useEffect((() => {
1073
+ const isValidElement = element => null !== element && element instanceof HTMLElement && element.isConnected;
1074
+ let rafId = null, lastSize = {
1075
+ width: 0,
1076
+ height: 0
1077
+ }, lastCornerRadius = effectiveCornerRadius;
1078
+ const updateGlassSize = (forceUpdate = !1) => {
1079
+ null !== rafId && cancelAnimationFrame(rafId), rafId = requestAnimationFrame((() => {
1080
+ if (!isValidElement(glassRef.current)) return void (rafId = null);
1081
+ const rect = glassRef.current.getBoundingClientRect();
1082
+ if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
1083
+ // Measure actual rendered size without artificial offsets to avoid feedback loops
1084
+ const newSize = {
1085
+ width: Math.round(rect.width),
1086
+ height: Math.round(rect.height)
1087
+ }, cornerRadiusChanged = lastCornerRadius !== effectiveCornerRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
1088
+ var size;
1089
+ (forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS.MAX_SIZE && size.height <= CONSTANTS.MAX_SIZE && (lastSize = newSize,
1090
+ lastCornerRadius = effectiveCornerRadius, setGlassSize(newSize)), rafId = null;
1091
+ }));
1092
+ };
1093
+ let resizeTimeoutId = null;
1094
+ const debouncedResizeHandler = () => {
1095
+ resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
1096
+ }, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
1097
+ let resizeObserver = null, resizeDebounceTimeout = null;
1098
+ // ResizeObserver has 98%+ browser support, no need for fallback
1099
+ if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
1100
+ resizeObserver = new ResizeObserver((entries => {
1101
+ for (const entry of entries) if (entry.target === glassRef.current) {
1102
+ // Update cached rect when size changes
1103
+ glassRef.current && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
1104
+ // Debounce resize updates to match RAF timing (16ms)
1105
+ resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
1106
+ break;
1107
+ }
1108
+ })), resizeObserver.observe(glassRef.current);
1109
+ } catch (error) {
1110
+ console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
1111
+ }
1112
+ return window.addEventListener("resize", debouncedResizeHandler, {
1113
+ passive: !0
1114
+ }), () => {
1115
+ clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
1116
+ resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
1117
+ resizeObserver?.disconnect();
1118
+ };
1119
+ }), [ effectiveCornerRadius, glassRef ]);
1120
+ // OverLight config
1121
+ /**
1122
+ * Get effective overLight value based on configuration
1123
+ * - boolean: returns the boolean value directly
1124
+ * - 'auto': returns detectedOverLight (auto-detected from background)
1125
+ * - object: returns detectedOverLight (auto-detected, but config object provides customization)
1126
+ */
1127
+ const getEffectiveOverLight = useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []), overLightConfig = useMemo((() => {
1128
+ const isOverLight = getEffectiveOverLight(), mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, baseConfig = {
1129
+ isOverLight: isOverLight,
1130
+ threshold: .7,
1131
+ opacity: isOverLight ? Math.min(.6, Math.max(.2, .5 * hoverIntensity * activeIntensity)) : 0,
1132
+ contrast: Math.min(1.8, Math.max(1, 1.4 + .3 * mouseInfluence)),
1133
+ brightness: Math.min(1.2, Math.max(.7, .85 + .15 * mouseInfluence)),
1134
+ saturationBoost: Math.min(2, Math.max(1, 1.3 + .4 * mouseInfluence)),
1135
+ shadowIntensity: Math.min(1.5, Math.max(.5, .9 + .5 * mouseInfluence)),
1136
+ borderOpacity: Math.min(1, Math.max(.3, .7 + .3 * mouseInfluence))
1137
+ };
1138
+ if ("object" == typeof overLight && null !== overLight) {
1139
+ const objConfig = overLight, validatedThreshold = validateConfigValue(objConfig.threshold, .1, 1, baseConfig.threshold), validatedOpacity = validateConfigValue(objConfig.opacity, .1, 1, baseConfig.opacity), validatedContrast = validateConfigValue(objConfig.contrast, .5, 2.5, baseConfig.contrast), validatedBrightness = validateConfigValue(objConfig.brightness, .5, 2, baseConfig.brightness), validatedSaturationBoost = validateConfigValue(objConfig.saturationBoost, .5, 3, baseConfig.saturationBoost), finalConfig = {
1140
+ ...baseConfig,
1141
+ threshold: validatedThreshold,
1142
+ opacity: validatedOpacity * hoverIntensity * activeIntensity,
1143
+ contrast: validatedContrast + .3 * mouseInfluence,
1144
+ brightness: validatedBrightness + .15 * mouseInfluence,
1145
+ saturationBoost: validatedSaturationBoost + .4 * mouseInfluence
1146
+ };
1147
+ // Validate and apply object config values with proper clamping
1148
+ return process.env.NODE_ENV, finalConfig;
1149
+ }
1150
+ // Debug logging for non-object configs
1151
+ return process.env.NODE_ENV, baseConfig;
1152
+ }), [ overLight, getEffectiveOverLight, mouseOffset, isHovered, isActive, validateConfigValue, debugOverLight ]), handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleKeyDown = useCallback((e => {
1153
+ !onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
1154
+ }), [ onClick ]), handleMouseMove = useCallback((_e => {}), []);
1155
+ /**
1156
+ * Validate and clamp a numeric config value
1157
+ * @param value - The value to validate
1158
+ * @param min - Minimum allowed value
1159
+ * @param max - Maximum allowed value
1160
+ * @param defaultValue - Default value if validation fails
1161
+ * @returns Validated and clamped value
1162
+ */ return {
1163
+ // State
1164
+ isHovered: isHovered,
1165
+ isActive: isActive,
1166
+ glassSize: glassSize,
1167
+ dynamicCornerRadius: dynamicCornerRadius,
1168
+ effectiveCornerRadius: effectiveCornerRadius,
1169
+ effectiveReducedMotion: effectiveReducedMotion,
1170
+ effectiveHighContrast: effectiveHighContrast,
1171
+ effectiveDisableEffects: effectiveDisableEffects,
1172
+ detectedOverLight: detectedOverLight,
1173
+ globalMousePosition: globalMousePosition,
1174
+ mouseOffset: mouseOffset,
1175
+ // OverLight config
1176
+ overLightConfig: overLightConfig,
1177
+ // Transform calculations
1178
+ elasticTranslation: elasticTranslation,
1179
+ directionalScale: directionalScale,
1180
+ transformStyle: transformStyle,
1181
+ // Event handlers
1182
+ handleMouseEnter: handleMouseEnter,
1183
+ handleMouseLeave: handleMouseLeave,
1184
+ handleMouseDown: handleMouseDown,
1185
+ handleMouseUp: handleMouseUp,
1186
+ handleMouseMove: handleMouseMove,
1187
+ handleKeyDown: handleKeyDown
1188
+ };
1189
+ }
1190
+
1191
+ /**
1192
+ * AtomixGlass - A high-performance glass morphism component with liquid distortion effects
1193
+ *
1194
+ * Features:
1195
+ * - Hardware-accelerated glass effects with SVG filters
1196
+ * - Mouse-responsive liquid distortion
1197
+ * - Dynamic border-radius extraction from children CSS properties
1198
+ * - Automatic light/dark theme detection via overLight prop
1199
+ * - Accessibility and performance optimizations
1200
+ * - Multiple displacement modes (standard, polar, prominent, shader)
1201
+ * - Design token integration for consistent theming
1202
+ * - Focus ring support for keyboard navigation
1203
+ * - Responsive breakpoints for mobile optimization
1204
+ * - Enhanced ARIA attributes for screen readers
1205
+ *
1206
+ * Design System Compliance:
1207
+ * - Uses design tokens for opacity, spacing, and colors
1208
+ * - Follows BEM methodology for class naming
1209
+ * - Implements focus-ring mixin for accessibility
1210
+ * - Supports reduced motion and high contrast preferences
1211
+ *
1212
+ * @example
1213
+ * // Basic usage with dynamic border-radius extraction
1214
+ * <AtomixGlass>
1215
+ * <div style={{ borderRadius: '12px' }}>Content with 12px radius</div>
1216
+ * </AtomixGlass>
1217
+ *
1218
+ * @example
1219
+ * // Manual border-radius override
1220
+ * <AtomixGlass cornerRadius={20}>
1221
+ * <div>Content with 20px glass radius</div>
1222
+ * </AtomixGlass>
1223
+ *
1224
+ * @example
1225
+ * // Interactive glass with click handler
1226
+ * <AtomixGlass onClick={() => console.log('Clicked')} aria-label="Glass card">
1227
+ * <div>Clickable content</div>
1228
+ * </AtomixGlass>
1229
+ *
1230
+ * @example
1231
+ * // OverLight - Boolean mode (explicit control)
1232
+ * <AtomixGlass overLight={true}>
1233
+ * <div>Content on light background</div>
1234
+ * </AtomixGlass>
1235
+ *
1236
+ * @example
1237
+ * // OverLight - Auto-detection mode
1238
+ * <AtomixGlass overLight="auto">
1239
+ * <div>Content with auto-detected background</div>
1240
+ * </AtomixGlass>
1241
+ *
1242
+ * @example
1243
+ * // OverLight - Object config with custom settings
1244
+ * <AtomixGlass
1245
+ * overLight={{
1246
+ * threshold: 0.8,
1247
+ * opacity: 0.6,
1248
+ * contrast: 1.8,
1249
+ * brightness: 1.0,
1250
+ * saturationBoost: 1.5
1251
+ * }}
1252
+ * >
1253
+ * <div>Content with custom overLight config</div>
1254
+ * </AtomixGlass>
1255
+ *
1256
+ * @example
1257
+ * // Debug mode for overLight detection
1258
+ * <AtomixGlass overLight="auto" debugOverLight={true}>
1259
+ * <div>Content with debug logging enabled</div>
1260
+ * </AtomixGlass>
1261
+ */ 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, cornerRadius: cornerRadius, 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, disableEffects: disableEffects = !1, enableLiquidBlur: enableLiquidBlur = !1, enableBorderEffect: enableBorderEffect = !0, enableOverLightLayers: enableOverLightLayers = ATOMIX_GLASS.DEFAULTS.ENABLE_OVER_LIGHT_LAYERS, enablePerformanceMonitoring: enablePerformanceMonitoring = !1, debugCornerRadius: debugCornerRadius = !1, debugOverLight: debugOverLight = !1}) {
1262
+ const glassRef = useRef(null), contentRef = useRef(null), opacityCacheRef = useRef(null), rgbCacheRef = useRef(null), {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveCornerRadius: effectiveCornerRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveDisableEffects: effectiveDisableEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
1263
+ glassRef: glassRef,
1264
+ contentRef: contentRef,
1265
+ cornerRadius: cornerRadius,
1266
+ globalMousePosition: externalGlobalMousePosition,
1267
+ mouseOffset: externalMouseOffset,
1268
+ mouseContainer: mouseContainer,
1269
+ overLight: overLight,
1270
+ reducedMotion: reducedMotion,
1271
+ highContrast: highContrast,
1272
+ disableEffects: disableEffects,
1273
+ elasticity: elasticity,
1274
+ onClick: onClick,
1275
+ debugCornerRadius: debugCornerRadius,
1276
+ debugOverLight: debugOverLight,
1277
+ enablePerformanceMonitoring: enablePerformanceMonitoring,
1278
+ children: children
1279
+ }), isOverLight = overLightConfig.isOverLight, shouldRenderOverLightLayers = enableOverLightLayers && isOverLight;
1280
+ // Read CSS custom properties once on mount and cache them
1281
+ useEffect((() => {
1282
+ if ("undefined" != typeof window && glassRef.current) try {
1283
+ const computedStyle = window.getComputedStyle(glassRef.current);
1284
+ // Cache opacity values
1285
+ if (!opacityCacheRef.current) {
1286
+ const opacity50Value = computedStyle.getPropertyValue("--atomix-opacity-50").trim(), opacity40Value = computedStyle.getPropertyValue("--atomix-opacity-40").trim(), opacity80Value = computedStyle.getPropertyValue("--atomix-opacity-80").trim(), opacity0Value = computedStyle.getPropertyValue("--atomix-opacity-0").trim(), parseOpacity = (value, defaultValue) => {
1287
+ if (!value) return defaultValue;
1288
+ const parsed = parseFloat(value);
1289
+ return isNaN(parsed) ? defaultValue : parsed;
1290
+ };
1291
+ opacityCacheRef.current = {
1292
+ opacity50: parseOpacity(opacity50Value, .5),
1293
+ opacity40: parseOpacity(opacity40Value, .4),
1294
+ opacity80: parseOpacity(opacity80Value, .8),
1295
+ opacity0: parseOpacity(opacity0Value, 0)
1296
+ };
1297
+ }
1298
+ // Cache RGB color values from design tokens
1299
+ if (!rgbCacheRef.current) {
1300
+ // Try to read from design tokens, fallback to defaults
1301
+ const whiteRgbValue = computedStyle.getPropertyValue("--atomix-light-rgb").trim() || computedStyle.getPropertyValue("--atomix-white-rgb").trim() || "", blackRgbValue = computedStyle.getPropertyValue("--atomix-dark-rgb").trim() || computedStyle.getPropertyValue("--atomix-black-rgb").trim() || "";
1302
+ rgbCacheRef.current = {
1303
+ whiteRgb: whiteRgbValue || "255, 255, 255",
1304
+ // Fallback to white RGB
1305
+ blackRgb: blackRgbValue || "0, 0, 0"
1306
+ };
1307
+ }
1308
+ } catch (error) {
1309
+ // Fallback to defaults if reading fails
1310
+ opacityCacheRef.current || (opacityCacheRef.current = {
1311
+ opacity50: .5,
1312
+ opacity40: .4,
1313
+ opacity80: .8,
1314
+ opacity0: 0
1315
+ }), rgbCacheRef.current || (rgbCacheRef.current = {
1316
+ whiteRgb: "255, 255, 255",
1317
+ blackRgb: "0, 0, 0"
1318
+ });
1319
+ }
1320
+ }), []);
1321
+ // Calculate base style with transforms (only dynamic values)
1322
+ const baseStyle = useMemo((() => ({
1323
+ ...style,
1324
+ ...0 !== elasticity && !effectiveDisableEffects && {
1325
+ transform: transformStyle
1326
+ }
1327
+ })), [ style, transformStyle, effectiveDisableEffects, elasticity ]), componentClassName = useMemo((() => [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveDisableEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className ].filter(Boolean).join(" ")), [ effectiveReducedMotion, effectiveHighContrast, effectiveDisableEffects, className ]), baseStylePosition = baseStyle.position, baseStyleTop = baseStyle.top, baseStyleLeft = baseStyle.left, positionStyles = useMemo((() => ({
1328
+ position: baseStylePosition || "absolute",
1329
+ top: baseStyleTop || 0,
1330
+ left: baseStyleLeft || 0
1331
+ })), [ baseStylePosition, baseStyleTop, baseStyleLeft ]), baseStyleWidth = baseStyle.width, baseStyleHeight = baseStyle.height, glassSizeWidth = glassSize.width, glassSizeHeight = glassSize.height, adjustedSize = useMemo((() => ({
1332
+ width: "fixed" !== baseStylePosition ? "100%" : baseStyleWidth || Math.max(glassSizeWidth, 0),
1333
+ height: "fixed" !== baseStylePosition ? "100%" : baseStyleHeight || Math.max(glassSizeHeight, 0)
1334
+ })), [ baseStylePosition, baseStyleWidth, baseStyleHeight, glassSizeWidth, glassSizeHeight ]), mouseOffsetX = mouseOffset.x, mouseOffsetY = mouseOffset.y, GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT, gradientCalculations = useMemo((() => {
1335
+ const mx = mouseOffsetX, my = mouseOffsetY, borderGradientAngle = GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER, borderStop1 = Math.max(GRADIENT.BORDER_STOP_1.MIN, GRADIENT.BORDER_STOP_1.BASE + my * GRADIENT.BORDER_STOP_1.MULTIPLIER), borderStop2 = Math.min(GRADIENT.BORDER_STOP_2.MAX, GRADIENT.BORDER_STOP_2.BASE + my * GRADIENT.BORDER_STOP_2.MULTIPLIER), borderOpacity1 = GRADIENT.BORDER_OPACITY.BASE_1 + Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW, borderOpacity2 = GRADIENT.BORDER_OPACITY.BASE_2 + Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH, borderOpacity3 = GRADIENT.BORDER_OPACITY.BASE_3 + Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW, borderOpacity4 = GRADIENT.BORDER_OPACITY.BASE_4 + Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH, hover1X = GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1, hover1Y = GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1, hover2X = GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_2, hover2Y = GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_2, hover3X = GRADIENT.CENTER_POSITION + mx * GRADIENT.HOVER_POSITION.MULTIPLIER_3, hover3Y = GRADIENT.CENTER_POSITION + my * GRADIENT.HOVER_POSITION.MULTIPLIER_3, baseX = GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER, baseY = GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER;
1336
+ return {
1337
+ isOverLight: isOverLight,
1338
+ mx: mx,
1339
+ my: my,
1340
+ borderGradientAngle: borderGradientAngle,
1341
+ borderStop1: borderStop1,
1342
+ borderStop2: borderStop2,
1343
+ borderOpacity1: borderOpacity1,
1344
+ borderOpacity2: borderOpacity2,
1345
+ borderOpacity3: borderOpacity3,
1346
+ borderOpacity4: borderOpacity4,
1347
+ hover1X: hover1X,
1348
+ hover1Y: hover1Y,
1349
+ hover2X: hover2X,
1350
+ hover2Y: hover2Y,
1351
+ hover3X: hover3X,
1352
+ hover3Y: hover3Y,
1353
+ baseX: baseX,
1354
+ baseY: baseY
1355
+ };
1356
+ }), [ mouseOffsetX, mouseOffsetY, isOverLight ]), overLightOpacity = overLightConfig.opacity, opacityValues = useMemo((() => {
1357
+ // Use cached values if available, otherwise fallback to defaults
1358
+ const opacity50 = opacityCacheRef.current?.opacity50 ?? .5, opacity40 = opacityCacheRef.current?.opacity40 ?? .4, opacity80 = opacityCacheRef.current?.opacity80 ?? .8, opacity0 = opacityCacheRef.current?.opacity0 ?? 0;
1359
+ // Dynamic multiplier for overlay
1360
+ return {
1361
+ hover1: isHovered || isActive ? opacity50 : opacity0,
1362
+ hover2: isActive ? opacity50 : opacity0,
1363
+ hover3: isHovered ? opacity40 : isActive ? opacity80 : opacity0,
1364
+ base: isOverLight ? overLightOpacity || opacity40 : opacity0,
1365
+ over: isOverLight ? 1.1 * (overLightOpacity || opacity40) : opacity0
1366
+ };
1367
+ }), [ isHovered, isActive, isOverLight, overLightOpacity ]), gradientIsOverLight = gradientCalculations.isOverLight, gradientMx = gradientCalculations.mx, gradientMy = gradientCalculations.my, gradientBorderGradientAngle = gradientCalculations.borderGradientAngle, gradientBorderStop1 = gradientCalculations.borderStop1, gradientBorderStop2 = gradientCalculations.borderStop2, gradientBorderOpacity1 = gradientCalculations.borderOpacity1, gradientBorderOpacity2 = gradientCalculations.borderOpacity2, gradientBorderOpacity3 = gradientCalculations.borderOpacity3, gradientBorderOpacity4 = gradientCalculations.borderOpacity4, gradientHover1X = gradientCalculations.hover1X, gradientHover1Y = gradientCalculations.hover1Y, gradientHover2X = gradientCalculations.hover2X, gradientHover2Y = gradientCalculations.hover2Y, gradientHover3X = gradientCalculations.hover3X, gradientHover3Y = gradientCalculations.hover3Y, gradientBaseX = gradientCalculations.baseX, gradientBaseY = gradientCalculations.baseY, positionStylesPosition = positionStyles.position, positionStylesTop = positionStyles.top, positionStylesLeft = positionStyles.left, adjustedSizeWidth = adjustedSize.width, adjustedSizeHeight = adjustedSize.height, baseStyleTransform = baseStyle.transform, opacityValuesHover1 = opacityValues.hover1, opacityValuesHover2 = opacityValues.hover2, opacityValuesHover3 = opacityValues.hover3, opacityValuesBase = opacityValues.base, opacityValuesOver = opacityValues.over, glassVars = useMemo((() => {
1368
+ // RGB color values for rgba() functions
1369
+ // Note: CSS doesn't support rgba(var(--rgb), opacity) syntax - this is a CSS specification
1370
+ // limitation, not a browser support issue. We read RGB values from design tokens at mount
1371
+ // and cache them for performance. Falls back to defaults if tokens are not available.
1372
+ // Uses design tokens: --atomix-light-rgb / --atomix-white-rgb and --atomix-dark-rgb / --atomix-black-rgb
1373
+ const whiteColor = rgbCacheRef.current?.whiteRgb || "255, 255, 255", blackColor = rgbCacheRef.current?.blackRgb || "0, 0, 0";
1374
+ return {
1375
+ // Standard CSS custom properties for dynamic values
1376
+ "--atomix-glass-radius": `${effectiveCornerRadius}px`,
1377
+ "--atomix-glass-transform": baseStyleTransform || "none",
1378
+ "--atomix-glass-position": positionStylesPosition,
1379
+ "--atomix-glass-top": "fixed" !== positionStylesTop ? `${positionStylesTop}px` : "0",
1380
+ "--atomix-glass-left": "fixed" !== positionStylesLeft ? `${positionStylesLeft}px` : "0",
1381
+ "--atomix-glass-width": "fixed" !== baseStylePosition ? adjustedSizeWidth : `${adjustedSizeWidth}px`,
1382
+ "--atomix-glass-height": "fixed" !== baseStylePosition ? adjustedSizeHeight : `${adjustedSizeHeight}px`,
1383
+ // Border width: Use spacing token for consistency
1384
+ "--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.09375rem)",
1385
+ "--atomix-glass-blend-mode": gradientIsOverLight ? "multiply" : "overlay",
1386
+ // Dynamic gradients and backgrounds
1387
+ // Note: RGB values use design token-aligned constants (white: 255,255,255; black: 0,0,0)
1388
+ "--atomix-glass-border-gradient-1": `linear-gradient(${gradientBorderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${gradientBorderOpacity1}) ${gradientBorderStop1}%, rgba(${whiteColor}, ${gradientBorderOpacity2}) ${gradientBorderStop2}%, rgba(${whiteColor}, 0) 100%)`,
1389
+ "--atomix-glass-border-gradient-2": `linear-gradient(${gradientBorderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${gradientBorderOpacity3}) ${gradientBorderStop1}%, rgba(${whiteColor}, ${gradientBorderOpacity4}) ${gradientBorderStop2}%, rgba(${whiteColor}, 0) 100%)`,
1390
+ "--atomix-glass-hover-1-opacity": opacityValuesHover1,
1391
+ "--atomix-glass-hover-1-gradient": gradientIsOverLight ? `radial-gradient(circle at ${gradientHover1X}% ${gradientHover1Y}%, 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 ${gradientHover1X}% ${gradientHover1Y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_STOP}%)`,
1392
+ "--atomix-glass-hover-2-opacity": opacityValuesHover2,
1393
+ "--atomix-glass-hover-2-gradient": gradientIsOverLight ? `radial-gradient(circle at ${gradientHover2X}% ${gradientHover2Y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_END}%)` : `radial-gradient(circle at ${gradientHover2X}% ${gradientHover2Y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_STOP}%)`,
1394
+ "--atomix-glass-hover-3-opacity": opacityValuesHover3,
1395
+ "--atomix-glass-hover-3-gradient": gradientIsOverLight ? `radial-gradient(circle at ${gradientHover3X}% ${gradientHover3Y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_END}%)` : `radial-gradient(circle at ${gradientHover3X}% ${gradientHover3Y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_STOP}%)`,
1396
+ "--atomix-glass-base-opacity": opacityValuesBase,
1397
+ "--atomix-glass-base-gradient": gradientIsOverLight ? `linear-gradient(${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.ANGLE}deg, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_BASE + gradientMx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_BASE + gradientMy * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_MULTIPLIER}) ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_BASE + Math.abs(gradientMx) * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.WHITE_OPACITY})`,
1398
+ "--atomix-glass-overlay-opacity": opacityValuesOver,
1399
+ "--atomix-glass-overlay-gradient": gradientIsOverLight ? `radial-gradient(circle at ${gradientBaseX}% ${gradientBaseY}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + Math.abs(gradientMx) * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_BASE + Math.abs(gradientMy) * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`
1400
+ };
1401
+ }), [
1402
+ // Position styles - only specific properties
1403
+ positionStylesPosition, positionStylesTop, positionStylesLeft,
1404
+ // Adjusted size - only specific properties
1405
+ adjustedSizeWidth, adjustedSizeHeight,
1406
+ // Base style - only transform property
1407
+ baseStyleTransform, baseStylePosition,
1408
+ // Other values
1409
+ effectiveCornerRadius, effectiveReducedMotion,
1410
+ // Gradient calculations - extracted properties
1411
+ gradientIsOverLight, gradientMx, gradientMy, gradientBorderGradientAngle, gradientBorderStop1, gradientBorderStop2, gradientBorderOpacity1, gradientBorderOpacity2, gradientBorderOpacity3, gradientBorderOpacity4, gradientHover1X, gradientHover1Y, gradientHover2X, gradientHover2Y, gradientHover3X, gradientHover3Y, gradientBaseX, gradientBaseY,
1412
+ // Opacity values - extracted properties
1413
+ opacityValuesHover1, opacityValuesHover2, opacityValuesHover3, opacityValuesBase, opacityValuesOver ]);
1414
+ // Build className with state modifiers
1415
+ return jsxs("div", {
1416
+ className: componentClassName,
1417
+ style: glassVars,
1418
+ role: role || (onClick ? "button" : void 0),
1419
+ tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
1420
+ "aria-label": ariaLabel,
1421
+ "aria-describedby": ariaDescribedBy,
1422
+ "aria-disabled": !(!onClick || !effectiveDisableEffects) || !onClick && void 0,
1423
+ "aria-pressed": !(!onClick || !isActive) || !onClick && void 0,
1424
+ onKeyDown: onClick ? handleKeyDown : void 0,
1425
+ children: [ jsx(AtomixGlassContainer, {
1426
+ ref: glassRef,
1427
+ contentRef: contentRef,
1428
+ className: className,
1429
+ style: baseStyle,
1430
+ cornerRadius: effectiveCornerRadius,
1431
+ displacementScale: effectiveDisableEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : overLightConfig.isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
1432
+ blurAmount: effectiveDisableEffects ? 0 : blurAmount,
1433
+ saturation: effectiveHighContrast ? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST : overLightConfig.isOverLight ? saturation * overLightConfig.saturationBoost : saturation,
1434
+ aberrationIntensity: effectiveDisableEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
1435
+ glassSize: glassSize,
1436
+ padding: padding,
1437
+ mouseOffset: effectiveDisableEffects ? {
1438
+ x: 0,
1439
+ y: 0
1440
+ } : mouseOffset,
1441
+ globalMousePosition: effectiveDisableEffects ? {
1442
+ x: 0,
1443
+ y: 0
1444
+ } : globalMousePosition,
1445
+ onMouseEnter: handleMouseEnter,
1446
+ onMouseLeave: handleMouseLeave,
1447
+ onMouseDown: handleMouseDown,
1448
+ onMouseUp: handleMouseUp,
1449
+ active: isActive,
1450
+ isHovered: isHovered,
1451
+ isActive: isActive,
1452
+ overLight: overLightConfig.isOverLight,
1453
+ onClick: onClick,
1454
+ mode: mode,
1455
+ transform: baseStyle.transform,
1456
+ effectiveDisableEffects: effectiveDisableEffects,
1457
+ effectiveReducedMotion: effectiveReducedMotion,
1458
+ shaderVariant: shaderVariant,
1459
+ elasticity: elasticity,
1460
+ enableLiquidBlur: enableLiquidBlur,
1461
+ children: children
1462
+ }), Boolean(onClick) && jsxs(Fragment, {
1463
+ children: [ jsx("div", {
1464
+ className: ATOMIX_GLASS.HOVER_1_CLASS
1465
+ }), jsx("div", {
1466
+ className: ATOMIX_GLASS.HOVER_2_CLASS
1467
+ }), jsx("div", {
1468
+ className: ATOMIX_GLASS.HOVER_3_CLASS
1469
+ }) ]
1470
+ }), jsx("div", {
1471
+ className: [ ATOMIX_GLASS.BACKGROUND_LAYER_CLASS, ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS, isOverLight ? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS ].filter(Boolean).join(" "),
1472
+ style: {
1473
+ ...positionStyles,
1474
+ height: adjustedSize.height,
1475
+ width: adjustedSize.width,
1476
+ borderRadius: `${effectiveCornerRadius}px`,
1477
+ transform: baseStyle.transform
1478
+ }
1479
+ }), jsx("div", {
1480
+ className: [ ATOMIX_GLASS.BACKGROUND_LAYER_CLASS, ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS, isOverLight ? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS ].filter(Boolean).join(" "),
1481
+ style: {
1482
+ ...positionStyles,
1483
+ height: adjustedSize.height,
1484
+ width: adjustedSize.width,
1485
+ borderRadius: `${effectiveCornerRadius}px`,
1486
+ transform: baseStyle.transform
1487
+ }
1488
+ }), shouldRenderOverLightLayers && jsxs(Fragment, {
1489
+ children: [ jsx("div", {
1490
+ className: ATOMIX_GLASS.BASE_LAYER_CLASS
1491
+ }), jsx("div", {
1492
+ className: ATOMIX_GLASS.OVERLAY_LAYER_CLASS
1493
+ }), jsx("div", {
1494
+ className: ATOMIX_GLASS.OVERLAY_HIGHLIGHT_CLASS,
1495
+ style: {
1496
+ opacity: opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
1497
+ background: `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}%)`
1498
+ }
1499
+ }) ]
1500
+ }), enableBorderEffect && jsxs(Fragment, {
1501
+ children: [ jsx("span", {
1502
+ className: ATOMIX_GLASS.BORDER_1_CLASS
1503
+ }), jsx("span", {
1504
+ className: ATOMIX_GLASS.BORDER_2_CLASS
1505
+ }) ]
1506
+ }) ]
1507
+ });
1508
+ }
1509
+
1510
+ /**
1511
+ * Checkbox - A component for checkbox inputs
1512
+ */ const Checkbox = memo((({label: label, checked: checked = !1, onChange: onChange, className: className = "", style: style, disabled: disabled = !1, required: required = !1, id: id, name: name, value: value, invalid: invalid = !1, valid: valid = !1, indeterminate: indeterminate = !1, ariaLabel: ariaLabel, ariaDescribedBy: ariaDescribedBy, glass: glass}) => {
1513
+ const {generateCheckboxClass: generateCheckboxClass, checkboxRef: checkboxRef} = function(initialProps) {
1514
+ // Default checkbox properties
1515
+ const defaultProps = {
1516
+ disabled: !1,
1517
+ invalid: !1,
1518
+ valid: !1,
1519
+ indeterminate: !1,
1520
+ ...initialProps
1521
+ }, checkboxRef = useRef(null);
1522
+ // Ref for the checkbox input element
1523
+ // Handle indeterminate state
1524
+ return useEffect((() => {
1525
+ checkboxRef.current && (checkboxRef.current.indeterminate = Boolean(defaultProps.indeterminate));
1526
+ }), [ defaultProps.indeterminate ]), {
1527
+ defaultProps: defaultProps,
1528
+ generateCheckboxClass: props => {
1529
+ const {disabled: disabled = defaultProps.disabled, invalid: invalid = defaultProps.invalid, valid: valid = defaultProps.valid, indeterminate: indeterminate = defaultProps.indeterminate, className: className = ""} = props;
1530
+ let validationClass = "";
1531
+ return invalid ? validationClass = "is-error" : valid && (validationClass = "is-valid"),
1532
+ `c-checkbox ${validationClass} ${disabled ? "is-disabled" : ""} ${indeterminate ? "c-checkbox--mixed" : ""} ${className}`.trim();
1533
+ },
1534
+ checkboxRef: checkboxRef
1535
+ };
1536
+ }
1537
+ /**
1538
+ * Default theme colors for components
1539
+ */
1540
+ /**
1541
+ * Form-specific constants
1542
+ */ ({
1543
+ indeterminate: indeterminate,
1544
+ disabled: disabled,
1545
+ invalid: invalid,
1546
+ valid: valid
1547
+ }), checkboxClass = generateCheckboxClass({
1548
+ className: `${className} ${glass ? "c-checkbox--glass" : ""}`.trim(),
1549
+ disabled: disabled,
1550
+ invalid: invalid,
1551
+ valid: valid,
1552
+ indeterminate: indeterminate
1553
+ }), checkboxContent = jsxs("div", {
1554
+ className: checkboxClass,
1555
+ style: style,
1556
+ children: [ jsx("input", {
1557
+ ref: checkboxRef,
1558
+ type: "checkbox",
1559
+ className: "c-checkbox__input",
1560
+ checked: checked,
1561
+ onChange: onChange,
1562
+ disabled: disabled,
1563
+ required: required,
1564
+ id: id,
1565
+ name: name,
1566
+ value: value,
1567
+ "aria-label": label ? void 0 : ariaLabel,
1568
+ "aria-describedby": ariaDescribedBy,
1569
+ "aria-invalid": invalid
1570
+ }), label && jsx("label", {
1571
+ className: "c-checkbox__label",
1572
+ htmlFor: id,
1573
+ children: label
1574
+ }) ]
1575
+ });
1576
+ if (glass) {
1577
+ // Default glass settings for checkboxes
1578
+ const defaultGlassProps = {
1579
+ displacementScale: 40,
1580
+ blurAmount: 1,
1581
+ saturation: 160,
1582
+ aberrationIntensity: .3,
1583
+ cornerRadius: 6,
1584
+ mode: "shader"
1585
+ }, glassProps = !0 === glass ? defaultGlassProps : {
1586
+ ...defaultGlassProps,
1587
+ ...glass
1588
+ };
1589
+ return jsx(AtomixGlass, {
1590
+ ...glassProps,
1591
+ children: checkboxContent
1592
+ });
1593
+ }
1594
+ return checkboxContent;
1595
+ }));
1596
+
1597
+ Checkbox.displayName = "Checkbox";
1598
+
1599
+ /**
1600
+ * Form - A component for creating form layouts
1601
+ */
1602
+ const Form = ({children: children, onSubmit: onSubmit, onReset: onReset, className: className = "", style: style, disabled: disabled = !1, id: id, method: method = "post", encType: encType, noValidate: noValidate = !1, autoComplete: autoComplete = "on"}) => {
1603
+ const {generateFormClass: generateFormClass, handleSubmit: handleSubmit, handleReset: handleReset} =
1604
+ /**
1605
+ * Form state and functionality
1606
+ * @param initialProps - Initial form properties
1607
+ * @returns Form state and methods
1608
+ */
1609
+ function(initialProps) {
1610
+ // Default form properties
1611
+ const defaultProps = {
1612
+ disabled: !1,
1613
+ ...initialProps
1614
+ };
1615
+ /**
1616
+ * Generate form class based on properties
1617
+ * @param props - Form properties
1618
+ * @returns Class string
1619
+ */ return {
1620
+ defaultProps: defaultProps,
1621
+ generateFormClass: props => {
1622
+ const {disabled: disabled = defaultProps.disabled, className: className = ""} = props;
1623
+ return `${FORM_CLASSES_BASE} ${disabled ? FORM_CLASSES_DISABLED : ""} ${className}`.trim();
1624
+ },
1625
+ handleSubmit: handler => event => {
1626
+ event.preventDefault(), !defaultProps.disabled && handler && handler(event);
1627
+ },
1628
+ handleReset: handler => event => {
1629
+ !defaultProps.disabled && handler && handler(event);
1630
+ }
1631
+ };
1632
+ }({
1633
+ disabled: disabled
1634
+ }), formClass = generateFormClass({
1635
+ className: className,
1636
+ disabled: disabled
1637
+ });
1638
+ return jsx("form", {
1639
+ id: id,
1640
+ className: formClass,
1641
+ style: style,
1642
+ onSubmit: handleSubmit(onSubmit),
1643
+ onReset: handleReset(onReset),
1644
+ method: method,
1645
+ encType: encType,
1646
+ noValidate: noValidate,
1647
+ autoComplete: autoComplete,
1648
+ children: children
1649
+ });
1650
+ };
1651
+
1652
+ Form.displayName = "Form";
1653
+
1654
+ /**
1655
+ * FormGroup - A component for grouping form controls with labels and help text
1656
+ */
1657
+ const FormGroup = ({children: children, label: label, helperText: helperText, htmlFor: htmlFor, className: className = "", style: style, disabled: disabled = !1, required: required = !1, invalid: invalid = !1, valid: valid = !1, size: size = "md"}) => {
1658
+ const {generateFormGroupClass: generateFormGroupClass} =
1659
+ /**
1660
+ * Form Group state and functionality
1661
+ * @param initialProps - Initial form group properties
1662
+ * @returns Form Group state and methods
1663
+ */
1664
+ function(initialProps) {
1665
+ // Default form group properties
1666
+ const defaultProps = {
1667
+ size: "md",
1668
+ disabled: !1,
1669
+ invalid: !1,
1670
+ valid: !1,
1671
+ ...initialProps
1672
+ };
1673
+ /**
1674
+ * Generate form group class based on properties
1675
+ * @param props - Form group properties
1676
+ * @returns Class string
1677
+ */ return {
1678
+ defaultProps: defaultProps,
1679
+ generateFormGroupClass: props => {
1680
+ const {size: size = defaultProps.size, disabled: disabled = defaultProps.disabled, invalid: invalid = defaultProps.invalid, valid: valid = defaultProps.valid, className: className = ""} = props;
1681
+ return `${FORM_GROUP_CLASSES_BASE} ${"md" === size ? "" : "sm" === size ? FORM_GROUP_CLASSES_SMALL : FORM_GROUP_CLASSES_LARGE} ${invalid ? FORM_GROUP_CLASSES_INVALID : valid ? FORM_GROUP_CLASSES_VALID : ""} ${disabled ? FORM_GROUP_CLASSES_DISABLED : ""} ${className}`.trim();
1682
+ }
1683
+ };
1684
+ }({
1685
+ size: size,
1686
+ disabled: disabled,
1687
+ invalid: invalid,
1688
+ valid: valid
1689
+ }), formGroupClass = generateFormGroupClass({
1690
+ className: className,
1691
+ disabled: disabled,
1692
+ invalid: invalid,
1693
+ valid: valid,
1694
+ size: size
1695
+ });
1696
+ return jsxs("div", {
1697
+ className: formGroupClass,
1698
+ style: style,
1699
+ children: [ label && jsxs("label", {
1700
+ className: "c-form-group__label",
1701
+ htmlFor: htmlFor,
1702
+ children: [ label, required && jsx("span", {
1703
+ className: "c-form-group__required",
1704
+ children: "*"
1705
+ }) ]
1706
+ }), jsx("div", {
1707
+ className: "c-form-group__field",
1708
+ children: children
1709
+ }), helperText && jsx("div", {
1710
+ className: "c-form-group__helper",
1711
+ children: helperText
1712
+ }) ]
1713
+ });
1714
+ };
1715
+
1716
+ FormGroup.displayName = "FormGroup";
1717
+
1718
+ /**
1719
+ * Input - A component for text input fields
1720
+ */
1721
+ const Input = memo( forwardRef((({type: type = "text", value: value, onChange: onChange, onBlur: onBlur, onFocus: onFocus, placeholder: placeholder, className: className = "", style: style, disabled: disabled = !1, required: required = !1, readOnly: readOnly = !1, id: id, name: name, autoComplete: autoComplete, autoFocus: autoFocus = !1, size: size = "md", variant: variant, invalid: invalid = !1, valid: valid = !1, maxLength: maxLength, minLength: minLength, pattern: pattern, min: min, max: max, step: step, ariaLabel: ariaLabel, ariaDescribedBy: ariaDescribedBy, glass: glass}, ref) => {
1722
+ const {generateInputClass: generateInputClass} =
1723
+ /**
1724
+ * Input state and functionality
1725
+ * @param initialProps - Initial input properties
1726
+ * @returns Input state and methods
1727
+ */
1728
+ function(initialProps) {
1729
+ // Default input properties
1730
+ const defaultProps = {
1731
+ size: "md",
1732
+ disabled: !1,
1733
+ invalid: !1,
1734
+ valid: !1,
1735
+ ...initialProps
1736
+ };
1737
+ /**
1738
+ * Generate input class based on properties
1739
+ * @param props - Input properties
1740
+ * @returns Class string
1741
+ */ return {
1742
+ defaultProps: defaultProps,
1743
+ generateInputClass: props => {
1744
+ const {size: size = defaultProps.size, variant: variant = defaultProps.variant, disabled: disabled = defaultProps.disabled, invalid: invalid = defaultProps.invalid, valid: valid = defaultProps.valid, className: className = "", type: type} = props;
1745
+ let validationClass = "";
1746
+ invalid ? validationClass = INPUT_CLASSES_INVALID : valid && (validationClass = INPUT_CLASSES_VALID);
1747
+ return `${INPUT_CLASSES_BASE} ${"md" === size ? "" : "sm" === size ? INPUT_CLASSES_SMALL : INPUT_CLASSES_LARGE} ${variant ? `c-input--${variant}` : ""} ${"textarea" === type ? "c-input--textarea" : ""} ${validationClass} ${disabled ? INPUT_CLASSES_DISABLED : ""} ${className}`.trim();
1748
+ },
1749
+ generateWrapperClass: props => {
1750
+ const {className: className = ""} = props, {prefixIcon: prefixIcon = !1, suffixIcon: suffixIcon = !1, clearable: clearable = !1, showCounter: showCounter = !1, showPasswordToggle: showPasswordToggle = !1, fullWidth: fullWidth = !1} = initialProps || {}, classes = [ INPUT_ELEMENTS_WRAPPER ];
1751
+ return prefixIcon && classes.push(INPUT_CLASSES_PREFIX_ICON), (suffixIcon || clearable || showPasswordToggle) && classes.push(INPUT_CLASSES_SUFFIX_ICON),
1752
+ clearable && classes.push(INPUT_CLASSES_CLEARABLE), showCounter && classes.push(INPUT_CLASSES_WITH_COUNTER),
1753
+ showPasswordToggle && classes.push(INPUT_CLASSES_PASSWORD_TOGGLE), fullWidth && classes.push(INPUT_CLASSES_FULL_WIDTH),
1754
+ className && classes.push(className), classes.filter(Boolean).join(" ");
1755
+ }
1756
+ };
1757
+ }({
1758
+ size: size,
1759
+ variant: variant,
1760
+ disabled: disabled,
1761
+ invalid: invalid,
1762
+ valid: valid
1763
+ }), inputClass = generateInputClass({
1764
+ className: `${className} ${glass ? "c-input--glass" : ""}`.trim(),
1765
+ size: size,
1766
+ variant: variant,
1767
+ disabled: disabled,
1768
+ invalid: invalid,
1769
+ valid: valid,
1770
+ type: type
1771
+ }), inputElement = jsx("input", {
1772
+ ref: ref,
1773
+ type: type,
1774
+ className: inputClass,
1775
+ value: value,
1776
+ onChange: onChange,
1777
+ onBlur: onBlur,
1778
+ onFocus: onFocus,
1779
+ placeholder: placeholder,
1780
+ disabled: disabled,
1781
+ required: required,
1782
+ readOnly: readOnly,
1783
+ id: id,
1784
+ name: name,
1785
+ autoComplete: autoComplete,
1786
+ autoFocus: autoFocus,
1787
+ maxLength: maxLength,
1788
+ minLength: minLength,
1789
+ pattern: pattern,
1790
+ min: min,
1791
+ max: max,
1792
+ step: step,
1793
+ "aria-label": ariaLabel,
1794
+ "aria-describedby": ariaDescribedBy,
1795
+ "aria-invalid": invalid,
1796
+ style: glass ? {
1797
+ ...style
1798
+ } : style
1799
+ });
1800
+ if (glass) {
1801
+ // Default glass settings for inputs
1802
+ const defaultGlassProps = {
1803
+ displacementScale: 60,
1804
+ blurAmount: 1,
1805
+ saturation: 180,
1806
+ aberrationIntensity: .2,
1807
+ cornerRadius: 12,
1808
+ mode: "shader"
1809
+ }, glassProps = !0 === glass ? defaultGlassProps : {
1810
+ ...defaultGlassProps,
1811
+ ...glass
1812
+ };
1813
+ return jsx(AtomixGlass, {
1814
+ ...glassProps,
1815
+ children: inputElement
1816
+ });
1817
+ }
1818
+ return inputElement;
1819
+ })));
1820
+
1821
+ Input.displayName = "Input";
1822
+
1823
+ /**
1824
+ * Radio - A component for radio button inputs
1825
+ */
1826
+ const Radio = memo((({label: label, checked: checked = !1, onChange: onChange, className: className = "", style: style, disabled: disabled = !1, required: required = !1, id: id, name: name, value: value, invalid: invalid = !1, valid: valid = !1, ariaLabel: ariaLabel, ariaDescribedBy: ariaDescribedBy, glass: glass}) => {
1827
+ const {generateRadioClass: generateRadioClass} =
1828
+ /**
1829
+ * Radio state and functionality
1830
+ * @param initialProps - Initial radio properties
1831
+ * @returns Radio state and methods
1832
+ */
1833
+ function(initialProps) {
1834
+ // Default radio properties
1835
+ const defaultProps = {
1836
+ disabled: !1,
1837
+ invalid: !1,
1838
+ valid: !1,
1839
+ ...initialProps
1840
+ };
1841
+ /**
1842
+ * Generate radio class based on properties
1843
+ * @param props - Radio properties
1844
+ * @returns Class string
1845
+ */ return {
1846
+ defaultProps: defaultProps,
1847
+ generateRadioClass: props => {
1848
+ const {disabled: disabled = defaultProps.disabled, invalid: invalid = defaultProps.invalid, valid: valid = defaultProps.valid, className: className = ""} = props;
1849
+ let validationClass = "";
1850
+ invalid ? validationClass = RADIO_CLASSES_INVALID : valid && (validationClass = RADIO_CLASSES_VALID);
1851
+ return `${RADIO_CLASSES_BASE} ${validationClass} ${disabled ? RADIO_CLASSES_DISABLED : ""} ${className}`.trim();
1852
+ }
1853
+ };
1854
+ }({
1855
+ disabled: disabled,
1856
+ invalid: invalid,
1857
+ valid: valid
1858
+ }), radioClass = generateRadioClass({
1859
+ className: `${className} ${glass ? "c-radio--glass" : ""}`.trim(),
1860
+ disabled: disabled,
1861
+ invalid: invalid,
1862
+ valid: valid
1863
+ }), radioContent = jsxs("div", {
1864
+ className: radioClass,
1865
+ style: style,
1866
+ children: [ jsx("input", {
1867
+ type: "radio",
1868
+ className: "c-radio__input",
1869
+ checked: checked,
1870
+ onChange: onChange,
1871
+ disabled: disabled,
1872
+ required: required,
1873
+ id: id,
1874
+ name: name,
1875
+ value: value,
1876
+ "aria-label": label ? void 0 : ariaLabel,
1877
+ "aria-describedby": ariaDescribedBy,
1878
+ "aria-invalid": invalid
1879
+ }), label && jsx("label", {
1880
+ className: "c-radio__label",
1881
+ htmlFor: id,
1882
+ children: label
1883
+ }) ]
1884
+ });
1885
+ if (glass) {
1886
+ // Default glass settings for radio buttons
1887
+ const defaultGlassProps = {
1888
+ displacementScale: 40,
1889
+ blurAmount: 1,
1890
+ saturation: 160,
1891
+ aberrationIntensity: .3,
1892
+ cornerRadius: 6,
1893
+ mode: "shader"
1894
+ }, glassProps = !0 === glass ? defaultGlassProps : {
1895
+ ...defaultGlassProps,
1896
+ ...glass
1897
+ };
1898
+ return jsx(AtomixGlass, {
1899
+ ...glassProps,
1900
+ children: radioContent
1901
+ });
1902
+ }
1903
+ return radioContent;
1904
+ }));
1905
+
1906
+ Radio.displayName = "Radio";
1907
+
1908
+ /**
1909
+ * Select - A component for dropdown selection
1910
+ */
1911
+ 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, ariaLabel: ariaLabel, ariaDescribedBy: ariaDescribedBy, glass: glass}) => {
1912
+ const {generateSelectClass: generateSelectClass} =
1913
+ /**
1914
+ * Select state and functionality
1915
+ * @param initialProps - Initial select properties
1916
+ * @returns Select state and methods
1917
+ */
1918
+ function(initialProps) {
1919
+ // Default select properties
1920
+ const defaultProps = {
1921
+ size: "md",
1922
+ disabled: !1,
1923
+ invalid: !1,
1924
+ valid: !1,
1925
+ ...initialProps
1926
+ };
1927
+ /**
1928
+ * Generate select class based on properties
1929
+ * @param props - Select properties
1930
+ * @returns Class string
1931
+ */ return {
1932
+ defaultProps: defaultProps,
1933
+ generateSelectClass: props => {
1934
+ const {size: size = defaultProps.size, disabled: disabled = defaultProps.disabled, invalid: invalid = defaultProps.invalid, valid: valid = defaultProps.valid, className: className = ""} = props;
1935
+ let validationClass = "";
1936
+ invalid ? validationClass = SELECT_CLASSES_INVALID : valid && (validationClass = SELECT_CLASSES_VALID);
1937
+ return `${SELECT_CLASSES_BASE} ${"md" === size ? "" : "sm" === size ? SELECT_CLASSES_SMALL : SELECT_CLASSES_LARGE} ${validationClass} ${disabled ? SELECT_CLASSES_DISABLED : ""} ${className}`.trim();
1938
+ }
1939
+ };
1940
+ }
1941
+ /**
1942
+ * Textarea state and functionality
1943
+ * @param initialProps - Initial textarea properties
1944
+ * @returns Textarea state and methods
1945
+ */ ({
1946
+ size: size,
1947
+ disabled: disabled,
1948
+ invalid: invalid,
1949
+ valid: valid
1950
+ }), selectClass = generateSelectClass({
1951
+ className: `${className} ${glass ? "c-select--glass" : ""}`.trim(),
1952
+ size: size,
1953
+ disabled: disabled,
1954
+ invalid: invalid,
1955
+ valid: valid
1956
+ }), [isOpen, setIsOpen] = useState(!1), [selectedLabel, setSelectedLabel] = useState(placeholder), dropdownRef = useRef(null), panelRef = useRef(null), bodyRef = useRef(null), nativeSelectRef = useRef(null);
1957
+ // Update selected label when value changes
1958
+ useEffect((() => {
1959
+ if (value) {
1960
+ const selectedOption = options.find((opt => opt.value === value));
1961
+ selectedOption && setSelectedLabel(selectedOption.label);
1962
+ } else setSelectedLabel(placeholder);
1963
+ }), [ value, options, placeholder ]),
1964
+ // Handle click outside to close dropdown
1965
+ useEffect((() => {
1966
+ const handleClickOutside = event => {
1967
+ dropdownRef.current && !dropdownRef.current.contains(event.target) && (setIsOpen(!1),
1968
+ bodyRef.current && (bodyRef.current.style.height = "0px"));
1969
+ };
1970
+ return document.addEventListener("mousedown", handleClickOutside), () => {
1971
+ document.removeEventListener("mousedown", handleClickOutside);
1972
+ };
1973
+ }), []);
1974
+ // Toggle dropdown
1975
+ const selectContent = jsxs("div", {
1976
+ className: `${selectClass} ${isOpen ? SELECT_CLASSES_IS_OPEN : ""}`,
1977
+ ref: dropdownRef,
1978
+ style: style,
1979
+ "aria-expanded": isOpen,
1980
+ children: [ jsxs("select", {
1981
+ ref: nativeSelectRef,
1982
+ value: value,
1983
+ onChange: onChange,
1984
+ onBlur: onBlur,
1985
+ onFocus: onFocus,
1986
+ disabled: disabled,
1987
+ required: required,
1988
+ id: id,
1989
+ name: name,
1990
+ multiple: multiple,
1991
+ "aria-label": ariaLabel,
1992
+ "aria-describedby": ariaDescribedBy,
1993
+ "aria-invalid": invalid,
1994
+ style: {
1995
+ display: "none"
1996
+ },
1997
+ children: [ placeholder && jsx("option", {
1998
+ value: "",
1999
+ disabled: !0,
2000
+ children: placeholder
2001
+ }), options.map((option => jsx("option", {
2002
+ value: option.value,
2003
+ disabled: option.disabled,
2004
+ children: option.label
2005
+ }, option.value))) ]
2006
+ }), jsx("div", {
2007
+ className: SELECT_CLASSES_SELECTED,
2008
+ onClick: () => {
2009
+ disabled || (!isOpen && bodyRef.current && panelRef.current ? bodyRef.current.style.height = `${panelRef.current.clientHeight}px` : bodyRef.current && (bodyRef.current.style.height = "0px"),
2010
+ setIsOpen(!isOpen));
2011
+ },
2012
+ "aria-disabled": disabled,
2013
+ children: selectedLabel
2014
+ }), jsx("i", {
2015
+ className: `${SELECT_CLASSES_ICON_CARET} ${SELECT_CLASSES_TOGGLE_ICON}`
2016
+ }), jsx("div", {
2017
+ className: SELECT_CLASSES_SELECT_BODY,
2018
+ ref: bodyRef,
2019
+ style: {
2020
+ height: 0
2021
+ },
2022
+ children: jsx("div", {
2023
+ className: SELECT_CLASSES_SELECT_PANEL,
2024
+ ref: panelRef,
2025
+ children: jsx("ul", {
2026
+ className: SELECT_CLASSES_SELECT_ITEMS,
2027
+ children: options.map(((option, index) => jsx("li", {
2028
+ className: SELECT_CLASSES_SELECT_ITEM,
2029
+ "data-value": option.value,
2030
+ onClick: () => !option.disabled && (option => {
2031
+ if (setSelectedLabel(option.label), setIsOpen(!1), bodyRef.current && (bodyRef.current.style.height = "0px"),
2032
+ nativeSelectRef.current && (nativeSelectRef.current.value = option.value), onChange) {
2033
+ // Create a synthetic event
2034
+ const event = {
2035
+ target: {
2036
+ name: name,
2037
+ value: option.value
2038
+ }
2039
+ };
2040
+ onChange(event);
2041
+ }
2042
+ })(option),
2043
+ children: jsxs("label", {
2044
+ htmlFor: `SelectItem${index}`,
2045
+ className: "c-checkbox",
2046
+ children: [ jsx("input", {
2047
+ type: "checkbox",
2048
+ id: `SelectItem${index}`,
2049
+ className: "c-checkbox__input c-select__item-input",
2050
+ checked: value === option.value,
2051
+ readOnly: !0,
2052
+ disabled: option.disabled
2053
+ }), jsx("div", {
2054
+ className: "c-select__item-label",
2055
+ children: option.label
2056
+ }) ]
2057
+ })
2058
+ }, option.value)))
2059
+ })
2060
+ })
2061
+ }) ]
2062
+ });
2063
+ // Handle item selection
2064
+ if (glass) {
2065
+ // Default glass settings for select components
2066
+ const defaultGlassProps = {
2067
+ displacementScale: 60,
2068
+ blurAmount: 1,
2069
+ saturation: 180,
2070
+ aberrationIntensity: .2,
2071
+ cornerRadius: 12,
2072
+ mode: "shader"
2073
+ }, glassProps = !0 === glass ? defaultGlassProps : {
2074
+ ...defaultGlassProps,
2075
+ ...glass
2076
+ };
2077
+ return jsx(AtomixGlass, {
2078
+ ...glassProps,
2079
+ children: selectContent
2080
+ });
2081
+ }
2082
+ return selectContent;
2083
+ }));
2084
+
2085
+ Select.displayName = "Select";
2086
+
2087
+ /**
2088
+ * Textarea - A component for multiline text input
2089
+ */
2090
+ const Textarea = memo( forwardRef((({value: value, onChange: onChange, onBlur: onBlur, onFocus: onFocus, placeholder: placeholder, className: className = "", style: style, disabled: disabled = !1, required: required = !1, readOnly: readOnly = !1, id: id, name: name, rows: rows = 4, cols: cols, maxLength: maxLength, minLength: minLength, size: size = "md", variant: variant, invalid: invalid = !1, valid: valid = !1, autoFocus: autoFocus = !1, ariaLabel: ariaLabel, ariaDescribedBy: ariaDescribedBy, glass: glass}, ref) => {
2091
+ const {generateTextareaClass: generateTextareaClass} = function(initialProps) {
2092
+ // Default textarea properties
2093
+ const defaultProps = {
2094
+ size: "md",
2095
+ disabled: !1,
2096
+ invalid: !1,
2097
+ valid: !1,
2098
+ ...initialProps
2099
+ };
2100
+ /**
2101
+ * Generate textarea class based on properties
2102
+ * @param props - Textarea properties
2103
+ * @returns Class string
2104
+ */ return {
2105
+ defaultProps: defaultProps,
2106
+ generateTextareaClass: props => {
2107
+ const {size: size = defaultProps.size, variant: variant = defaultProps.variant, disabled: disabled = defaultProps.disabled, invalid: invalid = defaultProps.invalid, valid: valid = defaultProps.valid, className: className = ""} = props;
2108
+ let validationClass = "";
2109
+ invalid ? validationClass = TEXTAREA_CLASSES_INVALID : valid && (validationClass = TEXTAREA_CLASSES_VALID);
2110
+ return `${TEXTAREA_CLASSES_BASE} ${"md" === size ? "" : "sm" === size ? TEXTAREA_CLASSES_SMALL : TEXTAREA_CLASSES_LARGE} ${variant ? `c-input--${variant}` : ""} ${validationClass} ${disabled ? TEXTAREA_CLASSES_DISABLED : ""} ${className}`.trim();
2111
+ }
2112
+ };
2113
+ }({
2114
+ size: size,
2115
+ variant: variant,
2116
+ disabled: disabled,
2117
+ invalid: invalid,
2118
+ valid: valid
2119
+ }), textareaClass = generateTextareaClass({
2120
+ className: `${className} ${glass ? "c-input--glass" : ""}`.trim(),
2121
+ size: size,
2122
+ variant: variant,
2123
+ disabled: disabled,
2124
+ invalid: invalid,
2125
+ valid: valid
2126
+ }), textareaElement = jsx("textarea", {
2127
+ ref: ref,
2128
+ className: textareaClass,
2129
+ value: value,
2130
+ onChange: onChange,
2131
+ onBlur: onBlur,
2132
+ onFocus: onFocus,
2133
+ placeholder: placeholder,
2134
+ disabled: disabled,
2135
+ required: required,
2136
+ readOnly: readOnly,
2137
+ id: id,
2138
+ name: name,
2139
+ rows: rows,
2140
+ cols: cols,
2141
+ maxLength: maxLength,
2142
+ minLength: minLength,
2143
+ autoFocus: autoFocus,
2144
+ "aria-label": ariaLabel,
2145
+ "aria-describedby": ariaDescribedBy,
2146
+ "aria-invalid": invalid,
2147
+ style: glass ? {
2148
+ ...style
2149
+ } : style
2150
+ });
2151
+ if (glass) {
2152
+ // Default glass settings for textareas
2153
+ const defaultGlassProps = {
2154
+ displacementScale: 60,
2155
+ blurAmount: 1,
2156
+ saturation: 180,
2157
+ aberrationIntensity: 1,
2158
+ cornerRadius: 8,
2159
+ mode: "shader"
2160
+ }, glassProps = !0 === glass ? defaultGlassProps : {
2161
+ ...defaultGlassProps,
2162
+ ...glass
2163
+ };
2164
+ return jsx(AtomixGlass, {
2165
+ ...glassProps,
2166
+ children: textareaElement
2167
+ });
2168
+ }
2169
+ return textareaElement;
2170
+ })));
2171
+
2172
+ Textarea.displayName = "Textarea";
2173
+
2174
+ // Adapted from https://github.com/shuding/liquid-glass
2175
+ // Constants
2176
+ const smoothStep = (a, b, t) => {
2177
+ // Add input validation
2178
+ if ("number" != typeof a || "number" != typeof b || "number" != typeof t) return 0;
2179
+ const clamped = Math.max(0, Math.min(1, (t - a) / (b - a)));
2180
+ return clamped * clamped * (3 - 2 * clamped);
2181
+ }, calculateLength = (x, y) => {
2182
+ // Add input validation and error handling
2183
+ if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
2184
+ // Prevent potential overflow
2185
+ const maxX = Math.max(Math.abs(x), Math.abs(y));
2186
+ if (0 === maxX) return 0;
2187
+ const scaledX = x / maxX, scaledY = y / maxX;
2188
+ return maxX * Math.sqrt(scaledX * scaledX + scaledY * scaledY);
2189
+ }, roundedRectSDF = (x, y, width, height, radius) => {
2190
+ // Add input validation
2191
+ if ("number" != typeof x || "number" != typeof y || "number" != typeof width || "number" != typeof height || "number" != typeof radius) return 0;
2192
+ const qx = Math.abs(x) - width + radius, qy = Math.abs(y) - height + radius;
2193
+ return Math.min(Math.max(qx, qy), 0) + calculateLength(Math.max(qx, 0), Math.max(qy, 0)) - radius;
2194
+ }, createTexture = (x, y) => ({
2195
+ x: "number" != typeof x || isNaN(x) ? .5 : Math.max(0, Math.min(1, x)),
2196
+ y: "number" != typeof y || isNaN(y) ? .5 : Math.max(0, Math.min(1, y))
2197
+ }), validateVec2 = vec => vec && "number" == typeof vec.x && "number" == typeof vec.y && !isNaN(vec.x) && !isNaN(vec.y), clampValue = (value, min, max) =>
2198
+ // Add input validation
2199
+ "number" != typeof value || "number" != typeof min || "number" != typeof max || isNaN(value) ? min : isNaN(min) ? 0 : isNaN(max) ? 1 : Math.max(min, Math.min(max, value)), easeInOutCubic = t => {
2200
+ // Add input validation
2201
+ if ("number" != typeof t || isNaN(t)) return 0;
2202
+ const clampedT = Math.max(0, Math.min(1, t));
2203
+ return clampedT < .5 ? 4 * clampedT * clampedT * clampedT : 1 - Math.pow(-2 * clampedT + 2, 3) / 2;
2204
+ }, easeOutQuart = t => {
2205
+ // Add input validation
2206
+ if ("number" != typeof t || isNaN(t)) return 0;
2207
+ const clampedT = Math.max(0, Math.min(1, t));
2208
+ return 1 - Math.pow(1 - clampedT, 4);
2209
+ }, noise2D = (x, y) => {
2210
+ // Add input validation
2211
+ if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
2212
+ const X = 255 & Math.floor(x), Y = 255 & Math.floor(y), xf = x - Math.floor(x), yf = y - Math.floor(y), u = easeInOutCubic(xf), v = easeInOutCubic(yf), hash = (i, j) => {
2213
+ // Add input validation
2214
+ if ("number" != typeof i || "number" != typeof j) return 0;
2215
+ const n = i + 57 * j, hashed = 43758.5453 * Math.sin(12.9898 * n + 78.233);
2216
+ // Use a more stable hash function
2217
+ return hashed - Math.floor(hashed);
2218
+ }, a = hash(X, Y), b = hash(X + 1, Y), c = hash(X, Y + 1), x1 = a + u * (b - a);
2219
+ return x1 + v * (c + u * (hash(X + 1, Y + 1) - c) - x1);
2220
+ }, fbm = (x, y, octaves = 4) => {
2221
+ // Add input validation
2222
+ if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
2223
+ // Clamp octaves to prevent performance issues
2224
+ const clampedOctaves = Math.max(1, Math.min(8, Math.floor(octaves)));
2225
+ let value = 0, amplitude = .5, frequency = 1;
2226
+ for (let i = 0; i < clampedOctaves; i++) value += amplitude * noise2D(x * frequency, y * frequency),
2227
+ frequency *= 2, amplitude *= .5;
2228
+ return value;
2229
+ }, calculateParallaxOffset = (x, y, depth, mouseX = 0, mouseY = 0) => {
2230
+ // Add input validation
2231
+ if ("number" != typeof x || "number" != typeof y || "number" != typeof depth || "number" != typeof mouseX || "number" != typeof mouseY || isNaN(x) || isNaN(y) || isNaN(depth) || isNaN(mouseX) || isNaN(mouseY)) return {
2232
+ x: 0,
2233
+ y: 0
2234
+ };
2235
+ const parallaxStrength = Math.min(.02 * depth, .1);
2236
+ // Limit strength to prevent extreme values
2237
+ // Calculate offset based on view angle (simulated by mouse position)
2238
+ return {
2239
+ x: (x - mouseX) * parallaxStrength,
2240
+ y: (y - mouseY) * parallaxStrength
2241
+ };
2242
+ }, fragmentShaders = {
2243
+ liquidGlass: (uv, mousePosition) => {
2244
+ if (!validateVec2(uv)) return {
2245
+ x: .5,
2246
+ y: .5
2247
+ };
2248
+ const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now(), mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = calculateLength(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(2 * mouseDistance, 1)), organicFlow = fbm(12 * (ix + .5 * mouseX) + time, 12 * (iy + .5 * mouseY) + .7 * time, 3) - .5, distanceToEdge = roundedRectSDF(ix, iy, .4, .3, .35), baseDisplacement = smoothStep(.8, 0, distanceToEdge - .05), radialDist = ((x, y, strength) => {
2249
+ // Add input validation
2250
+ if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y) || isNaN(strength)) return {
2251
+ x: 0,
2252
+ y: 0
2253
+ };
2254
+ const distance = calculateLength(x, y), distortion = Math.pow(Math.min(distance, 10), 2) * strength;
2255
+ // Limit distance to prevent extreme values
2256
+ return {
2257
+ x: x * (1 + distortion),
2258
+ y: y * (1 + distortion)
2259
+ };
2260
+ })(ix, iy, .4 * .1), refractionX = 1.2 * (radialDist.x - ix) * baseDisplacement, refractionY = 1.2 * (radialDist.y - iy) * baseDisplacement, flowX = .018 * Math.sin(8 * (ix + 2 * mouseX) + 2 * time), flowY = .018 * Math.cos(8 * (iy + 2 * mouseY) + 1.5 * time), rippleEffect = (.015 * Math.sin(12 * (ix - mouseX) + 12 * (iy - mouseY) + 3 * time) + .012 * Math.cos(10 * (ix + mouseX) - 10 * (iy - mouseY) - 2 * time)) * mouseFalloff * mouseDistance, depthEffect = (Math.sin(15 * ix + time) * Math.cos(15 * iy - time) * .008 + Math.sin(20 * ix - .5 * time) * Math.cos(20 * iy + .5 * time) * .006) * baseDisplacement, liquidFlow = .85 * (flowX + flowY + .025 * organicFlow), totalDistortionX = refractionX + liquidFlow + rippleEffect + depthEffect, totalDistortionY = refractionY + .8 * liquidFlow + .9 * rippleEffect + depthEffect, chromaticOffset = ((x, y, intensity) => {
2261
+ // Add input validation
2262
+ if ("number" != typeof x || "number" != typeof y || "number" != typeof intensity || isNaN(x) || isNaN(y) || isNaN(intensity)) return {
2263
+ x: 0,
2264
+ y: 0
2265
+ };
2266
+ const distance = calculateLength(x, y);
2267
+ // Prevent division by zero and extreme values
2268
+ if (0 === distance) return {
2269
+ x: 0,
2270
+ y: 0
2271
+ };
2272
+ const angle = Math.atan2(y, x);
2273
+ return {
2274
+ x: Math.cos(angle) * distance * intensity,
2275
+ y: Math.sin(angle) * distance * intensity
2276
+ };
2277
+ })(ix, iy, .015 * baseDisplacement), scaled = smoothStep(0, 1, 1.15 * baseDisplacement), finalX = ix + totalDistortionX + .5 * chromaticOffset.x, finalY = iy + totalDistortionY + .5 * chromaticOffset.y;
2278
+ return createTexture(clampValue(finalX * scaled + .5, 0, 1), clampValue(finalY * scaled + .5, 0, 1));
2279
+ },
2280
+ // Premium Apple-style fluid glass with enhanced organic flow
2281
+ appleFluid: (uv, mousePosition) => {
2282
+ if (!validateVec2(uv)) return {
2283
+ x: .5,
2284
+ y: .5
2285
+ };
2286
+ const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .6, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = calculateLength(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(1.5 * mouseDistance, 1)), organicX = fbm(10 * (ix + .3 * mouseX) + time, 10 * (iy + .3 * mouseY), 5) - .5, organicY = fbm(10 * (ix - .3 * mouseX), 10 * (iy - .3 * mouseY) + .8 * time, 5) - .5, distanceToEdge = roundedRectSDF(ix, iy, .42, .32, .38), mask = smoothStep(.85, -.1, distanceToEdge), fluidVelocityX = Math.sin(6 * ix + 2 * time) * Math.cos(4 * iy - time) * .025, fluidVelocityY = Math.cos(4 * ix - time) * Math.sin(6 * iy + 2 * time) * .025, vortexAngle = Math.atan2(iy - mouseY, ix - mouseX), vortexStrength = mouseFalloff * mouseDistance * .08, vortexX = Math.cos(vortexAngle + time) * vortexStrength, totalY = iy + (.035 * organicY + fluidVelocityY + Math.sin(vortexAngle + time) * vortexStrength) * mask;
2287
+ return createTexture(clampValue(ix + (.035 * organicX + fluidVelocityX + vortexX) * mask + .5, 0, 1), clampValue(totalY + .5, 0, 1));
2288
+ },
2289
+ // High-end glass with advanced refraction and depth
2290
+ premiumGlass: (uv, mousePosition) => {
2291
+ if (!validateVec2(uv)) return {
2292
+ x: .5,
2293
+ y: .5
2294
+ };
2295
+ const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .4, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = calculateLength(mouseX, mouseY), centerDistance = calculateLength(ix, iy), refractionStrength = .3 * Math.pow(Math.min(centerDistance, 1), 1.5), refractionAngle = Math.atan2(iy, ix);
2296
+ // Multi-layer depth effect
2297
+ let depthX = 0, depthY = 0;
2298
+ for (let layer = 0; layer < 3; layer++) {
2299
+ const layerScale = 5 * (layer + 1), layerTime = time * (1 + .3 * layer), layerStrength = .01 / (layer + 1);
2300
+ depthX += Math.sin(ix * layerScale + layerTime) * layerStrength, depthY += Math.cos(iy * layerScale - layerTime) * layerStrength;
2301
+ }
2302
+ // Glass refraction with mouse influence
2303
+ const refractionX = Math.cos(refractionAngle) * refractionStrength * (1 + .5 * mouseDistance), refractionY = Math.sin(refractionAngle) * refractionStrength * (1 + .5 * mouseDistance), organicNoise = fbm(8 * ix + time, 8 * iy - time, 2) - .5, distanceToEdge = roundedRectSDF(ix, iy, .43, .33, .36), edgeMask = smoothStep(.9, -.05, distanceToEdge), finalY = iy + (refractionY + depthY + .015 * organicNoise) * edgeMask;
2304
+ return createTexture(clampValue(ix + (refractionX + depthX + .015 * organicNoise) * edgeMask + .5, 0, 1), clampValue(finalY + .5, 0, 1));
2305
+ },
2306
+ // Metallic liquid effect with shimmer
2307
+ liquidMetal: (uv, mousePosition) => {
2308
+ if (!validateVec2(uv)) return {
2309
+ x: .5,
2310
+ y: .5
2311
+ };
2312
+ const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * 1.2, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, wave1 = Math.sin(20 * ix + 4 * time) * Math.cos(15 * iy - 3 * time) * .02, wave2 = Math.cos(15 * ix - 2 * time) * Math.sin(20 * iy + 5 * time) * .015, shimmer = .025 * fbm(25 * ix + 2 * time, 25 * iy - 2 * time, 4), flowAngle = Math.atan2(iy - mouseY, ix - mouseX), flowDistance = calculateLength(ix - mouseX, iy - mouseY), flowEffect = .02 * Math.sin(15 * flowDistance - 6 * time) * easeOutQuart(1 - Math.min(2 * flowDistance, 1)), distanceToEdge = roundedRectSDF(ix, iy, .41, .31, .37), mask = smoothStep(.88, -.08, distanceToEdge), totalX = ix + (wave1 + shimmer + Math.cos(flowAngle) * flowEffect) * mask, totalY = iy + (wave2 + .8 * shimmer + Math.sin(flowAngle) * flowEffect) * mask;
2313
+ return createTexture(clampValue(totalX + .5, 0, 1), clampValue(totalY + .5, 0, 1));
2314
+ },
2315
+ // basiBasi - Expert Premium Glass Shader
2316
+ // The most advanced shader with caustics, spectral dispersion, parallax depth, and volumetric effects
2317
+ basiBasi: (uv, mousePosition) => {
2318
+ if (!validateVec2(uv)) return {
2319
+ x: .5,
2320
+ y: .5
2321
+ };
2322
+ const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .5, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = calculateLength(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(1.2 * mouseDistance, 1)), causticIntensity = ((x, y, time, intensity = 1) =>
2323
+ // Add input validation
2324
+ "number" != typeof x || "number" != typeof y || "number" != typeof time || "number" != typeof intensity || isNaN(x) || isNaN(y) || isNaN(time) || isNaN(intensity) ? .5 : .5 * (Math.sin(8 * x + 2 * time) * Math.cos(8 * y - 2 * time) * .5 + Math.sin(8 * (x + .5) * 1.3 - 2 * time * .8) * Math.cos(8 * (y - .3) * 1.3 + 2 * time * .8) * .3 + Math.sin(8 * (x - .3) * .7 + 2 * time * 1.2) * Math.cos(8 * (y + .4) * .7 - 2 * time * 1.2) * .2 + 1) * intensity)(ix, iy, time, .8), causticDistortion = .02 * (causticIntensity - .5), refractionAngle = Math.atan2(iy, ix), spectralDispersion = ((x, y, angle) => {
2325
+ // Add input validation
2326
+ if ("number" != typeof x || "number" != typeof y || "number" != typeof angle || isNaN(x) || isNaN(y) || isNaN(angle) || isNaN(.025)) return {
2327
+ r: {
2328
+ x: 0,
2329
+ y: 0
2330
+ },
2331
+ g: {
2332
+ x: 0,
2333
+ y: 0
2334
+ },
2335
+ b: {
2336
+ x: 0,
2337
+ y: 0
2338
+ }
2339
+ };
2340
+ const distance = calculateLength(x, y), dispersionStrength = Math.min(.025 * distance, 1), redOffset = .8 * dispersionStrength, greenOffset = 1 * dispersionStrength, blueOffset = 1.2 * dispersionStrength;
2341
+ return {
2342
+ r: {
2343
+ x: Math.cos(angle) * redOffset,
2344
+ y: Math.sin(angle) * redOffset
2345
+ },
2346
+ g: {
2347
+ x: Math.cos(angle) * greenOffset,
2348
+ y: Math.sin(angle) * greenOffset
2349
+ },
2350
+ b: {
2351
+ x: Math.cos(angle) * blueOffset,
2352
+ y: Math.sin(angle) * blueOffset
2353
+ }
2354
+ };
2355
+ })(ix, iy, refractionAngle), spectralX = (spectralDispersion.r.x + spectralDispersion.g.x + spectralDispersion.b.x) / 3, spectralY = (spectralDispersion.r.y + spectralDispersion.g.y + spectralDispersion.b.y) / 3;
2356
+ // === MULTI-LAYER PARALLAX DEPTH ===
2357
+ // Create depth perception with 7 layers
2358
+ let parallaxX = 0, parallaxY = 0;
2359
+ for (let layer = 0; layer < 7; layer++) {
2360
+ const parallaxOffset = calculateParallaxOffset(ix, iy, (layer + 1) / 7, mouseX, mouseY), layerNoise = fbm((ix + parallaxOffset.x) * (8 + 2 * layer) + time * (.5 + .1 * layer), (iy + parallaxOffset.y) * (8 + 2 * layer) - time * (.5 + .1 * layer), 3) - .5, layerWeight = 1 / (layer + 1);
2361
+ parallaxX += (parallaxOffset.x + .01 * layerNoise) * layerWeight, parallaxY += (parallaxOffset.y + .01 * layerNoise) * layerWeight;
2362
+ }
2363
+ // Normalize parallax effect
2364
+ parallaxX /= 7, parallaxY /= 7;
2365
+ // === VOLUMETRIC SCATTERING ===
2366
+ // Simulate light scattering through glass volume
2367
+ const volumetricDensity = ((x, y, depth, time) =>
2368
+ // Add input validation
2369
+ "number" != typeof x || "number" != typeof y || "number" != typeof time || isNaN(x) || isNaN(y) || isNaN(.5) || isNaN(time) ? .5 : fbm(5 * x + .5 * time, 5 * y - .5 * time, 3) * Math.exp(2 * -Math.max(0, .5)) * .5 + .5)(ix, iy, 0, time), scatteringX = Math.cos(refractionAngle) * volumetricDensity * .015, scatteringY = Math.sin(refractionAngle) * volumetricDensity * .015, turbulence = ((x, y, time, octaves = 5) => {
2370
+ // Add input validation
2371
+ if ("number" != typeof x || "number" != typeof y || "number" != typeof time || "number" != typeof octaves || isNaN(x) || isNaN(y) || isNaN(time) || isNaN(octaves)) return 0;
2372
+ // Clamp octaves to prevent performance issues
2373
+ const clampedOctaves = Math.max(1, Math.min(8, Math.floor(octaves)));
2374
+ let turbulence = 0, amplitude = 1, frequency = 1;
2375
+ for (let i = 0; i < clampedOctaves; i++) turbulence += Math.abs(noise2D(x * frequency + time, y * frequency - time)) * amplitude,
2376
+ frequency *= 2, amplitude *= .5;
2377
+ return turbulence;
2378
+ })(6 * ix, 6 * iy, time, 6), turbulenceX = .012 * Math.cos(turbulence * Math.PI * 2), turbulenceY = .012 * Math.sin(turbulence * Math.PI * 2), microSurface = ((x, y, time) =>
2379
+ // Add input validation
2380
+ "number" != typeof x || "number" != typeof y || "number" != typeof time || isNaN(x) || isNaN(y) || isNaN(time) ? .5 : .5 * (.7 * fbm(40 * x + .3 * time, 40 * y - .3 * time, 6) + .3 * fbm(80 * x, 80 * y, 4)))(ix, iy, time), microDetailX = .008 * (microSurface - .5), microDetailY = .008 * (microSurface - .5), centerDistance = calculateLength(ix, iy), dynamicRefraction = .35 * Math.pow(Math.min(centerDistance, 1), 1.8) * (1 + mouseFalloff * mouseDistance * .8), refractionX = Math.cos(refractionAngle) * dynamicRefraction, refractionY = Math.sin(refractionAngle) * dynamicRefraction, vortexAngle = Math.atan2(iy - mouseY, ix - mouseX), vortexDistance = calculateLength(ix - mouseX, iy - mouseY), vortexStrength = mouseFalloff * Math.sin(10 * vortexDistance - 3 * time) * .025, vortexX = Math.cos(vortexAngle + 2 * time) * vortexStrength, vortexY = Math.sin(vortexAngle + 2 * time) * vortexStrength, fluidX = Math.sin(10 * ix + 5 * mouseX + 2.5 * time) * Math.cos(8 * iy - 2 * time) * .018, fluidY = Math.cos(8 * ix - 2 * time) * Math.sin(10 * iy + 5 * mouseY + 2.5 * time) * .018, rippleEffect = (.012 * Math.sin(15 * Math.min(centerDistance, 10) - 4 * time) + .008 * Math.cos(20 * Math.min(centerDistance, 10) + 3 * time)) * mouseFalloff, rippleX = Math.cos(refractionAngle) * rippleEffect, rippleY = Math.sin(refractionAngle) * rippleEffect, distanceToEdge = roundedRectSDF(ix, iy, .44, .34, .39), edgeMask = smoothStep(.92, -.12, distanceToEdge), edgeSoftness = smoothStep(.85, .1, distanceToEdge), finalY = iy + (1.2 * refractionY + .8 * spectralY + 1.5 * parallaxY + .9 * scatteringY + 1 * turbulenceY + .6 * microDetailY + 1.3 * vortexY + 1.1 * fluidY + .7 * rippleY + .8 * causticDistortion) * edgeMask * edgeSoftness * .85;
2381
+ return createTexture(clampValue(ix + (1.2 * refractionX + .8 * spectralX + 1.5 * parallaxX + .9 * scatteringX + 1 * turbulenceX + .6 * microDetailX + 1.3 * vortexX + 1.1 * fluidX + .7 * rippleX + causticDistortion) * edgeMask * edgeSoftness * .85 + .5, 0, 1), clampValue(finalY + .5, 0, 1));
2382
+ }
2383
+ }, shaderUtils = Object.freeze( Object.defineProperty({
2384
+ __proto__: null,
2385
+ ShaderDisplacementGenerator: class {
2386
+ constructor(options) {
2387
+ if (this.options = options, this.canvasDPI = 1, !this.validateOptions(options)) throw new Error("Invalid shader options provided");
2388
+ this.canvas = document.createElement("canvas"),
2389
+ // Enhanced validation for canvas dimensions
2390
+ this.canvas.width = Math.max(1, Math.min(4096, Math.round(options.width * this.canvasDPI || 256))),
2391
+ this.canvas.height = Math.max(1, Math.min(4096, Math.round(options.height * this.canvasDPI || 256))),
2392
+ this.canvas.style.display = "none";
2393
+ const context = this.canvas.getContext("2d");
2394
+ if (!context) throw new Error("AtomixGlass: Could not get 2D canvas context");
2395
+ this.context = context;
2396
+ }
2397
+ validateOptions(options) {
2398
+ try {
2399
+ return options && "number" == typeof options.width && options.width > 0 && options.width <= 4096 && "number" == typeof options.height && options.height > 0 && options.height <= 4096 && "function" == typeof options.fragment;
2400
+ } catch (e) {
2401
+ // Graceful error handling
2402
+ return !1;
2403
+ }
2404
+ }
2405
+ updateShader(mousePosition) {
2406
+ try {
2407
+ const w = this.options.width * this.canvasDPI, h = this.options.height * this.canvasDPI;
2408
+ let maxScale = 0;
2409
+ const rawValues = [];
2410
+ // Calculate displacement values with enhanced smoothing
2411
+ for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
2412
+ const uv = {
2413
+ x: x / w,
2414
+ y: y / h
2415
+ }, pos = this.options.fragment(uv, mousePosition);
2416
+ let dx = pos.x * w - x, dy = pos.y * h - y;
2417
+ // Apply edge smoothing for Apple-like effect
2418
+ const edgeX = 2 * Math.min(x / w, (w - x) / w), edgeY = 2 * Math.min(y / h, (h - y) / h), edgeFactor = Math.min(edgeX, edgeY);
2419
+ dx *= smoothStep(0, .2, edgeFactor), dy *= smoothStep(0, .2, edgeFactor), maxScale = Math.max(maxScale, Math.abs(dx), Math.abs(dy)),
2420
+ rawValues.push(dx, dy);
2421
+ }
2422
+ // Improved normalization to prevent artifacts while maintaining intensity
2423
+ maxScale = Math.max(maxScale, 1);
2424
+ // Create ImageData and fill it
2425
+ const imageData = this.context.createImageData(w, h), data = imageData.data;
2426
+ // Convert to image data with smoother normalization
2427
+ let rawIndex = 0;
2428
+ for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
2429
+ const dx = rawValues[rawIndex++] || 0, dy = rawValues[rawIndex++] || 0, edgeDistance = Math.min(x, y, w - x - 1, h - y - 1), edgeFactor = Math.min(1, edgeDistance / 2), r = dx * edgeFactor / maxScale + .5, g = dy * edgeFactor / maxScale + .5, pixelIndex = 4 * (y * w + x);
2430
+ data[pixelIndex] = clampValue(255 * r, 0, 255), // Red channel (X displacement)
2431
+ data[pixelIndex + 1] = clampValue(255 * g, 0, 255), // Green channel (Y displacement)
2432
+ data[pixelIndex + 2] = clampValue(255 * g, 0, 255), // Blue channel (Y displacement for SVG filter compatibility)
2433
+ data[pixelIndex + 3] = 255;
2434
+ }
2435
+ return this.context.putImageData(imageData, 0, 0), this.canvas.toDataURL();
2436
+ } catch (error) {
2437
+ // Graceful fallback on error
2438
+ return console.warn("ShaderDisplacementGenerator: Error generating shader map, using fallback", error),
2439
+ "";
2440
+ // Return empty string as fallback
2441
+ }
2442
+ }
2443
+ destroy() {
2444
+ try {
2445
+ // Clear canvas data to free memory
2446
+ this.context && this.context.clearRect(0, 0, this.canvas.width, this.canvas.height),
2447
+ // Reduce memory footprint by setting dimensions to 0
2448
+ this.canvas.width = 0, this.canvas.height = 0,
2449
+ // Remove from DOM
2450
+ this.canvas.remove();
2451
+ } catch (e) {
2452
+ // Silently handle cleanup errors
2453
+ console.warn("ShaderDisplacementGenerator: Error during cleanup", e);
2454
+ }
2455
+ }
2456
+ getScale() {
2457
+ return this.canvasDPI;
2458
+ }
2459
+ },
2460
+ fragmentShaders: fragmentShaders
2461
+ }, Symbol.toStringTag, {
2462
+ value: "Module"
2463
+ }));
2464
+
2465
+ export { Checkbox, Form, FormGroup, Input, Radio, Select, Textarea };
2466
+ //# sourceMappingURL=forms.js.map