@shohojdhara/atomix 0.3.12 → 0.3.14

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 (155) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +2 -0
  3. package/dist/atomix.css +101 -88
  4. package/dist/atomix.css.map +1 -1
  5. package/dist/atomix.min.css +5 -15258
  6. package/dist/atomix.min.css.map +1 -1
  7. package/dist/charts.d.ts +1 -1
  8. package/dist/charts.js +17 -19
  9. package/dist/charts.js.map +1 -1
  10. package/dist/core.d.ts +41 -11
  11. package/dist/core.js +55 -41
  12. package/dist/core.js.map +1 -1
  13. package/dist/forms.d.ts +28 -11
  14. package/dist/forms.js +25 -24
  15. package/dist/forms.js.map +1 -1
  16. package/dist/heavy.d.ts +1 -1
  17. package/dist/heavy.js +32 -25
  18. package/dist/heavy.js.map +1 -1
  19. package/dist/index.d.ts +122 -46
  20. package/dist/index.esm.js +865 -200
  21. package/dist/index.esm.js.map +1 -1
  22. package/dist/index.js +870 -204
  23. package/dist/index.js.map +1 -1
  24. package/dist/index.min.js +1 -1
  25. package/dist/index.min.js.map +1 -1
  26. package/dist/theme.d.ts +27 -2
  27. package/dist/theme.js +721 -108
  28. package/dist/theme.js.map +1 -1
  29. package/package.json +1 -1
  30. package/scripts/atomix-cli.js +610 -1111
  31. package/scripts/cli/component-generator.js +610 -0
  32. package/scripts/cli/documentation-sync.js +542 -0
  33. package/scripts/cli/interactive-init.js +84 -288
  34. package/scripts/cli/mappings.js +211 -0
  35. package/scripts/cli/migration-tools.js +95 -288
  36. package/scripts/cli/template-manager.js +107 -0
  37. package/scripts/cli/templates/README.md +123 -0
  38. package/scripts/cli/templates/composable-templates.js +149 -0
  39. package/scripts/cli/templates/config-templates.js +126 -0
  40. package/scripts/cli/templates/index.js +95 -0
  41. package/scripts/cli/templates/project-templates.js +214 -0
  42. package/scripts/cli/templates/react-templates.js +261 -0
  43. package/scripts/cli/templates/scss-templates.js +156 -0
  44. package/scripts/cli/templates/storybook-templates.js +236 -0
  45. package/scripts/cli/templates/testing-templates.js +45 -0
  46. package/scripts/cli/templates/token-templates.js +447 -0
  47. package/scripts/cli/templates/types-templates.js +133 -0
  48. package/scripts/cli/templates-original-backup.js +1655 -0
  49. package/scripts/cli/templates.js +35 -0
  50. package/scripts/cli/templates_backup.js +684 -0
  51. package/scripts/cli/theme-bridge.js +20 -14
  52. package/scripts/cli/token-manager.js +150 -77
  53. package/scripts/cli/utils.js +37 -25
  54. package/src/components/Accordion/Accordion.stories.tsx +5 -5
  55. package/src/components/Accordion/Accordion.test.tsx +57 -0
  56. package/src/components/Accordion/Accordion.tsx +4 -0
  57. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +41 -44
  58. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +1 -1
  59. package/src/components/AtomixGlass/stories/Examples.stories.tsx +37 -37
  60. package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -2
  61. package/src/components/AtomixGlass/stories/Playground.stories.tsx +50 -51
  62. package/src/components/Avatar/Avatar.stories.tsx +26 -26
  63. package/src/components/Badge/Badge.stories.tsx +31 -31
  64. package/src/components/Badge/Badge.test.tsx +51 -0
  65. package/src/components/Badge/Badge.tsx +20 -1
  66. package/src/components/Block/Block.stories.tsx +5 -5
  67. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +1 -1
  68. package/src/components/Breadcrumb/Breadcrumb.tsx +2 -2
  69. package/src/components/Button/Button.stories.tsx +13 -13
  70. package/src/components/Button/Button.tsx +4 -4
  71. package/src/components/Button/ButtonGroup.stories.tsx +2 -2
  72. package/src/components/Button/README.md +5 -0
  73. package/src/components/Callout/Callout.stories.tsx +11 -11
  74. package/src/components/Callout/Callout.test.tsx +10 -10
  75. package/src/components/Callout/Callout.tsx +7 -7
  76. package/src/components/Callout/README.md +9 -8
  77. package/src/components/Card/Card.tsx +2 -2
  78. package/src/components/Chart/Chart.stories.tsx +6 -6
  79. package/src/components/Chart/Chart.tsx +1 -1
  80. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +1 -1
  81. package/src/components/DataTable/DataTable.tsx +14 -12
  82. package/src/components/DatePicker/DatePicker.stories.tsx +6 -6
  83. package/src/components/Dropdown/Dropdown.stories.tsx +4 -4
  84. package/src/components/Form/Checkbox.stories.tsx +3 -3
  85. package/src/components/Form/Checkbox.tsx +4 -2
  86. package/src/components/Form/Form.stories.tsx +3 -3
  87. package/src/components/Form/FormGroup.stories.tsx +1 -1
  88. package/src/components/Form/Input.stories.tsx +28 -16
  89. package/src/components/Form/Input.test.tsx +59 -0
  90. package/src/components/Form/Input.tsx +97 -95
  91. package/src/components/Form/Radio.stories.tsx +94 -94
  92. package/src/components/Form/Radio.tsx +2 -2
  93. package/src/components/Form/Select.stories.tsx +4 -4
  94. package/src/components/Form/Select.tsx +2 -2
  95. package/src/components/Form/Textarea.stories.tsx +22 -7
  96. package/src/components/Form/Textarea.test.tsx +45 -0
  97. package/src/components/Form/Textarea.tsx +88 -86
  98. package/src/components/List/List.stories.tsx +2 -2
  99. package/src/components/Modal/Modal.stories.tsx +4 -4
  100. package/src/components/Navigation/Navbar/Navbar.stories.tsx +5 -5
  101. package/src/components/Navigation/Navbar/Navbar.tsx +1 -1
  102. package/src/components/Navigation/README.md +1 -1
  103. package/src/components/Pagination/Pagination.stories.tsx +5 -2
  104. package/src/components/Pagination/Pagination.tsx +1 -1
  105. package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -10
  106. package/src/components/Popover/Popover.stories.tsx +1 -1
  107. package/src/components/ProductReview/ProductReview.tsx +1 -1
  108. package/src/components/Progress/Progress.tsx +46 -46
  109. package/src/components/Rating/Rating.stories.tsx +4 -4
  110. package/src/components/Rating/Rating.tsx +8 -8
  111. package/src/components/Slider/Slider.stories.tsx +63 -63
  112. package/src/components/Spinner/Spinner.stories.tsx +2 -2
  113. package/src/components/Spinner/Spinner.test.tsx +35 -0
  114. package/src/components/Spinner/Spinner.tsx +9 -2
  115. package/src/components/Testimonial/Testimonial.stories.tsx +1 -1
  116. package/src/components/Toggle/Toggle.stories.tsx +32 -9
  117. package/src/components/Toggle/Toggle.test.tsx +91 -0
  118. package/src/components/Toggle/Toggle.tsx +44 -27
  119. package/src/components/Tooltip/Tooltip.tsx +1 -1
  120. package/src/layouts/Grid/Grid.stories.tsx +49 -49
  121. package/src/layouts/MasonryGrid/MasonryGrid.stories.tsx +2 -2
  122. package/src/lib/composables/useAccordion.ts +12 -3
  123. package/src/lib/composables/useBreadcrumb.ts +2 -2
  124. package/src/lib/composables/useCallout.ts +7 -7
  125. package/src/lib/composables/useNavbar.ts +1 -1
  126. package/src/lib/constants/components.ts +1 -1
  127. package/src/lib/storybook/InteractiveDemo.tsx +113 -0
  128. package/src/lib/storybook/PreviewContainer.tsx +36 -0
  129. package/src/lib/storybook/VariantsGrid.tsx +21 -0
  130. package/src/lib/storybook/index.ts +3 -0
  131. package/src/lib/theme/core/createThemeObject.ts +9 -5
  132. package/src/lib/theme/devtools/CLI.ts +155 -0
  133. package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +213 -0
  134. package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +566 -0
  135. package/src/lib/theme/devtools/LiveEditor.tsx +2 -1
  136. package/src/lib/theme/devtools/index.ts +3 -0
  137. package/src/lib/theme/errors/errors.ts +8 -0
  138. package/src/lib/theme/runtime/ThemeProvider.tsx +117 -57
  139. package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +305 -0
  140. package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +588 -0
  141. package/src/lib/theme/utils/__tests__/themeValidation.test.ts +264 -0
  142. package/src/lib/theme/utils/index.ts +1 -0
  143. package/src/lib/theme/utils/themeValidation.ts +501 -0
  144. package/src/lib/theme-tools.ts +32 -3
  145. package/src/lib/types/components.ts +81 -26
  146. package/src/lib/utils/themeNaming.ts +1 -1
  147. package/src/styles/06-components/_components.atomix-glass.scss +14 -15
  148. package/src/styles/06-components/_components.callout.scss +29 -33
  149. package/src/styles/06-components/_index.scss +1 -1
  150. package/src/styles/99-utilities/_utilities.display.scss +14 -3
  151. package/src/styles/99-utilities/_utilities.flex.scss +10 -10
  152. package/src/styles/99-utilities/_utilities.text.scss +28 -8
  153. package/scripts/cli/__tests__/cli-commands.test.js +0 -204
  154. package/scripts/cli/__tests__/utils.test.js +0 -201
  155. package/scripts/cli/__tests__/vitest.config.js +0 -26
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
  }
@@ -1581,7 +1581,12 @@ function useAccordion(initialProps) {
1581
1581
  panelHeight: panelHeight
1582
1582
  },
1583
1583
  toggle: () => {
1584
- defaultProps.disabled || (isControlled ? defaultProps.onOpenChange && defaultProps.onOpenChange(!isOpen) : setInternalOpen((prev => !prev)));
1584
+ if (!defaultProps.disabled) {
1585
+ const nextOpen = !isOpen;
1586
+ isControlled || setInternalOpen(nextOpen), defaultProps.onOpenChange?.(nextOpen),
1587
+ // Call legacy handlers
1588
+ nextOpen ? defaultProps.onOpen?.() : defaultProps.onClose?.();
1589
+ }
1585
1590
  },
1586
1591
  updatePanelHeight: updatePanelHeight,
1587
1592
  panelRef: panelRef,
@@ -1825,7 +1830,13 @@ const {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2)
1825
1830
  */ GlassFilterComponent.displayName = "GlassFilter";
1826
1831
 
1827
1832
  // Memoize component to prevent unnecessary re-renders
1828
- const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevProps.id === nextProps.id && prevProps.displacementScale === nextProps.displacementScale && prevProps.aberrationIntensity === nextProps.aberrationIntensity && prevProps.mode === nextProps.mode && prevProps.shaderMapUrl === nextProps.shaderMapUrl && prevProps.blurAmount === nextProps.blurAmount)), sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({children: children, className: className = "", style: style, displacementScale: displacementScale = 25, blurAmount: blurAmount = .0625, saturation: saturation = 180, aberrationIntensity: aberrationIntensity = 2, mouseOffset: mouseOffset = {
1833
+ const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevProps.id === nextProps.id && prevProps.displacementScale === nextProps.displacementScale && prevProps.aberrationIntensity === nextProps.aberrationIntensity && prevProps.mode === nextProps.mode && prevProps.shaderMapUrl === nextProps.shaderMapUrl && prevProps.blurAmount === nextProps.blurAmount));
1834
+
1835
+ // Module-level counter for deterministic ID generation
1836
+ let idCounter = 0;
1837
+
1838
+ // Module-level shared shader cache with LRU eviction
1839
+ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({children: children, className: className = "", style: style, displacementScale: displacementScale = 25, blurAmount: blurAmount = .0625, saturation: saturation = 180, aberrationIntensity: aberrationIntensity = 2, mouseOffset: mouseOffset = {
1829
1840
  x: 0,
1830
1841
  y: 0
1831
1842
  }, globalMousePosition: globalMousePosition = {
@@ -1836,10 +1847,8 @@ const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevP
1836
1847
  height: 0
1837
1848
  }, onClick: onClick, mode: mode = "standard", effectiveDisableEffects: effectiveDisableEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", enableLiquidBlur: enableLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
1838
1849
  // Generate a stable, deterministic ID for SSR compatibility
1839
- // Use a counter-based approach to avoid hydration mismatches
1840
- const [filterId] = useState((() =>
1841
- // Use a simple counter for deterministic IDs
1842
- "undefined" == typeof window ? `atomix-glass-filter-ssr-${Math.random().toString(36).substring(2, 11)}` : `atomix-glass-filter-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`)), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null);
1850
+ // Use a module-level counter that's consistent across server and client
1851
+ const filterId = useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null);
1843
1852
  // Lazy load shader utilities only when shader mode is needed
1844
1853
  useEffect((() => {
1845
1854
  "shader" === mode ?
@@ -1880,9 +1889,9 @@ const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevP
1880
1889
  width: glassSize.width,
1881
1890
  height: glassSize.height,
1882
1891
  fragment: selectedShader
1883
- });
1884
- // Use requestIdleCallback if available for non-blocking generation
1885
- const generate = () => {
1892
+ }),
1893
+ // Defer shader generation with longer delay to avoid blocking
1894
+ setTimeout((() => {
1886
1895
  const url = shaderGeneratorRef.current?.updateShader() || "";
1887
1896
  ((key, url) => {
1888
1897
  // Evict oldest entries if at capacity
@@ -1901,20 +1910,15 @@ const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevP
1901
1910
  // Development mode: log cache size
1902
1911
  "undefined" != typeof process && "production" === process.env?.NODE_ENV || sharedShaderCache.size;
1903
1912
  })(cacheKey, url), setShaderMapUrl(url);
1904
- };
1905
- "undefined" != typeof requestIdleCallback ? requestIdleCallback(generate, {
1906
- timeout: 1e3
1907
- }) :
1908
- // Fallback to setTimeout for browsers without requestIdleCallback
1909
- setTimeout(generate, 0);
1913
+ }), 100);
1910
1914
  } catch (error) {
1911
1915
  console.warn("AtomixGlassContainer: Error generating shader map", error), setShaderMapUrl("");
1912
1916
  } else
1913
1917
  // Shader utils not loaded yet, retry after a short delay
1914
1918
  shaderDebounceTimeoutRef.current = setTimeout(generateShader, 100);
1915
1919
  };
1916
- // Debounce with 300ms delay
1917
- shaderDebounceTimeoutRef.current = setTimeout(generateShader, 300);
1920
+ // Debounce with 500ms delay to reduce frequency
1921
+ shaderDebounceTimeoutRef.current = setTimeout(generateShader, 500);
1918
1922
  } else
1919
1923
  // Not in shader mode, clear URL
1920
1924
  setShaderMapUrl("");
@@ -1981,7 +1985,7 @@ const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevP
1981
1985
  backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
1982
1986
  };
1983
1987
  }
1984
- }), [ filterId, liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveDisableEffects, enableLiquidBlur ]), containerVars = useMemo((() => {
1988
+ }), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveDisableEffects, enableLiquidBlur ]), containerVars = useMemo((() => {
1985
1989
  try {
1986
1990
  // Safe extraction of mouse offset values
1987
1991
  const mx = mouseOffset && "number" == typeof mouseOffset.x && !isNaN(mouseOffset.x) ? mouseOffset.x : 0, my = mouseOffset && "number" == typeof mouseOffset.y && !isNaN(mouseOffset.y) ? mouseOffset.y : 0;
@@ -2070,7 +2074,6 @@ const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevP
2070
2074
  });
2071
2075
  }));
2072
2076
 
2073
- // Module-level shared shader cache with LRU eviction
2074
2077
  AtomixGlassContainer.displayName = "AtomixGlassContainer";
2075
2078
 
2076
2079
  // Singleton instance
@@ -2818,14 +2821,16 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
2818
2821
  });
2819
2822
  }
2820
2823
 
2821
- 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}) => {
2824
+ 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}) => {
2822
2825
  // Generate unique IDs for accessibility
2823
2826
  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({
2824
2827
  defaultOpen: defaultOpen,
2825
2828
  disabled: disabled,
2826
2829
  iconPosition: iconPosition,
2827
2830
  isOpen: controlledOpen,
2828
- onOpenChange: onOpenChange
2831
+ onOpenChange: onOpenChange,
2832
+ onOpen: onOpen,
2833
+ onClose: onClose
2829
2834
  }), defaultIcon = jsx("i", {
2830
2835
  className: "c-accordion__icon",
2831
2836
  "aria-hidden": "true",
@@ -3304,7 +3309,7 @@ function useBadge(initialProps) {
3304
3309
 
3305
3310
  AvatarGroup.displayName = "AvatarGroup";
3306
3311
 
3307
- const Badge = memo((({label: label, variant: variant = "primary", size: size = "md", disabled: disabled = !1, icon: icon, className: className = "", glass: glass, style: style}) => {
3312
+ 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}) => {
3308
3313
  const {generateBadgeClass: generateBadgeClass} = useBadge({
3309
3314
  variant: variant,
3310
3315
  size: size,
@@ -3317,6 +3322,7 @@ const Badge = memo((({label: label, variant: variant = "primary", size: size =
3317
3322
  }), badgeElement = jsxs("span", {
3318
3323
  className: badgeClass,
3319
3324
  "aria-disabled": disabled,
3325
+ "aria-label": ariaLabel,
3320
3326
  ref: ref,
3321
3327
  style: style,
3322
3328
  children: [ icon && jsx("span", {
@@ -3324,6 +3330,13 @@ const Badge = memo((({label: label, variant: variant = "primary", size: size =
3324
3330
  children: icon
3325
3331
  }), jsx("span", {
3326
3332
  children: label
3333
+ }), onRemove && jsx("button", {
3334
+ type: "button",
3335
+ className: "c-badge__close",
3336
+ onClick: onRemove,
3337
+ "aria-label": "Remove badge",
3338
+ disabled: disabled,
3339
+ children: "×"
3327
3340
  }) ]
3328
3341
  });
3329
3342
  if (glass) {
@@ -3451,7 +3464,7 @@ const useBlock = () => ({
3451
3464
  * ```
3452
3465
  */ Block.displayName = "Block";
3453
3466
 
3454
- const Breadcrumb = memo((({items: items, divider: divider, className: className = "", ariaLabel: ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style}) => {
3467
+ const Breadcrumb = memo((({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style}) => {
3455
3468
  const breadcrumbClasses = [ BREADCRUMB.CLASSES.BASE, className ].filter(Boolean).join(" ");
3456
3469
  return jsx("nav", {
3457
3470
  "aria-label": ariaLabel,
@@ -3548,7 +3561,7 @@ function useButton(initialProps) {
3548
3561
 
3549
3562
  Breadcrumb.displayName = "Breadcrumb";
3550
3563
 
3551
- const Spinner = memo((({size: size = "md", variant: variant = "primary", fullscreen: fullscreen = !1, className: className = "", style: style, glass: glass}) => {
3564
+ const Spinner = memo((({size: size = "md", variant: variant = "primary", fullscreen: fullscreen = !1, className: className = "", style: style, glass: glass, "aria-label": ariaLabel, role: role = "status"}) => {
3552
3565
  const {generateSpinnerClass: generateSpinnerClass} = useSpinner({
3553
3566
  size: size,
3554
3567
  variant: variant,
@@ -3561,10 +3574,11 @@ const Spinner = memo((({size: size = "md", variant: variant = "primary", fullsc
3561
3574
  }), spinnerContent = jsx("div", {
3562
3575
  className: spinnerClass,
3563
3576
  style: style,
3564
- role: "status",
3577
+ role: role,
3578
+ "aria-label": ariaLabel || "Loading",
3565
3579
  children: jsx("span", {
3566
3580
  className: SPINNER.VISUALLY_HIDDEN,
3567
- children: "Loading..."
3581
+ children: ariaLabel || "Loading..."
3568
3582
  })
3569
3583
  });
3570
3584
  if (glass) {
@@ -3616,7 +3630,7 @@ class ThemeNaming {
3616
3630
  * Convert kebab-case to camelCase for JavaScript properties
3617
3631
  * @param str - String to convert
3618
3632
  */ static kebabToCamel(str) {
3619
- return str.replace(/-([a-z])/g, (g => g[1].toUpperCase()));
3633
+ return str.replace(/-([a-z])/g, (g => g[1]?.toUpperCase() ?? ""));
3620
3634
  }
3621
3635
  /**
3622
3636
  * Create a CSS variable name
@@ -3677,7 +3691,7 @@ class ThemeNaming {
3677
3691
 
3678
3692
  ThemeNaming.prefix = "atomix";
3679
3693
 
3680
- 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) => {
3694
+ 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) => {
3681
3695
  const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href && !isDisabled), iconElement = iconName ? jsx(Icon, {
3682
3696
  name: iconName,
3683
3697
  size: iconSize
@@ -4203,7 +4217,7 @@ var includes$3 = getBuiltInPrototypeMethod$3("String", "includes"), isPrototypeO
4203
4217
  const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
4204
4218
  var own = it.includes;
4205
4219
  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;
4206
- })), 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}) => {
4220
+ })), 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}) => {
4207
4221
  const {generateCalloutClass: generateCalloutClass, handleClose: handleClose} =
4208
4222
  /**
4209
4223
  * Callout state and functionality
@@ -4214,8 +4228,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
4214
4228
  // Default callout properties
4215
4229
  const defaultProps = {
4216
4230
  variant: "primary",
4217
- oneLine: !1,
4218
- toast: !1,
4231
+ compact: !1,
4232
+ isToast: !1,
4219
4233
  glass: !1,
4220
4234
  ...initialProps
4221
4235
  };
@@ -4226,8 +4240,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
4226
4240
  */ return {
4227
4241
  defaultProps: defaultProps,
4228
4242
  generateCalloutClass: props => {
4229
- const {variant: variant = defaultProps.variant, oneLine: oneLine = defaultProps.oneLine, toast: toast = defaultProps.toast, glass: glass = defaultProps.glass, className: className = ""} = props;
4230
- return `c-callout ${variant ? `c-callout--${variant}` : ""} ${oneLine ? "c-callout--oneline" : ""} ${toast ? "c-callout--toast" : ""} ${glass ? "c-callout--glass" : ""} ${className}`.trim();
4243
+ const {variant: variant = defaultProps.variant, compact: compact = defaultProps.compact, isToast: isToast = defaultProps.isToast, glass: glass = defaultProps.glass, className: className = ""} = props;
4244
+ return `c-callout ${variant ? `c-callout--${variant}` : ""} ${compact ? "c-callout--compact" : ""} ${isToast ? "c-callout--toast" : ""} ${glass ? "c-callout--glass" : ""} ${className}`.trim();
4231
4245
  },
4232
4246
  handleClose: handler => () => {
4233
4247
  handler && handler();
@@ -4238,8 +4252,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
4238
4252
  * Callout component for displaying important messages, notifications, or alerts
4239
4253
  */ ({
4240
4254
  variant: variant,
4241
- oneLine: oneLine,
4242
- toast: toast,
4255
+ compact: compact,
4256
+ isToast: isToast,
4243
4257
  glass: glass,
4244
4258
  className: className,
4245
4259
  style: style
@@ -4249,7 +4263,7 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
4249
4263
  role: "region"
4250
4264
  };
4251
4265
  // For toast notifications or alerts, use appropriate role and live region
4252
- return toast ? (baseAttributes.role = "alert", baseAttributes["aria-live"] = "polite") : _includesInstanceProperty(_context = [ "warning", "error" ]).call(_context, variant) ? (baseAttributes.role = "alert",
4266
+ return isToast ? (baseAttributes.role = "alert", baseAttributes["aria-live"] = "polite") : _includesInstanceProperty(_context = [ "warning", "error" ]).call(_context, variant) ? (baseAttributes.role = "alert",
4253
4267
  baseAttributes["aria-live"] = "assertive") : _includesInstanceProperty(_context2 = [ "info", "success" ]).call(_context2, variant) && (baseAttributes.role = "status",
4254
4268
  baseAttributes["aria-live"] = "polite"), baseAttributes;
4255
4269
  }, calloutContent = jsxs(Fragment, {
@@ -4295,8 +4309,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
4295
4309
  return jsx("div", {
4296
4310
  className: generateCalloutClass({
4297
4311
  variant: variant,
4298
- oneLine: oneLine,
4299
- toast: toast,
4312
+ compact: compact,
4313
+ isToast: isToast,
4300
4314
  glass: glass,
4301
4315
  className: className
4302
4316
  }),
@@ -4318,8 +4332,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
4318
4332
  return jsx("div", {
4319
4333
  className: generateCalloutClass({
4320
4334
  variant: variant,
4321
- oneLine: oneLine,
4322
- toast: toast,
4335
+ compact: compact,
4336
+ isToast: isToast,
4323
4337
  glass: glass,
4324
4338
  className: className
4325
4339
  }),
@@ -4346,7 +4360,7 @@ onClick: onClick, onHover: onHover, onFocus: onFocus, href: href, target: target
4346
4360
  // Glass
4347
4361
  glass: glass,
4348
4362
  // Accessibility
4349
- role: role, ariaLabel: ariaLabel, ariaDescribedBy: ariaDescribedBy, tabIndex: tabIndex,
4363
+ role: role, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, tabIndex: tabIndex,
4350
4364
  // Styling
4351
4365
  className: className = "", style: style, ...rest}, ref) => {
4352
4366
  // Determine if card is clickable/interactive
@@ -5887,7 +5901,7 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
5887
5901
  tabIndex: 0,
5888
5902
  ...props,
5889
5903
  children: [ (title || subtitle || showToolbar) && jsxs("div", {
5890
- className: `${CHART.HEADER_CLASS} u-d-flex u-justify-between u-align-items-start u-gap-4`,
5904
+ className: `${CHART.HEADER_CLASS} u-flex u-justify-between u-items-start u-gap-4`,
5891
5905
  children: [ jsxs("div", {
5892
5906
  className: `${CHART.HEADER_CONTENT_CLASS} u-flex-1`,
5893
5907
  children: [ title && jsx("h3", {
@@ -9197,7 +9211,7 @@ const DOTS = "...", range = (start, end) => {
9197
9211
  "aria-hidden": "true"
9198
9212
  })
9199
9213
  })
9200
- }))), 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}) => {
9214
+ }))), 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}) => {
9201
9215
  const {paginationRange: paginationRange, goToPage: goToPage, nextPage: nextPage, prevPage: prevPage, firstPage: firstPage, lastPage: lastPage} = usePagination({
9202
9216
  currentPage: currentPage,
9203
9217
  totalPages: totalPages,
@@ -9364,7 +9378,7 @@ function useCheckbox(initialProps) {
9364
9378
 
9365
9379
  /**
9366
9380
  * Checkbox - A component for checkbox inputs
9367
- */ 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}) => {
9381
+ */ 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, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, onClick: onClick, glass: glass}) => {
9368
9382
  const {generateCheckboxClass: generateCheckboxClass, checkboxRef: checkboxRef} = useCheckbox({
9369
9383
  indeterminate: indeterminate,
9370
9384
  disabled: disabled,
@@ -9385,6 +9399,7 @@ function useCheckbox(initialProps) {
9385
9399
  className: "c-checkbox__input",
9386
9400
  checked: checked,
9387
9401
  onChange: onChange,
9402
+ onClick: onClick,
9388
9403
  disabled: disabled,
9389
9404
  required: required,
9390
9405
  id: id,
@@ -9673,7 +9688,7 @@ const DataTable = memo((({data: data, columns: columns, className: className, s
9673
9688
  }), []), handleDrop = useCallback(((e, dropIndex) => {
9674
9689
  if (e.preventDefault(), null !== dragStartIndex && dragStartIndex !== dropIndex && onColumnReorder) {
9675
9690
  const newOrder = [ ...visibleColumns.map((col => col.key)) ], [removed] = newOrder.splice(dragStartIndex, 1);
9676
- newOrder.splice(dropIndex, 0, removed), onColumnReorder(newOrder);
9691
+ removed && (newOrder.splice(dropIndex, 0, removed), onColumnReorder(newOrder));
9677
9692
  }
9678
9693
  setDragStartIndex(null), setDragOverIndex(null);
9679
9694
  }), [ dragStartIndex, visibleColumns, onColumnReorder ]), handleExport = useCallback((format => {
@@ -9983,7 +9998,7 @@ const DataTable = memo((({data: data, columns: columns, className: className, s
9983
9998
  showFirstLastButtons: !0,
9984
9999
  showPrevNextButtons: !0,
9985
10000
  size: "sm",
9986
- ariaLabel: "Data table pagination",
10001
+ "aria-label": "Data table pagination",
9987
10002
  className: "c-data-table__pagination"
9988
10003
  })
9989
10004
  }) ]
@@ -10967,7 +10982,7 @@ function useInput(initialProps) {
10967
10982
  * Input - A component for text input fields
10968
10983
  */ FormGroup.displayName = "FormGroup";
10969
10984
 
10970
- 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) => {
10985
+ 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) => {
10971
10986
  const {generateInputClass: generateInputClass} = useInput({
10972
10987
  size: size,
10973
10988
  variant: variant,
@@ -10987,6 +11002,7 @@ const Input = memo( forwardRef((({type: type = "text", value: value, onChange:
10987
11002
  type: type,
10988
11003
  className: inputClass,
10989
11004
  value: value,
11005
+ defaultValue: defaultValue,
10990
11006
  onChange: onChange,
10991
11007
  onBlur: onBlur,
10992
11008
  onFocus: onFocus,
@@ -11241,7 +11257,7 @@ function useHero(initialProps) {
11241
11257
  backdrop: !1,
11242
11258
  closeOnOutsideClick: !0,
11243
11259
  closeOnEscape: !0,
11244
- ariaLabel: "Main navigation",
11260
+ "aria-label": "Main navigation",
11245
11261
  ...initialProps
11246
11262
  }, [isExpanded, setIsExpanded] = useState(defaultProps.expanded || !1);
11247
11263
  // Local expanded state for when not controlled externally
@@ -12043,7 +12059,7 @@ function useTodo(initialProps) {
12043
12059
  items: [],
12044
12060
  divider: BREADCRUMB.DEFAULTS.DIVIDER,
12045
12061
  className: "",
12046
- ariaLabel: "Breadcrumb",
12062
+ "aria-label": "Breadcrumb",
12047
12063
  ...initialOptions
12048
12064
  },
12049
12065
  generateBreadcrumbClass: options => {
@@ -12376,21 +12392,21 @@ function useSlider(options) {
12376
12392
  const [interaction, setInteraction] = useState({
12377
12393
  hoveredIndex: null,
12378
12394
  selectedIndex: null
12379
- }), handlePointHover = useCallback((index => {
12380
- setInteraction((prev => ({
12381
- ...prev,
12382
- hoveredIndex: index
12383
- })));
12384
- }), []), handlePointClick = useCallback((index => {
12385
- setInteraction((prev => ({
12386
- ...prev,
12387
- selectedIndex: prev.selectedIndex === index ? null : index
12388
- })));
12389
- }), []);
12395
+ });
12390
12396
  return {
12391
12397
  interaction: interaction,
12392
- handlePointHover: handlePointHover,
12393
- handlePointClick: handlePointClick,
12398
+ handlePointHover: useCallback((index => {
12399
+ setInteraction((prev => ({
12400
+ ...prev,
12401
+ hoveredIndex: index
12402
+ })));
12403
+ }), []),
12404
+ handlePointClick: useCallback((index => {
12405
+ setInteraction((prev => ({
12406
+ ...prev,
12407
+ selectedIndex: prev.selectedIndex === index ? null : index
12408
+ })));
12409
+ }), []),
12394
12410
  clearInteraction: useCallback((() => {
12395
12411
  setInteraction({
12396
12412
  hoveredIndex: null,
@@ -12442,7 +12458,7 @@ const composablesImport = Object.freeze( Object.defineProperty({
12442
12458
  useTodo: useTodo
12443
12459
  }, Symbol.toStringTag, {
12444
12460
  value: "Module"
12445
- })), 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}) => {
12461
+ })), 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}) => {
12446
12462
  const {generateSelectClass: generateSelectClass} = useSelect({
12447
12463
  size: size,
12448
12464
  disabled: disabled,
@@ -12590,7 +12606,7 @@ const composablesImport = Object.freeze( Object.defineProperty({
12590
12606
  /**
12591
12607
  * Radio - A component for radio button inputs
12592
12608
  */
12593
- 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}) => {
12609
+ 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}) => {
12594
12610
  const {generateRadioClass: generateRadioClass} = useRadio({
12595
12611
  disabled: disabled,
12596
12612
  invalid: invalid,
@@ -12648,7 +12664,7 @@ Radio.displayName = "Radio";
12648
12664
  /**
12649
12665
  * Textarea - A component for multiline text input
12650
12666
  */
12651
- 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) => {
12667
+ 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) => {
12652
12668
  const {generateTextareaClass: generateTextareaClass} = useTextarea({
12653
12669
  size: size,
12654
12670
  variant: variant,
@@ -12666,6 +12682,7 @@ const Textarea = memo( forwardRef((({value: value, onChange: onChange, onBlur:
12666
12682
  ref: ref,
12667
12683
  className: textareaClass,
12668
12684
  value: value,
12685
+ defaultValue: defaultValue,
12669
12686
  onChange: onChange,
12670
12687
  onBlur: onBlur,
12671
12688
  onFocus: onFocus,
@@ -14208,7 +14225,7 @@ NavItem.displayName = "NavItem";
14208
14225
  * </Navbar>
14209
14226
  * ```
14210
14227
  */
14211
- 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) => {
14228
+ 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) => {
14212
14229
  const {generateNavbarClass: generateNavbarClass, generateContainerStyle: generateContainerStyle, generateCollapseClass: generateCollapseClass} = useNavbar({
14213
14230
  position: position,
14214
14231
  collapsible: collapsible,
@@ -16286,7 +16303,7 @@ const PopoverContext = createContext({
16286
16303
  /**
16287
16304
  * Hook for managing rating component state and interactions
16288
16305
  */
16289
- 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) => {
16306
+ 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) => {
16290
16307
  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}) => {
16291
16308
  // Determine if component is in controlled mode
16292
16309
  const isControlled = void 0 !== onChange, [internalValue, setInternalValue] = useState(value), [hoverValue, setHoverValue] = useState(null), [focusedIndex, setFocusedIndex] = useState(null), currentValue = isControlled ? value : internalValue, handleMouseEnter = useCallback((starValue => {
@@ -16381,7 +16398,7 @@ const Rating = forwardRef((({value: valueProp = 0, defaultValue: defaultValue,
16381
16398
  return () => {
16382
16399
  ratingInstance.current && ratingInstance.current.destroy();
16383
16400
  };
16384
- }), [ useVanillaJS, valueProp, defaultValue, maxValue, allowHalf, readOnly, size, color, onChange ]),
16401
+ }), [ useVanillaJS, valueProp, defaultValue, maxValue, allowHalf, readOnly, size, variant, onChange ]),
16385
16402
  // Update vanilla JS implementation when props change
16386
16403
  useEffect((() => {
16387
16404
  useVanillaJS && ratingInstance.current && ratingInstance.current.updateOptions({
@@ -16390,11 +16407,11 @@ const Rating = forwardRef((({value: valueProp = 0, defaultValue: defaultValue,
16390
16407
  allowHalf: allowHalf,
16391
16408
  readOnly: readOnly,
16392
16409
  size: size,
16393
- color: color
16410
+ variant: variant
16394
16411
  });
16395
- }), [ useVanillaJS, valueProp, defaultValue, maxValue, allowHalf, readOnly, size, color ]);
16412
+ }), [ useVanillaJS, valueProp, defaultValue, maxValue, allowHalf, readOnly, size, variant ]);
16396
16413
  // Determine CSS classes
16397
- const ratingClasses = [ "c-rating", "sm" === size ? RATING.CLASSES.SMALL : "", "lg" === size ? RATING.CLASSES.LARGE : "", color ? `c-rating--${color}` : "", className ].filter(Boolean).join(" ");
16414
+ const ratingClasses = [ "c-rating", "sm" === size ? RATING.CLASSES.SMALL : "", "lg" === size ? RATING.CLASSES.LARGE : "", variant ? `c-rating--${variant}` : "", className ].filter(Boolean).join(" ");
16398
16415
  // If using vanilla JS, just render the container
16399
16416
  if (useVanillaJS) return jsx("div", {
16400
16417
  className: ratingClasses,
@@ -16418,7 +16435,7 @@ const Rating = forwardRef((({value: valueProp = 0, defaultValue: defaultValue,
16418
16435
  const stars = [], roundedValue = allowHalf ? Math.floor(2 * effectiveValue) / 2 : Math.round(effectiveValue), componentId = id || `rating-${Math.random().toString(36).substring(2, 9)}`;
16419
16436
  for (let i = 1; i <= maxValue; i++) {
16420
16437
  // For half-star support
16421
- 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}`;
16438
+ 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}`;
16422
16439
  stars.push(jsx("div", {
16423
16440
  id: starId,
16424
16441
  className: starClass,
@@ -16498,8 +16515,8 @@ const Rating = forwardRef((({value: valueProp = 0, defaultValue: defaultValue,
16498
16515
  * <Rating value={3} onChange={handleRatingChange} />
16499
16516
  *
16500
16517
  * @example
16501
- * // Read-only with custom color
16502
- * <Rating value={4.5} readOnly color="warning" />
16518
+ * // Read-only with custom variant
16519
+ * <Rating value={4.5} readOnly variant="warning" />
16503
16520
  *
16504
16521
  * @example
16505
16522
  * // With half-star support
@@ -16573,7 +16590,7 @@ const ProductReview = ({productName: productName, productImage: productImage, in
16573
16590
  allowHalf: allowHalf,
16574
16591
  maxValue: maxRating,
16575
16592
  size: "lg",
16576
- color: ratingColor
16593
+ variant: ratingColor
16577
16594
  }), jsx("span", {
16578
16595
  className: "c-rating__value",
16579
16596
  children: rating > 0 ? rating.toFixed(1) : "Select a rating"
@@ -16611,7 +16628,7 @@ ProductReview.displayName = "ProductReview";
16611
16628
  /**
16612
16629
  * Hook for managing Progress component state and behavior
16613
16630
  */
16614
- 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) => {
16631
+ 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) => {
16615
16632
  const {progressValue: progressValue, progressStyle: progressStyle, progressClasses: progressClasses} = (({value: value, variant: variant = "primary", size: size = "md", className: className = ""}) => {
16616
16633
  // Clamp value between 0 and 100
16617
16634
  const progressValue = Math.min(Math.max(value, 0), 100), baseClass = "c-progress";
@@ -17301,28 +17318,29 @@ Todo.displayName = "Todo";
17301
17318
  /**
17302
17319
  * Toggle component for switching between two states
17303
17320
  */
17304
- const Toggle = ({initialOn: initialOn = !1, onToggleOn: onToggleOn, onToggleOff: onToggleOff, disabled: disabled = !1, className: className = "", style: style, glass: glass}) => {
17305
- const [isOn, setIsOn] = useState(initialOn), handleClick = () => {
17321
+ const Toggle = ({checked: controlledChecked, defaultChecked: defaultChecked = !1, onChange: onChange, disabled: disabled = !1, className: className = "", style: style, glass: glass, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy}) => {
17322
+ const isControlled = void 0 !== controlledChecked, [internalChecked, setInternalChecked] = useState(defaultChecked), isChecked = isControlled ? controlledChecked : internalChecked, handleClick = useCallback((() => {
17306
17323
  if (disabled) return;
17307
- const newState = !isOn;
17308
- setIsOn(newState), newState ? onToggleOn && onToggleOn() : onToggleOff && onToggleOff();
17309
- }, toggleContent = jsx("div", {
17310
- className: `c-toggle ${isOn ? TOGGLE.CLASSES.IS_ON : ""} ${disabled ? "is-disabled" : ""} ${className}`,
17324
+ const nextChecked = !isChecked;
17325
+ isControlled || setInternalChecked(nextChecked), onChange?.(nextChecked);
17326
+ }), [ disabled, isChecked, isControlled, onChange ]), toggleClass = [ "c-toggle", isChecked && TOGGLE.CLASSES.IS_ON, disabled && "is-disabled", className ].filter(Boolean).join(" "), toggleContent = jsx("div", {
17327
+ className: toggleClass,
17311
17328
  style: style,
17312
17329
  onClick: handleClick,
17313
17330
  onKeyDown: e => {
17314
17331
  disabled || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), handleClick());
17315
17332
  },
17316
17333
  role: "switch",
17317
- "aria-checked": isOn,
17334
+ "aria-checked": isChecked,
17318
17335
  tabIndex: disabled ? -1 : 0,
17319
17336
  "aria-disabled": disabled,
17337
+ "aria-label": ariaLabel,
17338
+ "aria-describedby": ariaDescribedBy,
17320
17339
  children: jsx("div", {
17321
17340
  className: "c-toggle__switch"
17322
17341
  })
17323
17342
  });
17324
- // Handle toggle click
17325
- if (glass) {
17343
+ if (glass) {
17326
17344
  // Default glass settings for toggles
17327
17345
  const defaultGlassProps = {
17328
17346
  displacementScale: 60,
@@ -17468,7 +17486,7 @@ const Tooltip = memo((({content: content, children: children, position: positio
17468
17486
  delay: delay
17469
17487
  });
17470
17488
  return jsxs("div", {
17471
- className: "u-position-relative u-d-inline-block",
17489
+ className: "u-position-relative u-inline-block",
17472
17490
  style: style,
17473
17491
  ...wrapperProps,
17474
17492
  children: [ jsx("div", {
@@ -19110,6 +19128,14 @@ function createTokens(overrides) {
19110
19128
  ThemeErrorCode.INVALID_THEME_NAME = "INVALID_THEME_NAME",
19111
19129
  /** CSS injection failed */
19112
19130
  ThemeErrorCode.CSS_INJECTION_FAILED = "CSS_INJECTION_FAILED",
19131
+ /** Invalid color format */
19132
+ ThemeErrorCode.INVALID_COLOR_FORMAT = "INVALID_COLOR_FORMAT",
19133
+ /** Missing required token */
19134
+ ThemeErrorCode.MISSING_REQUIRED_TOKEN = "MISSING_REQUIRED_TOKEN",
19135
+ /** Accessibility contrast violation */
19136
+ ThemeErrorCode.CONTRAST_VIOLATION = "CONTRAST_VIOLATION",
19137
+ /** Invalid token type */
19138
+ ThemeErrorCode.INVALID_TOKEN_TYPE = "INVALID_TOKEN_TYPE",
19113
19139
  /** Unknown error */
19114
19140
  ThemeErrorCode.UNKNOWN_ERROR = "UNKNOWN_ERROR";
19115
19141
  }(ThemeErrorCode || (ThemeErrorCode = {}));
@@ -19411,29 +19437,6 @@ class ThemeLogger {
19411
19437
  return Object.keys(registry).length;
19412
19438
  }
19413
19439
 
19414
- /**
19415
- * Core Theme Engine
19416
- *
19417
- * Core theme creation, composition, and registry functionality
19418
- */ const index = Object.freeze( Object.defineProperty({
19419
- __proto__: null,
19420
- clearThemes: clearThemes,
19421
- createTheme: createTheme,
19422
- createThemeRegistry: createThemeRegistry,
19423
- deepMerge: deepMerge,
19424
- extendTheme: extendTheme,
19425
- getAllThemes: getAllThemes,
19426
- getTheme: getTheme,
19427
- getThemeCount: getThemeCount,
19428
- getThemeIds: getThemeIds,
19429
- hasTheme: hasTheme,
19430
- mergeTheme: mergeTheme,
19431
- registerTheme: registerTheme,
19432
- unregisterTheme: unregisterTheme
19433
- }, Symbol.toStringTag, {
19434
- value: "Module"
19435
- }));
19436
-
19437
19440
  /**
19438
19441
  * CSS Injection Utilities
19439
19442
  *
@@ -19606,7 +19609,7 @@ const isBrowser = () => "undefined" != typeof window && "undefined" != typeof do
19606
19609
  /**
19607
19610
  * Convert hex color to RGB object
19608
19611
  */
19609
- function hexToRgb(hex) {
19612
+ function hexToRgb$1(hex) {
19610
19613
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
19611
19614
  return result ? {
19612
19615
  r: parseInt(result[1], 16),
@@ -19626,7 +19629,7 @@ function hexToRgb(hex) {
19626
19629
  * Calculate relative luminance of a color
19627
19630
  * Used for determining contrast ratios
19628
19631
  */ function getLuminance(color) {
19629
- const rgb = hexToRgb(color);
19632
+ const rgb = hexToRgb$1(color);
19630
19633
  if (!rgb) return 0;
19631
19634
  const {r: r, g: g, b: b} = rgb, [rs, gs, bs] = [ r ?? 0, g ?? 0, b ?? 0 ].map((c => {
19632
19635
  const val = c / 255;
@@ -19656,7 +19659,7 @@ function hexToRgb(hex) {
19656
19659
  * @param amount - Amount to lighten (0-1), default 0.2
19657
19660
  * @returns Lightened hex color
19658
19661
  */ function lighten(color, amount = .2) {
19659
- const rgb = hexToRgb(color);
19662
+ const rgb = hexToRgb$1(color);
19660
19663
  if (!rgb) return color;
19661
19664
  const {r: r, g: g, b: b} = rgb, lightenValue = val => Math.min(255, Math.round(val + (255 - val) * amount));
19662
19665
  return rgbToHex(lightenValue(r), lightenValue(g), lightenValue(b));
@@ -19669,7 +19672,7 @@ function hexToRgb(hex) {
19669
19672
  * @param amount - Amount to darken (0-1), default 0.2
19670
19673
  * @returns Darkened hex color
19671
19674
  */ function darken(color, amount = .2) {
19672
- const rgb = hexToRgb(color);
19675
+ const rgb = hexToRgb$1(color);
19673
19676
  if (!rgb) return color;
19674
19677
  const {r: r, g: g, b: b} = rgb, darkenValue = val => Math.max(0, Math.round(val * (1 - amount)));
19675
19678
  return rgbToHex(darkenValue(r), darkenValue(g), darkenValue(b));
@@ -19682,7 +19685,7 @@ function hexToRgb(hex) {
19682
19685
  * @param opacity - Opacity value (0-1)
19683
19686
  * @returns RGBA color string
19684
19687
  */ function alpha(color, opacity) {
19685
- const rgb = hexToRgb(color);
19688
+ const rgb = hexToRgb$1(color);
19686
19689
  if (!rgb) return color;
19687
19690
  const {r: r, g: g, b: b} = rgb;
19688
19691
  return `rgba(${r}, ${g}, ${b}, ${Math.max(0, Math.min(1, opacity))})`;
@@ -19701,7 +19704,7 @@ function hexToRgb(hex) {
19701
19704
  */
19702
19705
  function generateColorScale(baseColor, prefix, colorName) {
19703
19706
  const vars = {};
19704
- if (!hexToRgb(baseColor)) return vars;
19707
+ if (!hexToRgb$1(baseColor)) return vars;
19705
19708
  // Generate 10-step scale
19706
19709
  // Steps 1-5: lighter variations
19707
19710
  // Step 6: base color
@@ -19747,7 +19750,7 @@ function generateCSSVariables(theme, options = {}) {
19747
19750
  // Main color (flat structure, matches SCSS: --atomix-primary)
19748
19751
  vars[`${prefix}-${key}`] = color.main;
19749
19752
  // Generate RGB for transparency support (matches SCSS: --atomix-primary-rgb)
19750
- const rgb = hexToRgb(color.main);
19753
+ const rgb = hexToRgb$1(color.main);
19751
19754
  // Generate full color scale (1-10) - matches SCSS: --atomix-primary-1 through --atomix-primary-10
19752
19755
  // Only for primary, secondary, error, warning, info, success (not for light/dark)
19753
19756
  if (rgb && (vars[`${prefix}-${key}-rgb`] = `${rgb.r}, ${rgb.g}, ${rgb.b}`), "light" !== key && "dark" !== key) {
@@ -19830,11 +19833,11 @@ function generateCSSVariables(theme, options = {}) {
19830
19833
  // Heading color (defaults to text primary) - matches SCSS: --atomix-heading-color
19831
19834
  palette.text && (vars[`${prefix}-heading-color`] = palette.text.primary), palette.primary) {
19832
19835
  vars[`${prefix}-link-color`] = palette.primary.main;
19833
- const linkRgb = hexToRgb(palette.primary.main);
19836
+ const linkRgb = hexToRgb$1(palette.primary.main);
19834
19837
  linkRgb && (vars[`${prefix}-link-color-rgb`] = `${linkRgb.r}, ${linkRgb.g}, ${linkRgb.b}`),
19835
19838
  // Link hover color (slightly darker)
19836
19839
  vars[`${prefix}-link-hover-color`] = palette.primary.dark || darken(palette.primary.main, .1);
19837
- const linkHoverRgb = hexToRgb(palette.primary.dark || darken(palette.primary.main, .1));
19840
+ const linkHoverRgb = hexToRgb$1(palette.primary.dark || darken(palette.primary.main, .1));
19838
19841
  linkHoverRgb && (vars[`${prefix}-link-hover-color-rgb`] = `${linkHoverRgb.r}, ${linkHoverRgb.g}, ${linkHoverRgb.b}`),
19839
19842
  // Link decoration (default: none, matching tokens list)
19840
19843
  vars[`${prefix}-link-decoration`] = "none";
@@ -20292,17 +20295,292 @@ function generateClassName(block, element, modifiers) {
20292
20295
  ThemeContext.displayName = "ThemeContext";
20293
20296
 
20294
20297
  /**
20295
- * Theme Provider
20296
- *
20297
- * React context provider for theme management with separated concerns.
20298
- * Simplified version focusing on core functionality:
20299
- * - String-based themes (CSS files)
20300
- * - DesignTokens (dynamic themes)
20301
- * - Persistence via localStorage
20298
+ * Theme Validation Utilities
20302
20299
  *
20303
- * Falls back to 'default' theme if no configuration is found.
20300
+ * Comprehensive validation utilities for DesignTokens objects.
20301
+ * Includes color format validation, accessibility checks, and required properties verification.
20302
+ */
20303
+ const logger$1 = getLogger(), COLOR_PATTERNS = {
20304
+ /** Hex color: #RGB, #RRGGBB, #RRGGBBAA */
20305
+ hex: /^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$/,
20306
+ /** RGB color: rgb(r, g, b) or rgb(r, g, b, a) */
20307
+ rgb: /^rgb\(\s*(\d{1,3}(?:\.\d+)?)\s*,\s*(\d{1,3}(?:\.\d+)?)\s*,\s*(\d{1,3}(?:\.\d+)?)\s*(?:,\s*([01]?\.?\d+))?\s*\)$/,
20308
+ /** RGBA color: rgba(r, g, b, a) */
20309
+ rgba: /^rgba\(\s*(\d{1,3}(?:\.\d+)?)\s*,\s*(\d{1,3}(?:\.\d+)?)\s*,\s*(\d{1,3}(?:\.\d+)?)\s*,\s*([01]?\.?\d+)\s*\)$/,
20310
+ /** HSL color: hsl(h, s%, l%) */
20311
+ hsl: /^hsl\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*\)$/,
20312
+ /** HSLA color: hsla(h, s%, l%, a) */
20313
+ hsla: /^hsla\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*,\s*([01]?\.?\d+)\s*\)$/
20314
+ }, 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 = [ {
20315
+ text: "primary-text-emphasis",
20316
+ background: "primary-bg-subtle",
20317
+ name: "Primary text on subtle background"
20318
+ }, {
20319
+ text: "secondary-text-emphasis",
20320
+ background: "secondary-bg-subtle",
20321
+ name: "Secondary text on subtle background"
20322
+ }, {
20323
+ text: "error-text-emphasis",
20324
+ background: "error-bg-subtle",
20325
+ name: "Error text on subtle background"
20326
+ }, {
20327
+ text: "success-text-emphasis",
20328
+ background: "success-bg-subtle",
20329
+ name: "Success text on subtle background"
20330
+ } ];
20331
+
20332
+ /**
20333
+ * Color format validation patterns
20334
+ */
20335
+ /**
20336
+ * Parse RGB/RGBA color string to RGB values
20304
20337
  */
20305
- 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}) => {
20338
+ function rgbToRgb(rgb) {
20339
+ const match = rgb.match(COLOR_PATTERNS.rgb) || rgb.match(COLOR_PATTERNS.rgba);
20340
+ if (!match) return null;
20341
+ const r = parseInt(match[1] ?? "0", 10), g = parseInt(match[2] ?? "0", 10), b = parseInt(match[3] ?? "0", 10);
20342
+ // Validate RGB ranges
20343
+ return r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255 ? null : {
20344
+ r: r,
20345
+ g: g,
20346
+ b: b
20347
+ };
20348
+ }
20349
+
20350
+ /**
20351
+ * Parse HSL/HSLA color string to RGB values
20352
+ */ function hslToRgb(hsl) {
20353
+ const match = hsl.match(COLOR_PATTERNS.hsl) || hsl.match(COLOR_PATTERNS.hsla);
20354
+ if (!match) return null;
20355
+ let h = parseInt(match[1] ?? "0", 10) / 360, s = parseInt(match[2] ?? "0", 10) / 100, l = parseInt(match[3] ?? "0", 10) / 100;
20356
+ // Validate HSL ranges
20357
+ if (h < 0 || h > 1 || s < 0 || s > 1 || l < 0 || l > 1) return null;
20358
+ 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);
20359
+ let r, g, b;
20360
+ if (0 === s) r = g = b = l; // achromatic
20361
+ else {
20362
+ const q = l < .5 ? l * (1 + s) : l + s - l * s, p = 2 * l - q;
20363
+ r = hue2rgb(p, q, h + 1 / 3), g = hue2rgb(p, q, h), b = hue2rgb(p, q, h - 1 / 3);
20364
+ }
20365
+ return {
20366
+ r: Math.round(255 * r),
20367
+ g: Math.round(255 * g),
20368
+ b: Math.round(255 * b)
20369
+ };
20370
+ }
20371
+
20372
+ /**
20373
+ * Convert any valid color format to RGB values
20374
+ */ function colorToRgb(color) {
20375
+ // Try hex first
20376
+ return COLOR_PATTERNS.hex.test(color) ?
20377
+ /**
20378
+ * Convert hex color to RGB values
20379
+ */
20380
+ function(hex) {
20381
+ const result = COLOR_PATTERNS.hex.exec(hex);
20382
+ if (!result || !result[1]) return null;
20383
+ const digits = result[1];
20384
+ let r, g, b;
20385
+ switch (digits.length) {
20386
+ case 3:
20387
+ case 4:
20388
+ // #RGBA (ignore alpha)
20389
+ r = parseInt((digits[0] ?? "0") + (digits[0] ?? "0"), 16), g = parseInt((digits[1] ?? "0") + (digits[1] ?? "0"), 16),
20390
+ b = parseInt((digits[2] ?? "0") + (digits[2] ?? "0"), 16);
20391
+ break;
20392
+
20393
+ case 6:
20394
+ case 8:
20395
+ // #RRGGBBAA (ignore alpha)
20396
+ r = parseInt(digits.slice(0, 2), 16), g = parseInt(digits.slice(2, 4), 16), b = parseInt(digits.slice(4, 6), 16);
20397
+ break;
20398
+
20399
+ default:
20400
+ return null;
20401
+ }
20402
+ return {
20403
+ r: r,
20404
+ g: g,
20405
+ b: b
20406
+ };
20407
+ }(color) :
20408
+ // Try RGB/RGBA
20409
+ color.startsWith("rgb") ? rgbToRgb(color) :
20410
+ // Try HSL/HSLA
20411
+ color.startsWith("hsl") ? hslToRgb(color) : null;
20412
+ }
20413
+
20414
+ /**
20415
+ * Validate that a color string is in a valid format (hex, rgb, hsl, etc.)
20416
+ * Includes validation of value ranges for RGB and HSL
20417
+ */
20418
+ /**
20419
+ * Calculate relative luminance of a color
20420
+ * Based on WCAG guidelines: https://www.w3.org/TR/WCAG20-TECHS/G17.html
20421
+ */
20422
+ function getRelativeLuminance(r, g, b) {
20423
+ const normalize = val => (val /= 255) <= .03928 ? val / 12.92 : Math.pow((val + .055) / 1.055, 2.4);
20424
+ return .2126 * normalize(r) + .7152 * normalize(g) + .0722 * normalize(b);
20425
+ }
20426
+
20427
+ /**
20428
+ * Calculate contrast ratio between two colors (supports multiple formats)
20429
+ */
20430
+ /**
20431
+ * Check if contrast ratio meets WCAG AA standards
20432
+ * AA requires 4.5:1 for normal text, 3:1 for large text
20433
+ */
20434
+ function validateContrastRatio(foreground, background, isLargeText = !1) {
20435
+ const ratio = function(color1, color2) {
20436
+ const rgb1 = colorToRgb(color1), rgb2 = colorToRgb(color2);
20437
+ if (!rgb1 || !rgb2) return null;
20438
+ const lum1 = getRelativeLuminance(rgb1.r, rgb1.g, rgb1.b), lum2 = getRelativeLuminance(rgb2.r, rgb2.g, rgb2.b);
20439
+ return (Math.max(lum1, lum2) + .05) / (Math.min(lum1, lum2) + .05);
20440
+ }(foreground, background);
20441
+ if (null === ratio) return {
20442
+ valid: !1,
20443
+ ratio: 0,
20444
+ requiredRatio: isLargeText ? 3 : 4.5
20445
+ };
20446
+ const requiredRatio = isLargeText ? 3 : 4.5;
20447
+ return {
20448
+ valid: ratio >= requiredRatio,
20449
+ ratio: ratio,
20450
+ requiredRatio: requiredRatio
20451
+ };
20452
+ }
20453
+
20454
+ /**
20455
+ * Validate all color formats in DesignTokens
20456
+ */
20457
+ /**
20458
+ * Comprehensive validation of DesignTokens
20459
+ */
20460
+ function validateDesignTokens(tokens, options = {}) {
20461
+ const results = [];
20462
+ options.skipRequiredTokens || results.push(
20463
+ /**
20464
+ * Validate that all required tokens are present
20465
+ */
20466
+ function(tokens) {
20467
+ const errors = [], warnings = [];
20468
+ // Check required color tokens
20469
+ for (const token of REQUIRED_COLOR_TOKENS) token in tokens || errors.push(`Required color token '${token}' is missing`);
20470
+ // Check required text emphasis tokens
20471
+ for (const token of REQUIRED_TEXT_EMPHASIS_TOKENS) token in tokens || errors.push(`Required text emphasis token '${token}' is missing`);
20472
+ // Check for RGB versions of base colors
20473
+ for (const token of REQUIRED_COLOR_TOKENS) {
20474
+ const rgbToken = `${token}-rgb`;
20475
+ rgbToken in tokens || warnings.push(`RGB version of '${token}' token '${rgbToken}' is missing`);
20476
+ }
20477
+ return {
20478
+ valid: 0 === errors.length,
20479
+ errors: errors,
20480
+ warnings: warnings
20481
+ };
20482
+ }
20483
+ /**
20484
+ * Validate accessibility contrast ratios
20485
+ */ (tokens)), options.skipColorValidation || results.push(function(tokens) {
20486
+ const errors = [], colorTokenKeys = new Set([
20487
+ // Base colors
20488
+ "primary", "secondary", "success", "info", "warning", "error", "light", "dark",
20489
+ // Text emphasis
20490
+ "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",
20491
+ // Background subtle
20492
+ "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",
20493
+ // Border subtle
20494
+ "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",
20495
+ // Hover states
20496
+ "primary-hover", "secondary-hover", "light-hover", "dark-hover", "error-hover", "success-hover", "warning-hover", "info-hover",
20497
+ // Colors from scales (primary, red, green, blue, yellow)
20498
+ ...Array.from({
20499
+ length: 10
20500
+ }, ((_, i) => [ `primary-${i + 1}`, `red-${i + 1}`, `green-${i + 1}`, `blue-${i + 1}`, `yellow-${i + 1}` ])).flat(),
20501
+ // Gray scale
20502
+ ...Array.from({
20503
+ length: 10
20504
+ }, ((_, i) => `gray-${i + 1}`)),
20505
+ // Body colors
20506
+ "body-color", "heading-color",
20507
+ // Link colors
20508
+ "link-color", "link-hover-color",
20509
+ // Highlight & code
20510
+ "highlight-bg", "code-color",
20511
+ // Border colors
20512
+ "border-color", "border-color-translucent",
20513
+ // Focus ring
20514
+ "focus-border-color",
20515
+ // Form validation
20516
+ "form-valid-color", "form-valid-border-color", "form-invalid-color", "form-invalid-border-color" ]);
20517
+ for (const key of colorTokenKeys) {
20518
+ if (!(key in tokens)) continue;
20519
+ // Skip if token not present
20520
+ const value = tokens[key];
20521
+ "string" == typeof value ? (color = value,
20522
+ // Check hex first (regex is sufficient)
20523
+ COLOR_PATTERNS.hex.test(color) || (
20524
+ // Check RGB/RGBA with value validation
20525
+ COLOR_PATTERNS.rgb.test(color) || COLOR_PATTERNS.rgba.test(color) ? null !== rgbToRgb(color) :
20526
+ // Check HSL/HSLA with value validation
20527
+ (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}`);
20528
+ }
20529
+ var color;
20530
+ return {
20531
+ valid: 0 === errors.length,
20532
+ errors: errors,
20533
+ warnings: []
20534
+ };
20535
+ }(tokens)), options.skipAccessibility || results.push(function(tokens) {
20536
+ const errors = [], warnings = [];
20537
+ for (const check of ACCESSIBILITY_CHECKS) {
20538
+ const textColor = tokens[check.text], bgColor = tokens[check.background];
20539
+ if (!textColor || !bgColor) {
20540
+ warnings.push(`Cannot validate contrast for ${check.name}: missing tokens`);
20541
+ continue;
20542
+ }
20543
+ const contrast = validateContrastRatio(textColor, bgColor);
20544
+ if (!contrast.valid) {
20545
+ const level = 3 === contrast.requiredRatio ? "large text (AA)" : "normal text (AA)";
20546
+ errors.push(`${check.name}: contrast ratio ${contrast.ratio.toFixed(2)}:1 is below required ${contrast.requiredRatio}:1 for ${level}`);
20547
+ }
20548
+ }
20549
+ return {
20550
+ valid: 0 === errors.length,
20551
+ errors: errors,
20552
+ warnings: warnings
20553
+ };
20554
+ }(tokens));
20555
+ const allErrors = results.flatMap((r => r.errors)), allWarnings = results.flatMap((r => r.warnings)), valid = 0 === allErrors.length;
20556
+ // Log validation results
20557
+ return valid ? allWarnings.length > 0 ? logger$1.warn(`DesignTokens validation passed with ${allWarnings.length} warnings`, {
20558
+ warnings: allWarnings
20559
+ }) : logger$1.debug("DesignTokens validation passed") : logger$1.error("DesignTokens validation failed", new Error(`Validation failed with ${allErrors.length} errors and ${allWarnings.length} warnings`), {
20560
+ errors: allErrors,
20561
+ warnings: allWarnings,
20562
+ tokenCount: Object.keys(tokens).length
20563
+ }), {
20564
+ valid: valid,
20565
+ errors: allErrors,
20566
+ warnings: allWarnings
20567
+ };
20568
+ }
20569
+
20570
+ /**
20571
+ * Safely validate and merge partial tokens with defaults
20572
+ */ function validateAndMergeTokens(partialTokens) {
20573
+ const merged = {
20574
+ ...defaultTokens,
20575
+ ...partialTokens
20576
+ };
20577
+ return {
20578
+ tokens: merged,
20579
+ validation: validateDesignTokens(merged)
20580
+ };
20581
+ }
20582
+
20583
+ 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}) => {
20306
20584
  // Store callbacks in refs to avoid recreating when they change
20307
20585
  const onThemeChangeRef = useRef(onThemeChange), onErrorRef = useRef(onError);
20308
20586
  // Update ref when callback changes
@@ -20323,12 +20601,20 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
20323
20601
  // If defaultTheme is provided, use it
20324
20602
  return null != defaultTheme ? defaultTheme : "default";
20325
20603
  // Default fallback
20326
- }), [ defaultTheme, enablePersistence, storageKey ]), [currentTheme, setCurrentTheme] = useState((() => "string" == typeof initialDefaultTheme ? initialDefaultTheme : "tokens-theme")), [activeTokens, setActiveTokens] = useState((() =>
20327
- // If defaultTheme is DesignTokens, store them
20328
- defaultTheme && "string" != typeof defaultTheme ? createTokens(defaultTheme) : null)), [isLoading, setIsLoading] = useState(!1), [error, setError] = useState(null), loadedThemesRef = useRef(new Set), themePromisesRef = useRef({}), abortControllerRef = useRef(null);
20604
+ }), [ defaultTheme, enablePersistence, storageKey ]), [currentTheme, setCurrentTheme] = useState((() => "string" == typeof initialDefaultTheme ? initialDefaultTheme : "tokens-theme")), [activeTokens, setActiveTokens] = useState((() => {
20605
+ // If defaultTheme is DesignTokens, validate and store them
20606
+ if (defaultTheme && "string" != typeof defaultTheme) {
20607
+ const {tokens: tokens, validation: validation} = validateAndMergeTokens(defaultTheme);
20608
+ return validation.valid ? tokens : (logger.warn("Invalid default theme tokens, using defaults", {
20609
+ errors: validation.errors,
20610
+ warnings: validation.warnings
20611
+ }), createTokens({}));
20612
+ }
20613
+ return null;
20614
+ })), [isLoading, setIsLoading] = useState(!1), [error, setError] = useState(null), loadedThemesRef = useRef(new Set), themePromisesRef = useRef({}), abortControllerRef = useRef(null);
20329
20615
  // Handle initial DesignTokens defaultTheme
20330
20616
  useEffect((() => {
20331
- defaultTheme && "string" != typeof defaultTheme && activeTokens && !isServer() && injectCSS$1(createTheme(defaultTheme), "theme-tokens-theme");
20617
+ defaultTheme && "string" != typeof defaultTheme && activeTokens && !isServer() && injectCSS$1(createTheme(activeTokens), "theme-tokens-theme");
20332
20618
  }), [ defaultTheme, activeTokens ]), // Run when defaultTheme or activeTokens change
20333
20619
  // Apply initial theme attributes to document element
20334
20620
  useEffect((() => {
@@ -20358,19 +20644,42 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
20358
20644
  if ("string" != typeof theme) {
20359
20645
  // Check if aborted before processing
20360
20646
  if (abortController.signal.aborted) return;
20361
- // For DesignTokens, create CSS and inject it
20362
- const {createTheme: createTheme} = await Promise.resolve().then((() => index)), css = createTheme(theme), themeId = "tokens-theme";
20647
+ // Validate and merge DesignTokens
20648
+ const {tokens: validatedTokens, validation: validation} = validateAndMergeTokens(theme);
20649
+ if (!validation.valid) {
20650
+ const errorMsg = `Invalid DesignTokens provided: ${validation.errors.join(", ")}`, validationError = new Error(errorMsg);
20651
+ // Default to true
20652
+ if (logger.error("Theme validation failed", validationError, {
20653
+ errors: validation.errors,
20654
+ warnings: validation.warnings
20655
+ }), !1 !== options?.fallbackOnError) {
20656
+ logger.warn("Falling back to default theme due to validation errors");
20657
+ // Use default tokens instead
20658
+ const {tokens: defaultTokens} = validateAndMergeTokens({}), css = createTheme(defaultTokens), themeId = "tokens-theme-fallback";
20659
+ // Check if aborted before state update
20660
+ if (abortController.signal.aborted) return;
20661
+ // Remove any previously loaded theme CSS
20662
+ return removeCSS(`theme-${currentTheme}`),
20663
+ // Inject new theme CSS
20664
+ injectCSS$1(css, `theme-${themeId}`),
20665
+ // Store default tokens
20666
+ setActiveTokens(defaultTokens), setCurrentTheme(themeId), handleThemeChange(defaultTokens),
20667
+ handleError(validationError, themeId), void setIsLoading(!1);
20668
+ }
20669
+ // No fallback, throw the error
20670
+ throw validationError;
20671
+ }
20672
+ // For valid DesignTokens, create CSS and inject it
20673
+ const css = createTheme(validatedTokens), themeId = "tokens-theme";
20363
20674
  // Check if aborted after async operation
20364
20675
  if (abortController.signal.aborted) return;
20365
20676
  // Remove any previously loaded theme CSS
20366
- removeCSS(`theme-${currentTheme}`),
20367
- // Inject new theme CSS
20368
- injectCSS$1(css, `theme-${themeId}`);
20369
- // Store tokens for reference
20370
- const fullTokens = createTokens(theme);
20677
+ // Store validated tokens for reference
20371
20678
  // Check if aborted before state update
20372
- if (abortController.signal.aborted) return;
20373
- return setActiveTokens(fullTokens), setCurrentTheme(themeId), handleThemeChange(fullTokens),
20679
+ if (removeCSS(`theme-${currentTheme}`),
20680
+ // Inject new theme CSS
20681
+ injectCSS$1(css, `theme-${themeId}`), abortController.signal.aborted) return;
20682
+ return setActiveTokens(validatedTokens), setCurrentTheme(themeId), handleThemeChange(validatedTokens),
20374
20683
  void setIsLoading(!1);
20375
20684
  }
20376
20685
  // If it's a string theme name, load the associated CSS
@@ -20385,30 +20694,33 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
20385
20694
  // If previous load failed, continue with new load
20386
20695
  }
20387
20696
  // Load CSS theme
20388
- const themeLoadPromise = new Promise((async (resolve, reject) => {
20389
- try {
20390
- // Check if aborted
20391
- if (abortController.signal.aborted) return void resolve();
20392
- if (!themes[theme]) throw new Error(`Theme metadata not found for theme: ${theme}`);
20393
- {
20394
- // Build CSS path using utility function
20395
- const cssPath = buildThemePath(theme, basePath, useMinified, cdnPath);
20697
+ const themeLoadPromise = new Promise(((resolve, reject) => {
20698
+ // Start the async operation
20699
+ (async () => {
20700
+ try {
20396
20701
  // Check if aborted
20397
- if (abortController.signal.aborted) return void resolve();
20398
- // Load CSS file (using loadThemeCSS from domUtils)
20399
- const {loadThemeCSS: loadThemeCSS} = await Promise.resolve().then((() => domUtils));
20400
- // Check if aborted after async operation
20401
- if (await loadThemeCSS(cssPath, `theme-${theme}`), abortController.signal.aborted) return void resolve();
20402
- // Remove any previously loaded theme CSS
20403
- removeCSS(`theme-${String(currentTheme)}`), loadedThemesRef.current.add(theme),
20404
- setCurrentTheme(theme), setActiveTokens(null), handleThemeChange(theme), resolve();
20702
+ if (abortController.signal.aborted) return void resolve();
20703
+ if (!themes[theme]) throw new Error(`Theme metadata not found for theme: ${theme}`);
20704
+ {
20705
+ // Build CSS path using utility function
20706
+ const cssPath = buildThemePath(theme, basePath, useMinified, cdnPath);
20707
+ // Check if aborted
20708
+ if (abortController.signal.aborted) return void resolve();
20709
+ // Load CSS file (using loadThemeCSS from domUtils)
20710
+ const {loadThemeCSS: loadThemeCSS} = await Promise.resolve().then((() => domUtils));
20711
+ // Check if aborted after async operation
20712
+ if (await loadThemeCSS(cssPath, `theme-${theme}`), abortController.signal.aborted) return void resolve();
20713
+ // Remove any previously loaded theme CSS
20714
+ removeCSS(`theme-${String(currentTheme)}`), loadedThemesRef.current.add(theme),
20715
+ setCurrentTheme(theme), setActiveTokens(null), handleThemeChange(theme), resolve();
20716
+ }
20717
+ } catch (err) {
20718
+ // Don't reject if aborted
20719
+ if (abortController.signal.aborted) return void resolve();
20720
+ const error = err instanceof Error ? err : new Error(String(err));
20721
+ setError(error), handleError(error, String(theme)), reject(error);
20405
20722
  }
20406
- } catch (err) {
20407
- // Don't reject if aborted
20408
- if (abortController.signal.aborted) return void resolve();
20409
- const error = err instanceof Error ? err : new Error(String(err));
20410
- setError(error), handleError(error, String(theme)), reject(error);
20411
- }
20723
+ })();
20412
20724
  }));
20413
20725
  themePromisesRef.current[theme] = themeLoadPromise;
20414
20726
  try {
@@ -20473,6 +20785,17 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
20473
20785
  });
20474
20786
  };
20475
20787
 
20788
+ /**
20789
+ * Theme Provider
20790
+ *
20791
+ * React context provider for theme management with separated concerns.
20792
+ * Simplified version focusing on core functionality:
20793
+ * - String-based themes (CSS files)
20794
+ * - DesignTokens (dynamic themes)
20795
+ * - Persistence via localStorage
20796
+ *
20797
+ * Falls back to 'default' theme if no configuration is found.
20798
+ */
20476
20799
  /**
20477
20800
  * useTheme Hook
20478
20801
  *
@@ -20498,7 +20821,8 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
20498
20821
  * );
20499
20822
  * }
20500
20823
  * ```
20501
- */ function useTheme() {
20824
+ */
20825
+ function useTheme() {
20502
20826
  const context = useContext(ThemeContext);
20503
20827
  if (!context) throw new Error("useTheme must be used within a ThemeProvider");
20504
20828
  return {
@@ -22515,8 +22839,8 @@ function createPaletteColor(color) {
22515
22839
  * @returns Complete theme object
22516
22840
  */
22517
22841
  function createThemeObject(...options) {
22518
- // Merge all options
22519
- const mergedOptions = _reduceInstanceProperty(options).call(options, ((acc, option) => deepMerge(acc, option)), {}), palette = {
22842
+ // Merge all options by spreading them into a single object
22843
+ const mergedOptions = _reduceInstanceProperty(options).call(options, ((acc, option) => deepMerge(acc, option || {})), {}), palette = {
22520
22844
  primary: createPaletteColor(mergedOptions.palette?.primary || DEFAULT_PALETTE.primary),
22521
22845
  secondary: createPaletteColor(mergedOptions.palette?.secondary || DEFAULT_PALETTE.secondary),
22522
22846
  error: createPaletteColor(mergedOptions.palette?.error || DEFAULT_PALETTE.error),
@@ -22701,43 +23025,45 @@ function createThemeObject(...options) {
22701
23025
 
22702
23026
  case "hsl":
22703
23027
  case "hsla":
22704
- // Convert RGB to HSL (simplified)
22705
- const hsl =
22706
- /**
23028
+ {
23029
+ // Convert RGB to HSL (simplified)
23030
+ const hsl =
23031
+ /**
22707
23032
  * Convert RGB to HSL
22708
23033
  */
22709
- function(r, g, b) {
22710
- r /= 255, g /= 255, b /= 255;
22711
- const max = Math.max(r, g, b), min = Math.min(r, g, b);
22712
- let h = 0, s = 0;
22713
- const l = (max + min) / 2;
22714
- if (max !== min) {
22715
- const d = max - min;
22716
- switch (s = l > .5 ? d / (2 - max - min) : d / (max + min), max) {
22717
- case r:
22718
- h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
22719
- break;
22720
-
22721
- case g:
22722
- h = ((b - r) / d + 2) / 6;
22723
- break;
22724
-
22725
- case b:
22726
- h = ((r - g) / d + 4) / 6;
23034
+ function(r, g, b) {
23035
+ r /= 255, g /= 255, b /= 255;
23036
+ const max = Math.max(r, g, b), min = Math.min(r, g, b);
23037
+ let h = 0, s = 0;
23038
+ const l = (max + min) / 2;
23039
+ if (max !== min) {
23040
+ const d = max - min;
23041
+ switch (s = l > .5 ? d / (2 - max - min) : d / (max + min), max) {
23042
+ case r:
23043
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
23044
+ break;
23045
+
23046
+ case g:
23047
+ h = ((b - r) / d + 2) / 6;
23048
+ break;
23049
+
23050
+ case b:
23051
+ h = ((r - g) / d + 4) / 6;
23052
+ }
22727
23053
  }
23054
+ return {
23055
+ h: Math.round(360 * h),
23056
+ s: Math.round(100 * s),
23057
+ l: Math.round(100 * l)
23058
+ };
22728
23059
  }
22729
- return {
22730
- h: Math.round(360 * h),
22731
- s: Math.round(100 * s),
22732
- l: Math.round(100 * l)
22733
- };
22734
- }
22735
- /**
23060
+ /**
22736
23061
  * Theme Live Editor Component
22737
23062
  *
22738
23063
  * Allows live editing of theme properties with instant preview
22739
23064
  */ (r, g, b);
22740
- return "hsl" === format ? `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)` : `hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${a})`;
23065
+ return "hsl" === format ? `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)` : `hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${a})`;
23066
+ }
22741
23067
 
22742
23068
  default:
22743
23069
  return color;
@@ -23063,8 +23389,312 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
23063
23389
  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 "
23064
23390
  }) ]
23065
23391
  });
23392
+ }, DesignTokensCustomizer = ({initialTokens: initialTokens = {}, onTokensChange: onTokensChange, className: className, style: style}) => {
23393
+ // Current tokens state
23394
+ const [tokens, setTokens] = useState((() => createTokens(initialTokens))), [colorFormat, setColorFormat] = useState("hex"), [activeCategory, setActiveCategory] = useState("colors"), [cssPreview, setCssPreview] = useState("");
23395
+ // Generate CSS when tokens change
23396
+ useEffect((() => {
23397
+ const css = createTheme(tokens, {
23398
+ selector: ":root",
23399
+ prefix: "atomix-preview"
23400
+ });
23401
+ setCssPreview(css), onTokensChange?.(tokens);
23402
+ }), [ tokens, onTokensChange ]);
23403
+ // Create theme object for preview
23404
+ const previewTheme = useMemo((() => createThemeObject({
23405
+ palette: {
23406
+ primary: {
23407
+ main: tokens.primary
23408
+ },
23409
+ secondary: {
23410
+ main: tokens.secondary
23411
+ },
23412
+ error: {
23413
+ main: tokens.error
23414
+ },
23415
+ warning: {
23416
+ main: tokens.warning
23417
+ },
23418
+ info: {
23419
+ main: tokens.info
23420
+ },
23421
+ success: {
23422
+ main: tokens.success
23423
+ },
23424
+ background: {
23425
+ default: "#ffffff",
23426
+ subtle: tokens["secondary-bg-subtle"] || "#f3f4f6"
23427
+ },
23428
+ text: {
23429
+ primary: tokens["primary-text-emphasis"] || "#111827",
23430
+ secondary: tokens["secondary-text-emphasis"] || "#374151",
23431
+ disabled: tokens["disabled-text-emphasis"] || "#9ca3af"
23432
+ }
23433
+ },
23434
+ typography: {
23435
+ fontFamily: tokens["body-font-family"] || '"Roboto", sans-serif',
23436
+ fontSize: parseInt(tokens["body-font-size"] || "16")
23437
+ },
23438
+ spacing: factor => .25 * factor + "rem"
23439
+ })), [ tokens ]), updateToken = useCallback(((key, value) => {
23440
+ setTokens((prev => ({
23441
+ ...prev,
23442
+ [key]: value
23443
+ })));
23444
+ }), []), convertColorFormat = useCallback(((color, format) => {
23445
+ // Parse current color
23446
+ const temp = document.createElement("div");
23447
+ temp.style.color = color, document.body.appendChild(temp);
23448
+ const computed = window.getComputedStyle(temp).color;
23449
+ document.body.removeChild(temp);
23450
+ const rgbMatch = computed.match(/\d+/g);
23451
+ if (!rgbMatch || rgbMatch.length < 3) return color;
23452
+ 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;
23453
+ switch (format) {
23454
+ case "hex":
23455
+ return `#${[ r, g, b ].map((x => x.toString(16).padStart(2, "0"))).join("")}`;
23456
+
23457
+ case "rgb":
23458
+ return `rgb(${r}, ${g}, ${b})`;
23459
+
23460
+ case "rgba":
23461
+ return `rgba(${r}, ${g}, ${b}, ${a})`;
23462
+
23463
+ case "hsl":
23464
+ case "hsla":
23465
+ {
23466
+ const hsl =
23467
+ // RGB to HSL conversion
23468
+ function(r, g, b) {
23469
+ r /= 255, g /= 255, b /= 255;
23470
+ const max = Math.max(r, g, b), min = Math.min(r, g, b);
23471
+ let h = 0, s = 0;
23472
+ const l = (max + min) / 2;
23473
+ if (max !== min) {
23474
+ const d = max - min;
23475
+ switch (s = l > .5 ? d / (2 - max - min) : d / (max + min), max) {
23476
+ case r:
23477
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
23478
+ break;
23479
+
23480
+ case g:
23481
+ h = ((b - r) / d + 2) / 6;
23482
+ break;
23483
+
23484
+ case b:
23485
+ h = ((r - g) / d + 4) / 6;
23486
+ }
23487
+ }
23488
+ return {
23489
+ h: Math.round(360 * h),
23490
+ s: Math.round(100 * s),
23491
+ l: Math.round(100 * l)
23492
+ };
23493
+ }
23494
+ // Export functions
23495
+ (r, g, b);
23496
+ return "hsl" === format ? `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)` : `hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${a})`;
23497
+ }
23498
+
23499
+ default:
23500
+ return color;
23501
+ }
23502
+ }), []), exportTokens = useCallback((() => {
23503
+ const dataStr = JSON.stringify(tokens, null, 2), dataUri = "data:application/json;charset=utf-8," + encodeURIComponent(dataStr), linkElement = document.createElement("a");
23504
+ linkElement.setAttribute("href", dataUri), linkElement.setAttribute("download", "design-tokens.json"),
23505
+ linkElement.click();
23506
+ }), [ tokens ]), exportTheme = useCallback((() => {
23507
+ const themeCss = createTheme(tokens), dataUri = "data:text/css;charset=utf-8," + encodeURIComponent(themeCss), linkElement = document.createElement("a");
23508
+ linkElement.setAttribute("href", dataUri), linkElement.setAttribute("download", "theme.css"),
23509
+ linkElement.click();
23510
+ }), [ tokens ]), copyToClipboard = useCallback((() => {
23511
+ navigator.clipboard?.writeText(JSON.stringify(tokens, null, 2));
23512
+ }), [ tokens ]), resetToDefaults = useCallback((() => {
23513
+ setTokens(defaultTokens);
23514
+ }), []), loadTokensFromFile = useCallback((event => {
23515
+ const file = event.target.files?.[0];
23516
+ if (!file) return;
23517
+ const reader = new FileReader;
23518
+ reader.onload = e => {
23519
+ try {
23520
+ const content = e.target?.result, mergedTokens = createTokens(JSON.parse(content));
23521
+ setTokens(mergedTokens);
23522
+ } catch (error) {
23523
+ console.error("Failed to load tokens:", error), alert("Invalid JSON file. Please select a valid design tokens JSON file.");
23524
+ }
23525
+ }, reader.readAsText(file);
23526
+ }), []), tokenCategories = {
23527
+ colors: {
23528
+ label: "Colors",
23529
+ tokens: [
23530
+ // Base colors
23531
+ "primary", "secondary", "success", "info", "warning", "error", "light", "dark",
23532
+ // RGB versions
23533
+ "primary-rgb", "secondary-rgb", "success-rgb", "info-rgb", "warning-rgb", "error-rgb", "light-rgb", "dark-rgb",
23534
+ // Gray scale
23535
+ "gray-1", "gray-2", "gray-3", "gray-4", "gray-5", "gray-6", "gray-7", "gray-8", "gray-9", "gray-10",
23536
+ // Primary scale
23537
+ "primary-1", "primary-2", "primary-3", "primary-4", "primary-5", "primary-6", "primary-7", "primary-8", "primary-9", "primary-10",
23538
+ // Text emphasis
23539
+ "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",
23540
+ // Background subtle
23541
+ "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",
23542
+ // Border subtle
23543
+ "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",
23544
+ // Hover states
23545
+ "primary-hover", "secondary-hover", "light-hover", "dark-hover", "error-hover", "success-hover", "warning-hover", "info-hover",
23546
+ // Gradients
23547
+ "primary-gradient", "secondary-gradient", "light-gradient", "dark-gradient", "success-gradient", "info-gradient", "warning-gradient", "error-gradient", "gradient" ]
23548
+ },
23549
+ typography: {
23550
+ label: "Typography",
23551
+ 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" ]
23552
+ },
23553
+ spacing: {
23554
+ label: "Spacing",
23555
+ 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" ]
23556
+ },
23557
+ shadows: {
23558
+ label: "Shadows",
23559
+ tokens: [ "box-shadow", "box-shadow-xs", "box-shadow-sm", "box-shadow-lg", "box-shadow-xl", "box-shadow-inset" ]
23560
+ },
23561
+ borders: {
23562
+ label: "Borders",
23563
+ 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" ]
23564
+ },
23565
+ transitions: {
23566
+ label: "Transitions",
23567
+ 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" ]
23568
+ },
23569
+ zindex: {
23570
+ label: "Z-Index",
23571
+ 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" ]
23572
+ },
23573
+ breakpoints: {
23574
+ label: "Breakpoints",
23575
+ tokens: [ "breakpoint-xs", "breakpoint-sm", "breakpoint-md", "breakpoint-lg", "breakpoint-xl", "breakpoint-xxl" ]
23576
+ }
23577
+ };
23578
+ // Update token value
23579
+ return jsxs("div", {
23580
+ className: `design-tokens-customizer ${className || ""}`,
23581
+ style: style,
23582
+ children: [ jsxs("div", {
23583
+ className: "customizer-header",
23584
+ children: [ jsx("h2", {
23585
+ children: "Interactive Theme Customizer"
23586
+ }), jsxs("div", {
23587
+ className: "customizer-controls",
23588
+ children: [ jsxs("select", {
23589
+ value: colorFormat,
23590
+ onChange: e => setColorFormat(e.target.value),
23591
+ children: [ jsx("option", {
23592
+ value: "hex",
23593
+ children: "HEX"
23594
+ }), jsx("option", {
23595
+ value: "rgb",
23596
+ children: "RGB"
23597
+ }), jsx("option", {
23598
+ value: "rgba",
23599
+ children: "RGBA"
23600
+ }), jsx("option", {
23601
+ value: "hsl",
23602
+ children: "HSL"
23603
+ }), jsx("option", {
23604
+ value: "hsla",
23605
+ children: "HSLA"
23606
+ }) ]
23607
+ }), jsx("button", {
23608
+ onClick: resetToDefaults,
23609
+ children: "Reset to Defaults"
23610
+ }), jsxs("label", {
23611
+ className: "file-input-button",
23612
+ children: [ "Load Tokens", jsx("input", {
23613
+ type: "file",
23614
+ accept: ".json",
23615
+ onChange: loadTokensFromFile,
23616
+ style: {
23617
+ display: "none"
23618
+ }
23619
+ }) ]
23620
+ }), jsx("button", {
23621
+ onClick: copyToClipboard,
23622
+ children: "Copy Tokens"
23623
+ }), jsx("button", {
23624
+ onClick: exportTokens,
23625
+ children: "Export Tokens"
23626
+ }), jsx("button", {
23627
+ onClick: exportTheme,
23628
+ children: "Export Theme CSS"
23629
+ }) ]
23630
+ }) ]
23631
+ }), jsxs("div", {
23632
+ className: "customizer-content",
23633
+ children: [ jsx("div", {
23634
+ className: "customizer-sidebar",
23635
+ children: Object.entries(tokenCategories).map((([key, category]) => jsx("button", {
23636
+ className: "category-button " + (activeCategory === key ? "active" : ""),
23637
+ onClick: () => setActiveCategory(key),
23638
+ children: category.label
23639
+ }, key)))
23640
+ }), jsxs("div", {
23641
+ className: "customizer-editor",
23642
+ children: [ jsx("h3", {
23643
+ children: tokenCategories[activeCategory].label
23644
+ }), jsx("div", {
23645
+ className: "tokens-grid",
23646
+ children: tokenCategories[activeCategory].tokens.map((tokenKey => {
23647
+ var _context;
23648
+ 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+$/);
23649
+ return jsxs("div", {
23650
+ className: "token-item",
23651
+ children: [ jsx("label", {
23652
+ children: tokenKey
23653
+ }), isColor ? jsxs("div", {
23654
+ className: "color-input-group",
23655
+ children: [ jsx("input", {
23656
+ type: "color",
23657
+ value: value.startsWith("#") ? value : convertColorFormat(value, "hex"),
23658
+ onChange: e => updateToken(tokenKey, e.target.value)
23659
+ }), jsx("input", {
23660
+ type: "text",
23661
+ value: convertColorFormat(value, colorFormat),
23662
+ onChange: e => {
23663
+ const converted = convertColorFormat(e.target.value, "hex");
23664
+ updateToken(tokenKey, converted);
23665
+ }
23666
+ }) ]
23667
+ }) : jsx("input", {
23668
+ type: "text",
23669
+ value: value,
23670
+ onChange: e => updateToken(tokenKey, e.target.value)
23671
+ }) ]
23672
+ }, tokenKey);
23673
+ }))
23674
+ }) ]
23675
+ }), jsxs("div", {
23676
+ className: "customizer-preview",
23677
+ children: [ jsx("h3", {
23678
+ children: "Live Preview"
23679
+ }), jsx("style", {
23680
+ children: cssPreview
23681
+ }), jsx(ThemePreview, {
23682
+ theme: previewTheme,
23683
+ showDetails: !1,
23684
+ showPalette: !0,
23685
+ showTypography: !0,
23686
+ showSpacing: !0
23687
+ }) ]
23688
+ }) ]
23689
+ }), jsx("style", {
23690
+ 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 "
23691
+ }) ]
23692
+ });
23066
23693
  };
23067
23694
 
23695
+ /**
23696
+ * Design Tokens Customizer Component
23697
+ */
23068
23698
  /**
23069
23699
  * Theme Adapter
23070
23700
  *
@@ -23075,7 +23705,8 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
23075
23705
  *
23076
23706
  * @param tokens - DesignTokens object
23077
23707
  * @returns CSS variables object compatible with Theme.cssVars
23078
- */ function designTokensToCSSVars(tokens) {
23708
+ */
23709
+ function designTokensToCSSVars(tokens) {
23079
23710
  const cssVars = {};
23080
23711
  return Object.entries(tokens).forEach((([key, value]) => {
23081
23712
  void 0 !== value && (cssVars[`--atomix-${key}`] = String(value));
@@ -23329,6 +23960,7 @@ class RTLManager {
23329
23960
 
23330
23961
  const themeImport = Object.freeze( Object.defineProperty({
23331
23962
  __proto__: null,
23963
+ DesignTokensCustomizer: DesignTokensCustomizer,
23332
23964
  RTLManager: RTLManager,
23333
23965
  ThemeApplicator: ThemeApplicator,
23334
23966
  ThemeComparator: ThemeComparator,
@@ -23916,20 +24548,53 @@ function quickTheme(name, primaryColor, secondaryColor) {
23916
24548
  /**
23917
24549
  * Create a dark theme variant from a light theme
23918
24550
  */ function createDarkVariant(lightTheme) {
23919
- return extendTheme(lightTheme, {
24551
+ // We'll extend the theme by merging the new properties with the existing theme
24552
+ const darkVariant = {
23920
24553
  name: `${lightTheme.name} Dark`,
23921
24554
  palette: {
23922
24555
  mode: "dark",
24556
+ primary: lightTheme.palette?.primary,
24557
+ // Preserve original primary
24558
+ secondary: lightTheme.palette?.secondary,
24559
+ // Preserve original secondary
24560
+ error: lightTheme.palette?.error,
24561
+ // Preserve original error
24562
+ warning: lightTheme.palette?.warning,
24563
+ // Preserve original warning
24564
+ info: lightTheme.palette?.info,
24565
+ // Preserve original info
24566
+ success: lightTheme.palette?.success,
24567
+ // Preserve original success
23923
24568
  background: {
23924
24569
  default: "#121212",
24570
+ paper: "#1e1e1e",
24571
+ // Added missing paper property
23925
24572
  subtle: "#1e1e1e"
23926
24573
  },
23927
24574
  text: {
23928
24575
  primary: "#ffffff",
23929
- secondary: "rgba(255, 255, 255, 0.7)"
24576
+ secondary: "rgba(255, 255, 255, 0.7)",
24577
+ disabled: "rgba(255, 255, 255, 0.38)"
23930
24578
  }
23931
24579
  }
23932
- });
24580
+ };
24581
+ // Create a new theme by extending the light theme with the dark variant
24582
+ return {
24583
+ ...lightTheme,
24584
+ ...darkVariant,
24585
+ palette: {
24586
+ ...lightTheme.palette,
24587
+ ...darkVariant.palette,
24588
+ background: {
24589
+ ...lightTheme.palette?.background,
24590
+ ...darkVariant.palette?.background
24591
+ },
24592
+ text: {
24593
+ ...lightTheme.palette?.text,
24594
+ ...darkVariant.palette?.text
24595
+ }
24596
+ }
24597
+ };
23933
24598
  }
23934
24599
 
23935
24600
  /**
@@ -24005,5 +24670,5 @@ const atomix = {
24005
24670
  types: types
24006
24671
  };
24007
24672
 
24008
- 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 };
24673
+ 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, 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 };
24009
24674
  //# sourceMappingURL=index.esm.js.map