@shohojdhara/atomix 0.3.13 → 0.3.15

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 (249) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +2 -0
  3. package/build-tools/EXAMPLES.md +372 -0
  4. package/build-tools/README.md +242 -0
  5. package/build-tools/__tests__/error-handler.test.js +230 -0
  6. package/build-tools/__tests__/index.test.js +141 -0
  7. package/build-tools/__tests__/rollup-plugin.test.js +194 -0
  8. package/build-tools/__tests__/utils.test.js +161 -0
  9. package/build-tools/__tests__/vite-plugin.test.js +129 -0
  10. package/build-tools/__tests__/webpack-loader.test.js +190 -0
  11. package/build-tools/error-handler.js +308 -0
  12. package/build-tools/index.d.ts +43 -0
  13. package/build-tools/index.js +88 -0
  14. package/build-tools/package.json +67 -0
  15. package/build-tools/rollup-plugin.js +236 -0
  16. package/build-tools/types.d.ts +163 -0
  17. package/build-tools/utils.js +203 -0
  18. package/build-tools/vite-plugin.js +161 -0
  19. package/build-tools/webpack-loader.js +123 -0
  20. package/dist/atomix.css +298 -167
  21. package/dist/atomix.css.map +1 -1
  22. package/dist/atomix.min.css +3 -3
  23. package/dist/atomix.min.css.map +1 -1
  24. package/dist/build-tools/EXAMPLES.md +372 -0
  25. package/dist/build-tools/README.md +242 -0
  26. package/dist/build-tools/__tests__/error-handler.test.js +230 -0
  27. package/dist/build-tools/__tests__/index.test.js +141 -0
  28. package/dist/build-tools/__tests__/rollup-plugin.test.js +194 -0
  29. package/dist/build-tools/__tests__/utils.test.js +161 -0
  30. package/dist/build-tools/__tests__/vite-plugin.test.js +129 -0
  31. package/dist/build-tools/__tests__/webpack-loader.test.js +190 -0
  32. package/dist/build-tools/error-handler.js +308 -0
  33. package/dist/build-tools/index.d.ts +43 -0
  34. package/dist/build-tools/index.js +88 -0
  35. package/dist/build-tools/package.json +67 -0
  36. package/dist/build-tools/rollup-plugin.js +236 -0
  37. package/dist/build-tools/types.d.ts +163 -0
  38. package/dist/build-tools/utils.js +203 -0
  39. package/dist/build-tools/vite-plugin.js +161 -0
  40. package/dist/build-tools/webpack-loader.js +123 -0
  41. package/dist/charts.d.ts +2 -2
  42. package/dist/charts.js +87 -58
  43. package/dist/charts.js.map +1 -1
  44. package/dist/core.d.ts +42 -12
  45. package/dist/core.js +175 -135
  46. package/dist/core.js.map +1 -1
  47. package/dist/forms.d.ts +30 -16
  48. package/dist/forms.js +146 -131
  49. package/dist/forms.js.map +1 -1
  50. package/dist/heavy.d.ts +2 -2
  51. package/dist/heavy.js +151 -118
  52. package/dist/heavy.js.map +1 -1
  53. package/dist/index.d.ts +130 -106
  54. package/dist/index.esm.js +1083 -465
  55. package/dist/index.esm.js.map +1 -1
  56. package/dist/index.js +1102 -483
  57. package/dist/index.js.map +1 -1
  58. package/dist/index.min.js +1 -1
  59. package/dist/index.min.js.map +1 -1
  60. package/dist/theme.d.ts +27 -2
  61. package/dist/theme.js +721 -108
  62. package/dist/theme.js.map +1 -1
  63. package/package.json +23 -8
  64. package/scripts/atomix-cli.js +749 -1153
  65. package/scripts/cli/__tests__/README.md +81 -0
  66. package/scripts/cli/__tests__/basic.test.js +115 -0
  67. package/scripts/cli/__tests__/component-generator.test.js +332 -0
  68. package/scripts/cli/__tests__/integration.test.js +327 -0
  69. package/scripts/cli/__tests__/test-setup.js +133 -0
  70. package/scripts/cli/__tests__/token-manager.test.js +251 -0
  71. package/scripts/cli/__tests__/utils.test.js +78 -118
  72. package/scripts/cli/component-generator.js +564 -0
  73. package/scripts/cli/dependency-checker.js +355 -0
  74. package/scripts/cli/documentation-sync.js +542 -0
  75. package/scripts/cli/interactive-init.js +129 -292
  76. package/scripts/cli/mappings.js +211 -0
  77. package/scripts/cli/migration-tools.js +95 -288
  78. package/scripts/cli/template-manager.js +105 -0
  79. package/scripts/cli/templates/README.md +123 -0
  80. package/scripts/cli/templates/common-templates.js +636 -0
  81. package/scripts/cli/templates/composable-templates.js +171 -0
  82. package/scripts/cli/templates/config-templates.js +126 -0
  83. package/scripts/cli/templates/index.js +102 -0
  84. package/scripts/cli/templates/project-templates.js +342 -0
  85. package/scripts/cli/templates/react-templates.js +331 -0
  86. package/scripts/cli/templates/scss-templates.js +155 -0
  87. package/scripts/cli/templates/storybook-templates.js +236 -0
  88. package/scripts/cli/templates/testing-templates.js +224 -0
  89. package/scripts/cli/templates/testing-utils.js +278 -0
  90. package/scripts/cli/templates/token-templates.js +447 -0
  91. package/scripts/cli/templates/types-templates.js +147 -0
  92. package/scripts/cli/templates.js +35 -0
  93. package/scripts/cli/theme-bridge.js +28 -16
  94. package/scripts/cli/token-manager.js +432 -247
  95. package/scripts/cli/utils.js +37 -26
  96. package/src/components/Accordion/Accordion.stories.tsx +369 -870
  97. package/src/components/Accordion/Accordion.test.tsx +57 -0
  98. package/src/components/Accordion/Accordion.tsx +4 -0
  99. package/src/components/AtomixGlass/AtomixGlass.tsx +80 -39
  100. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +103 -81
  101. package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +8 -7
  102. package/src/components/AtomixGlass/glass-utils.ts +2 -2
  103. package/src/components/AtomixGlass/shader-utils.ts +5 -0
  104. package/src/components/AtomixGlass/stories/Customization.stories.tsx +131 -0
  105. package/src/components/AtomixGlass/stories/Examples.stories.tsx +2965 -2861
  106. package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -1
  107. package/src/components/AtomixGlass/stories/Overview.stories.tsx +348 -0
  108. package/src/components/AtomixGlass/stories/Performance.stories.tsx +103 -0
  109. package/src/components/AtomixGlass/stories/Playground.stories.tsx +73 -59
  110. package/src/components/AtomixGlass/stories/{ShaderVariants.stories.tsx → Shaders.stories.tsx} +1 -1
  111. package/src/components/AtomixGlass/stories/shared-components.tsx +90 -190
  112. package/src/components/Avatar/Avatar.stories.tsx +239 -27
  113. package/src/components/Badge/Badge.stories.tsx +132 -373
  114. package/src/components/Badge/Badge.test.tsx +51 -0
  115. package/src/components/Badge/Badge.tsx +20 -1
  116. package/src/components/Block/Block.stories.tsx +26 -17
  117. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +141 -23
  118. package/src/components/Breadcrumb/Breadcrumb.tsx +2 -2
  119. package/src/components/Button/Button.stories.tsx +463 -1126
  120. package/src/components/Button/Button.test.tsx +107 -0
  121. package/src/components/Button/Button.tsx +50 -54
  122. package/src/components/Button/ButtonGroup.stories.tsx +373 -217
  123. package/src/components/Button/README.md +5 -0
  124. package/src/components/Callout/Callout.stories.tsx +299 -644
  125. package/src/components/Callout/Callout.test.tsx +10 -10
  126. package/src/components/Callout/Callout.tsx +7 -7
  127. package/src/components/Callout/README.md +9 -8
  128. package/src/components/Card/Card.stories.tsx +248 -68
  129. package/src/components/Card/Card.tsx +2 -2
  130. package/src/components/Chart/Chart.stories.tsx +156 -14
  131. package/src/components/Chart/Chart.tsx +1 -1
  132. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +151 -69
  133. package/src/components/Countdown/Countdown.stories.tsx +115 -8
  134. package/src/components/DataTable/DataTable.stories.tsx +346 -146
  135. package/src/components/DataTable/DataTable.tsx +14 -12
  136. package/src/components/DatePicker/DatePicker.stories.tsx +325 -1066
  137. package/src/components/Dropdown/Dropdown.stories.tsx +157 -37
  138. package/src/components/EdgePanel/EdgePanel.stories.tsx +230 -21
  139. package/src/components/Footer/Footer.stories.tsx +392 -328
  140. package/src/components/Form/Checkbox.stories.tsx +143 -9
  141. package/src/components/Form/Checkbox.test.tsx +63 -0
  142. package/src/components/Form/Checkbox.tsx +90 -52
  143. package/src/components/Form/Form.stories.tsx +121 -22
  144. package/src/components/Form/FormGroup.stories.tsx +128 -5
  145. package/src/components/Form/Input.stories.tsx +28 -16
  146. package/src/components/Form/Input.test.tsx +59 -0
  147. package/src/components/Form/Input.tsx +97 -95
  148. package/src/components/Form/Radio.stories.tsx +232 -97
  149. package/src/components/Form/Radio.tsx +2 -2
  150. package/src/components/Form/Select.stories.tsx +144 -12
  151. package/src/components/Form/Select.tsx +2 -2
  152. package/src/components/Form/Textarea.stories.tsx +171 -13
  153. package/src/components/Form/Textarea.test.tsx +45 -0
  154. package/src/components/Form/Textarea.tsx +88 -86
  155. package/src/components/Hero/Hero.stories.tsx +333 -32
  156. package/src/components/List/List.stories.tsx +143 -5
  157. package/src/components/Modal/Modal.stories.tsx +185 -46
  158. package/src/components/Navigation/Navbar/Navbar.stories.tsx +5 -5
  159. package/src/components/Navigation/Navbar/Navbar.tsx +1 -1
  160. package/src/components/Navigation/README.md +1 -1
  161. package/src/components/Pagination/Pagination.stories.tsx +5 -2
  162. package/src/components/Pagination/Pagination.tsx +1 -1
  163. package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -10
  164. package/src/components/Popover/Popover.stories.tsx +449 -99
  165. package/src/components/ProductReview/ProductReview.tsx +1 -1
  166. package/src/components/Progress/Progress.stories.tsx +167 -5
  167. package/src/components/Progress/Progress.tsx +46 -46
  168. package/src/components/Rating/Rating.stories.tsx +4 -4
  169. package/src/components/Rating/Rating.tsx +8 -8
  170. package/src/components/River/River.stories.tsx +1 -1
  171. package/src/components/SectionIntro/SectionIntro.stories.tsx +240 -48
  172. package/src/components/Slider/Slider.stories.tsx +63 -63
  173. package/src/components/Spinner/Spinner.stories.tsx +104 -10
  174. package/src/components/Spinner/Spinner.test.tsx +35 -0
  175. package/src/components/Spinner/Spinner.tsx +9 -2
  176. package/src/components/Steps/Steps.stories.tsx +172 -43
  177. package/src/components/Tabs/Tabs.stories.tsx +136 -10
  178. package/src/components/Testimonial/Testimonial.stories.tsx +121 -4
  179. package/src/components/Todo/Todo.stories.tsx +198 -9
  180. package/src/components/Toggle/Toggle.stories.tsx +153 -43
  181. package/src/components/Toggle/Toggle.test.tsx +91 -0
  182. package/src/components/Toggle/Toggle.tsx +44 -27
  183. package/src/components/Tooltip/Tooltip.stories.tsx +194 -104
  184. package/src/components/Tooltip/Tooltip.tsx +1 -1
  185. package/src/components/Upload/Upload.stories.tsx +113 -24
  186. package/src/layouts/Grid/Grid.stories.tsx +49 -49
  187. package/src/layouts/MasonryGrid/MasonryGrid.stories.tsx +2 -2
  188. package/src/lib/README.md +2 -2
  189. package/src/lib/__tests__/theme-tools.test.ts +193 -0
  190. package/src/lib/composables/index.ts +2 -2
  191. package/src/lib/composables/useAccordion.ts +12 -3
  192. package/src/lib/composables/useAtomixGlass.ts +28 -56
  193. package/src/lib/composables/useBreadcrumb.ts +2 -2
  194. package/src/lib/composables/useCallout.ts +7 -7
  195. package/src/lib/composables/useChartExport.ts +2 -7
  196. package/src/lib/composables/useDataTable.ts +46 -29
  197. package/src/lib/composables/useNavbar.ts +1 -1
  198. package/src/lib/constants/components.ts +10 -33
  199. package/src/lib/storybook/InteractiveDemo.tsx +113 -0
  200. package/src/lib/storybook/PreviewContainer.tsx +36 -0
  201. package/src/lib/storybook/VariantsGrid.tsx +21 -0
  202. package/src/lib/storybook/index.ts +3 -0
  203. package/src/lib/theme/core/createThemeObject.ts +9 -5
  204. package/src/lib/theme/devtools/CLI.ts +155 -0
  205. package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +213 -0
  206. package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +566 -0
  207. package/src/lib/theme/devtools/LiveEditor.tsx +2 -1
  208. package/src/lib/theme/devtools/index.ts +3 -0
  209. package/src/lib/theme/errors/errors.ts +8 -0
  210. package/src/lib/theme/runtime/ThemeProvider.tsx +117 -57
  211. package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +305 -0
  212. package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +588 -0
  213. package/src/lib/theme/utils/__tests__/themeValidation.test.ts +264 -0
  214. package/src/lib/theme/utils/index.ts +1 -0
  215. package/src/lib/theme/utils/themeValidation.ts +501 -0
  216. package/src/lib/theme-tools.ts +32 -3
  217. package/src/lib/types/components.ts +82 -27
  218. package/src/lib/utils/__tests__/csv.test.ts +45 -0
  219. package/src/lib/utils/csv.ts +17 -0
  220. package/src/lib/utils/dataTableExport.ts +1 -10
  221. package/src/lib/utils/themeNaming.ts +1 -1
  222. package/src/styles/01-settings/_index.scss +2 -1
  223. package/src/styles/01-settings/_settings.accordion.scss +28 -7
  224. package/src/styles/01-settings/_settings.colors.scss +11 -11
  225. package/src/styles/01-settings/_settings.typography.scss +5 -5
  226. package/src/styles/02-tools/_tools.utility-api.scss +14 -0
  227. package/src/styles/06-components/_components.accordion.scss +56 -14
  228. package/src/styles/06-components/_components.callout.scss +29 -33
  229. package/src/styles/06-components/_components.checkbox.scss +23 -17
  230. package/src/styles/06-components/_index.scss +1 -1
  231. package/src/styles/99-utilities/_index.scss +2 -0
  232. package/src/styles/99-utilities/_utilities.display.scss +14 -3
  233. package/src/styles/99-utilities/_utilities.flex.scss +10 -10
  234. package/src/styles/99-utilities/_utilities.scss +3 -1
  235. package/src/styles/99-utilities/_utilities.text-gradient.scss +45 -0
  236. package/src/styles/99-utilities/_utilities.text.scss +28 -8
  237. package/themes/dark-complementary/README.md +98 -0
  238. package/themes/dark-complementary/index.scss +158 -0
  239. package/themes/default-light/README.md +81 -0
  240. package/themes/default-light/index.scss +154 -0
  241. package/themes/high-contrast/README.md +105 -0
  242. package/themes/high-contrast/index.scss +172 -0
  243. package/themes/test-theme/README.md +38 -0
  244. package/themes/test-theme/index.scss +47 -0
  245. package/scripts/cli/__tests__/cli-commands.test.js +0 -204
  246. package/scripts/cli/__tests__/vitest.config.js +0 -26
  247. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +0 -1438
  248. package/src/lib/composables/useButton.ts +0 -93
  249. package/src/lib/composables/useCheckbox.ts +0 -70
package/dist/index.esm.js CHANGED
@@ -50,7 +50,7 @@ import { createPortal } from "react-dom";
50
50
  CLOSE_BTN_CLASS: "c-callout__close-btn",
51
51
  VARIANT_PREFIX: "c-callout--",
52
52
  CLASSES: {
53
- ONELINE: "c-callout--oneline",
53
+ COMPACT: "c-callout--compact",
54
54
  TOAST: "c-callout--toast",
55
55
  HIDE: "is-hide"
56
56
  }
@@ -1226,29 +1226,6 @@ import { createPortal } from "react-dom";
1226
1226
  SIZES: [ "xs", "sm", "md", "lg", "xl", "none" ],
1227
1227
  DEFAULT: "md"
1228
1228
  }
1229
- }, GLASS_CONTAINER = {
1230
- CLASSES: {
1231
- BASE: "c-glass-container",
1232
- GLASS: "c-glass-container__glass",
1233
- WARP: "c-glass-container__warp",
1234
- CONTENT: "c-glass-container__content",
1235
- OVERLAY: "c-glass-container__overlay",
1236
- OVERLAY_VISIBLE: "c-glass-container__overlay--visible",
1237
- OVERLAY_HIDDEN: "c-glass-container__overlay--hidden",
1238
- OVERLAY_BLEND: "c-glass-container__overlay-blend",
1239
- BORDER: "c-glass-container__border",
1240
- BORDER_OVERLAY: "c-glass-container__border-overlay",
1241
- HOVER_EFFECT: "c-glass-container__hover-effect",
1242
- ACTIVE_EFFECT: "c-glass-container__active-effect",
1243
- INTERACTION_EFFECT: "c-glass-container__interaction-effect",
1244
- ACTIVE: "c-glass-container--active",
1245
- CLICKABLE: "c-glass-container--clickable"
1246
- },
1247
- DISPLACEMENT_MAPS: {
1248
- STANDARD: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjcwIiBoZWlnaHQ9IjY5IiB2aWV3Qm94PSIwIDAgMjcwIDY5IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxyYWRpYWxHcmFkaWVudCBpZD0iZ3JhZGllbnQiIGN4PSI1MCUiIGN5PSI1MCUiIHI9IjUwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzgwODA4MCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzgwODA4MCIvPjwvcmFkaWFsR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZGllbnQpIi8+PC9zdmc+",
1249
- POLAR: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjcwIiBoZWlnaHQ9IjY5IiB2aWV3Qm94PSIwIDAgMjcwIDY5IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxyYWRpYWxHcmFkaWVudCBpZD0icG9sYXIiIGN4PSI1MCUiIGN5PSI1MCUiIHI9IjUwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzQwNDA0MCIvPjxzdG9wIG9mZnNldD0iNTAlIiBzdG9wLWNvbG9yPSIjODA4MDgwIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjNDA0MDQwIi8+PC9yYWRpYWxHcmFkaWVudD48L2RlZnM+PHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNwb2xhcikiLz48L3N2Zz4=",
1250
- PROMINENT: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjcwIiBoZWlnaHQ9IjY5IiB2aWV3Qm94PSIwIDAgMjcwIDY5IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0icHJvbWluZW50IiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIxMDAlIj48c3RvcCBvZmZzZXQ9IjAlIiBzdG9wLWNvbG9yPSIjNDA0MDQwIi8+PHN0b3Agb2Zmc2V0PSI1MCUiIHN0b3AtY29sb3I9IiNjMGMwYzAiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiM0MDQwNDAiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI3Byb21pbmVudCkiLz48L3N2Zz4="
1251
- }
1252
1229
  }, FOOTER = {
1253
1230
  SELECTORS: {
1254
1231
  FOOTER: ".c-footer",
@@ -1387,10 +1364,16 @@ import { createPortal } from "react-dom";
1387
1364
  MIN_BLUR: .1,
1388
1365
  MOUSE_INFLUENCE_DIVISOR: 100,
1389
1366
  EDGE_FADE_PIXELS: 2,
1367
+ // Note: This default must match the SCSS variable --atomix-radius-md
1368
+ // @see src/styles/01-settings/_settings.global.scss
1390
1369
  DEFAULT_CORNER_RADIUS: 16,
1391
- // Fallback value matching design system
1392
1370
  MAX_SIZE: 4096,
1393
1371
  // Maximum width/height for glass size
1372
+ // Palette for internal calculations (matches design system base colors)
1373
+ PALETTE: {
1374
+ WHITE: "255, 255, 255",
1375
+ BLACK: "0, 0, 0"
1376
+ },
1394
1377
  // Gradient calculation constants
1395
1378
  GRADIENT: {
1396
1379
  BASE_ANGLE: 135,
@@ -1581,7 +1564,12 @@ function useAccordion(initialProps) {
1581
1564
  panelHeight: panelHeight
1582
1565
  },
1583
1566
  toggle: () => {
1584
- defaultProps.disabled || (isControlled ? defaultProps.onOpenChange && defaultProps.onOpenChange(!isOpen) : setInternalOpen((prev => !prev)));
1567
+ if (!defaultProps.disabled) {
1568
+ const nextOpen = !isOpen;
1569
+ isControlled || setInternalOpen(nextOpen), defaultProps.onOpenChange?.(nextOpen),
1570
+ // Call legacy handlers
1571
+ nextOpen ? defaultProps.onOpen?.() : defaultProps.onClose?.();
1572
+ }
1585
1573
  },
1586
1574
  updatePanelHeight: updatePanelHeight,
1587
1575
  panelRef: panelRef,
@@ -1603,10 +1591,10 @@ const {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
1603
1591
  y: 0
1604
1592
  }, calculateMouseInfluence = mouseOffset => {
1605
1593
  if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
1606
- // More responsive calculation for overlight effects
1594
+ // Bounded calculation keeps the glass effect subtle and stable
1607
1595
  const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$1.MOUSE_INFLUENCE_DIVISOR;
1608
- return Math.min(1.5, influence);
1609
- // Cap influence for better control
1596
+ return Math.min(.8, influence);
1597
+ // Tighter cap to prevent blur/filter blow-out
1610
1598
  }, 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 => {
1611
1599
  if ("number" == typeof value) return Math.max(0, value);
1612
1600
  if ("string" != typeof value || !value.trim()) return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
@@ -1837,7 +1825,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
1837
1825
  }, globalMousePosition: globalMousePosition = {
1838
1826
  x: 0,
1839
1827
  y: 0
1840
- }, 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 = {
1828
+ }, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isHovered: isHovered = !1, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, cornerRadius: cornerRadius = 0, padding: padding = "0 0", glassSize: glassSize = {
1841
1829
  width: 0,
1842
1830
  height: 0
1843
1831
  }, onClick: onClick, mode: mode = "standard", effectiveDisableEffects: effectiveDisableEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", enableLiquidBlur: enableLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
@@ -1950,28 +1938,29 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
1950
1938
  flowBlur: 1.2 * blurAmount
1951
1939
  };
1952
1940
  // Enhanced validation for liquid blur
1953
- if (!enableLiquidBlur || !rectCache || !globalMousePosition || "number" != typeof globalMousePosition.x || "number" != typeof globalMousePosition.y || isNaN(globalMousePosition.x) || isNaN(globalMousePosition.y)) return defaultBlur;
1941
+ if (!enableLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
1954
1942
  try {
1955
- // Cache center and distance calculations
1956
- 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);
1943
+ const mouseInfluence = calculateMouseInfluence(mouseOffset), maxBlur = 2 * blurAmount, baseBlur = Math.min(maxBlur, blurAmount + mouseInfluence * blurAmount * .15), edgeIntensity = .15 * mouseInfluence, edgeBlur = Math.min(maxBlur, baseBlur * (.8 + .4 * edgeIntensity)), centerIntensity = .1 * mouseInfluence, centerBlur = Math.min(maxBlur, baseBlur * (.3 + .3 * centerIntensity)), flowBlur = Math.min(maxBlur, 1.2 * baseBlur);
1944
+ // NOTE: hover/active multipliers intentionally omitted here
1945
+ // they belong on opacity layers, not the blur filter itself.
1957
1946
  return {
1958
- baseBlur: clampBlur(baseBlur * stateMultiplier),
1959
- edgeBlur: clampBlur(edgeBlur * stateMultiplier),
1960
- centerBlur: clampBlur(centerBlur * stateMultiplier),
1961
- flowBlur: clampBlur(flowBlur * stateMultiplier)
1947
+ baseBlur: clampBlur(baseBlur),
1948
+ edgeBlur: clampBlur(edgeBlur),
1949
+ centerBlur: clampBlur(centerBlur),
1950
+ flowBlur: clampBlur(flowBlur)
1962
1951
  };
1963
1952
  } catch (error) {
1964
1953
  return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
1965
1954
  defaultBlur;
1966
1955
  }
1967
- }), [ enableLiquidBlur, blurAmount, globalMousePosition, mouseOffset, isHovered, isActive, rectCache, style, glassSize ]), backdropStyle = useMemo((() => {
1956
+ }), [ enableLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
1968
1957
  try {
1969
1958
  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;
1970
1959
  // Validate blur values before using them
1971
1960
  return !enableLiquidBlur || effectiveReducedMotion || effectiveDisableEffects || area > 18e4 ? {
1972
- 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)`
1961
+ backdropFilter: `blur(${clampBlur(Math.max(validatedBaseBlur, .8 * validatedEdgeBlur, 1.1 * validatedCenterBlur, .9 * validatedFlowBlur))}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1.05}) brightness(${overLightConfig?.brightness || 1.05})`
1973
1962
  } : {
1974
- 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)`
1963
+ backdropFilter: `blur(${clampBlur(.4 * validatedBaseBlur + .25 * validatedEdgeBlur + .15 * validatedCenterBlur + .2 * validatedFlowBlur)}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1.05}) brightness(${overLightConfig?.brightness || 1.05})`
1975
1964
  };
1976
1965
  // Single-pass fallback: stronger radius to match perceived blur of multi-pass
1977
1966
  } catch (error) {
@@ -1990,7 +1979,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
1990
1979
  "--atomix-glass-container-padding": padding || "0 0",
1991
1980
  "--atomix-glass-container-radius": `${"number" != typeof cornerRadius || isNaN(cornerRadius) ? 0 : cornerRadius}px`,
1992
1981
  "--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
1993
- "--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",
1982
+ "--atomix-glass-container-shadow": overLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.4 + .002 * mx) * (overLightConfig?.shadowIntensity || 1)})`, `inset 0 -1px 0 rgba(0, 0, 0, ${(.2 + .001 * Math.abs(my)) * (overLightConfig?.shadowIntensity || 1)})`, `inset 0 0 20px rgba(0, 0, 0, ${(.08 + .001 * Math.abs(mx + my)) * (overLightConfig?.shadowIntensity || 1)})`, `0 2px 12px rgba(0, 0, 0, ${(.12 + .002 * Math.abs(my)) * (overLightConfig?.shadowIntensity || 1)})` ].join(", ") : "0 0 20px rgba(0, 0, 0, 0.15) inset, 0 4px 8px rgba(0, 0, 0, 0.08) inset",
1994
1983
  "--atomix-glass-container-shadow-opacity": effectiveDisableEffects ? 0 : 1,
1995
1984
  // Background and shadow values use design token-aligned RGB values
1996
1985
  "--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",
@@ -2009,10 +1998,18 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
2009
1998
  "--atomix-glass-container-text-shadow": "none"
2010
1999
  };
2011
2000
  }
2012
- }), [ glassSize, padding, cornerRadius, backdropStyle, mouseOffset, overLight, effectiveDisableEffects ]);
2001
+ }), [ glassSize, padding, cornerRadius, backdropStyle, mouseOffset, overLight, effectiveDisableEffects ]), setForceNoTransition = el => {
2002
+ el && (el.style.setProperty("transition-duration", "0s", "important"), el.style.setProperty("animation-duration", "0s", "important"),
2003
+ el.style.setProperty("transition-delay", "0s", "important"));
2004
+ };
2013
2005
  return jsx("div", {
2014
- ref: ref,
2015
- className: `${ATOMIX_GLASS.CONTAINER_CLASS} ${className} ${active ? ATOMIX_GLASS.CLASSES.ACTIVE : ""} ${overLight ? ATOMIX_GLASS.CLASSES.OVER_LIGHT : ""}`,
2006
+ ref: el => {
2007
+ // Apply force no-transition
2008
+ setForceNoTransition(el),
2009
+ // Handle forwarded ref
2010
+ "function" == typeof ref ? ref(el) : ref && (ref.current = el);
2011
+ },
2012
+ className: `${ATOMIX_GLASS.CONTAINER_CLASS} ${className} ${isActive ? ATOMIX_GLASS.CLASSES.ACTIVE : ""} ${overLight ? ATOMIX_GLASS.CLASSES.OVER_LIGHT : ""}`,
2016
2013
  style: {
2017
2014
  ...style,
2018
2015
  ...containerVars
@@ -2030,6 +2027,11 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
2030
2027
  onMouseUp: onMouseUp,
2031
2028
  children: [ jsxs("div", {
2032
2029
  className: ATOMIX_GLASS.FILTER_CLASS,
2030
+ style: {
2031
+ zIndex: 1,
2032
+ position: "absolute",
2033
+ inset: 0
2034
+ },
2033
2035
  children: [ jsx(GlassFilter, {
2034
2036
  blurAmount: blurAmount,
2035
2037
  mode: mode,
@@ -2038,6 +2040,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
2038
2040
  aberrationIntensity: "number" != typeof aberrationIntensity || isNaN(aberrationIntensity) ? 0 : aberrationIntensity,
2039
2041
  shaderMapUrl: shaderMapUrl
2040
2042
  }), jsx("div", {
2043
+ ref: setForceNoTransition,
2041
2044
  className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
2042
2045
  style: {
2043
2046
  filter: `url(#${filterId})`,
@@ -2059,9 +2062,8 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
2059
2062
  style: {
2060
2063
  position: "relative",
2061
2064
  textShadow: "var(--atomix-glass-container-text-shadow)",
2062
- ...elasticity > 0 ? {
2063
- zIndex: 100
2064
- } : {}
2065
+ // Ensure content is always above the filter layer (zIndex 1)
2066
+ zIndex: elasticity > 0 ? 100 : 2
2065
2067
  },
2066
2068
  children: children
2067
2069
  }) ]
@@ -2179,12 +2181,12 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2179
2181
  }), [internalMouseOffset, setInternalMouseOffset] = useState({
2180
2182
  x: 0,
2181
2183
  y: 0
2182
- }), [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 ]);
2184
+ }), [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 ]), 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 ]);
2183
2185
  // Extract border-radius from children
2184
2186
  useEffect((() => {
2185
2187
  const extractRadius = () => {
2186
2188
  try {
2187
- let extractedRadius = null, extractionSource = "default";
2189
+ let extractedRadius = null;
2188
2190
  if (contentRef.current) {
2189
2191
  const firstChild = contentRef.current.firstElementChild;
2190
2192
  if (firstChild) {
@@ -2201,15 +2203,14 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2201
2203
  return null;
2202
2204
  }
2203
2205
  })(firstChild);
2204
- null !== domRadius && domRadius > 0 && (extractedRadius = domRadius, extractionSource = "DOM element");
2206
+ null !== domRadius && domRadius > 0 && (extractedRadius = domRadius);
2205
2207
  }
2206
2208
  }
2207
2209
  if (null === extractedRadius) {
2208
2210
  const childRadius = extractBorderRadiusFromChildren(children);
2209
- childRadius > 0 && childRadius !== CONSTANTS.DEFAULT_CORNER_RADIUS && (extractedRadius = childRadius,
2210
- extractionSource = "React children");
2211
+ childRadius > 0 && childRadius !== CONSTANTS.DEFAULT_CORNER_RADIUS && (extractedRadius = childRadius);
2211
2212
  }
2212
- null !== extractedRadius && extractedRadius > 0 ? setDynamicCornerRadius(extractedRadius) : "undefined" == typeof process || process.env;
2213
+ null !== extractedRadius && extractedRadius > 0 && setDynamicCornerRadius(extractedRadius);
2213
2214
  } catch (error) {
2214
2215
  "undefined" != typeof process && "production" === process.env?.NODE_ENV || !debugCornerRadius || console.error("[AtomixGlass] Error extracting corner radius:", error);
2215
2216
  }
@@ -2338,7 +2339,6 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2338
2339
  }
2339
2340
  if ("boolean" == typeof overLight &&
2340
2341
  // For boolean values, disable auto-detection
2341
- // Cache is automatically managed by WeakMap (no manual clearing needed)
2342
2342
  setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
2343
2343
  const mediaQueryReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"), mediaQueryHighContrast = window.matchMedia("(prefers-contrast: high)");
2344
2344
  setUserPrefersReducedMotion(mediaQueryReducedMotion.matches), setUserPrefersHighContrast(mediaQueryHighContrast.matches);
@@ -2408,6 +2408,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2408
2408
  }), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveDisableEffects ]);
2409
2409
  // Transform calculations
2410
2410
  const calculateDirectionalScale = useCallback((() => {
2411
+ if (!0 === overLight || "auto" === overLight && detectedOverLight || "object" == typeof overLight && null !== overLight && detectedOverLight) return "scale(1)";
2411
2412
  if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return "scale(1)";
2412
2413
  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({
2413
2414
  x: edgeDistanceX,
@@ -2421,7 +2422,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2421
2422
  if (0 === centerDistance) return "scale(1)";
2422
2423
  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;
2423
2424
  return `scaleX(${Math.max(.8, scaleX)}) scaleY(${Math.max(.8, scaleY)})`;
2424
- }), [ globalMousePosition, elasticity, glassSize, glassRef ]), calculateFadeInFactor = useCallback((() => {
2425
+ }), [ globalMousePosition, elasticity, glassSize, glassRef, overLight, detectedOverLight ]), calculateFadeInFactor = useCallback((() => {
2425
2426
  if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return 0;
2426
2427
  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({
2427
2428
  x: edgeDistanceX,
@@ -2506,20 +2507,21 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2506
2507
  isOverLight: isOverLight,
2507
2508
  threshold: .7,
2508
2509
  opacity: isOverLight ? Math.min(.6, Math.max(.2, .5 * hoverIntensity * activeIntensity)) : 0,
2509
- contrast: Math.min(1.8, Math.max(1, 1.4 + .3 * mouseInfluence)),
2510
- brightness: Math.min(1.2, Math.max(.7, .85 + .15 * mouseInfluence)),
2511
- saturationBoost: Math.min(2, Math.max(1, 1.3 + .4 * mouseInfluence)),
2512
- shadowIntensity: Math.min(1.5, Math.max(.5, .9 + .5 * mouseInfluence)),
2513
- borderOpacity: Math.min(1, Math.max(.3, .7 + .3 * mouseInfluence))
2510
+ contrast: Math.min(1.6, Math.max(1, 1.4 + .1 * mouseInfluence)),
2511
+ brightness: Math.min(1.1, Math.max(.8, .9 + .05 * mouseInfluence)),
2512
+ saturationBoost: 1.3,
2513
+ // Fixed value dynamic saturation amplifies perceived displacement
2514
+ shadowIntensity: Math.min(1.2, Math.max(.5, .9 + .2 * mouseInfluence)),
2515
+ borderOpacity: Math.min(1, Math.max(.3, .7 + .1 * mouseInfluence))
2514
2516
  };
2515
2517
  if ("object" == typeof overLight && null !== overLight) {
2516
2518
  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 = {
2517
2519
  ...baseConfig,
2518
2520
  threshold: validatedThreshold,
2519
2521
  opacity: validatedOpacity * hoverIntensity * activeIntensity,
2520
- contrast: validatedContrast + .3 * mouseInfluence,
2521
- brightness: validatedBrightness + .15 * mouseInfluence,
2522
- saturationBoost: validatedSaturationBoost + .4 * mouseInfluence
2522
+ contrast: Math.min(1.6, validatedContrast + .1 * mouseInfluence),
2523
+ brightness: Math.min(1.1, validatedBrightness + .05 * mouseInfluence),
2524
+ saturationBoost: validatedSaturationBoost
2523
2525
  };
2524
2526
  // Validate and apply object config values with proper clamping
2525
2527
  return "undefined" == typeof process || process.env, finalConfig;
@@ -2653,19 +2655,19 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2653
2655
  debugOverLight: debugOverLight,
2654
2656
  enablePerformanceMonitoring: enablePerformanceMonitoring,
2655
2657
  children: children
2656
- }), isOverLight = overLightConfig.isOverLight, shouldRenderOverLightLayers = enableOverLightLayers && isOverLight, baseStyle = {
2658
+ }), isOverLight = useMemo((() => overLightConfig?.isOverLight), [ overLight ]), shouldRenderOverLightLayers = enableOverLightLayers && isOverLight, baseStyle = {
2657
2659
  ...style,
2658
- ...0 !== elasticity && !effectiveDisableEffects && {
2660
+ ...!effectiveDisableEffects && {
2659
2661
  transform: transformStyle
2660
2662
  }
2661
- }, componentClassName = [ 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(" "), positionStyles = {
2663
+ }, componentClassName = [ 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(" "), positionStyles = useMemo((() => ({
2662
2664
  position: style.position || "absolute",
2663
2665
  top: style.top || 0,
2664
2666
  left: style.left || 0
2665
- }, adjustedSize = {
2667
+ })), [ style.position, style.top, style.left ]), adjustedSize = useMemo((() => ({
2666
2668
  width: "fixed" !== style.position ? "100%" : style.width ? style.width : Math.max(glassSize.width, 0),
2667
2669
  height: "fixed" !== style.position ? "100%" : style.height ? style.height : Math.max(glassSize.height, 0)
2668
- }, gradientValues = useMemo((() => {
2670
+ })), [ style.position, style.width, style.height, glassSize.width, glassSize.height ]), gradientValues = useMemo((() => {
2669
2671
  const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT;
2670
2672
  return {
2671
2673
  borderGradientAngle: GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER,
@@ -2705,7 +2707,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2705
2707
  over: isOverLight ? 1.1 * (overLightOpacity || .4) : 0
2706
2708
  };
2707
2709
  }), [ isHovered, isActive, isOverLight, overLightConfig.opacity ]), glassVars = useMemo((() => {
2708
- const whiteColor = "255, 255, 255", {borderGradientAngle: borderGradientAngle, borderStop1: borderStop1, borderStop2: borderStop2, borderOpacities: borderOpacities, hoverPositions: hoverPositions, basePosition: basePosition, mx: mx, my: my, absMx: absMx, absMy: absMy} = gradientValues;
2710
+ const whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, {borderGradientAngle: borderGradientAngle, borderStop1: borderStop1, borderStop2: borderStop2, borderOpacities: borderOpacities, hoverPositions: hoverPositions, basePosition: basePosition, mx: mx, my: my, absMx: absMx, absMy: absMy} = gradientValues, configBorderOpacity = overLightConfig?.borderOpacity ?? 1;
2709
2711
  return {
2710
2712
  "--atomix-glass-radius": `${effectiveCornerRadius}px`,
2711
2713
  "--atomix-glass-transform": transformStyle || "none",
@@ -2716,20 +2718,20 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2716
2718
  "--atomix-glass-height": "fixed" !== style.position ? adjustedSize.height : `${adjustedSize.height}px`,
2717
2719
  "--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.09375rem)",
2718
2720
  "--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay",
2719
- "--atomix-glass-border-gradient-1": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${borderOpacities[0]}) ${borderStop1}%, rgba(${whiteColor}, ${borderOpacities[1]}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
2720
- "--atomix-glass-border-gradient-2": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${borderOpacities[2]}) ${borderStop1}%, rgba(${whiteColor}, ${borderOpacities[3]}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
2721
+ "--atomix-glass-border-gradient-1": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
2722
+ "--atomix-glass-border-gradient-2": `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[2] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[3] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
2721
2723
  "--atomix-glass-hover-1-opacity": opacityValues.hover1,
2722
- "--atomix-glass-hover-1-gradient": isOverLight ? `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_START}) 0%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_STOP}%, rgba(0, 0, 0, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_END}%)` : `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_STOP}%)`,
2724
+ "--atomix-glass-hover-1-gradient": isOverLight ? `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_END}%)` : `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_STOP}%)`,
2723
2725
  "--atomix-glass-hover-2-opacity": opacityValues.hover2,
2724
- "--atomix-glass-hover-2-gradient": isOverLight ? `radial-gradient(circle at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_START}) 0%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_STOP}%, rgba(0, 0, 0, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_END}%)` : `radial-gradient(circle at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_STOP}%)`,
2726
+ "--atomix-glass-hover-2-gradient": isOverLight ? `radial-gradient(circle at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, 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 ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_STOP}%)`,
2725
2727
  "--atomix-glass-hover-3-opacity": opacityValues.hover3,
2726
- "--atomix-glass-hover-3-gradient": isOverLight ? `radial-gradient(circle at ${hoverPositions.hover3.x}% ${hoverPositions.hover3.y}%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_START}) 0%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_STOP}%, rgba(0, 0, 0, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_END}%)` : `radial-gradient(circle at ${hoverPositions.hover3.x}% ${hoverPositions.hover3.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_STOP}%)`,
2728
+ "--atomix-glass-hover-3-gradient": isOverLight ? `radial-gradient(circle at ${hoverPositions.hover3.x}% ${hoverPositions.hover3.y}%, 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 ${hoverPositions.hover3.x}% ${hoverPositions.hover3.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_STOP}%)`,
2727
2729
  "--atomix-glass-base-opacity": opacityValues.base,
2728
- "--atomix-glass-base-gradient": isOverLight ? `linear-gradient(${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.ANGLE}deg, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_BASE + mx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_BASE + my * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_MULTIPLIER}) ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_STOP}%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_BASE + absMx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.WHITE_OPACITY})`,
2730
+ "--atomix-glass-base-gradient": isOverLight ? `linear-gradient(${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.ANGLE}deg, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_BASE + mx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_BASE + my * 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 + absMx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.WHITE_OPACITY})`,
2729
2731
  "--atomix-glass-overlay-opacity": opacityValues.over,
2730
- "--atomix-glass-overlay-gradient": isOverLight ? `radial-gradient(circle at ${basePosition.x}% ${basePosition.y}%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + absMx * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID_STOP}%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_BASE + absMy * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`
2732
+ "--atomix-glass-overlay-gradient": isOverLight ? `radial-gradient(circle at ${basePosition.x}% ${basePosition.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + absMx * 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 + absMy * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`
2731
2733
  };
2732
- }), [ gradientValues, opacityValues, effectiveCornerRadius, transformStyle, positionStyles, adjustedSize, style.position, isOverLight ]), renderBackgroundLayer = layerType => jsx("div", {
2734
+ }), [ gradientValues, opacityValues, effectiveCornerRadius, transformStyle, positionStyles, adjustedSize, style.position, isOverLight, overLightConfig.borderOpacity ]), renderBackgroundLayer = layerType => jsx("div", {
2733
2735
  className: [ ATOMIX_GLASS.BACKGROUND_LAYER_CLASS, "dark" === layerType ? ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS, isOverLight ? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS ].filter(Boolean).join(" "),
2734
2736
  style: {
2735
2737
  ...positionStyles,
@@ -2755,9 +2757,9 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2755
2757
  className: className,
2756
2758
  style: baseStyle,
2757
2759
  cornerRadius: effectiveCornerRadius,
2758
- displacementScale: effectiveDisableEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : overLightConfig.isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
2760
+ displacementScale: effectiveDisableEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
2759
2761
  blurAmount: effectiveDisableEffects ? 0 : blurAmount,
2760
- saturation: effectiveHighContrast ? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST : overLightConfig.isOverLight ? saturation * overLightConfig.saturationBoost : saturation,
2762
+ saturation: effectiveHighContrast ? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST : isOverLight ? saturation * overLightConfig.saturationBoost : saturation,
2761
2763
  aberrationIntensity: effectiveDisableEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
2762
2764
  glassSize: glassSize,
2763
2765
  padding: padding,
@@ -2773,10 +2775,15 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2773
2775
  onMouseLeave: handleMouseLeave,
2774
2776
  onMouseDown: handleMouseDown,
2775
2777
  onMouseUp: handleMouseUp,
2776
- active: isActive,
2777
2778
  isHovered: isHovered,
2778
2779
  isActive: isActive,
2779
- overLight: overLightConfig.isOverLight,
2780
+ overLight: isOverLight,
2781
+ overLightConfig: {
2782
+ contrast: overLightConfig.contrast,
2783
+ brightness: overLightConfig.brightness,
2784
+ shadowIntensity: overLightConfig.shadowIntensity,
2785
+ borderOpacity: overLightConfig.borderOpacity
2786
+ },
2780
2787
  onClick: onClick,
2781
2788
  mode: mode,
2782
2789
  transform: baseStyle.transform,
@@ -2816,14 +2823,16 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2816
2823
  });
2817
2824
  }
2818
2825
 
2819
- const Accordion = memo((({title: title, children: children, defaultOpen: defaultOpen = !1, isOpen: controlledOpen, onOpenChange: onOpenChange, disabled: disabled = !1, iconPosition: iconPosition = "right", icon: icon, className: className = "", style: style, glass: glass}) => {
2826
+ const Accordion = memo((({title: title, children: children, defaultOpen: defaultOpen = !1, isOpen: controlledOpen, onOpenChange: onOpenChange, onOpen: onOpen, onClose: onClose, disabled: disabled = !1, iconPosition: iconPosition = "right", icon: icon, className: className = "", style: style, glass: glass}) => {
2820
2827
  // Generate unique IDs for accessibility
2821
2828
  const instanceId = useId(), buttonId = `accordion-header-${instanceId}`, panelId = `accordion-panel-${instanceId}`, {state: state, toggle: toggle, updatePanelHeight: updatePanelHeight, panelRef: panelRef, contentRef: contentRef, generateClassNames: generateClassNames, generateHeaderClassNames: generateHeaderClassNames} = useAccordion({
2822
2829
  defaultOpen: defaultOpen,
2823
2830
  disabled: disabled,
2824
2831
  iconPosition: iconPosition,
2825
2832
  isOpen: controlledOpen,
2826
- onOpenChange: onOpenChange
2833
+ onOpenChange: onOpenChange,
2834
+ onOpen: onOpen,
2835
+ onClose: onClose
2827
2836
  }), defaultIcon = jsx("i", {
2828
2837
  className: "c-accordion__icon",
2829
2838
  "aria-hidden": "true",
@@ -3112,7 +3121,11 @@ const AtomixLogo = ({height: height = 24, width: width = 24, color: color = "cur
3112
3121
  // Add input validation
3113
3122
  "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;
3114
3123
  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));
3115
- }
3124
+ },
3125
+ // Aliases for compatibility
3126
+ plasma: (uv, mousePosition) => fragmentShaders.premiumGlass(uv, mousePosition),
3127
+ waves: (uv, mousePosition) => fragmentShaders.liquidMetal(uv, mousePosition),
3128
+ noise: (uv, mousePosition) => fragmentShaders.appleFluid(uv, mousePosition)
3116
3129
  }, shaderUtils = Object.freeze( Object.defineProperty({
3117
3130
  __proto__: null,
3118
3131
  ShaderDisplacementGenerator: class {
@@ -3302,7 +3315,7 @@ function useBadge(initialProps) {
3302
3315
 
3303
3316
  AvatarGroup.displayName = "AvatarGroup";
3304
3317
 
3305
- const Badge = memo((({label: label, variant: variant = "primary", size: size = "md", disabled: disabled = !1, icon: icon, className: className = "", glass: glass, style: style}) => {
3318
+ const Badge = memo((({label: label, variant: variant = "primary", size: size = "md", disabled: disabled = !1, icon: icon, onRemove: onRemove, "aria-label": ariaLabel, className: className = "", glass: glass, style: style}) => {
3306
3319
  const {generateBadgeClass: generateBadgeClass} = useBadge({
3307
3320
  variant: variant,
3308
3321
  size: size,
@@ -3315,6 +3328,7 @@ const Badge = memo((({label: label, variant: variant = "primary", size: size =
3315
3328
  }), badgeElement = jsxs("span", {
3316
3329
  className: badgeClass,
3317
3330
  "aria-disabled": disabled,
3331
+ "aria-label": ariaLabel,
3318
3332
  ref: ref,
3319
3333
  style: style,
3320
3334
  children: [ icon && jsx("span", {
@@ -3322,6 +3336,13 @@ const Badge = memo((({label: label, variant: variant = "primary", size: size =
3322
3336
  children: icon
3323
3337
  }), jsx("span", {
3324
3338
  children: label
3339
+ }), onRemove && jsx("button", {
3340
+ type: "button",
3341
+ className: "c-badge__close",
3342
+ onClick: onRemove,
3343
+ "aria-label": "Remove badge",
3344
+ disabled: disabled,
3345
+ children: "×"
3325
3346
  }) ]
3326
3347
  });
3327
3348
  if (glass) {
@@ -3449,7 +3470,7 @@ const useBlock = () => ({
3449
3470
  * ```
3450
3471
  */ Block.displayName = "Block";
3451
3472
 
3452
- const Breadcrumb = memo((({items: items, divider: divider, className: className = "", ariaLabel: ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style}) => {
3473
+ const Breadcrumb = memo((({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style}) => {
3453
3474
  const breadcrumbClasses = [ BREADCRUMB.CLASSES.BASE, className ].filter(Boolean).join(" ");
3454
3475
  return jsx("nav", {
3455
3476
  "aria-label": ariaLabel,
@@ -3484,46 +3505,12 @@ const Breadcrumb = memo((({items: items, divider: divider, className: className
3484
3505
  });
3485
3506
  }));
3486
3507
 
3487
- /**
3488
- * Button state and functionality
3489
- * @param initialProps - Initial button properties
3490
- * @returns Button state and methods
3491
- */
3492
- function useButton(initialProps) {
3493
- // Default button properties
3494
- const defaultProps = {
3495
- variant: "primary",
3496
- size: "md",
3497
- disabled: !1,
3498
- rounded: !1,
3499
- loading: !1,
3500
- fullWidth: !1,
3501
- block: !1,
3502
- active: !1,
3503
- selected: !1,
3504
- ...initialProps
3505
- };
3506
- /**
3507
- * Generate button class based on properties
3508
- * @param props - Button properties
3509
- * @returns Class string
3510
- */ return {
3511
- defaultProps: defaultProps,
3512
- generateButtonClass: props => {
3513
- const {variant: variant = defaultProps.variant, size: size = defaultProps.size, disabled: disabled = defaultProps.disabled, rounded: rounded = defaultProps.rounded, iconOnly: iconOnly = !1, glass: glass = defaultProps.glass, loading: loading = defaultProps.loading, fullWidth: fullWidth = defaultProps.fullWidth, block: block = defaultProps.block, active: active = defaultProps.active, selected: selected = defaultProps.selected, className: className = ""} = props, sizeClass = "md" === size ? "" : `c-btn--${size}`, iconOnlyClass = iconOnly ? "c-btn--icon" : "", roundedClass = rounded ? "c-btn--rounded" : "", disabledClass = disabled ? "c-btn--disabled" : "", glassClass = glass ? "c-btn--glass" : "", loadingClass = loading ? BUTTON.CLASSES.LOADING : "", fullWidthClass = fullWidth ? BUTTON.CLASSES.FULL_WIDTH : "", blockClass = block ? BUTTON.CLASSES.BLOCK : "", activeClass = active ? BUTTON.CLASSES.ACTIVE : "", selectedClass = selected ? BUTTON.CLASSES.SELECTED : "";
3514
- return [ BUTTON.BASE_CLASS, `c-btn--${variant}`, sizeClass, iconOnlyClass, roundedClass, disabledClass, glassClass, loadingClass, fullWidthClass, blockClass, activeClass, selectedClass, className ].filter(Boolean).join(" ");
3515
- },
3516
- handleClick: handler => event => {
3517
- defaultProps.disabled || defaultProps.loading || !handler || handler(event);
3518
- }
3519
- };
3520
- }
3521
-
3522
3508
  /**
3523
3509
  * Spinner state and functionality
3524
3510
  * @param initialProps - Initial spinner properties
3525
3511
  * @returns Spinner state and methods
3526
- */ function useSpinner(initialProps) {
3512
+ */
3513
+ function useSpinner(initialProps) {
3527
3514
  // Default spinner properties
3528
3515
  const defaultProps = {
3529
3516
  variant: "primary",
@@ -3546,7 +3533,7 @@ function useButton(initialProps) {
3546
3533
 
3547
3534
  Breadcrumb.displayName = "Breadcrumb";
3548
3535
 
3549
- const Spinner = memo((({size: size = "md", variant: variant = "primary", fullscreen: fullscreen = !1, className: className = "", style: style, glass: glass}) => {
3536
+ const Spinner = memo((({size: size = "md", variant: variant = "primary", fullscreen: fullscreen = !1, className: className = "", style: style, glass: glass, "aria-label": ariaLabel, role: role = "status"}) => {
3550
3537
  const {generateSpinnerClass: generateSpinnerClass} = useSpinner({
3551
3538
  size: size,
3552
3539
  variant: variant,
@@ -3559,10 +3546,11 @@ const Spinner = memo((({size: size = "md", variant: variant = "primary", fullsc
3559
3546
  }), spinnerContent = jsx("div", {
3560
3547
  className: spinnerClass,
3561
3548
  style: style,
3562
- role: "status",
3549
+ role: role,
3550
+ "aria-label": ariaLabel || "Loading",
3563
3551
  children: jsx("span", {
3564
3552
  className: SPINNER.VISUALLY_HIDDEN,
3565
- children: "Loading..."
3553
+ children: ariaLabel || "Loading..."
3566
3554
  })
3567
3555
  });
3568
3556
  if (glass) {
@@ -3614,7 +3602,7 @@ class ThemeNaming {
3614
3602
  * Convert kebab-case to camelCase for JavaScript properties
3615
3603
  * @param str - String to convert
3616
3604
  */ static kebabToCamel(str) {
3617
- return str.replace(/-([a-z])/g, (g => g[1].toUpperCase()));
3605
+ return str.replace(/-([a-z])/g, (g => g[1]?.toUpperCase() ?? ""));
3618
3606
  }
3619
3607
  /**
3620
3608
  * Create a CSS variable name
@@ -3675,25 +3663,11 @@ class ThemeNaming {
3675
3663
 
3676
3664
  ThemeNaming.prefix = "atomix";
3677
3665
 
3678
- const Button = React.memo( forwardRef((({label: label, children: children, onClick: onClick, variant: variant = "primary", size: size = "md", disabled: disabled = !1, loading: loading = !1, loadingText: loadingText, icon: icon, iconName: iconName, iconSize: iconSize = "sm", iconPosition: iconPosition = "start", iconOnly: iconOnly = !1, rounded: rounded = !1, fullWidth: fullWidth = !1, block: block = !1, active: active = !1, selected: selected = !1, type: type = "button", className: className = "", as: Component = "button", href: href, target: target, glass: glass, onHover: onHover, onFocus: onFocus, onBlur: onBlur, ariaLabel: ariaLabel, ariaDescribedBy: ariaDescribedBy, ariaExpanded: ariaExpanded, ariaControls: ariaControls, tabIndex: tabIndex, style: style, LinkComponent: LinkComponent, ...props}, ref) => {
3666
+ const Button = React.memo( forwardRef((({label: label, children: children, onClick: onClick, variant: variant = "primary", size: size = "md", disabled: disabled = !1, loading: loading = !1, loadingText: loadingText, icon: icon, iconName: iconName, iconSize: iconSize = "sm", iconPosition: iconPosition = "start", iconOnly: iconOnly = !1, rounded: rounded = !1, fullWidth: fullWidth = !1, block: block = !1, active: active = !1, selected: selected = !1, type: type = "button", className: className = "", as: Component = "button", href: href, target: target, glass: glass, onHover: onHover, onFocus: onFocus, onBlur: onBlur, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, tabIndex: tabIndex, style: style, LinkComponent: LinkComponent, ...props}, ref) => {
3679
3667
  const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href && !isDisabled), iconElement = iconName ? jsx(Icon, {
3680
3668
  name: iconName,
3681
3669
  size: iconSize
3682
- }) : icon;
3683
- // Determine if we should render as a link
3684
- useButton({
3685
- variant: variant,
3686
- size: size,
3687
- disabled: isDisabled,
3688
- rounded: rounded,
3689
- glass: glass,
3690
- loading: loading,
3691
- fullWidth: fullWidth,
3692
- block: block,
3693
- active: active,
3694
- selected: selected
3695
- });
3696
- const buttonClass = [ BUTTON.BASE_CLASS, ThemeNaming.variantClass(THEME_NAMING.BUTTON_PREFIX, variant), "md" !== size ? ThemeNaming.sizeClass(THEME_NAMING.BUTTON_PREFIX, size) : "", iconOnly ? ThemeNaming.stateClass(THEME_NAMING.BUTTON_PREFIX, THEME_NAMING.ICON_ELEMENT) : "", rounded ? ThemeNaming.stateClass(THEME_NAMING.BUTTON_PREFIX, "rounded") : "", isDisabled ? ThemeNaming.stateClass(THEME_NAMING.BUTTON_PREFIX, "disabled") : "", glass ? ThemeNaming.stateClass(THEME_NAMING.BUTTON_PREFIX, "glass") : "", loading ? BUTTON.CLASSES.LOADING : "", fullWidth ? BUTTON.CLASSES.FULL_WIDTH : "", block ? BUTTON.CLASSES.BLOCK : "", active ? BUTTON.CLASSES.ACTIVE : "", selected ? BUTTON.CLASSES.SELECTED : "", className ].filter(Boolean).join(" "), handleClickEvent = useCallback((event => {
3670
+ }) : icon, buttonClass = [ BUTTON.BASE_CLASS, ThemeNaming.variantClass(THEME_NAMING.BUTTON_PREFIX, variant), "md" !== size ? ThemeNaming.sizeClass(THEME_NAMING.BUTTON_PREFIX, size) : "", iconOnly ? ThemeNaming.stateClass(THEME_NAMING.BUTTON_PREFIX, THEME_NAMING.ICON_ELEMENT) : "", rounded ? ThemeNaming.stateClass(THEME_NAMING.BUTTON_PREFIX, "rounded") : "", isDisabled ? ThemeNaming.stateClass(THEME_NAMING.BUTTON_PREFIX, "disabled") : "", glass ? ThemeNaming.stateClass(THEME_NAMING.BUTTON_PREFIX, "glass") : "", loading ? BUTTON.CLASSES.LOADING : "", fullWidth ? BUTTON.CLASSES.FULL_WIDTH : "", block ? BUTTON.CLASSES.BLOCK : "", active ? BUTTON.CLASSES.ACTIVE : "", selected ? BUTTON.CLASSES.SELECTED : "", className ].filter(Boolean).join(" "), handleClickEvent = useCallback((event => {
3697
3671
  isDisabled ? event.preventDefault() : onClick?.(event);
3698
3672
  }), [ isDisabled, onClick ]), handleMouseEnter = useCallback((event => {
3699
3673
  isDisabled || onHover?.(event);
@@ -3701,7 +3675,7 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
3701
3675
  isDisabled || onFocus?.(event);
3702
3676
  }), [ isDisabled, onFocus ]), handleBlurEvent = useCallback((event => {
3703
3677
  isDisabled || onBlur?.(event);
3704
- }), [ isDisabled, onBlur ]), buttonText = loading && loadingText ? loadingText : label || children, spinnerSize = "sm" === size ? "sm" : "lg" === size ? "md" : "sm", buttonContent = jsxs(Fragment, {
3678
+ }), [ isDisabled, onBlur ]), buttonText = loading && loadingText ? loadingText : label || children, spinnerSize = "sm" === size ? "sm" : "lg" === size ? "md" : "sm", safeAriaLabel = ariaLabel || (iconOnly ? "string" == typeof label ? label : "string" == typeof children ? children : void 0 : void 0), buttonContent = jsxs(Fragment, {
3705
3679
  children: [ loading && jsx("span", {
3706
3680
  className: ThemeNaming.bemClass(THEME_NAMING.BUTTON_PREFIX, THEME_NAMING.SPINNER_ELEMENT),
3707
3681
  "aria-hidden": "true",
@@ -3718,80 +3692,77 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
3718
3692
  children: buttonText
3719
3693
  }) ]
3720
3694
  }), buttonProps = {
3721
- ref: ref,
3722
3695
  className: buttonClass,
3723
- type: "button" !== Component || shouldRenderAsLink ? void 0 : type,
3724
3696
  onClick: handleClickEvent,
3725
3697
  onMouseEnter: onHover ? handleMouseEnter : void 0,
3726
3698
  onFocus: onFocus ? handleFocusEvent : void 0,
3727
3699
  onBlur: onBlur ? handleBlurEvent : void 0,
3728
- disabled: isDisabled && "button" === Component && !shouldRenderAsLink,
3729
3700
  "aria-disabled": isDisabled,
3730
3701
  "aria-busy": loading,
3731
- "aria-label": ariaLabel || (iconOnly ? label || children : void 0),
3702
+ "aria-label": safeAriaLabel,
3732
3703
  "aria-describedby": ariaDescribedBy,
3733
3704
  "aria-expanded": ariaExpanded,
3734
3705
  "aria-controls": ariaControls,
3735
3706
  tabIndex: void 0 !== tabIndex ? tabIndex : isDisabled ? -1 : 0,
3736
3707
  style: style,
3737
3708
  ...props
3738
- }, defaultGlassProps = {
3739
- displacementScale: 20,
3740
- blurAmount: 0,
3741
- saturation: 200,
3742
- elasticity: 0
3743
- }, glassProps = !0 === glass ? defaultGlassProps : {
3744
- ...defaultGlassProps,
3745
- ...glass
3746
3709
  };
3747
- // Handle click with loading check
3748
- // Render as anchor if href is provided
3749
- if (shouldRenderAsLink) {
3750
- const {ref: _, ...buttonPropsWithoutRef} = buttonProps, anchorButtonProps = {
3751
- ...buttonPropsWithoutRef,
3752
- type: void 0,
3753
- disabled: void 0
3754
- };
3755
- // Use custom LinkComponent if provided (e.g., Next.js Link)
3756
- if (LinkComponent) {
3757
- const LinkComp = LinkComponent, linkProps = {
3758
- ...anchorButtonProps,
3759
- ref: ref,
3760
- href: href,
3761
- target: target,
3762
- rel: "_blank" === target ? "noopener noreferrer" : void 0
3763
- }, linkElement = jsx(LinkComp, {
3764
- ...linkProps,
3765
- children: buttonContent
3766
- });
3767
- return glass ? jsx(AtomixGlass, {
3768
- ...glassProps,
3769
- children: linkElement
3770
- }) : linkElement;
3771
- }
3772
- // Fallback to regular anchor tag
3773
- const anchorElement = jsx("a", {
3774
- ...anchorButtonProps,
3710
+ // Determine if we should render as a link
3711
+ // If disabled, we still check href, but we might want to render as button or anchor with aria-disabled
3712
+ // The previous logic was Boolean(href && !isDisabled). This meant if disabled, it renders as <button>.
3713
+ // This is a safe fallback for disabled links.
3714
+ let content;
3715
+ // Render as anchor if href is provided
3716
+ if (shouldRenderAsLink)
3717
+ // Use custom LinkComponent if provided (e.g., Next.js Link)
3718
+ if (LinkComponent) {
3719
+ const LinkComp = LinkComponent, linkProps = {
3720
+ ...buttonProps,
3775
3721
  ref: ref,
3722
+ // LinkComponent usually forwards ref to anchor
3776
3723
  href: href,
3777
3724
  target: target,
3778
- rel: "_blank" === target ? "noopener noreferrer" : void 0,
3725
+ rel: "_blank" === target ? "noopener noreferrer" : void 0
3726
+ };
3727
+ content = jsx(LinkComp, {
3728
+ ...linkProps,
3779
3729
  children: buttonContent
3780
3730
  });
3781
- return glass ? jsx(AtomixGlass, {
3782
- ...glassProps,
3783
- children: anchorElement
3784
- }) : anchorElement;
3785
- }
3731
+ } else
3732
+ // Fallback to regular anchor tag
3733
+ content = jsx("a", {
3734
+ ...buttonProps,
3735
+ ref: ref,
3736
+ href: href,
3737
+ target: target,
3738
+ rel: "_blank" === target ? "noopener noreferrer" : void 0,
3739
+ children: buttonContent
3740
+ }); else
3786
3741
  // Default button rendering
3787
- const buttonElement = jsx(Component, {
3742
+ content = jsx(Component, {
3788
3743
  ...buttonProps,
3744
+ ref: ref,
3745
+ type: "button" === Component ? type : void 0,
3746
+ disabled: isDisabled,
3789
3747
  children: buttonContent
3790
3748
  });
3791
- return glass ? jsx(AtomixGlass, {
3792
- ...glassProps,
3793
- children: buttonElement
3794
- }) : buttonElement;
3749
+ if (glass) {
3750
+ // Default glass props
3751
+ const defaultGlassProps = {
3752
+ displacementScale: 20,
3753
+ blurAmount: 0,
3754
+ saturation: 200,
3755
+ elasticity: 0
3756
+ }, glassProps = !0 === glass ? defaultGlassProps : {
3757
+ ...defaultGlassProps,
3758
+ ...glass
3759
+ };
3760
+ return jsx(AtomixGlass, {
3761
+ ...glassProps,
3762
+ children: content
3763
+ });
3764
+ }
3765
+ return content;
3795
3766
  })));
3796
3767
 
3797
3768
  Button.displayName = "Button";
@@ -4201,7 +4172,7 @@ var includes$3 = getBuiltInPrototypeMethod$3("String", "includes"), isPrototypeO
4201
4172
  const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
4202
4173
  var own = it.includes;
4203
4174
  return it === ArrayPrototype$1 || isPrototypeOf$1(ArrayPrototype$1, it) && own === ArrayPrototype$1.includes ? arrayMethod : "string" == typeof it || it === StringPrototype || isPrototypeOf$1(StringPrototype, it) && own === StringPrototype.includes ? stringMethod : own;
4204
- })), Callout = ({title: title, children: children, icon: icon, variant: variant = "primary", onClose: onClose, actions: actions, oneLine: oneLine = !1, toast: toast = !1, glass: glass, className: className, style: style, ...props}) => {
4175
+ })), Callout = ({title: title, children: children, icon: icon, variant: variant = "primary", onClose: onClose, actions: actions, compact: compact = !1, isToast: isToast = !1, glass: glass, className: className, style: style, ...props}) => {
4205
4176
  const {generateCalloutClass: generateCalloutClass, handleClose: handleClose} =
4206
4177
  /**
4207
4178
  * Callout state and functionality
@@ -4212,8 +4183,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
4212
4183
  // Default callout properties
4213
4184
  const defaultProps = {
4214
4185
  variant: "primary",
4215
- oneLine: !1,
4216
- toast: !1,
4186
+ compact: !1,
4187
+ isToast: !1,
4217
4188
  glass: !1,
4218
4189
  ...initialProps
4219
4190
  };
@@ -4224,8 +4195,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
4224
4195
  */ return {
4225
4196
  defaultProps: defaultProps,
4226
4197
  generateCalloutClass: props => {
4227
- const {variant: variant = defaultProps.variant, oneLine: oneLine = defaultProps.oneLine, toast: toast = defaultProps.toast, glass: glass = defaultProps.glass, className: className = ""} = props;
4228
- return `c-callout ${variant ? `c-callout--${variant}` : ""} ${oneLine ? "c-callout--oneline" : ""} ${toast ? "c-callout--toast" : ""} ${glass ? "c-callout--glass" : ""} ${className}`.trim();
4198
+ const {variant: variant = defaultProps.variant, compact: compact = defaultProps.compact, isToast: isToast = defaultProps.isToast, glass: glass = defaultProps.glass, className: className = ""} = props;
4199
+ return `c-callout ${variant ? `c-callout--${variant}` : ""} ${compact ? "c-callout--compact" : ""} ${isToast ? "c-callout--toast" : ""} ${glass ? "c-callout--glass" : ""} ${className}`.trim();
4229
4200
  },
4230
4201
  handleClose: handler => () => {
4231
4202
  handler && handler();
@@ -4236,8 +4207,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
4236
4207
  * Callout component for displaying important messages, notifications, or alerts
4237
4208
  */ ({
4238
4209
  variant: variant,
4239
- oneLine: oneLine,
4240
- toast: toast,
4210
+ compact: compact,
4211
+ isToast: isToast,
4241
4212
  glass: glass,
4242
4213
  className: className,
4243
4214
  style: style
@@ -4247,7 +4218,7 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
4247
4218
  role: "region"
4248
4219
  };
4249
4220
  // For toast notifications or alerts, use appropriate role and live region
4250
- return toast ? (baseAttributes.role = "alert", baseAttributes["aria-live"] = "polite") : _includesInstanceProperty(_context = [ "warning", "error" ]).call(_context, variant) ? (baseAttributes.role = "alert",
4221
+ return isToast ? (baseAttributes.role = "alert", baseAttributes["aria-live"] = "polite") : _includesInstanceProperty(_context = [ "warning", "error" ]).call(_context, variant) ? (baseAttributes.role = "alert",
4251
4222
  baseAttributes["aria-live"] = "assertive") : _includesInstanceProperty(_context2 = [ "info", "success" ]).call(_context2, variant) && (baseAttributes.role = "status",
4252
4223
  baseAttributes["aria-live"] = "polite"), baseAttributes;
4253
4224
  }, calloutContent = jsxs(Fragment, {
@@ -4293,8 +4264,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
4293
4264
  return jsx("div", {
4294
4265
  className: generateCalloutClass({
4295
4266
  variant: variant,
4296
- oneLine: oneLine,
4297
- toast: toast,
4267
+ compact: compact,
4268
+ isToast: isToast,
4298
4269
  glass: glass,
4299
4270
  className: className
4300
4271
  }),
@@ -4316,8 +4287,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
4316
4287
  return jsx("div", {
4317
4288
  className: generateCalloutClass({
4318
4289
  variant: variant,
4319
- oneLine: oneLine,
4320
- toast: toast,
4290
+ compact: compact,
4291
+ isToast: isToast,
4321
4292
  glass: glass,
4322
4293
  className: className
4323
4294
  }),
@@ -4344,7 +4315,7 @@ onClick: onClick, onHover: onHover, onFocus: onFocus, href: href, target: target
4344
4315
  // Glass
4345
4316
  glass: glass,
4346
4317
  // Accessibility
4347
- role: role, ariaLabel: ariaLabel, ariaDescribedBy: ariaDescribedBy, tabIndex: tabIndex,
4318
+ role: role, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, tabIndex: tabIndex,
4348
4319
  // Styling
4349
4320
  className: className = "", style: style, ...rest}, ref) => {
4350
4321
  // Determine if card is clickable/interactive
@@ -5885,7 +5856,7 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
5885
5856
  tabIndex: 0,
5886
5857
  ...props,
5887
5858
  children: [ (title || subtitle || showToolbar) && jsxs("div", {
5888
- className: `${CHART.HEADER_CLASS} u-d-flex u-justify-between u-align-items-start u-gap-4`,
5859
+ className: `${CHART.HEADER_CLASS} u-flex u-justify-between u-items-start u-gap-4`,
5889
5860
  children: [ jsxs("div", {
5890
5861
  className: `${CHART.HEADER_CONTENT_CLASS} u-flex-1`,
5891
5862
  children: [ title && jsx("h3", {
@@ -8829,6 +8800,22 @@ const WaterfallChart = memo( forwardRef((({waterfallData: waterfallData = [], c
8829
8800
  });
8830
8801
  })));
8831
8802
 
8803
+ /**
8804
+ * CSV Utility Functions
8805
+ */
8806
+ /**
8807
+ * Sanitize cell content to prevent CSV injection
8808
+ *
8809
+ * Replaces newlines and tabs with spaces, escapes double quotes,
8810
+ * and prefixes dangerous characters (=, +, -, @) with a single quote
8811
+ * to prevent formula injection.
8812
+ */
8813
+ function sanitizeCSVCell(cell) {
8814
+ const sanitized = String(cell ?? "").replace(/[\r\n\t]/g, " ").replace(/"/g, '""');
8815
+ // Prevent formula injection by prefixing dangerous characters
8816
+ return /^[=+\-@]/.test(sanitized) ? `'${sanitized}` : sanitized;
8817
+ }
8818
+
8832
8819
  WaterfallChart.displayName = "WaterfallChart";
8833
8820
 
8834
8821
  const SIZE_MAP = {
@@ -9030,29 +9017,38 @@ function getRowId$1(row, rowKey) {
9030
9017
  } // Reset to first page when filtering
9031
9018
  ), []), clearColumnFilters = useCallback((() => {
9032
9019
  setColumnFilterValues({}), setCurrentPage(1);
9033
- }), []), filteredData = useMemo((() => {
9034
- let result = data;
9035
- // Apply global search
9036
- if (searchQuery) {
9037
- const lowercaseQuery = searchQuery.toLowerCase();
9038
- result = result.filter((row => visibleColumns.some((column => {
9020
+ }), []), activeColumnFilters = useMemo((() => columnFilters ? Object.entries(columnFilterValues).filter((([, value]) => null != value && "" !== value)).map((([columnKey, value]) => {
9021
+ const column = columns.find((col => col.key === columnKey));
9022
+ return column && column.filterable ? {
9023
+ key: columnKey,
9024
+ value: value,
9025
+ lowercaseValue: "string" == typeof value ? value.toLowerCase() : String(value).toLowerCase(),
9026
+ column: column
9027
+ } : null;
9028
+ })).filter((f => null !== f)) : []), [ columnFilters, columnFilterValues, columns ]), filteredData = useMemo((() => {
9029
+ if (!searchQuery && 0 === activeColumnFilters.length) return data;
9030
+ const lowercaseQuery = searchQuery ? searchQuery.toLowerCase() : "";
9031
+ return data.filter((row => {
9032
+ // Apply global search
9033
+ if (searchQuery && !visibleColumns.some((column => {
9039
9034
  var _context;
9040
9035
  const value = row[column.key];
9041
9036
  return null != value && _includesInstanceProperty(_context = String(value).toLowerCase()).call(_context, lowercaseQuery);
9042
- }))));
9043
- }
9044
- // Apply column-specific filters
9045
- return columnFilters && (result = result.filter((row => Object.entries(columnFilterValues).every((([columnKey, filterValue]) => {
9046
- var _context2;
9047
- if (!filterValue) return !0;
9048
- const column = columns.find((col => col.key === columnKey));
9049
- if (!column || !column.filterable) return !0;
9050
- const cellValue = row[columnKey];
9051
- return null != cellValue && (
9052
- // Use custom filter function if provided
9053
- column.filterFunction ? column.filterFunction(cellValue, filterValue) : _includesInstanceProperty(_context2 = String(cellValue).toLowerCase()).call(_context2, filterValue.toLowerCase()));
9054
- }))))), result;
9055
- }), [ data, visibleColumns, searchQuery, columnFilterValues, columnFilters, columns ]), sortedData = useMemo((() => sortConfig && sortable ? [ ...filteredData ].sort(((a, b) => {
9037
+ }))) return !1;
9038
+ // Apply column-specific filters
9039
+ for (let i = 0; i < activeColumnFilters.length; i++) {
9040
+ const {key: key, value: value, lowercaseValue: lowercaseValue, column: column} = activeColumnFilters[i], cellValue = row[key];
9041
+ if (null == cellValue) return !1;
9042
+ // Use custom filter function if provided
9043
+ var _context2;
9044
+ // Default text filter
9045
+ if (column.filterFunction) {
9046
+ if (!column.filterFunction(cellValue, value)) return !1;
9047
+ } else if (!_includesInstanceProperty(_context2 = String(cellValue).toLowerCase()).call(_context2, lowercaseValue)) return !1;
9048
+ }
9049
+ return !0;
9050
+ }));
9051
+ }), [ data, visibleColumns, searchQuery, activeColumnFilters ]), sortedData = useMemo((() => sortConfig && sortable ? [ ...filteredData ].sort(((a, b) => {
9056
9052
  const aValue = a[sortConfig.key], bValue = b[sortConfig.key];
9057
9053
  return null == aValue ? "asc" === sortConfig.direction ? -1 : 1 : null == bValue ? "asc" === sortConfig.direction ? 1 : -1 : "string" == typeof aValue && "string" == typeof bValue ? "asc" === sortConfig.direction ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue) : "asc" === sortConfig.direction ? aValue > bValue ? 1 : -1 : aValue > bValue ? -1 : 1;
9058
9054
  })) : filteredData), [ filteredData, sortConfig, sortable ]), paginatedData = useMemo((() => {
@@ -9195,7 +9191,7 @@ const DOTS = "...", range = (start, end) => {
9195
9191
  "aria-hidden": "true"
9196
9192
  })
9197
9193
  })
9198
- }))), Pagination = memo((({currentPage: currentPage = PAGINATION_DEFAULTS.currentPage, totalPages: totalPages = PAGINATION_DEFAULTS.totalPages, onPageChange: onPageChange, siblingCount: siblingCount = PAGINATION_DEFAULTS.siblingCount, showFirstLastButtons: showFirstLastButtons = PAGINATION_DEFAULTS.showFirstLastButtons, showPrevNextButtons: showPrevNextButtons = PAGINATION_DEFAULTS.showPrevNextButtons, showSearch: showSearch = !1, searchPlaceholder: searchPlaceholder = "Go to page", size: size = PAGINATION_DEFAULTS.size, className: className = "", style: style, ariaLabel: ariaLabel = "Pagination", glass: glass}) => {
9194
+ }))), Pagination = memo((({currentPage: currentPage = PAGINATION_DEFAULTS.currentPage, totalPages: totalPages = PAGINATION_DEFAULTS.totalPages, onPageChange: onPageChange, siblingCount: siblingCount = PAGINATION_DEFAULTS.siblingCount, showFirstLastButtons: showFirstLastButtons = PAGINATION_DEFAULTS.showFirstLastButtons, showPrevNextButtons: showPrevNextButtons = PAGINATION_DEFAULTS.showPrevNextButtons, showSearch: showSearch = !1, searchPlaceholder: searchPlaceholder = "Go to page", size: size = PAGINATION_DEFAULTS.size, className: className = "", style: style, "aria-label": ariaLabel = "Pagination", glass: glass}) => {
9199
9195
  const {paginationRange: paginationRange, goToPage: goToPage, nextPage: nextPage, prevPage: prevPage, firstPage: firstPage, lastPage: lastPage} = usePagination({
9200
9196
  currentPage: currentPage,
9201
9197
  totalPages: totalPages,
@@ -9330,75 +9326,56 @@ const DOTS = "...", range = (start, end) => {
9330
9326
 
9331
9327
  Pagination.displayName = "Pagination", PaginationNavButton.displayName = "PaginationNavButton";
9332
9328
 
9333
- /**
9334
- * Checkbox state and functionality
9335
- * @param initialProps - Initial checkbox properties
9336
- * @returns Checkbox state and methods
9337
- */
9338
- function useCheckbox(initialProps) {
9339
- // Default checkbox properties
9340
- const defaultProps = {
9341
- disabled: !1,
9342
- invalid: !1,
9343
- valid: !1,
9344
- indeterminate: !1,
9345
- ...initialProps
9346
- }, checkboxRef = useRef(null);
9347
- // Ref for the checkbox input element
9348
- // Handle indeterminate state
9349
- return useEffect((() => {
9350
- checkboxRef.current && (checkboxRef.current.indeterminate = Boolean(defaultProps.indeterminate));
9351
- }), [ defaultProps.indeterminate ]), {
9352
- defaultProps: defaultProps,
9353
- generateCheckboxClass: props => {
9354
- const {disabled: disabled = defaultProps.disabled, invalid: invalid = defaultProps.invalid, valid: valid = defaultProps.valid, indeterminate: indeterminate = defaultProps.indeterminate, className: className = ""} = props;
9355
- let validationClass = "";
9356
- return invalid ? validationClass = "is-error" : valid && (validationClass = "is-valid"),
9357
- `c-checkbox ${validationClass} ${disabled ? "is-disabled" : ""} ${indeterminate ? "c-checkbox--mixed" : ""} ${className}`.trim();
9358
- },
9359
- checkboxRef: checkboxRef
9360
- };
9361
- }
9362
-
9363
- /**
9364
- * Checkbox - A component for checkbox inputs
9365
- */ 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}) => {
9366
- const {generateCheckboxClass: generateCheckboxClass, checkboxRef: checkboxRef} = useCheckbox({
9367
- indeterminate: indeterminate,
9368
- disabled: disabled,
9369
- invalid: invalid,
9370
- valid: valid
9371
- }), checkboxClass = generateCheckboxClass({
9372
- className: `${className} ${glass ? "c-checkbox--glass" : ""}`.trim(),
9329
+ const Checkbox = React.memo( forwardRef((({label: label, checked: checked, 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, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, onClick: onClick, glass: glass, ...props}, ref) => {
9330
+ // Local ref to handle indeterminate state
9331
+ const localRef = useRef(null);
9332
+ // Merge refs
9333
+ useImperativeHandle(ref, (() => localRef.current)),
9334
+ // Handle indeterminate
9335
+ useEffect((() => {
9336
+ localRef.current && (localRef.current.indeterminate = Boolean(indeterminate));
9337
+ }), [ indeterminate ]);
9338
+ // Generate classes
9339
+ let validationClass = "";
9340
+ invalid ? validationClass = "is-error" : valid && (validationClass = "is-valid");
9341
+ const checkboxClass = `c-checkbox ${validationClass} ${disabled ? "is-disabled" : ""} ${indeterminate ? "c-checkbox--mixed" : ""} ${glass ? "c-checkbox--glass" : ""} ${className}`.trim(), inputElement = jsx("input", {
9342
+ ref: localRef,
9343
+ type: "checkbox",
9344
+ className: "c-checkbox__input",
9345
+ checked: checked,
9346
+ onChange: onChange,
9347
+ onClick: onClick,
9373
9348
  disabled: disabled,
9374
- invalid: invalid,
9375
- valid: valid,
9376
- indeterminate: indeterminate
9377
- }), checkboxContent = jsxs("div", {
9349
+ required: required,
9350
+ id: id,
9351
+ name: name,
9352
+ value: value,
9353
+ "aria-label": label ? void 0 : ariaLabel,
9354
+ "aria-describedby": ariaDescribedBy,
9355
+ "aria-invalid": invalid,
9356
+ ...props
9357
+ });
9358
+ let content;
9359
+ if (content = id && label ? jsxs("div", {
9378
9360
  className: checkboxClass,
9379
9361
  style: style,
9380
- children: [ jsx("input", {
9381
- ref: checkboxRef,
9382
- type: "checkbox",
9383
- className: "c-checkbox__input",
9384
- checked: checked,
9385
- onChange: onChange,
9386
- disabled: disabled,
9387
- required: required,
9388
- id: id,
9389
- name: name,
9390
- value: value,
9391
- "aria-label": label ? void 0 : ariaLabel,
9392
- "aria-describedby": ariaDescribedBy,
9393
- "aria-invalid": invalid
9394
- }), label && jsx("label", {
9362
+ children: [ inputElement, jsx("label", {
9395
9363
  className: "c-checkbox__label",
9396
9364
  htmlFor: id,
9397
9365
  children: label
9398
9366
  }) ]
9399
- });
9400
- if (glass) {
9401
- // Default glass settings for checkboxes
9367
+ }) : label ? jsxs("label", {
9368
+ className: checkboxClass,
9369
+ style: style,
9370
+ children: [ inputElement, jsx("span", {
9371
+ className: "c-checkbox__label",
9372
+ children: label
9373
+ }) ]
9374
+ }) : jsx("div", {
9375
+ className: checkboxClass,
9376
+ style: style,
9377
+ children: inputElement
9378
+ }), glass) {
9402
9379
  const defaultGlassProps = {
9403
9380
  displacementScale: 40,
9404
9381
  blurAmount: 1,
@@ -9412,11 +9389,11 @@ function useCheckbox(initialProps) {
9412
9389
  };
9413
9390
  return jsx(AtomixGlass, {
9414
9391
  ...glassProps,
9415
- children: checkboxContent
9392
+ children: content
9416
9393
  });
9417
9394
  }
9418
- return checkboxContent;
9419
- }));
9395
+ return content;
9396
+ })));
9420
9397
 
9421
9398
  Checkbox.displayName = "Checkbox";
9422
9399
 
@@ -9593,18 +9570,6 @@ const DropdownContext = createContext({
9593
9570
 
9594
9571
  /**
9595
9572
  * DropdownItem component for menu items
9596
- */
9597
- /**
9598
- * Sanitize cell content to prevent CSV injection
9599
- */
9600
- function sanitizeCSVCell(cell) {
9601
- const sanitized = String(cell ?? "").replace(/[\r\n\t]/g, " ").replace(/"/g, '""');
9602
- // Prevent formula injection by prefixing dangerous characters
9603
- return /^[=+\-@]/.test(sanitized) ? `'${sanitized}` : sanitized;
9604
- }
9605
-
9606
- /**
9607
- * Export data as CSV
9608
9573
  */ Dropdown.displayName = "Dropdown", DropdownItem.displayName = "DropdownItem",
9609
9574
  DropdownDivider.displayName = "DropdownDivider", DropdownHeader.displayName = "DropdownHeader";
9610
9575
 
@@ -9671,7 +9636,7 @@ const DataTable = memo((({data: data, columns: columns, className: className, s
9671
9636
  }), []), handleDrop = useCallback(((e, dropIndex) => {
9672
9637
  if (e.preventDefault(), null !== dragStartIndex && dragStartIndex !== dropIndex && onColumnReorder) {
9673
9638
  const newOrder = [ ...visibleColumns.map((col => col.key)) ], [removed] = newOrder.splice(dragStartIndex, 1);
9674
- newOrder.splice(dropIndex, 0, removed), onColumnReorder(newOrder);
9639
+ removed && (newOrder.splice(dropIndex, 0, removed), onColumnReorder(newOrder));
9675
9640
  }
9676
9641
  setDragStartIndex(null), setDragOverIndex(null);
9677
9642
  }), [ dragStartIndex, visibleColumns, onColumnReorder ]), handleExport = useCallback((format => {
@@ -9683,7 +9648,11 @@ const DataTable = memo((({data: data, columns: columns, className: className, s
9683
9648
  const defaultFilename = filename || "data-table";
9684
9649
  switch (format) {
9685
9650
  case "csv":
9686
- !function(data, columns, filename = "data-table.csv") {
9651
+ !
9652
+ /**
9653
+ * Export data as CSV
9654
+ */
9655
+ function(data, columns, filename = "data-table.csv") {
9687
9656
  if (!data.length || !columns.length) return;
9688
9657
  // Create headers
9689
9658
  const headers = columns.map((col => col.title || col.key)), rows = data.map((row => columns.map((col => {
@@ -9981,7 +9950,7 @@ const DataTable = memo((({data: data, columns: columns, className: className, s
9981
9950
  showFirstLastButtons: !0,
9982
9951
  showPrevNextButtons: !0,
9983
9952
  size: "sm",
9984
- ariaLabel: "Data table pagination",
9953
+ "aria-label": "Data table pagination",
9985
9954
  className: "c-data-table__pagination"
9986
9955
  })
9987
9956
  }) ]
@@ -10965,7 +10934,7 @@ function useInput(initialProps) {
10965
10934
  * Input - A component for text input fields
10966
10935
  */ FormGroup.displayName = "FormGroup";
10967
10936
 
10968
- 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) => {
10937
+ const Input = memo( forwardRef((({type: type = "text", value: value, defaultValue: defaultValue, 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, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, glass: glass}, ref) => {
10969
10938
  const {generateInputClass: generateInputClass} = useInput({
10970
10939
  size: size,
10971
10940
  variant: variant,
@@ -10985,6 +10954,7 @@ const Input = memo( forwardRef((({type: type = "text", value: value, onChange:
10985
10954
  type: type,
10986
10955
  className: inputClass,
10987
10956
  value: value,
10957
+ defaultValue: defaultValue,
10988
10958
  onChange: onChange,
10989
10959
  onBlur: onBlur,
10990
10960
  onFocus: onFocus,
@@ -11239,7 +11209,7 @@ function useHero(initialProps) {
11239
11209
  backdrop: !1,
11240
11210
  closeOnOutsideClick: !0,
11241
11211
  closeOnEscape: !0,
11242
- ariaLabel: "Main navigation",
11212
+ "aria-label": "Main navigation",
11243
11213
  ...initialProps
11244
11214
  }, [isExpanded, setIsExpanded] = useState(defaultProps.expanded || !1);
11245
11215
  // Local expanded state for when not controlled externally
@@ -12041,7 +12011,7 @@ function useTodo(initialProps) {
12041
12011
  items: [],
12042
12012
  divider: BREADCRUMB.DEFAULTS.DIVIDER,
12043
12013
  className: "",
12044
- ariaLabel: "Breadcrumb",
12014
+ "aria-label": "Breadcrumb",
12045
12015
  ...initialOptions
12046
12016
  },
12047
12017
  generateBreadcrumbClass: options => {
@@ -12374,21 +12344,21 @@ function useSlider(options) {
12374
12344
  const [interaction, setInteraction] = useState({
12375
12345
  hoveredIndex: null,
12376
12346
  selectedIndex: null
12377
- }), handlePointHover = useCallback((index => {
12378
- setInteraction((prev => ({
12379
- ...prev,
12380
- hoveredIndex: index
12381
- })));
12382
- }), []), handlePointClick = useCallback((index => {
12383
- setInteraction((prev => ({
12384
- ...prev,
12385
- selectedIndex: prev.selectedIndex === index ? null : index
12386
- })));
12387
- }), []);
12347
+ });
12388
12348
  return {
12389
12349
  interaction: interaction,
12390
- handlePointHover: handlePointHover,
12391
- handlePointClick: handlePointClick,
12350
+ handlePointHover: useCallback((index => {
12351
+ setInteraction((prev => ({
12352
+ ...prev,
12353
+ hoveredIndex: index
12354
+ })));
12355
+ }), []),
12356
+ handlePointClick: useCallback((index => {
12357
+ setInteraction((prev => ({
12358
+ ...prev,
12359
+ selectedIndex: prev.selectedIndex === index ? null : index
12360
+ })));
12361
+ }), []),
12392
12362
  clearInteraction: useCallback((() => {
12393
12363
  setInteraction({
12394
12364
  hoveredIndex: null,
@@ -12399,6 +12369,8 @@ function useSlider(options) {
12399
12369
  }
12400
12370
 
12401
12371
  // Button composables
12372
+ // export * from './useButton';
12373
+ // Accordion composables
12402
12374
  const composablesImport = Object.freeze( Object.defineProperty({
12403
12375
  __proto__: null,
12404
12376
  DOTS: "...",
@@ -12408,12 +12380,10 @@ const composablesImport = Object.freeze( Object.defineProperty({
12408
12380
  useBarChart: useBarChart,
12409
12381
  useBlock: useBlock,
12410
12382
  useBreadcrumb: useBreadcrumb,
12411
- useButton: useButton,
12412
12383
  useCard: useCard,
12413
12384
  useChartData: useChartData,
12414
12385
  useChartInteraction: useChartInteraction,
12415
12386
  useChartScale: useChartScale,
12416
- useCheckbox: useCheckbox,
12417
12387
  useDataTable: useDataTable,
12418
12388
  useEdgePanel: useEdgePanel,
12419
12389
  useForm: useForm,
@@ -12440,7 +12410,7 @@ const composablesImport = Object.freeze( Object.defineProperty({
12440
12410
  useTodo: useTodo
12441
12411
  }, Symbol.toStringTag, {
12442
12412
  value: "Module"
12443
- })), 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}) => {
12413
+ })), Select = memo((({options: options = [], value: value, onChange: onChange, onBlur: onBlur, onFocus: onFocus, placeholder: placeholder = "Select an option", className: className = "", style: style, disabled: disabled = !1, required: required = !1, id: id, name: name, size: size = "md", invalid: invalid = !1, valid: valid = !1, multiple: multiple = !1, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, glass: glass}) => {
12444
12414
  const {generateSelectClass: generateSelectClass} = useSelect({
12445
12415
  size: size,
12446
12416
  disabled: disabled,
@@ -12588,7 +12558,7 @@ const composablesImport = Object.freeze( Object.defineProperty({
12588
12558
  /**
12589
12559
  * Radio - A component for radio button inputs
12590
12560
  */
12591
- 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}) => {
12561
+ 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, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, glass: glass}) => {
12592
12562
  const {generateRadioClass: generateRadioClass} = useRadio({
12593
12563
  disabled: disabled,
12594
12564
  invalid: invalid,
@@ -12646,7 +12616,7 @@ Radio.displayName = "Radio";
12646
12616
  /**
12647
12617
  * Textarea - A component for multiline text input
12648
12618
  */
12649
- 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) => {
12619
+ const Textarea = memo( forwardRef((({value: value, defaultValue: defaultValue, 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, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, glass: glass}, ref) => {
12650
12620
  const {generateTextareaClass: generateTextareaClass} = useTextarea({
12651
12621
  size: size,
12652
12622
  variant: variant,
@@ -12664,6 +12634,7 @@ const Textarea = memo( forwardRef((({value: value, onChange: onChange, onBlur:
12664
12634
  ref: ref,
12665
12635
  className: textareaClass,
12666
12636
  value: value,
12637
+ defaultValue: defaultValue,
12667
12638
  onChange: onChange,
12668
12639
  onBlur: onBlur,
12669
12640
  onFocus: onFocus,
@@ -14206,7 +14177,7 @@ NavItem.displayName = "NavItem";
14206
14177
  * </Navbar>
14207
14178
  * ```
14208
14179
  */
14209
- const Navbar = forwardRef((({brand: brand, children: children, variant: variant, position: position = "static", containerWidth: containerWidth, collapsible: collapsible = !0, expanded: expanded, onToggle: onToggle, className: className = "", style: style, disabled: disabled = !1, backdrop: backdrop = !1, closeOnOutsideClick: closeOnOutsideClick = !0, closeOnEscape: closeOnEscape = !0, ariaLabel: ariaLabel = "Main navigation", id: id, glass: glass}, ref) => {
14180
+ const Navbar = forwardRef((({brand: brand, children: children, variant: variant, position: position = "static", containerWidth: containerWidth, collapsible: collapsible = !0, expanded: expanded, onToggle: onToggle, className: className = "", style: style, disabled: disabled = !1, backdrop: backdrop = !1, closeOnOutsideClick: closeOnOutsideClick = !0, closeOnEscape: closeOnEscape = !0, "aria-label": ariaLabel = "Main navigation", id: id, glass: glass}, ref) => {
14210
14181
  const {generateNavbarClass: generateNavbarClass, generateContainerStyle: generateContainerStyle, generateCollapseClass: generateCollapseClass} = useNavbar({
14211
14182
  position: position,
14212
14183
  collapsible: collapsible,
@@ -16284,7 +16255,7 @@ const PopoverContext = createContext({
16284
16255
  /**
16285
16256
  * Hook for managing rating component state and interactions
16286
16257
  */
16287
- const Rating = forwardRef((({value: valueProp = 0, defaultValue: defaultValue, maxValue: maxValue = 5, allowHalf: allowHalf = !1, readOnly: readOnly = !1, size: size = "md", color: color, onChange: onChange, className: className = "", style: style, label: label, id: id, useVanillaJS: useVanillaJS = !1, glass: glass, ...restProps}, ref) => {
16258
+ const Rating = forwardRef((({value: valueProp = 0, defaultValue: defaultValue, maxValue: maxValue = 5, allowHalf: allowHalf = !1, readOnly: readOnly = !1, size: size = "md", variant: variant, onChange: onChange, className: className = "", style: style, label: label, id: id, useVanillaJS: useVanillaJS = !1, glass: glass, ...restProps}, ref) => {
16288
16259
  const internalRef = useRef(null), ratingInstance = useRef(null), {currentValue: currentValue, hoverValue: hoverValue, focusedIndex: focusedIndex, setHoverValue: setHoverValue, setFocused: setFocused, handleKeyDown: handleKeyDown} = (({value: value = 0, maxValue: maxValue = 5, allowHalf: allowHalf = !1, readOnly: readOnly = !1, onChange: onChange}) => {
16289
16260
  // Determine if component is in controlled mode
16290
16261
  const isControlled = void 0 !== onChange, [internalValue, setInternalValue] = useState(value), [hoverValue, setHoverValue] = useState(null), [focusedIndex, setFocusedIndex] = useState(null), currentValue = isControlled ? value : internalValue, handleMouseEnter = useCallback((starValue => {
@@ -16379,7 +16350,7 @@ const Rating = forwardRef((({value: valueProp = 0, defaultValue: defaultValue,
16379
16350
  return () => {
16380
16351
  ratingInstance.current && ratingInstance.current.destroy();
16381
16352
  };
16382
- }), [ useVanillaJS, valueProp, defaultValue, maxValue, allowHalf, readOnly, size, color, onChange ]),
16353
+ }), [ useVanillaJS, valueProp, defaultValue, maxValue, allowHalf, readOnly, size, variant, onChange ]),
16383
16354
  // Update vanilla JS implementation when props change
16384
16355
  useEffect((() => {
16385
16356
  useVanillaJS && ratingInstance.current && ratingInstance.current.updateOptions({
@@ -16388,11 +16359,11 @@ const Rating = forwardRef((({value: valueProp = 0, defaultValue: defaultValue,
16388
16359
  allowHalf: allowHalf,
16389
16360
  readOnly: readOnly,
16390
16361
  size: size,
16391
- color: color
16362
+ variant: variant
16392
16363
  });
16393
- }), [ useVanillaJS, valueProp, defaultValue, maxValue, allowHalf, readOnly, size, color ]);
16364
+ }), [ useVanillaJS, valueProp, defaultValue, maxValue, allowHalf, readOnly, size, variant ]);
16394
16365
  // Determine CSS classes
16395
- const ratingClasses = [ "c-rating", "sm" === size ? RATING.CLASSES.SMALL : "", "lg" === size ? RATING.CLASSES.LARGE : "", color ? `c-rating--${color}` : "", className ].filter(Boolean).join(" ");
16366
+ const ratingClasses = [ "c-rating", "sm" === size ? RATING.CLASSES.SMALL : "", "lg" === size ? RATING.CLASSES.LARGE : "", variant ? `c-rating--${variant}` : "", className ].filter(Boolean).join(" ");
16396
16367
  // If using vanilla JS, just render the container
16397
16368
  if (useVanillaJS) return jsx("div", {
16398
16369
  className: ratingClasses,
@@ -16416,7 +16387,7 @@ const Rating = forwardRef((({value: valueProp = 0, defaultValue: defaultValue,
16416
16387
  const stars = [], roundedValue = allowHalf ? Math.floor(2 * effectiveValue) / 2 : Math.round(effectiveValue), componentId = id || `rating-${Math.random().toString(36).substring(2, 9)}`;
16417
16388
  for (let i = 1; i <= maxValue; i++) {
16418
16389
  // For half-star support
16419
- const isFullStar = i <= Math.floor(roundedValue), isHalfStar = allowHalf && i - .5 === roundedValue, starClass = [ "c-rating__star", isFullStar ? RATING.CLASSES.FULL : "", isHalfStar ? RATING.CLASSES.HALF : "", color ? `c-rating__star--${color}` : "", focusedIndex === i ? "c-rating__star--focused" : "" ].filter(Boolean).join(" "), starId = `${componentId}-star-${i}`;
16390
+ const isFullStar = i <= Math.floor(roundedValue), isHalfStar = allowHalf && i - .5 === roundedValue, starClass = [ "c-rating__star", isFullStar ? RATING.CLASSES.FULL : "", isHalfStar ? RATING.CLASSES.HALF : "", variant ? `c-rating__star--${variant}` : "", focusedIndex === i ? "c-rating__star--focused" : "" ].filter(Boolean).join(" "), starId = `${componentId}-star-${i}`;
16420
16391
  stars.push(jsx("div", {
16421
16392
  id: starId,
16422
16393
  className: starClass,
@@ -16496,8 +16467,8 @@ const Rating = forwardRef((({value: valueProp = 0, defaultValue: defaultValue,
16496
16467
  * <Rating value={3} onChange={handleRatingChange} />
16497
16468
  *
16498
16469
  * @example
16499
- * // Read-only with custom color
16500
- * <Rating value={4.5} readOnly color="warning" />
16470
+ * // Read-only with custom variant
16471
+ * <Rating value={4.5} readOnly variant="warning" />
16501
16472
  *
16502
16473
  * @example
16503
16474
  * // With half-star support
@@ -16571,7 +16542,7 @@ const ProductReview = ({productName: productName, productImage: productImage, in
16571
16542
  allowHalf: allowHalf,
16572
16543
  maxValue: maxRating,
16573
16544
  size: "lg",
16574
- color: ratingColor
16545
+ variant: ratingColor
16575
16546
  }), jsx("span", {
16576
16547
  className: "c-rating__value",
16577
16548
  children: rating > 0 ? rating.toFixed(1) : "Select a rating"
@@ -16609,7 +16580,7 @@ ProductReview.displayName = "ProductReview";
16609
16580
  /**
16610
16581
  * Hook for managing Progress component state and behavior
16611
16582
  */
16612
- const Progress = memo( forwardRef((({value: value, variant: variant = "primary", size: size = "md", className: className = "", style: style, disabled: disabled = !1, ariaLabel: ariaLabel = PROGRESS.DEFAULTS.ARIA_LABEL, glass: glass}, ref) => {
16583
+ const Progress = memo( forwardRef((({value: value, variant: variant = "primary", size: size = "md", className: className = "", style: style, disabled: disabled = !1, "aria-label": ariaLabel = PROGRESS.DEFAULTS.ARIA_LABEL, glass: glass}, ref) => {
16613
16584
  const {progressValue: progressValue, progressStyle: progressStyle, progressClasses: progressClasses} = (({value: value, variant: variant = "primary", size: size = "md", className: className = ""}) => {
16614
16585
  // Clamp value between 0 and 100
16615
16586
  const progressValue = Math.min(Math.max(value, 0), 100), baseClass = "c-progress";
@@ -17299,28 +17270,29 @@ Todo.displayName = "Todo";
17299
17270
  /**
17300
17271
  * Toggle component for switching between two states
17301
17272
  */
17302
- const Toggle = ({initialOn: initialOn = !1, onToggleOn: onToggleOn, onToggleOff: onToggleOff, disabled: disabled = !1, className: className = "", style: style, glass: glass}) => {
17303
- const [isOn, setIsOn] = useState(initialOn), handleClick = () => {
17273
+ const Toggle = ({checked: controlledChecked, defaultChecked: defaultChecked = !1, onChange: onChange, disabled: disabled = !1, className: className = "", style: style, glass: glass, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy}) => {
17274
+ const isControlled = void 0 !== controlledChecked, [internalChecked, setInternalChecked] = useState(defaultChecked), isChecked = isControlled ? controlledChecked : internalChecked, handleClick = useCallback((() => {
17304
17275
  if (disabled) return;
17305
- const newState = !isOn;
17306
- setIsOn(newState), newState ? onToggleOn && onToggleOn() : onToggleOff && onToggleOff();
17307
- }, toggleContent = jsx("div", {
17308
- className: `c-toggle ${isOn ? TOGGLE.CLASSES.IS_ON : ""} ${disabled ? "is-disabled" : ""} ${className}`,
17276
+ const nextChecked = !isChecked;
17277
+ isControlled || setInternalChecked(nextChecked), onChange?.(nextChecked);
17278
+ }), [ disabled, isChecked, isControlled, onChange ]), toggleClass = [ "c-toggle", isChecked && TOGGLE.CLASSES.IS_ON, disabled && "is-disabled", className ].filter(Boolean).join(" "), toggleContent = jsx("div", {
17279
+ className: toggleClass,
17309
17280
  style: style,
17310
17281
  onClick: handleClick,
17311
17282
  onKeyDown: e => {
17312
17283
  disabled || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), handleClick());
17313
17284
  },
17314
17285
  role: "switch",
17315
- "aria-checked": isOn,
17286
+ "aria-checked": isChecked,
17316
17287
  tabIndex: disabled ? -1 : 0,
17317
17288
  "aria-disabled": disabled,
17289
+ "aria-label": ariaLabel,
17290
+ "aria-describedby": ariaDescribedBy,
17318
17291
  children: jsx("div", {
17319
17292
  className: "c-toggle__switch"
17320
17293
  })
17321
17294
  });
17322
- // Handle toggle click
17323
- if (glass) {
17295
+ if (glass) {
17324
17296
  // Default glass settings for toggles
17325
17297
  const defaultGlassProps = {
17326
17298
  displacementScale: 60,
@@ -17466,7 +17438,7 @@ const Tooltip = memo((({content: content, children: children, position: positio
17466
17438
  delay: delay
17467
17439
  });
17468
17440
  return jsxs("div", {
17469
- className: "u-position-relative u-d-inline-block",
17441
+ className: "u-position-relative u-inline-block",
17470
17442
  style: style,
17471
17443
  ...wrapperProps,
17472
17444
  children: [ jsx("div", {
@@ -18677,7 +18649,6 @@ const components = Object.freeze( Object.defineProperty({
18677
18649
  FOOTER: FOOTER,
18678
18650
  FORM: FORM,
18679
18651
  FORM_GROUP: FORM_GROUP,
18680
- GLASS_CONTAINER: GLASS_CONTAINER,
18681
18652
  HERO: HERO,
18682
18653
  INPUT: INPUT,
18683
18654
  LIST: LIST,
@@ -19108,6 +19079,14 @@ function createTokens(overrides) {
19108
19079
  ThemeErrorCode.INVALID_THEME_NAME = "INVALID_THEME_NAME",
19109
19080
  /** CSS injection failed */
19110
19081
  ThemeErrorCode.CSS_INJECTION_FAILED = "CSS_INJECTION_FAILED",
19082
+ /** Invalid color format */
19083
+ ThemeErrorCode.INVALID_COLOR_FORMAT = "INVALID_COLOR_FORMAT",
19084
+ /** Missing required token */
19085
+ ThemeErrorCode.MISSING_REQUIRED_TOKEN = "MISSING_REQUIRED_TOKEN",
19086
+ /** Accessibility contrast violation */
19087
+ ThemeErrorCode.CONTRAST_VIOLATION = "CONTRAST_VIOLATION",
19088
+ /** Invalid token type */
19089
+ ThemeErrorCode.INVALID_TOKEN_TYPE = "INVALID_TOKEN_TYPE",
19111
19090
  /** Unknown error */
19112
19091
  ThemeErrorCode.UNKNOWN_ERROR = "UNKNOWN_ERROR";
19113
19092
  }(ThemeErrorCode || (ThemeErrorCode = {}));
@@ -19409,29 +19388,6 @@ class ThemeLogger {
19409
19388
  return Object.keys(registry).length;
19410
19389
  }
19411
19390
 
19412
- /**
19413
- * Core Theme Engine
19414
- *
19415
- * Core theme creation, composition, and registry functionality
19416
- */ const index = Object.freeze( Object.defineProperty({
19417
- __proto__: null,
19418
- clearThemes: clearThemes,
19419
- createTheme: createTheme,
19420
- createThemeRegistry: createThemeRegistry,
19421
- deepMerge: deepMerge,
19422
- extendTheme: extendTheme,
19423
- getAllThemes: getAllThemes,
19424
- getTheme: getTheme,
19425
- getThemeCount: getThemeCount,
19426
- getThemeIds: getThemeIds,
19427
- hasTheme: hasTheme,
19428
- mergeTheme: mergeTheme,
19429
- registerTheme: registerTheme,
19430
- unregisterTheme: unregisterTheme
19431
- }, Symbol.toStringTag, {
19432
- value: "Module"
19433
- }));
19434
-
19435
19391
  /**
19436
19392
  * CSS Injection Utilities
19437
19393
  *
@@ -19604,7 +19560,7 @@ const isBrowser = () => "undefined" != typeof window && "undefined" != typeof do
19604
19560
  /**
19605
19561
  * Convert hex color to RGB object
19606
19562
  */
19607
- function hexToRgb(hex) {
19563
+ function hexToRgb$1(hex) {
19608
19564
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
19609
19565
  return result ? {
19610
19566
  r: parseInt(result[1], 16),
@@ -19624,7 +19580,7 @@ function hexToRgb(hex) {
19624
19580
  * Calculate relative luminance of a color
19625
19581
  * Used for determining contrast ratios
19626
19582
  */ function getLuminance(color) {
19627
- const rgb = hexToRgb(color);
19583
+ const rgb = hexToRgb$1(color);
19628
19584
  if (!rgb) return 0;
19629
19585
  const {r: r, g: g, b: b} = rgb, [rs, gs, bs] = [ r ?? 0, g ?? 0, b ?? 0 ].map((c => {
19630
19586
  const val = c / 255;
@@ -19654,7 +19610,7 @@ function hexToRgb(hex) {
19654
19610
  * @param amount - Amount to lighten (0-1), default 0.2
19655
19611
  * @returns Lightened hex color
19656
19612
  */ function lighten(color, amount = .2) {
19657
- const rgb = hexToRgb(color);
19613
+ const rgb = hexToRgb$1(color);
19658
19614
  if (!rgb) return color;
19659
19615
  const {r: r, g: g, b: b} = rgb, lightenValue = val => Math.min(255, Math.round(val + (255 - val) * amount));
19660
19616
  return rgbToHex(lightenValue(r), lightenValue(g), lightenValue(b));
@@ -19667,7 +19623,7 @@ function hexToRgb(hex) {
19667
19623
  * @param amount - Amount to darken (0-1), default 0.2
19668
19624
  * @returns Darkened hex color
19669
19625
  */ function darken(color, amount = .2) {
19670
- const rgb = hexToRgb(color);
19626
+ const rgb = hexToRgb$1(color);
19671
19627
  if (!rgb) return color;
19672
19628
  const {r: r, g: g, b: b} = rgb, darkenValue = val => Math.max(0, Math.round(val * (1 - amount)));
19673
19629
  return rgbToHex(darkenValue(r), darkenValue(g), darkenValue(b));
@@ -19680,7 +19636,7 @@ function hexToRgb(hex) {
19680
19636
  * @param opacity - Opacity value (0-1)
19681
19637
  * @returns RGBA color string
19682
19638
  */ function alpha(color, opacity) {
19683
- const rgb = hexToRgb(color);
19639
+ const rgb = hexToRgb$1(color);
19684
19640
  if (!rgb) return color;
19685
19641
  const {r: r, g: g, b: b} = rgb;
19686
19642
  return `rgba(${r}, ${g}, ${b}, ${Math.max(0, Math.min(1, opacity))})`;
@@ -19699,7 +19655,7 @@ function hexToRgb(hex) {
19699
19655
  */
19700
19656
  function generateColorScale(baseColor, prefix, colorName) {
19701
19657
  const vars = {};
19702
- if (!hexToRgb(baseColor)) return vars;
19658
+ if (!hexToRgb$1(baseColor)) return vars;
19703
19659
  // Generate 10-step scale
19704
19660
  // Steps 1-5: lighter variations
19705
19661
  // Step 6: base color
@@ -19745,7 +19701,7 @@ function generateCSSVariables(theme, options = {}) {
19745
19701
  // Main color (flat structure, matches SCSS: --atomix-primary)
19746
19702
  vars[`${prefix}-${key}`] = color.main;
19747
19703
  // Generate RGB for transparency support (matches SCSS: --atomix-primary-rgb)
19748
- const rgb = hexToRgb(color.main);
19704
+ const rgb = hexToRgb$1(color.main);
19749
19705
  // Generate full color scale (1-10) - matches SCSS: --atomix-primary-1 through --atomix-primary-10
19750
19706
  // Only for primary, secondary, error, warning, info, success (not for light/dark)
19751
19707
  if (rgb && (vars[`${prefix}-${key}-rgb`] = `${rgb.r}, ${rgb.g}, ${rgb.b}`), "light" !== key && "dark" !== key) {
@@ -19828,11 +19784,11 @@ function generateCSSVariables(theme, options = {}) {
19828
19784
  // Heading color (defaults to text primary) - matches SCSS: --atomix-heading-color
19829
19785
  palette.text && (vars[`${prefix}-heading-color`] = palette.text.primary), palette.primary) {
19830
19786
  vars[`${prefix}-link-color`] = palette.primary.main;
19831
- const linkRgb = hexToRgb(palette.primary.main);
19787
+ const linkRgb = hexToRgb$1(palette.primary.main);
19832
19788
  linkRgb && (vars[`${prefix}-link-color-rgb`] = `${linkRgb.r}, ${linkRgb.g}, ${linkRgb.b}`),
19833
19789
  // Link hover color (slightly darker)
19834
19790
  vars[`${prefix}-link-hover-color`] = palette.primary.dark || darken(palette.primary.main, .1);
19835
- const linkHoverRgb = hexToRgb(palette.primary.dark || darken(palette.primary.main, .1));
19791
+ const linkHoverRgb = hexToRgb$1(palette.primary.dark || darken(palette.primary.main, .1));
19836
19792
  linkHoverRgb && (vars[`${prefix}-link-hover-color-rgb`] = `${linkHoverRgb.r}, ${linkHoverRgb.g}, ${linkHoverRgb.b}`),
19837
19793
  // Link decoration (default: none, matching tokens list)
19838
19794
  vars[`${prefix}-link-decoration`] = "none";
@@ -20290,17 +20246,292 @@ function generateClassName(block, element, modifiers) {
20290
20246
  ThemeContext.displayName = "ThemeContext";
20291
20247
 
20292
20248
  /**
20293
- * Theme Provider
20249
+ * Theme Validation Utilities
20294
20250
  *
20295
- * React context provider for theme management with separated concerns.
20296
- * Simplified version focusing on core functionality:
20297
- * - String-based themes (CSS files)
20298
- * - DesignTokens (dynamic themes)
20299
- * - Persistence via localStorage
20300
- *
20301
- * Falls back to 'default' theme if no configuration is found.
20251
+ * Comprehensive validation utilities for DesignTokens objects.
20252
+ * Includes color format validation, accessibility checks, and required properties verification.
20253
+ */
20254
+ const logger$1 = getLogger(), COLOR_PATTERNS = {
20255
+ /** Hex color: #RGB, #RRGGBB, #RRGGBBAA */
20256
+ hex: /^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$/,
20257
+ /** RGB color: rgb(r, g, b) or rgb(r, g, b, a) */
20258
+ rgb: /^rgb\(\s*(\d{1,3}(?:\.\d+)?)\s*,\s*(\d{1,3}(?:\.\d+)?)\s*,\s*(\d{1,3}(?:\.\d+)?)\s*(?:,\s*([01]?\.?\d+))?\s*\)$/,
20259
+ /** RGBA color: rgba(r, g, b, a) */
20260
+ rgba: /^rgba\(\s*(\d{1,3}(?:\.\d+)?)\s*,\s*(\d{1,3}(?:\.\d+)?)\s*,\s*(\d{1,3}(?:\.\d+)?)\s*,\s*([01]?\.?\d+)\s*\)$/,
20261
+ /** HSL color: hsl(h, s%, l%) */
20262
+ hsl: /^hsl\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*\)$/,
20263
+ /** HSLA color: hsla(h, s%, l%, a) */
20264
+ hsla: /^hsla\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*,\s*([01]?\.?\d+)\s*\)$/
20265
+ }, REQUIRED_COLOR_TOKENS = [ "primary", "secondary", "success", "info", "warning", "error", "light", "dark" ], REQUIRED_TEXT_EMPHASIS_TOKENS = [ "primary-text-emphasis", "secondary-text-emphasis", "tertiary-text-emphasis", "disabled-text-emphasis" ], ACCESSIBILITY_CHECKS = [ {
20266
+ text: "primary-text-emphasis",
20267
+ background: "primary-bg-subtle",
20268
+ name: "Primary text on subtle background"
20269
+ }, {
20270
+ text: "secondary-text-emphasis",
20271
+ background: "secondary-bg-subtle",
20272
+ name: "Secondary text on subtle background"
20273
+ }, {
20274
+ text: "error-text-emphasis",
20275
+ background: "error-bg-subtle",
20276
+ name: "Error text on subtle background"
20277
+ }, {
20278
+ text: "success-text-emphasis",
20279
+ background: "success-bg-subtle",
20280
+ name: "Success text on subtle background"
20281
+ } ];
20282
+
20283
+ /**
20284
+ * Color format validation patterns
20285
+ */
20286
+ /**
20287
+ * Parse RGB/RGBA color string to RGB values
20288
+ */
20289
+ function rgbToRgb(rgb) {
20290
+ const match = rgb.match(COLOR_PATTERNS.rgb) || rgb.match(COLOR_PATTERNS.rgba);
20291
+ if (!match) return null;
20292
+ const r = parseInt(match[1] ?? "0", 10), g = parseInt(match[2] ?? "0", 10), b = parseInt(match[3] ?? "0", 10);
20293
+ // Validate RGB ranges
20294
+ return r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255 ? null : {
20295
+ r: r,
20296
+ g: g,
20297
+ b: b
20298
+ };
20299
+ }
20300
+
20301
+ /**
20302
+ * Parse HSL/HSLA color string to RGB values
20303
+ */ function hslToRgb(hsl) {
20304
+ const match = hsl.match(COLOR_PATTERNS.hsl) || hsl.match(COLOR_PATTERNS.hsla);
20305
+ if (!match) return null;
20306
+ let h = parseInt(match[1] ?? "0", 10) / 360, s = parseInt(match[2] ?? "0", 10) / 100, l = parseInt(match[3] ?? "0", 10) / 100;
20307
+ // Validate HSL ranges
20308
+ if (h < 0 || h > 1 || s < 0 || s > 1 || l < 0 || l > 1) return null;
20309
+ const hue2rgb = (p, q, t) => (t < 0 && (t += 1), t > 1 && (t -= 1), t < 1 / 6 ? p + 6 * (q - p) * t : t < .5 ? q : t < 2 / 3 ? p + (q - p) * (2 / 3 - t) * 6 : p);
20310
+ let r, g, b;
20311
+ if (0 === s) r = g = b = l; // achromatic
20312
+ else {
20313
+ const q = l < .5 ? l * (1 + s) : l + s - l * s, p = 2 * l - q;
20314
+ r = hue2rgb(p, q, h + 1 / 3), g = hue2rgb(p, q, h), b = hue2rgb(p, q, h - 1 / 3);
20315
+ }
20316
+ return {
20317
+ r: Math.round(255 * r),
20318
+ g: Math.round(255 * g),
20319
+ b: Math.round(255 * b)
20320
+ };
20321
+ }
20322
+
20323
+ /**
20324
+ * Convert any valid color format to RGB values
20325
+ */ function colorToRgb(color) {
20326
+ // Try hex first
20327
+ return COLOR_PATTERNS.hex.test(color) ?
20328
+ /**
20329
+ * Convert hex color to RGB values
20330
+ */
20331
+ function(hex) {
20332
+ const result = COLOR_PATTERNS.hex.exec(hex);
20333
+ if (!result || !result[1]) return null;
20334
+ const digits = result[1];
20335
+ let r, g, b;
20336
+ switch (digits.length) {
20337
+ case 3:
20338
+ case 4:
20339
+ // #RGBA (ignore alpha)
20340
+ r = parseInt((digits[0] ?? "0") + (digits[0] ?? "0"), 16), g = parseInt((digits[1] ?? "0") + (digits[1] ?? "0"), 16),
20341
+ b = parseInt((digits[2] ?? "0") + (digits[2] ?? "0"), 16);
20342
+ break;
20343
+
20344
+ case 6:
20345
+ case 8:
20346
+ // #RRGGBBAA (ignore alpha)
20347
+ r = parseInt(digits.slice(0, 2), 16), g = parseInt(digits.slice(2, 4), 16), b = parseInt(digits.slice(4, 6), 16);
20348
+ break;
20349
+
20350
+ default:
20351
+ return null;
20352
+ }
20353
+ return {
20354
+ r: r,
20355
+ g: g,
20356
+ b: b
20357
+ };
20358
+ }(color) :
20359
+ // Try RGB/RGBA
20360
+ color.startsWith("rgb") ? rgbToRgb(color) :
20361
+ // Try HSL/HSLA
20362
+ color.startsWith("hsl") ? hslToRgb(color) : null;
20363
+ }
20364
+
20365
+ /**
20366
+ * Validate that a color string is in a valid format (hex, rgb, hsl, etc.)
20367
+ * Includes validation of value ranges for RGB and HSL
20368
+ */
20369
+ /**
20370
+ * Calculate relative luminance of a color
20371
+ * Based on WCAG guidelines: https://www.w3.org/TR/WCAG20-TECHS/G17.html
20302
20372
  */
20303
- const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes: themes = {}, basePath: basePath = "/themes", cdnPath: cdnPath = null, useMinified: useMinified = !1, storageKey: storageKey = "atomix-theme", dataAttribute: dataAttribute = "data-theme", enablePersistence: enablePersistence = !0, onThemeChange: onThemeChange, onError: onError}) => {
20373
+ function getRelativeLuminance(r, g, b) {
20374
+ const normalize = val => (val /= 255) <= .03928 ? val / 12.92 : Math.pow((val + .055) / 1.055, 2.4);
20375
+ return .2126 * normalize(r) + .7152 * normalize(g) + .0722 * normalize(b);
20376
+ }
20377
+
20378
+ /**
20379
+ * Calculate contrast ratio between two colors (supports multiple formats)
20380
+ */
20381
+ /**
20382
+ * Check if contrast ratio meets WCAG AA standards
20383
+ * AA requires 4.5:1 for normal text, 3:1 for large text
20384
+ */
20385
+ function validateContrastRatio(foreground, background, isLargeText = !1) {
20386
+ const ratio = function(color1, color2) {
20387
+ const rgb1 = colorToRgb(color1), rgb2 = colorToRgb(color2);
20388
+ if (!rgb1 || !rgb2) return null;
20389
+ const lum1 = getRelativeLuminance(rgb1.r, rgb1.g, rgb1.b), lum2 = getRelativeLuminance(rgb2.r, rgb2.g, rgb2.b);
20390
+ return (Math.max(lum1, lum2) + .05) / (Math.min(lum1, lum2) + .05);
20391
+ }(foreground, background);
20392
+ if (null === ratio) return {
20393
+ valid: !1,
20394
+ ratio: 0,
20395
+ requiredRatio: isLargeText ? 3 : 4.5
20396
+ };
20397
+ const requiredRatio = isLargeText ? 3 : 4.5;
20398
+ return {
20399
+ valid: ratio >= requiredRatio,
20400
+ ratio: ratio,
20401
+ requiredRatio: requiredRatio
20402
+ };
20403
+ }
20404
+
20405
+ /**
20406
+ * Validate all color formats in DesignTokens
20407
+ */
20408
+ /**
20409
+ * Comprehensive validation of DesignTokens
20410
+ */
20411
+ function validateDesignTokens(tokens, options = {}) {
20412
+ const results = [];
20413
+ options.skipRequiredTokens || results.push(
20414
+ /**
20415
+ * Validate that all required tokens are present
20416
+ */
20417
+ function(tokens) {
20418
+ const errors = [], warnings = [];
20419
+ // Check required color tokens
20420
+ for (const token of REQUIRED_COLOR_TOKENS) token in tokens || errors.push(`Required color token '${token}' is missing`);
20421
+ // Check required text emphasis tokens
20422
+ for (const token of REQUIRED_TEXT_EMPHASIS_TOKENS) token in tokens || errors.push(`Required text emphasis token '${token}' is missing`);
20423
+ // Check for RGB versions of base colors
20424
+ for (const token of REQUIRED_COLOR_TOKENS) {
20425
+ const rgbToken = `${token}-rgb`;
20426
+ rgbToken in tokens || warnings.push(`RGB version of '${token}' token '${rgbToken}' is missing`);
20427
+ }
20428
+ return {
20429
+ valid: 0 === errors.length,
20430
+ errors: errors,
20431
+ warnings: warnings
20432
+ };
20433
+ }
20434
+ /**
20435
+ * Validate accessibility contrast ratios
20436
+ */ (tokens)), options.skipColorValidation || results.push(function(tokens) {
20437
+ const errors = [], colorTokenKeys = new Set([
20438
+ // Base colors
20439
+ "primary", "secondary", "success", "info", "warning", "error", "light", "dark",
20440
+ // Text emphasis
20441
+ "primary-text-emphasis", "secondary-text-emphasis", "tertiary-text-emphasis", "disabled-text-emphasis", "invert-text-emphasis", "brand-text-emphasis", "error-text-emphasis", "success-text-emphasis", "warning-text-emphasis", "info-text-emphasis", "light-text-emphasis", "dark-text-emphasis",
20442
+ // Background subtle
20443
+ "primary-bg-subtle", "secondary-bg-subtle", "tertiary-bg-subtle", "invert-bg-subtle", "brand-bg-subtle", "error-bg-subtle", "success-bg-subtle", "warning-bg-subtle", "info-bg-subtle", "light-bg-subtle", "dark-bg-subtle",
20444
+ // Border subtle
20445
+ "primary-border-subtle", "secondary-border-subtle", "success-border-subtle", "error-border-subtle", "warning-border-subtle", "info-border-subtle", "brand-border-subtle", "light-border-subtle", "dark-border-subtle",
20446
+ // Hover states
20447
+ "primary-hover", "secondary-hover", "light-hover", "dark-hover", "error-hover", "success-hover", "warning-hover", "info-hover",
20448
+ // Colors from scales (primary, red, green, blue, yellow)
20449
+ ...Array.from({
20450
+ length: 10
20451
+ }, ((_, i) => [ `primary-${i + 1}`, `red-${i + 1}`, `green-${i + 1}`, `blue-${i + 1}`, `yellow-${i + 1}` ])).flat(),
20452
+ // Gray scale
20453
+ ...Array.from({
20454
+ length: 10
20455
+ }, ((_, i) => `gray-${i + 1}`)),
20456
+ // Body colors
20457
+ "body-color", "heading-color",
20458
+ // Link colors
20459
+ "link-color", "link-hover-color",
20460
+ // Highlight & code
20461
+ "highlight-bg", "code-color",
20462
+ // Border colors
20463
+ "border-color", "border-color-translucent",
20464
+ // Focus ring
20465
+ "focus-border-color",
20466
+ // Form validation
20467
+ "form-valid-color", "form-valid-border-color", "form-invalid-color", "form-invalid-border-color" ]);
20468
+ for (const key of colorTokenKeys) {
20469
+ if (!(key in tokens)) continue;
20470
+ // Skip if token not present
20471
+ const value = tokens[key];
20472
+ "string" == typeof value ? (color = value,
20473
+ // Check hex first (regex is sufficient)
20474
+ COLOR_PATTERNS.hex.test(color) || (
20475
+ // Check RGB/RGBA with value validation
20476
+ COLOR_PATTERNS.rgb.test(color) || COLOR_PATTERNS.rgba.test(color) ? null !== rgbToRgb(color) :
20477
+ // Check HSL/HSLA with value validation
20478
+ (COLOR_PATTERNS.hsl.test(color) || COLOR_PATTERNS.hsla.test(color)) && null !== hslToRgb(color)) || errors.push(`Token '${key}' has invalid color format: '${value}'`)) : errors.push(`Token '${key}' must be a string, got ${typeof value}`);
20479
+ }
20480
+ var color;
20481
+ return {
20482
+ valid: 0 === errors.length,
20483
+ errors: errors,
20484
+ warnings: []
20485
+ };
20486
+ }(tokens)), options.skipAccessibility || results.push(function(tokens) {
20487
+ const errors = [], warnings = [];
20488
+ for (const check of ACCESSIBILITY_CHECKS) {
20489
+ const textColor = tokens[check.text], bgColor = tokens[check.background];
20490
+ if (!textColor || !bgColor) {
20491
+ warnings.push(`Cannot validate contrast for ${check.name}: missing tokens`);
20492
+ continue;
20493
+ }
20494
+ const contrast = validateContrastRatio(textColor, bgColor);
20495
+ if (!contrast.valid) {
20496
+ const level = 3 === contrast.requiredRatio ? "large text (AA)" : "normal text (AA)";
20497
+ errors.push(`${check.name}: contrast ratio ${contrast.ratio.toFixed(2)}:1 is below required ${contrast.requiredRatio}:1 for ${level}`);
20498
+ }
20499
+ }
20500
+ return {
20501
+ valid: 0 === errors.length,
20502
+ errors: errors,
20503
+ warnings: warnings
20504
+ };
20505
+ }(tokens));
20506
+ const allErrors = results.flatMap((r => r.errors)), allWarnings = results.flatMap((r => r.warnings)), valid = 0 === allErrors.length;
20507
+ // Log validation results
20508
+ return valid ? allWarnings.length > 0 ? logger$1.warn(`DesignTokens validation passed with ${allWarnings.length} warnings`, {
20509
+ warnings: allWarnings
20510
+ }) : logger$1.debug("DesignTokens validation passed") : logger$1.error("DesignTokens validation failed", new Error(`Validation failed with ${allErrors.length} errors and ${allWarnings.length} warnings`), {
20511
+ errors: allErrors,
20512
+ warnings: allWarnings,
20513
+ tokenCount: Object.keys(tokens).length
20514
+ }), {
20515
+ valid: valid,
20516
+ errors: allErrors,
20517
+ warnings: allWarnings
20518
+ };
20519
+ }
20520
+
20521
+ /**
20522
+ * Safely validate and merge partial tokens with defaults
20523
+ */ function validateAndMergeTokens(partialTokens) {
20524
+ const merged = {
20525
+ ...defaultTokens,
20526
+ ...partialTokens
20527
+ };
20528
+ return {
20529
+ tokens: merged,
20530
+ validation: validateDesignTokens(merged)
20531
+ };
20532
+ }
20533
+
20534
+ const logger = getLogger(), ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes: themes = {}, basePath: basePath = "/themes", cdnPath: cdnPath = null, useMinified: useMinified = !1, storageKey: storageKey = "atomix-theme", dataAttribute: dataAttribute = "data-theme", enablePersistence: enablePersistence = !0, onThemeChange: onThemeChange, onError: onError}) => {
20304
20535
  // Store callbacks in refs to avoid recreating when they change
20305
20536
  const onThemeChangeRef = useRef(onThemeChange), onErrorRef = useRef(onError);
20306
20537
  // Update ref when callback changes
@@ -20321,12 +20552,20 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
20321
20552
  // If defaultTheme is provided, use it
20322
20553
  return null != defaultTheme ? defaultTheme : "default";
20323
20554
  // Default fallback
20324
- }), [ defaultTheme, enablePersistence, storageKey ]), [currentTheme, setCurrentTheme] = useState((() => "string" == typeof initialDefaultTheme ? initialDefaultTheme : "tokens-theme")), [activeTokens, setActiveTokens] = useState((() =>
20325
- // If defaultTheme is DesignTokens, store them
20326
- defaultTheme && "string" != typeof defaultTheme ? createTokens(defaultTheme) : null)), [isLoading, setIsLoading] = useState(!1), [error, setError] = useState(null), loadedThemesRef = useRef(new Set), themePromisesRef = useRef({}), abortControllerRef = useRef(null);
20555
+ }), [ defaultTheme, enablePersistence, storageKey ]), [currentTheme, setCurrentTheme] = useState((() => "string" == typeof initialDefaultTheme ? initialDefaultTheme : "tokens-theme")), [activeTokens, setActiveTokens] = useState((() => {
20556
+ // If defaultTheme is DesignTokens, validate and store them
20557
+ if (defaultTheme && "string" != typeof defaultTheme) {
20558
+ const {tokens: tokens, validation: validation} = validateAndMergeTokens(defaultTheme);
20559
+ return validation.valid ? tokens : (logger.warn("Invalid default theme tokens, using defaults", {
20560
+ errors: validation.errors,
20561
+ warnings: validation.warnings
20562
+ }), createTokens({}));
20563
+ }
20564
+ return null;
20565
+ })), [isLoading, setIsLoading] = useState(!1), [error, setError] = useState(null), loadedThemesRef = useRef(new Set), themePromisesRef = useRef({}), abortControllerRef = useRef(null);
20327
20566
  // Handle initial DesignTokens defaultTheme
20328
20567
  useEffect((() => {
20329
- defaultTheme && "string" != typeof defaultTheme && activeTokens && !isServer() && injectCSS$1(createTheme(defaultTheme), "theme-tokens-theme");
20568
+ defaultTheme && "string" != typeof defaultTheme && activeTokens && !isServer() && injectCSS$1(createTheme(activeTokens), "theme-tokens-theme");
20330
20569
  }), [ defaultTheme, activeTokens ]), // Run when defaultTheme or activeTokens change
20331
20570
  // Apply initial theme attributes to document element
20332
20571
  useEffect((() => {
@@ -20356,19 +20595,42 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
20356
20595
  if ("string" != typeof theme) {
20357
20596
  // Check if aborted before processing
20358
20597
  if (abortController.signal.aborted) return;
20359
- // For DesignTokens, create CSS and inject it
20360
- const {createTheme: createTheme} = await Promise.resolve().then((() => index)), css = createTheme(theme), themeId = "tokens-theme";
20598
+ // Validate and merge DesignTokens
20599
+ const {tokens: validatedTokens, validation: validation} = validateAndMergeTokens(theme);
20600
+ if (!validation.valid) {
20601
+ const errorMsg = `Invalid DesignTokens provided: ${validation.errors.join(", ")}`, validationError = new Error(errorMsg);
20602
+ // Default to true
20603
+ if (logger.error("Theme validation failed", validationError, {
20604
+ errors: validation.errors,
20605
+ warnings: validation.warnings
20606
+ }), !1 !== options?.fallbackOnError) {
20607
+ logger.warn("Falling back to default theme due to validation errors");
20608
+ // Use default tokens instead
20609
+ const {tokens: defaultTokens} = validateAndMergeTokens({}), css = createTheme(defaultTokens), themeId = "tokens-theme-fallback";
20610
+ // Check if aborted before state update
20611
+ if (abortController.signal.aborted) return;
20612
+ // Remove any previously loaded theme CSS
20613
+ return removeCSS(`theme-${currentTheme}`),
20614
+ // Inject new theme CSS
20615
+ injectCSS$1(css, `theme-${themeId}`),
20616
+ // Store default tokens
20617
+ setActiveTokens(defaultTokens), setCurrentTheme(themeId), handleThemeChange(defaultTokens),
20618
+ handleError(validationError, themeId), void setIsLoading(!1);
20619
+ }
20620
+ // No fallback, throw the error
20621
+ throw validationError;
20622
+ }
20623
+ // For valid DesignTokens, create CSS and inject it
20624
+ const css = createTheme(validatedTokens), themeId = "tokens-theme";
20361
20625
  // Check if aborted after async operation
20362
20626
  if (abortController.signal.aborted) return;
20363
20627
  // Remove any previously loaded theme CSS
20364
- removeCSS(`theme-${currentTheme}`),
20365
- // Inject new theme CSS
20366
- injectCSS$1(css, `theme-${themeId}`);
20367
- // Store tokens for reference
20368
- const fullTokens = createTokens(theme);
20628
+ // Store validated tokens for reference
20369
20629
  // Check if aborted before state update
20370
- if (abortController.signal.aborted) return;
20371
- return setActiveTokens(fullTokens), setCurrentTheme(themeId), handleThemeChange(fullTokens),
20630
+ if (removeCSS(`theme-${currentTheme}`),
20631
+ // Inject new theme CSS
20632
+ injectCSS$1(css, `theme-${themeId}`), abortController.signal.aborted) return;
20633
+ return setActiveTokens(validatedTokens), setCurrentTheme(themeId), handleThemeChange(validatedTokens),
20372
20634
  void setIsLoading(!1);
20373
20635
  }
20374
20636
  // If it's a string theme name, load the associated CSS
@@ -20383,30 +20645,33 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
20383
20645
  // If previous load failed, continue with new load
20384
20646
  }
20385
20647
  // Load CSS theme
20386
- const themeLoadPromise = new Promise((async (resolve, reject) => {
20387
- try {
20388
- // Check if aborted
20389
- if (abortController.signal.aborted) return void resolve();
20390
- if (!themes[theme]) throw new Error(`Theme metadata not found for theme: ${theme}`);
20391
- {
20392
- // Build CSS path using utility function
20393
- const cssPath = buildThemePath(theme, basePath, useMinified, cdnPath);
20648
+ const themeLoadPromise = new Promise(((resolve, reject) => {
20649
+ // Start the async operation
20650
+ (async () => {
20651
+ try {
20394
20652
  // Check if aborted
20395
- if (abortController.signal.aborted) return void resolve();
20396
- // Load CSS file (using loadThemeCSS from domUtils)
20397
- const {loadThemeCSS: loadThemeCSS} = await Promise.resolve().then((() => domUtils));
20398
- // Check if aborted after async operation
20399
- if (await loadThemeCSS(cssPath, `theme-${theme}`), abortController.signal.aborted) return void resolve();
20400
- // Remove any previously loaded theme CSS
20401
- removeCSS(`theme-${String(currentTheme)}`), loadedThemesRef.current.add(theme),
20402
- setCurrentTheme(theme), setActiveTokens(null), handleThemeChange(theme), resolve();
20653
+ if (abortController.signal.aborted) return void resolve();
20654
+ if (!themes[theme]) throw new Error(`Theme metadata not found for theme: ${theme}`);
20655
+ {
20656
+ // Build CSS path using utility function
20657
+ const cssPath = buildThemePath(theme, basePath, useMinified, cdnPath);
20658
+ // Check if aborted
20659
+ if (abortController.signal.aborted) return void resolve();
20660
+ // Load CSS file (using loadThemeCSS from domUtils)
20661
+ const {loadThemeCSS: loadThemeCSS} = await Promise.resolve().then((() => domUtils));
20662
+ // Check if aborted after async operation
20663
+ if (await loadThemeCSS(cssPath, `theme-${theme}`), abortController.signal.aborted) return void resolve();
20664
+ // Remove any previously loaded theme CSS
20665
+ removeCSS(`theme-${String(currentTheme)}`), loadedThemesRef.current.add(theme),
20666
+ setCurrentTheme(theme), setActiveTokens(null), handleThemeChange(theme), resolve();
20667
+ }
20668
+ } catch (err) {
20669
+ // Don't reject if aborted
20670
+ if (abortController.signal.aborted) return void resolve();
20671
+ const error = err instanceof Error ? err : new Error(String(err));
20672
+ setError(error), handleError(error, String(theme)), reject(error);
20403
20673
  }
20404
- } catch (err) {
20405
- // Don't reject if aborted
20406
- if (abortController.signal.aborted) return void resolve();
20407
- const error = err instanceof Error ? err : new Error(String(err));
20408
- setError(error), handleError(error, String(theme)), reject(error);
20409
- }
20674
+ })();
20410
20675
  }));
20411
20676
  themePromisesRef.current[theme] = themeLoadPromise;
20412
20677
  try {
@@ -20471,6 +20736,17 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
20471
20736
  });
20472
20737
  };
20473
20738
 
20739
+ /**
20740
+ * Theme Provider
20741
+ *
20742
+ * React context provider for theme management with separated concerns.
20743
+ * Simplified version focusing on core functionality:
20744
+ * - String-based themes (CSS files)
20745
+ * - DesignTokens (dynamic themes)
20746
+ * - Persistence via localStorage
20747
+ *
20748
+ * Falls back to 'default' theme if no configuration is found.
20749
+ */
20474
20750
  /**
20475
20751
  * useTheme Hook
20476
20752
  *
@@ -20496,7 +20772,8 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
20496
20772
  * );
20497
20773
  * }
20498
20774
  * ```
20499
- */ function useTheme() {
20775
+ */
20776
+ function useTheme() {
20500
20777
  const context = useContext(ThemeContext);
20501
20778
  if (!context) throw new Error("useTheme must be used within a ThemeProvider");
20502
20779
  return {
@@ -22513,8 +22790,8 @@ function createPaletteColor(color) {
22513
22790
  * @returns Complete theme object
22514
22791
  */
22515
22792
  function createThemeObject(...options) {
22516
- // Merge all options
22517
- const mergedOptions = _reduceInstanceProperty(options).call(options, ((acc, option) => deepMerge(acc, option)), {}), palette = {
22793
+ // Merge all options by spreading them into a single object
22794
+ const mergedOptions = _reduceInstanceProperty(options).call(options, ((acc, option) => deepMerge(acc, option || {})), {}), palette = {
22518
22795
  primary: createPaletteColor(mergedOptions.palette?.primary || DEFAULT_PALETTE.primary),
22519
22796
  secondary: createPaletteColor(mergedOptions.palette?.secondary || DEFAULT_PALETTE.secondary),
22520
22797
  error: createPaletteColor(mergedOptions.palette?.error || DEFAULT_PALETTE.error),
@@ -22699,43 +22976,45 @@ function createThemeObject(...options) {
22699
22976
 
22700
22977
  case "hsl":
22701
22978
  case "hsla":
22702
- // Convert RGB to HSL (simplified)
22703
- const hsl =
22704
- /**
22979
+ {
22980
+ // Convert RGB to HSL (simplified)
22981
+ const hsl =
22982
+ /**
22705
22983
  * Convert RGB to HSL
22706
22984
  */
22707
- function(r, g, b) {
22708
- r /= 255, g /= 255, b /= 255;
22709
- const max = Math.max(r, g, b), min = Math.min(r, g, b);
22710
- let h = 0, s = 0;
22711
- const l = (max + min) / 2;
22712
- if (max !== min) {
22713
- const d = max - min;
22714
- switch (s = l > .5 ? d / (2 - max - min) : d / (max + min), max) {
22715
- case r:
22716
- h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
22717
- break;
22718
-
22719
- case g:
22720
- h = ((b - r) / d + 2) / 6;
22721
- break;
22722
-
22723
- case b:
22724
- h = ((r - g) / d + 4) / 6;
22985
+ function(r, g, b) {
22986
+ r /= 255, g /= 255, b /= 255;
22987
+ const max = Math.max(r, g, b), min = Math.min(r, g, b);
22988
+ let h = 0, s = 0;
22989
+ const l = (max + min) / 2;
22990
+ if (max !== min) {
22991
+ const d = max - min;
22992
+ switch (s = l > .5 ? d / (2 - max - min) : d / (max + min), max) {
22993
+ case r:
22994
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
22995
+ break;
22996
+
22997
+ case g:
22998
+ h = ((b - r) / d + 2) / 6;
22999
+ break;
23000
+
23001
+ case b:
23002
+ h = ((r - g) / d + 4) / 6;
23003
+ }
22725
23004
  }
23005
+ return {
23006
+ h: Math.round(360 * h),
23007
+ s: Math.round(100 * s),
23008
+ l: Math.round(100 * l)
23009
+ };
22726
23010
  }
22727
- return {
22728
- h: Math.round(360 * h),
22729
- s: Math.round(100 * s),
22730
- l: Math.round(100 * l)
22731
- };
22732
- }
22733
- /**
23011
+ /**
22734
23012
  * Theme Live Editor Component
22735
23013
  *
22736
23014
  * Allows live editing of theme properties with instant preview
22737
23015
  */ (r, g, b);
22738
- return "hsl" === format ? `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)` : `hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${a})`;
23016
+ return "hsl" === format ? `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)` : `hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${a})`;
23017
+ }
22739
23018
 
22740
23019
  default:
22741
23020
  return color;
@@ -23061,8 +23340,312 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
23061
23340
  children: "\n .atomix-theme-live-editor {\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n background: white;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n\n .editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 24px;\n border-bottom: 1px solid #e0e0e0;\n background: #f5f5f5;\n border-radius: 8px 8px 0 0;\n }\n\n .editor-header h2 {\n margin: 0;\n font-size: 20px;\n color: #333;\n }\n\n .editor-controls {\n display: flex;\n gap: 12px;\n align-items: center;\n }\n\n .history-controls,\n .mode-controls,\n .action-controls {\n display: flex;\n gap: 8px;\n }\n\n .history-button,\n .mode-button,\n .export-button,\n .copy-button {\n padding: 8px 16px;\n border: 1px solid #e0e0e0;\n background: white;\n border-radius: 4px;\n cursor: pointer;\n font-size: 14px;\n transition: all 0.2s;\n }\n\n .history-button:hover:not(:disabled),\n .mode-button:hover,\n .export-button:hover,\n .copy-button:hover {\n background: #f5f5f5;\n }\n\n .history-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .mode-button.active {\n background: #2196f3;\n color: white;\n border-color: #2196f3;\n }\n\n .export-button {\n background: #4caf50;\n color: white;\n border-color: #4caf50;\n }\n\n .copy-button {\n background: #ff9800;\n color: white;\n border-color: #ff9800;\n }\n\n .editor-content {\n display: flex;\n position: relative;\n min-height: 600px;\n }\n\n .editor-panel,\n .preview-panel {\n overflow-y: auto;\n padding: 24px;\n }\n\n .resizer {\n width: 4px;\n background: #e0e0e0;\n cursor: col-resize;\n position: relative;\n flex-shrink: 0;\n transition: background 0.2s;\n }\n\n .resizer:hover,\n .resizer.resizing {\n background: #2196f3;\n }\n\n .resizer::before {\n content: '';\n position: absolute;\n left: -2px;\n right: -2px;\n top: 0;\n bottom: 0;\n }\n\n .editor-panel h3,\n .preview-panel h3 {\n margin: 0 0 16px 0;\n font-size: 16px;\n color: #333;\n border-bottom: 2px solid #2196f3;\n padding-bottom: 8px;\n }\n\n .visual-editor {\n display: flex;\n flex-direction: column;\n gap: 24px;\n }\n\n .editor-section {\n display: flex;\n flex-direction: column;\n gap: 16px;\n }\n\n .color-format-selector {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n }\n\n .color-format-selector label {\n font-size: 14px;\n font-weight: 500;\n color: #666;\n }\n\n .color-format-selector select {\n padding: 6px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n font-size: 14px;\n background: white;\n cursor: pointer;\n }\n\n .editor-field {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .editor-field label {\n font-size: 14px;\n font-weight: 500;\n color: #666;\n }\n\n .color-input-group {\n display: flex;\n gap: 8px;\n align-items: center;\n }\n\n .color-input-group input[type=\"color\"] {\n width: 50px;\n height: 40px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n cursor: pointer;\n }\n\n .color-input-group input[type=\"text\"],\n .editor-field input[type=\"text\"],\n .editor-field input[type=\"number\"] {\n flex: 1;\n padding: 8px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n font-size: 14px;\n font-family: 'Monaco', 'Menlo', monospace;\n }\n\n .json-editor {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n\n .json-editor textarea {\n flex: 1;\n padding: 16px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n font-family: 'Monaco', 'Menlo', monospace;\n font-size: 12px;\n line-height: 1.5;\n resize: none;\n }\n\n .error-message {\n padding: 12px;\n background: #ffebee;\n color: #d32f2f;\n border-radius: 4px;\n margin-top: 8px;\n font-size: 14px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .error-dismiss {\n background: none;\n border: none;\n color: #d32f2f;\n font-size: 20px;\n cursor: pointer;\n padding: 0;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .error-dismiss:hover {\n background: rgba(211, 47, 47, 0.1);\n border-radius: 50%;\n }\n\n .preview-panel {\n border-left: 1px solid #e0e0e0;\n }\n "
23062
23341
  }) ]
23063
23342
  });
23343
+ }, DesignTokensCustomizer = ({initialTokens: initialTokens = {}, onTokensChange: onTokensChange, className: className, style: style}) => {
23344
+ // Current tokens state
23345
+ const [tokens, setTokens] = useState((() => createTokens(initialTokens))), [colorFormat, setColorFormat] = useState("hex"), [activeCategory, setActiveCategory] = useState("colors"), [cssPreview, setCssPreview] = useState("");
23346
+ // Generate CSS when tokens change
23347
+ useEffect((() => {
23348
+ const css = createTheme(tokens, {
23349
+ selector: ":root",
23350
+ prefix: "atomix-preview"
23351
+ });
23352
+ setCssPreview(css), onTokensChange?.(tokens);
23353
+ }), [ tokens, onTokensChange ]);
23354
+ // Create theme object for preview
23355
+ const previewTheme = useMemo((() => createThemeObject({
23356
+ palette: {
23357
+ primary: {
23358
+ main: tokens.primary
23359
+ },
23360
+ secondary: {
23361
+ main: tokens.secondary
23362
+ },
23363
+ error: {
23364
+ main: tokens.error
23365
+ },
23366
+ warning: {
23367
+ main: tokens.warning
23368
+ },
23369
+ info: {
23370
+ main: tokens.info
23371
+ },
23372
+ success: {
23373
+ main: tokens.success
23374
+ },
23375
+ background: {
23376
+ default: "#ffffff",
23377
+ subtle: tokens["secondary-bg-subtle"] || "#f3f4f6"
23378
+ },
23379
+ text: {
23380
+ primary: tokens["primary-text-emphasis"] || "#111827",
23381
+ secondary: tokens["secondary-text-emphasis"] || "#374151",
23382
+ disabled: tokens["disabled-text-emphasis"] || "#9ca3af"
23383
+ }
23384
+ },
23385
+ typography: {
23386
+ fontFamily: tokens["body-font-family"] || '"Roboto", sans-serif',
23387
+ fontSize: parseInt(tokens["body-font-size"] || "16")
23388
+ },
23389
+ spacing: factor => .25 * factor + "rem"
23390
+ })), [ tokens ]), updateToken = useCallback(((key, value) => {
23391
+ setTokens((prev => ({
23392
+ ...prev,
23393
+ [key]: value
23394
+ })));
23395
+ }), []), convertColorFormat = useCallback(((color, format) => {
23396
+ // Parse current color
23397
+ const temp = document.createElement("div");
23398
+ temp.style.color = color, document.body.appendChild(temp);
23399
+ const computed = window.getComputedStyle(temp).color;
23400
+ document.body.removeChild(temp);
23401
+ const rgbMatch = computed.match(/\d+/g);
23402
+ if (!rgbMatch || rgbMatch.length < 3) return color;
23403
+ const r = parseInt(rgbMatch[0] || "0", 10), g = parseInt(rgbMatch[1] || "0", 10), b = parseInt(rgbMatch[2] || "0", 10), a = rgbMatch[3] ? parseFloat(rgbMatch[3]) : 1;
23404
+ switch (format) {
23405
+ case "hex":
23406
+ return `#${[ r, g, b ].map((x => x.toString(16).padStart(2, "0"))).join("")}`;
23407
+
23408
+ case "rgb":
23409
+ return `rgb(${r}, ${g}, ${b})`;
23410
+
23411
+ case "rgba":
23412
+ return `rgba(${r}, ${g}, ${b}, ${a})`;
23413
+
23414
+ case "hsl":
23415
+ case "hsla":
23416
+ {
23417
+ const hsl =
23418
+ // RGB to HSL conversion
23419
+ function(r, g, b) {
23420
+ r /= 255, g /= 255, b /= 255;
23421
+ const max = Math.max(r, g, b), min = Math.min(r, g, b);
23422
+ let h = 0, s = 0;
23423
+ const l = (max + min) / 2;
23424
+ if (max !== min) {
23425
+ const d = max - min;
23426
+ switch (s = l > .5 ? d / (2 - max - min) : d / (max + min), max) {
23427
+ case r:
23428
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
23429
+ break;
23430
+
23431
+ case g:
23432
+ h = ((b - r) / d + 2) / 6;
23433
+ break;
23434
+
23435
+ case b:
23436
+ h = ((r - g) / d + 4) / 6;
23437
+ }
23438
+ }
23439
+ return {
23440
+ h: Math.round(360 * h),
23441
+ s: Math.round(100 * s),
23442
+ l: Math.round(100 * l)
23443
+ };
23444
+ }
23445
+ // Export functions
23446
+ (r, g, b);
23447
+ return "hsl" === format ? `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)` : `hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${a})`;
23448
+ }
23449
+
23450
+ default:
23451
+ return color;
23452
+ }
23453
+ }), []), exportTokens = useCallback((() => {
23454
+ const dataStr = JSON.stringify(tokens, null, 2), dataUri = "data:application/json;charset=utf-8," + encodeURIComponent(dataStr), linkElement = document.createElement("a");
23455
+ linkElement.setAttribute("href", dataUri), linkElement.setAttribute("download", "design-tokens.json"),
23456
+ linkElement.click();
23457
+ }), [ tokens ]), exportTheme = useCallback((() => {
23458
+ const themeCss = createTheme(tokens), dataUri = "data:text/css;charset=utf-8," + encodeURIComponent(themeCss), linkElement = document.createElement("a");
23459
+ linkElement.setAttribute("href", dataUri), linkElement.setAttribute("download", "theme.css"),
23460
+ linkElement.click();
23461
+ }), [ tokens ]), copyToClipboard = useCallback((() => {
23462
+ navigator.clipboard?.writeText(JSON.stringify(tokens, null, 2));
23463
+ }), [ tokens ]), resetToDefaults = useCallback((() => {
23464
+ setTokens(defaultTokens);
23465
+ }), []), loadTokensFromFile = useCallback((event => {
23466
+ const file = event.target.files?.[0];
23467
+ if (!file) return;
23468
+ const reader = new FileReader;
23469
+ reader.onload = e => {
23470
+ try {
23471
+ const content = e.target?.result, mergedTokens = createTokens(JSON.parse(content));
23472
+ setTokens(mergedTokens);
23473
+ } catch (error) {
23474
+ console.error("Failed to load tokens:", error), alert("Invalid JSON file. Please select a valid design tokens JSON file.");
23475
+ }
23476
+ }, reader.readAsText(file);
23477
+ }), []), tokenCategories = {
23478
+ colors: {
23479
+ label: "Colors",
23480
+ tokens: [
23481
+ // Base colors
23482
+ "primary", "secondary", "success", "info", "warning", "error", "light", "dark",
23483
+ // RGB versions
23484
+ "primary-rgb", "secondary-rgb", "success-rgb", "info-rgb", "warning-rgb", "error-rgb", "light-rgb", "dark-rgb",
23485
+ // Gray scale
23486
+ "gray-1", "gray-2", "gray-3", "gray-4", "gray-5", "gray-6", "gray-7", "gray-8", "gray-9", "gray-10",
23487
+ // Primary scale
23488
+ "primary-1", "primary-2", "primary-3", "primary-4", "primary-5", "primary-6", "primary-7", "primary-8", "primary-9", "primary-10",
23489
+ // Text emphasis
23490
+ "primary-text-emphasis", "secondary-text-emphasis", "tertiary-text-emphasis", "disabled-text-emphasis", "invert-text-emphasis", "brand-text-emphasis", "error-text-emphasis", "success-text-emphasis", "warning-text-emphasis", "info-text-emphasis", "light-text-emphasis", "dark-text-emphasis",
23491
+ // Background subtle
23492
+ "primary-bg-subtle", "secondary-bg-subtle", "tertiary-bg-subtle", "invert-bg-subtle", "brand-bg-subtle", "error-bg-subtle", "success-bg-subtle", "warning-bg-subtle", "info-bg-subtle", "light-bg-subtle", "dark-bg-subtle",
23493
+ // Border subtle
23494
+ "primary-border-subtle", "secondary-border-subtle", "success-border-subtle", "error-border-subtle", "warning-border-subtle", "info-border-subtle", "brand-border-subtle", "light-border-subtle", "dark-border-subtle",
23495
+ // Hover states
23496
+ "primary-hover", "secondary-hover", "light-hover", "dark-hover", "error-hover", "success-hover", "warning-hover", "info-hover",
23497
+ // Gradients
23498
+ "primary-gradient", "secondary-gradient", "light-gradient", "dark-gradient", "success-gradient", "info-gradient", "warning-gradient", "error-gradient", "gradient" ]
23499
+ },
23500
+ typography: {
23501
+ label: "Typography",
23502
+ tokens: [ "font-sans-serif", "font-monospace", "body-font-family", "body-font-size", "body-font-weight", "body-line-height", "body-color", "body-bg", "heading-color", "font-size-xl", "font-size-2xl", "display-1", "font-weight-light", "font-weight-normal", "font-weight-medium", "font-weight-semibold", "font-weight-bold", "font-weight-heavy", "font-weight-black", "line-height-base", "line-height-sm", "line-height-lg", "letter-spacing-h1", "letter-spacing-h2", "letter-spacing-h3", "letter-spacing-h4", "letter-spacing-h5", "letter-spacing-h6", "link-color", "link-color-rgb", "link-decoration", "link-hover-color", "link-hover-color-rgb", "highlight-bg", "code-color" ]
23503
+ },
23504
+ spacing: {
23505
+ label: "Spacing",
23506
+ tokens: [ "spacing-0", "spacing-1", "spacing-px-6", "spacing-2", "spacing-px-10", "spacing-3", "spacing-px-14", "spacing-4", "spacing-5", "spacing-px-22", "spacing-6", "spacing-7", "spacing-px-30", "spacing-8", "spacing-9", "spacing-10", "spacing-11", "spacing-12", "spacing-14", "spacing-16", "spacing-20", "spacing-24", "spacing-28", "spacing-32", "spacing-36", "spacing-40", "spacing-44", "spacing-48", "spacing-52", "spacing-56", "spacing-60", "spacing-64", "spacing-72", "spacing-80", "spacing-90", "spacing-200" ]
23507
+ },
23508
+ shadows: {
23509
+ label: "Shadows",
23510
+ tokens: [ "box-shadow", "box-shadow-xs", "box-shadow-sm", "box-shadow-lg", "box-shadow-xl", "box-shadow-inset" ]
23511
+ },
23512
+ borders: {
23513
+ label: "Borders",
23514
+ tokens: [ "border-width", "border-style", "border-color", "border-color-translucent", "border-radius", "border-radius-sm", "border-radius-lg", "border-radius-xl", "border-radius-xxl", "border-radius-2xl", "border-radius-3xl", "border-radius-4xl", "border-radius-pill", "focus-border-color", "focus-ring-width", "focus-ring-offset", "focus-ring-opacity", "form-valid-color", "form-valid-border-color", "form-invalid-color", "form-invalid-border-color" ]
23515
+ },
23516
+ transitions: {
23517
+ label: "Transitions",
23518
+ tokens: [ "transition-duration-fast", "transition-duration-base", "transition-duration-slow", "transition-duration-slower", "easing-base", "easing-ease-in-out", "easing-ease-out", "easing-ease-in", "easing-ease-linear", "transition-fast", "transition-base", "transition-slow" ]
23519
+ },
23520
+ zindex: {
23521
+ label: "Z-Index",
23522
+ tokens: [ "z-n1", "z-0", "z-1", "z-2", "z-3", "z-4", "z-5", "z-dropdown", "z-sticky", "z-fixed", "z-modal", "z-popover", "z-tooltip", "z-drawer" ]
23523
+ },
23524
+ breakpoints: {
23525
+ label: "Breakpoints",
23526
+ tokens: [ "breakpoint-xs", "breakpoint-sm", "breakpoint-md", "breakpoint-lg", "breakpoint-xl", "breakpoint-xxl" ]
23527
+ }
23528
+ };
23529
+ // Update token value
23530
+ return jsxs("div", {
23531
+ className: `design-tokens-customizer ${className || ""}`,
23532
+ style: style,
23533
+ children: [ jsxs("div", {
23534
+ className: "customizer-header",
23535
+ children: [ jsx("h2", {
23536
+ children: "Interactive Theme Customizer"
23537
+ }), jsxs("div", {
23538
+ className: "customizer-controls",
23539
+ children: [ jsxs("select", {
23540
+ value: colorFormat,
23541
+ onChange: e => setColorFormat(e.target.value),
23542
+ children: [ jsx("option", {
23543
+ value: "hex",
23544
+ children: "HEX"
23545
+ }), jsx("option", {
23546
+ value: "rgb",
23547
+ children: "RGB"
23548
+ }), jsx("option", {
23549
+ value: "rgba",
23550
+ children: "RGBA"
23551
+ }), jsx("option", {
23552
+ value: "hsl",
23553
+ children: "HSL"
23554
+ }), jsx("option", {
23555
+ value: "hsla",
23556
+ children: "HSLA"
23557
+ }) ]
23558
+ }), jsx("button", {
23559
+ onClick: resetToDefaults,
23560
+ children: "Reset to Defaults"
23561
+ }), jsxs("label", {
23562
+ className: "file-input-button",
23563
+ children: [ "Load Tokens", jsx("input", {
23564
+ type: "file",
23565
+ accept: ".json",
23566
+ onChange: loadTokensFromFile,
23567
+ style: {
23568
+ display: "none"
23569
+ }
23570
+ }) ]
23571
+ }), jsx("button", {
23572
+ onClick: copyToClipboard,
23573
+ children: "Copy Tokens"
23574
+ }), jsx("button", {
23575
+ onClick: exportTokens,
23576
+ children: "Export Tokens"
23577
+ }), jsx("button", {
23578
+ onClick: exportTheme,
23579
+ children: "Export Theme CSS"
23580
+ }) ]
23581
+ }) ]
23582
+ }), jsxs("div", {
23583
+ className: "customizer-content",
23584
+ children: [ jsx("div", {
23585
+ className: "customizer-sidebar",
23586
+ children: Object.entries(tokenCategories).map((([key, category]) => jsx("button", {
23587
+ className: "category-button " + (activeCategory === key ? "active" : ""),
23588
+ onClick: () => setActiveCategory(key),
23589
+ children: category.label
23590
+ }, key)))
23591
+ }), jsxs("div", {
23592
+ className: "customizer-editor",
23593
+ children: [ jsx("h3", {
23594
+ children: tokenCategories[activeCategory].label
23595
+ }), jsx("div", {
23596
+ className: "tokens-grid",
23597
+ children: tokenCategories[activeCategory].tokens.map((tokenKey => {
23598
+ var _context;
23599
+ const value = tokens[tokenKey] || "", isColor = _includesInstanceProperty(tokenKey).call(tokenKey, "color") || _includesInstanceProperty(tokenKey).call(tokenKey, "bg") || _includesInstanceProperty(tokenKey).call(tokenKey, "gradient") || _includesInstanceProperty(_context = [ "primary", "secondary", "success", "info", "warning", "error", "light", "dark" ]).call(_context, tokenKey) || tokenKey.match(/^(gray|primary|red|green|blue|yellow)-\d+$/);
23600
+ return jsxs("div", {
23601
+ className: "token-item",
23602
+ children: [ jsx("label", {
23603
+ children: tokenKey
23604
+ }), isColor ? jsxs("div", {
23605
+ className: "color-input-group",
23606
+ children: [ jsx("input", {
23607
+ type: "color",
23608
+ value: value.startsWith("#") ? value : convertColorFormat(value, "hex"),
23609
+ onChange: e => updateToken(tokenKey, e.target.value)
23610
+ }), jsx("input", {
23611
+ type: "text",
23612
+ value: convertColorFormat(value, colorFormat),
23613
+ onChange: e => {
23614
+ const converted = convertColorFormat(e.target.value, "hex");
23615
+ updateToken(tokenKey, converted);
23616
+ }
23617
+ }) ]
23618
+ }) : jsx("input", {
23619
+ type: "text",
23620
+ value: value,
23621
+ onChange: e => updateToken(tokenKey, e.target.value)
23622
+ }) ]
23623
+ }, tokenKey);
23624
+ }))
23625
+ }) ]
23626
+ }), jsxs("div", {
23627
+ className: "customizer-preview",
23628
+ children: [ jsx("h3", {
23629
+ children: "Live Preview"
23630
+ }), jsx("style", {
23631
+ children: cssPreview
23632
+ }), jsx(ThemePreview, {
23633
+ theme: previewTheme,
23634
+ showDetails: !1,
23635
+ showPalette: !0,
23636
+ showTypography: !0,
23637
+ showSpacing: !0
23638
+ }) ]
23639
+ }) ]
23640
+ }), jsx("style", {
23641
+ children: "\n .design-tokens-customizer {\n display: flex;\n flex-direction: column;\n height: 100vh;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n\n .customizer-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 24px;\n border-bottom: 1px solid #e0e0e0;\n background: #f5f5f5;\n }\n\n .customizer-header h2 {\n margin: 0;\n font-size: 24px;\n color: #333;\n }\n\n .customizer-controls {\n display: flex;\n gap: 8px;\n align-items: center;\n }\n\n .customizer-controls select,\n .customizer-controls button {\n padding: 8px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n }\n\n .customizer-controls button:hover,\n .file-input-button:hover {\n background: #f0f0f0;\n }\n\n .file-input-button {\n padding: 8px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n font-size: 14px;\n display: inline-block;\n }\n\n .customizer-content {\n display: flex;\n flex: 1;\n overflow: hidden;\n }\n\n .customizer-sidebar {\n width: 200px;\n border-right: 1px solid #e0e0e0;\n padding: 16px;\n background: #fafafa;\n overflow-y: auto;\n }\n\n .category-button {\n display: block;\n width: 100%;\n padding: 12px;\n margin-bottom: 8px;\n border: none;\n background: white;\n border-radius: 4px;\n cursor: pointer;\n text-align: left;\n font-size: 14px;\n }\n\n .category-button:hover,\n .category-button.active {\n background: #e0e0e0;\n }\n\n .customizer-editor {\n flex: 1;\n padding: 24px;\n overflow-y: auto;\n }\n\n .customizer-editor h3 {\n margin-top: 0;\n margin-bottom: 16px;\n color: #333;\n }\n\n .tokens-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n }\n\n .token-item {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .token-item label {\n font-size: 14px;\n font-weight: 500;\n color: #666;\n }\n\n .color-input-group {\n display: flex;\n gap: 8px;\n align-items: center;\n }\n\n .color-input-group input[type=\"color\"] {\n width: 50px;\n height: 40px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n cursor: pointer;\n }\n\n .color-input-group input[type=\"text\"],\n .token-item input[type=\"text\"] {\n flex: 1;\n padding: 8px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n font-size: 14px;\n font-family: 'Monaco', 'Menlo', monospace;\n }\n\n .customizer-preview {\n width: 400px;\n border-left: 1px solid #e0e0e0;\n padding: 24px;\n overflow-y: auto;\n background: #fafafa;\n }\n\n .customizer-preview h3 {\n margin-top: 0;\n margin-bottom: 16px;\n color: #333;\n }\n "
23642
+ }) ]
23643
+ });
23064
23644
  };
23065
23645
 
23646
+ /**
23647
+ * Design Tokens Customizer Component
23648
+ */
23066
23649
  /**
23067
23650
  * Theme Adapter
23068
23651
  *
@@ -23073,7 +23656,8 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
23073
23656
  *
23074
23657
  * @param tokens - DesignTokens object
23075
23658
  * @returns CSS variables object compatible with Theme.cssVars
23076
- */ function designTokensToCSSVars(tokens) {
23659
+ */
23660
+ function designTokensToCSSVars(tokens) {
23077
23661
  const cssVars = {};
23078
23662
  return Object.entries(tokens).forEach((([key, value]) => {
23079
23663
  void 0 !== value && (cssVars[`--atomix-${key}`] = String(value));
@@ -23327,6 +23911,7 @@ class RTLManager {
23327
23911
 
23328
23912
  const themeImport = Object.freeze( Object.defineProperty({
23329
23913
  __proto__: null,
23914
+ DesignTokensCustomizer: DesignTokensCustomizer,
23330
23915
  RTLManager: RTLManager,
23331
23916
  ThemeApplicator: ThemeApplicator,
23332
23917
  ThemeComparator: ThemeComparator,
@@ -23914,20 +24499,53 @@ function quickTheme(name, primaryColor, secondaryColor) {
23914
24499
  /**
23915
24500
  * Create a dark theme variant from a light theme
23916
24501
  */ function createDarkVariant(lightTheme) {
23917
- return extendTheme(lightTheme, {
24502
+ // We'll extend the theme by merging the new properties with the existing theme
24503
+ const darkVariant = {
23918
24504
  name: `${lightTheme.name} Dark`,
23919
24505
  palette: {
23920
24506
  mode: "dark",
24507
+ primary: lightTheme.palette?.primary,
24508
+ // Preserve original primary
24509
+ secondary: lightTheme.palette?.secondary,
24510
+ // Preserve original secondary
24511
+ error: lightTheme.palette?.error,
24512
+ // Preserve original error
24513
+ warning: lightTheme.palette?.warning,
24514
+ // Preserve original warning
24515
+ info: lightTheme.palette?.info,
24516
+ // Preserve original info
24517
+ success: lightTheme.palette?.success,
24518
+ // Preserve original success
23921
24519
  background: {
23922
24520
  default: "#121212",
24521
+ paper: "#1e1e1e",
24522
+ // Added missing paper property
23923
24523
  subtle: "#1e1e1e"
23924
24524
  },
23925
24525
  text: {
23926
24526
  primary: "#ffffff",
23927
- secondary: "rgba(255, 255, 255, 0.7)"
24527
+ secondary: "rgba(255, 255, 255, 0.7)",
24528
+ disabled: "rgba(255, 255, 255, 0.38)"
23928
24529
  }
23929
24530
  }
23930
- });
24531
+ };
24532
+ // Create a new theme by extending the light theme with the dark variant
24533
+ return {
24534
+ ...lightTheme,
24535
+ ...darkVariant,
24536
+ palette: {
24537
+ ...lightTheme.palette,
24538
+ ...darkVariant.palette,
24539
+ background: {
24540
+ ...lightTheme.palette?.background,
24541
+ ...darkVariant.palette?.background
24542
+ },
24543
+ text: {
24544
+ ...lightTheme.palette?.text,
24545
+ ...darkVariant.palette?.text
24546
+ }
24547
+ }
24548
+ };
23931
24549
  }
23932
24550
 
23933
24551
  /**
@@ -24003,5 +24621,5 @@ const atomix = {
24003
24621
  types: types
24004
24622
  };
24005
24623
 
24006
- export { ACCORDION, ATOMIX_GLASS, AVATAR, AVATAR_GROUP, Accordion, AnimatedChart, AreaChart, AtomixGlass, AtomixLogo, Avatar, AvatarGroup, BADGE, BADGE_CSS_VARS, BLOCK, BREADCRUMB, BUTTON, BUTTON_CSS_VARS, BUTTON_GROUP, Badge, BarChart, Block, Breadcrumb, BubbleChart, Button, ButtonGroup, CALLOUT, CARD, CARD_CSS_VARS, CHART, CHECKBOX_CSS_VARS, CLASS_PREFIX, CODE_SNIPPET, COMPONENT_CSS_VARS, COUNTDOWN, Callout, CandlestickChart, Card, Chart, ChartRenderer, Checkbox, ColorModeToggle, Container, Countdown, DATA_TABLE_CLASSES, DATA_TABLE_SELECTORS, DATEPICKER, DEFAULT_ATOMIX_FONTS, DOTS, DROPDOWN, DROPDOWN_CSS_VARS, DataTable, DatePicker, DonutChart, Dropdown, EDGE_PANEL, EdgePanel, ElevationCard, FOOTER, FORM, FORM_GROUP, Footer, FooterLink, FooterSection, FooterSocialLink, Form, FormGroup, FunnelChart, GLASS_CONTAINER, GaugeChart, Grid, GridCol, HERO, HeatmapChart, Hero, INPUT, INPUT_CSS_VARS, Icon, Input, LIST, LIST_GROUP, LineChart, List, ListGroup, MESSAGES, MODAL, MODAL_CSS_VARS, MasonryGrid, MasonryGridItem, MegaMenu, MegaMenuColumn, MegaMenuLink, Menu, MenuDivider, MenuItem, Messages, Modal, MultiAxisChart, NAV, NAVBAR, Nav, NavDropdown, NavItem, Navbar, PAGINATION_DEFAULTS, PHOTOVIEWER, POPOVER, PROGRESS, PROGRESS_CSS_VARS, Pagination, PhotoViewer, PieChart, Popover, ProductReview, Progress, RADIO, RADIO_CSS_VARS, RATING, RIVER, RTLManager, RadarChart, Radio, Rating, River, Row, SECTION_INTRO, SELECT, SIDE_MENU, SIZES, SLIDER, SPINNER, STEPS, ScatterChart, SectionIntro, Select, SideMenu, SideMenuItem, SideMenuList, Slider, Spinner, Steps, TAB, TABS_CSS_VARS, TESTIMONIAL, TEXTAREA, THEME_COLORS, THEME_NAMING, TODO, TOGGLE, TOOLTIP, TOOLTIP_CSS_VARS, Tabs, Testimonial, Textarea, ThemeApplicator, ThemeComparator, ThemeContext, ThemeErrorBoundary, ThemeInspector, ThemeLiveEditor, ThemePreview, ThemeProvider, ThemeValidator, Todo, Toggle, Tooltip, TreemapChart, UPLOAD, Upload, VIDEO_PLAYER, VideoPlayer, WaterfallChart, applyCSSVariables, applyCSSVarsToStyle, applyComponentTheme, applyPartStyles, applyTheme, camelToKebab, clearThemes, composables, constants, createCSSVarStyle, createDarkVariant, createDebugAttrs, createFontPreloadLink, createPartProps, createSlotComponent, createSlotProps, createTheme, createThemeRegistry, createTokens, cssVarsToStyle, deepMerge, atomix as default, defaultTokens, defineConfig, designTokensToCSSVars, exportTheme, extendTheme, extractComponentName, extractYouTubeId, generateCSSVariableName, generateCSSVariables$1 as generateCSSVariables, generateCSSVariablesForSelector, generateClassName, generateComponentCSSVars, generateFontPreloadTags, generateUUID, getAllThemes, getCSSVariable, getComponentCSSVars, getComponentThemeValue, getPartStyles, getTheme, getThemeApplicator, getThemeCount, getThemeIds, getThemeMetadata, hasCustomization, hasTheme, importTheme, injectCSS$1 as injectCSS, injectTheme, isCSSInjected, isDesignTokens, isSlot, isValidCSSVariableName, isYouTubeUrl, mapSCSSTokensToCSSVars, mergeCSSVars, mergeClassNames, mergeComponentProps, mergePartStyles, mergeSlots, mergeTheme, normalizeThemeTokens, preloadFonts, quickTheme, registerTheme, removeCSS, removeCSSVariables, removeTheme, renderSlot, sliderConstants, supportsDarkMode, theme, themePropertyToCSSVar, themeToCSS, types, unregisterTheme, useAccordion, useAtomixGlass, useBadge, useBarChart, useBlock, useBreadcrumb, useButton, useCard, useChartData, useChartInteraction, useChartScale, useCheckbox, useComponentCustomization, useComponentDefaultProps, useComponentTheme, useDataTable, useEdgePanel, useForm, useFormGroup, useGlassContainer, useHero, useHistory, useInput, useLineChart, useMergedProps, useModal$1 as useModal, useNav, useNavDropdown, useNavItem, useNavbar, usePagination, usePieChart, useRadio, useRiver, useSelect, useSideMenu, useSideMenuItem, useSlider, useSlot, useSpinner, useTextarea, useTheme, useThemeTokens, useTodo, utils, validateTheme };
24624
+ export { ACCORDION, ATOMIX_GLASS, AVATAR, AVATAR_GROUP, Accordion, AnimatedChart, AreaChart, AtomixGlass, AtomixLogo, Avatar, AvatarGroup, BADGE, BADGE_CSS_VARS, BLOCK, BREADCRUMB, BUTTON, BUTTON_CSS_VARS, BUTTON_GROUP, Badge, BarChart, Block, Breadcrumb, BubbleChart, Button, ButtonGroup, CALLOUT, CARD, CARD_CSS_VARS, CHART, CHECKBOX_CSS_VARS, CLASS_PREFIX, CODE_SNIPPET, COMPONENT_CSS_VARS, COUNTDOWN, Callout, CandlestickChart, Card, Chart, ChartRenderer, Checkbox, ColorModeToggle, Container, Countdown, DATA_TABLE_CLASSES, DATA_TABLE_SELECTORS, DATEPICKER, DEFAULT_ATOMIX_FONTS, DOTS, DROPDOWN, DROPDOWN_CSS_VARS, DataTable, DatePicker, DesignTokensCustomizer, DonutChart, Dropdown, EDGE_PANEL, EdgePanel, ElevationCard, FOOTER, FORM, FORM_GROUP, Footer, FooterLink, FooterSection, FooterSocialLink, Form, FormGroup, FunnelChart, GaugeChart, Grid, GridCol, HERO, HeatmapChart, Hero, INPUT, INPUT_CSS_VARS, Icon, Input, LIST, LIST_GROUP, LineChart, List, ListGroup, MESSAGES, MODAL, MODAL_CSS_VARS, MasonryGrid, MasonryGridItem, MegaMenu, MegaMenuColumn, MegaMenuLink, Menu, MenuDivider, MenuItem, Messages, Modal, MultiAxisChart, NAV, NAVBAR, Nav, NavDropdown, NavItem, Navbar, PAGINATION_DEFAULTS, PHOTOVIEWER, POPOVER, PROGRESS, PROGRESS_CSS_VARS, Pagination, PhotoViewer, PieChart, Popover, ProductReview, Progress, RADIO, RADIO_CSS_VARS, RATING, RIVER, RTLManager, RadarChart, Radio, Rating, River, Row, SECTION_INTRO, SELECT, SIDE_MENU, SIZES, SLIDER, SPINNER, STEPS, ScatterChart, SectionIntro, Select, SideMenu, SideMenuItem, SideMenuList, Slider, Spinner, Steps, TAB, TABS_CSS_VARS, TESTIMONIAL, TEXTAREA, THEME_COLORS, THEME_NAMING, TODO, TOGGLE, TOOLTIP, TOOLTIP_CSS_VARS, Tabs, Testimonial, Textarea, ThemeApplicator, ThemeComparator, ThemeContext, ThemeErrorBoundary, ThemeInspector, ThemeLiveEditor, ThemePreview, ThemeProvider, ThemeValidator, Todo, Toggle, Tooltip, TreemapChart, UPLOAD, Upload, VIDEO_PLAYER, VideoPlayer, WaterfallChart, applyCSSVariables, applyCSSVarsToStyle, applyComponentTheme, applyPartStyles, applyTheme, camelToKebab, clearThemes, composables, constants, createCSSVarStyle, createDarkVariant, createDebugAttrs, createFontPreloadLink, createPartProps, createSlotComponent, createSlotProps, createTheme, createThemeRegistry, createTokens, cssVarsToStyle, deepMerge, atomix as default, defaultTokens, defineConfig, designTokensToCSSVars, exportTheme, extendTheme, extractComponentName, extractYouTubeId, generateCSSVariableName, generateCSSVariables$1 as generateCSSVariables, generateCSSVariablesForSelector, generateClassName, generateComponentCSSVars, generateFontPreloadTags, generateUUID, getAllThemes, getCSSVariable, getComponentCSSVars, getComponentThemeValue, getPartStyles, getTheme, getThemeApplicator, getThemeCount, getThemeIds, getThemeMetadata, hasCustomization, hasTheme, importTheme, injectCSS$1 as injectCSS, injectTheme, isCSSInjected, isDesignTokens, isSlot, isValidCSSVariableName, isYouTubeUrl, mapSCSSTokensToCSSVars, mergeCSSVars, mergeClassNames, mergeComponentProps, mergePartStyles, mergeSlots, mergeTheme, normalizeThemeTokens, preloadFonts, quickTheme, registerTheme, removeCSS, removeCSSVariables, removeTheme, renderSlot, sliderConstants, supportsDarkMode, theme, themePropertyToCSSVar, themeToCSS, types, unregisterTheme, useAccordion, useAtomixGlass, useBadge, useBarChart, useBlock, useBreadcrumb, useCard, useChartData, useChartInteraction, useChartScale, useComponentCustomization, useComponentDefaultProps, useComponentTheme, useDataTable, useEdgePanel, useForm, useFormGroup, useGlassContainer, useHero, useHistory, useInput, useLineChart, useMergedProps, useModal$1 as useModal, useNav, useNavDropdown, useNavItem, useNavbar, usePagination, usePieChart, useRadio, useRiver, useSelect, useSideMenu, useSideMenuItem, useSlider, useSlot, useSpinner, useTextarea, useTheme, useThemeTokens, useTodo, utils, validateTheme };
24007
24625
  //# sourceMappingURL=index.esm.js.map