@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/core.d.ts CHANGED
@@ -384,7 +384,7 @@ interface OverLightObjectConfig {
384
384
  * AtomixGlass component props interface
385
385
  */
386
386
  interface AtomixGlassProps {
387
- children: React.ReactNode;
387
+ children?: React.ReactNode;
388
388
  displacementScale?: number;
389
389
  blurAmount?: number;
390
390
  saturation?: number;
@@ -500,6 +500,7 @@ interface ListProps extends BaseComponentProps {
500
500
  variant?: listvariant;
501
501
  /**
502
502
  * List size
503
+ * @default 'md'
503
504
  */
504
505
  size?: Size;
505
506
  /**
@@ -542,10 +543,12 @@ interface ButtonProps extends BaseComponentProps {
542
543
  onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
543
544
  /**
544
545
  * Button variant
546
+ * @default 'solid'
545
547
  */
546
548
  variant?: Variant;
547
549
  /**
548
550
  * Button size
551
+ * @default 'md'
549
552
  */
550
553
  size?: Size;
551
554
  /**
@@ -642,19 +645,19 @@ interface ButtonProps extends BaseComponentProps {
642
645
  /**
643
646
  * ARIA label for accessibility
644
647
  */
645
- ariaLabel?: string;
648
+ 'aria-label'?: string;
646
649
  /**
647
650
  * ARIA described by reference
648
651
  */
649
- ariaDescribedBy?: string;
652
+ 'aria-describedby'?: string;
650
653
  /**
651
654
  * ARIA expanded state (for toggle buttons)
652
655
  */
653
- ariaExpanded?: boolean;
656
+ 'aria-expanded'?: boolean;
654
657
  /**
655
658
  * ARIA controls reference
656
659
  */
657
- ariaControls?: string;
660
+ 'aria-controls'?: string;
658
661
  /**
659
662
  * Tab index for keyboard navigation
660
663
  */
@@ -683,16 +686,26 @@ interface BadgeProps extends BaseComponentProps {
683
686
  label: string;
684
687
  /**
685
688
  * Badge color variant
689
+ * @default 'primary'
686
690
  */
687
691
  variant?: ThemeColor;
688
692
  /**
689
693
  * Badge size
694
+ * @default 'md'
690
695
  */
691
696
  size?: Size;
692
697
  /**
693
698
  * Optional icon
694
699
  */
695
700
  icon?: ReactNode;
701
+ /**
702
+ * Callback for dismissible badges (shows close button when provided)
703
+ */
704
+ onRemove?: () => void;
705
+ /**
706
+ * Accessible label for the badge
707
+ */
708
+ 'aria-label'?: string;
696
709
  /**
697
710
  * Glass morphism effect for the badge
698
711
  * Can be a boolean to enable with default settings, or an object with AtomixGlassProps to customize the effect
@@ -764,13 +777,13 @@ interface CalloutProps extends BaseComponentProps {
764
777
  */
765
778
  actions?: ReactNode;
766
779
  /**
767
- * Display in one line mode
780
+ * Display in compact (one-line) mode
768
781
  */
769
- oneLine?: boolean;
782
+ compact?: boolean;
770
783
  /**
771
784
  * Display as toast notification
772
785
  */
773
- toast?: boolean;
786
+ isToast?: boolean;
774
787
  /**
775
788
  * Glass morphism effect for the callout
776
789
  * Can be a boolean to enable with default settings, or an object with AtomixGlassProps to customize the effect
@@ -813,12 +826,17 @@ interface AccordionProps$1 extends BaseComponentProps {
813
826
  * Whether the accordion is disabled
814
827
  */
815
828
  disabled?: boolean;
829
+ /**
830
+ * Callback called when the open state changes
831
+ */
816
832
  onOpenChange?: (open: boolean) => void;
817
833
  /**
834
+ * @deprecated Use onOpenChange instead
818
835
  * Optional open handler
819
836
  */
820
837
  onOpen?: () => void;
821
838
  /**
839
+ * @deprecated Use onOpenChange instead
822
840
  * Optional close handler
823
841
  */
824
842
  onClose?: () => void;
@@ -834,16 +852,28 @@ interface AccordionProps$1 extends BaseComponentProps {
834
852
  interface SpinnerProps extends BaseComponentProps {
835
853
  /**
836
854
  * Spinner color variant
855
+ * @default 'primary'
837
856
  */
838
857
  variant?: ThemeColor;
839
858
  /**
840
859
  * Spinner size
860
+ * @default 'md'
841
861
  */
842
862
  size?: Size;
843
863
  /**
844
864
  * Whether the spinner should be displayed fullscreen
845
865
  */
846
866
  fullscreen?: boolean;
867
+ /**
868
+ * Accessible label for screen readers
869
+ * @default 'Loading'
870
+ */
871
+ 'aria-label'?: string;
872
+ /**
873
+ * ARIA role for the spinner
874
+ * @default 'status'
875
+ */
876
+ role?: 'status' | 'alert';
847
877
  /**
848
878
  * Glass morphism effect for the spinner
849
879
  * Can be a boolean to enable with default settings, or an object with AtomixGlassProps to customize the effect
@@ -982,11 +1012,11 @@ interface CardProps extends BaseComponentProps {
982
1012
  /**
983
1013
  * ARIA label for accessibility
984
1014
  */
985
- ariaLabel?: string;
1015
+ 'aria-label'?: string;
986
1016
  /**
987
1017
  * ARIA described by reference
988
1018
  */
989
- ariaDescribedBy?: string;
1019
+ 'aria-describedby'?: string;
990
1020
  /**
991
1021
  * Tab index for keyboard navigation
992
1022
  */
@@ -1210,7 +1240,7 @@ interface BreadcrumbProps {
1210
1240
  /**
1211
1241
  * Aria label for the navigation
1212
1242
  */
1213
- ariaLabel?: string;
1243
+ 'aria-label'?: string;
1214
1244
  /**
1215
1245
  * Optional custom link component
1216
1246
  */
package/dist/core.js CHANGED
@@ -588,7 +588,13 @@ import * as PhosphorIcons from "@phosphor-icons/react";
588
588
  GlassFilterComponent.displayName = "GlassFilter";
589
589
 
590
590
  // Memoize component to prevent unnecessary re-renders
591
- 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 = {
591
+ 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));
592
+
593
+ // Module-level counter for deterministic ID generation
594
+ let idCounter = 0;
595
+
596
+ // Module-level shared shader cache with LRU eviction
597
+ 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 = {
592
598
  x: 0,
593
599
  y: 0
594
600
  }, globalMousePosition: globalMousePosition = {
@@ -599,10 +605,8 @@ const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevP
599
605
  height: 0
600
606
  }, onClick: onClick, mode: mode = "standard", effectiveDisableEffects: effectiveDisableEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", enableLiquidBlur: enableLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
601
607
  // Generate a stable, deterministic ID for SSR compatibility
602
- // Use a counter-based approach to avoid hydration mismatches
603
- const [filterId] = useState((() =>
604
- // Use a simple counter for deterministic IDs
605
- "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);
608
+ // Use a module-level counter that's consistent across server and client
609
+ const filterId = useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null);
606
610
  // Lazy load shader utilities only when shader mode is needed
607
611
  useEffect((() => {
608
612
  "shader" === mode ?
@@ -643,9 +647,9 @@ const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevP
643
647
  width: glassSize.width,
644
648
  height: glassSize.height,
645
649
  fragment: selectedShader
646
- });
647
- // Use requestIdleCallback if available for non-blocking generation
648
- const generate = () => {
650
+ }),
651
+ // Defer shader generation with longer delay to avoid blocking
652
+ setTimeout((() => {
649
653
  const url = shaderGeneratorRef.current?.updateShader() || "";
650
654
  ((key, url) => {
651
655
  // Evict oldest entries if at capacity
@@ -664,20 +668,15 @@ const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevP
664
668
  // Development mode: log cache size
665
669
  "undefined" != typeof process && "production" === process.env?.NODE_ENV || sharedShaderCache.size;
666
670
  })(cacheKey, url), setShaderMapUrl(url);
667
- };
668
- "undefined" != typeof requestIdleCallback ? requestIdleCallback(generate, {
669
- timeout: 1e3
670
- }) :
671
- // Fallback to setTimeout for browsers without requestIdleCallback
672
- setTimeout(generate, 0);
671
+ }), 100);
673
672
  } catch (error) {
674
673
  console.warn("AtomixGlassContainer: Error generating shader map", error), setShaderMapUrl("");
675
674
  } else
676
675
  // Shader utils not loaded yet, retry after a short delay
677
676
  shaderDebounceTimeoutRef.current = setTimeout(generateShader, 100);
678
677
  };
679
- // Debounce with 300ms delay
680
- shaderDebounceTimeoutRef.current = setTimeout(generateShader, 300);
678
+ // Debounce with 500ms delay to reduce frequency
679
+ shaderDebounceTimeoutRef.current = setTimeout(generateShader, 500);
681
680
  } else
682
681
  // Not in shader mode, clear URL
683
682
  setShaderMapUrl("");
@@ -744,7 +743,7 @@ const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevP
744
743
  backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
745
744
  };
746
745
  }
747
- }), [ filterId, liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveDisableEffects, enableLiquidBlur ]), containerVars = useMemo((() => {
746
+ }), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveDisableEffects, enableLiquidBlur ]), containerVars = useMemo((() => {
748
747
  try {
749
748
  // Safe extraction of mouse offset values
750
749
  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;
@@ -833,7 +832,6 @@ const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevP
833
832
  });
834
833
  }));
835
834
 
836
- // Module-level shared shader cache with LRU eviction
837
835
  AtomixGlassContainer.displayName = "AtomixGlassContainer";
838
836
 
839
837
  // Singleton instance
@@ -1581,7 +1579,7 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadiu
1581
1579
  });
1582
1580
  }
1583
1581
 
1584
- 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}) => {
1582
+ 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}) => {
1585
1583
  // Generate unique IDs for accessibility
1586
1584
  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} =
1587
1585
  /**
@@ -1623,7 +1621,12 @@ const Accordion = memo((({title: title, children: children, defaultOpen: defaul
1623
1621
  panelHeight: panelHeight
1624
1622
  },
1625
1623
  toggle: () => {
1626
- defaultProps.disabled || (isControlled ? defaultProps.onOpenChange && defaultProps.onOpenChange(!isOpen) : setInternalOpen((prev => !prev)));
1624
+ if (!defaultProps.disabled) {
1625
+ const nextOpen = !isOpen;
1626
+ isControlled || setInternalOpen(nextOpen), defaultProps.onOpenChange?.(nextOpen),
1627
+ // Call legacy handlers
1628
+ nextOpen ? defaultProps.onOpen?.() : defaultProps.onClose?.();
1629
+ }
1627
1630
  },
1628
1631
  updatePanelHeight: updatePanelHeight,
1629
1632
  panelRef: panelRef,
@@ -1636,7 +1639,9 @@ const Accordion = memo((({title: title, children: children, defaultOpen: defaul
1636
1639
  disabled: disabled,
1637
1640
  iconPosition: iconPosition,
1638
1641
  isOpen: controlledOpen,
1639
- onOpenChange: onOpenChange
1642
+ onOpenChange: onOpenChange,
1643
+ onOpen: onOpen,
1644
+ onClose: onClose
1640
1645
  }), defaultIcon = jsx("i", {
1641
1646
  className: "c-accordion__icon",
1642
1647
  "aria-hidden": "true",
@@ -1705,7 +1710,7 @@ const Accordion = memo((({title: title, children: children, defaultOpen: defaul
1705
1710
  // Set display name for debugging
1706
1711
  Accordion.displayName = "Accordion";
1707
1712
 
1708
- const Badge = memo((({label: label, variant: variant = "primary", size: size = "md", disabled: disabled = !1, icon: icon, className: className = "", glass: glass, style: style}) => {
1713
+ 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}) => {
1709
1714
  const {generateBadgeClass: generateBadgeClass} =
1710
1715
  /**
1711
1716
  * Badge state and functionality
@@ -1743,6 +1748,7 @@ const Badge = memo((({label: label, variant: variant = "primary", size: size =
1743
1748
  }), badgeElement = jsxs("span", {
1744
1749
  className: badgeClass,
1745
1750
  "aria-disabled": disabled,
1751
+ "aria-label": ariaLabel,
1746
1752
  ref: ref,
1747
1753
  style: style,
1748
1754
  children: [ icon && jsx("span", {
@@ -1750,6 +1756,13 @@ const Badge = memo((({label: label, variant: variant = "primary", size: size =
1750
1756
  children: icon
1751
1757
  }), jsx("span", {
1752
1758
  children: label
1759
+ }), onRemove && jsx("button", {
1760
+ type: "button",
1761
+ className: "c-badge__close",
1762
+ onClick: onRemove,
1763
+ "aria-label": "Remove badge",
1764
+ disabled: disabled,
1765
+ children: "×"
1753
1766
  }) ]
1754
1767
  });
1755
1768
  if (glass) {
@@ -1877,7 +1890,7 @@ const Block = forwardRef((({children: children, as: Component = "section", spac
1877
1890
  * ```
1878
1891
  */ Block.displayName = "Block";
1879
1892
 
1880
- const Breadcrumb = memo((({items: items, divider: divider, className: className = "", ariaLabel: ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style}) => {
1893
+ const Breadcrumb = memo((({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style}) => {
1881
1894
  const breadcrumbClasses = [ BREADCRUMB.CLASSES.BASE, className ].filter(Boolean).join(" ");
1882
1895
  return jsx("nav", {
1883
1896
  "aria-label": ariaLabel,
@@ -1914,7 +1927,7 @@ const Breadcrumb = memo((({items: items, divider: divider, className: className
1914
1927
 
1915
1928
  Breadcrumb.displayName = "Breadcrumb";
1916
1929
 
1917
- const Spinner = memo((({size: size = "md", variant: variant = "primary", fullscreen: fullscreen = !1, className: className = "", style: style, glass: glass}) => {
1930
+ const Spinner = memo((({size: size = "md", variant: variant = "primary", fullscreen: fullscreen = !1, className: className = "", style: style, glass: glass, "aria-label": ariaLabel, role: role = "status"}) => {
1918
1931
  const {generateSpinnerClass: generateSpinnerClass} =
1919
1932
  /**
1920
1933
  * Spinner state and functionality
@@ -1952,10 +1965,11 @@ const Spinner = memo((({size: size = "md", variant: variant = "primary", fullsc
1952
1965
  }), spinnerContent = jsx("div", {
1953
1966
  className: spinnerClass,
1954
1967
  style: style,
1955
- role: "status",
1968
+ role: role,
1969
+ "aria-label": ariaLabel || "Loading",
1956
1970
  children: jsx("span", {
1957
1971
  className: "u-visually-hidden",
1958
- children: "Loading..."
1972
+ children: ariaLabel || "Loading..."
1959
1973
  })
1960
1974
  });
1961
1975
  if (glass) {
@@ -2036,7 +2050,7 @@ class ThemeNaming {
2036
2050
  * Convert kebab-case to camelCase for JavaScript properties
2037
2051
  * @param str - String to convert
2038
2052
  */ static kebabToCamel(str) {
2039
- return str.replace(/-([a-z])/g, (g => g[1].toUpperCase()));
2053
+ return str.replace(/-([a-z])/g, (g => g[1]?.toUpperCase() ?? ""));
2040
2054
  }
2041
2055
  /**
2042
2056
  * Create a CSS variable name
@@ -2097,7 +2111,7 @@ class ThemeNaming {
2097
2111
 
2098
2112
  ThemeNaming.prefix = "atomix";
2099
2113
 
2100
- 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) => {
2114
+ 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) => {
2101
2115
  const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href && !isDisabled), iconElement = iconName ? jsx(Icon, {
2102
2116
  name: iconName,
2103
2117
  size: iconSize
@@ -2220,7 +2234,7 @@ onClick: onClick, onHover: onHover, onFocus: onFocus, href: href, target: target
2220
2234
  // Glass
2221
2235
  glass: glass,
2222
2236
  // Accessibility
2223
- role: role, ariaLabel: ariaLabel, ariaDescribedBy: ariaDescribedBy, tabIndex: tabIndex,
2237
+ role: role, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, tabIndex: tabIndex,
2224
2238
  // Styling
2225
2239
  className: className = "", style: style, ...rest}, ref) => {
2226
2240
  // Determine if card is clickable/interactive
@@ -2838,7 +2852,7 @@ var includes$3 = getBuiltInPrototypeMethod$2("String", "includes"), isPrototypeO
2838
2852
  const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
2839
2853
  var own = it.includes;
2840
2854
  return it === ArrayPrototype || isPrototypeOf(ArrayPrototype, it) && own === ArrayPrototype.includes ? arrayMethod : "string" == typeof it || it === StringPrototype || isPrototypeOf(StringPrototype, it) && own === StringPrototype.includes ? stringMethod : own;
2841
- })), 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}) => {
2855
+ })), 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}) => {
2842
2856
  const {generateCalloutClass: generateCalloutClass, handleClose: handleClose} =
2843
2857
  /**
2844
2858
  * Callout state and functionality
@@ -2849,8 +2863,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
2849
2863
  // Default callout properties
2850
2864
  const defaultProps = {
2851
2865
  variant: "primary",
2852
- oneLine: !1,
2853
- toast: !1,
2866
+ compact: !1,
2867
+ isToast: !1,
2854
2868
  glass: !1,
2855
2869
  ...initialProps
2856
2870
  };
@@ -2861,8 +2875,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
2861
2875
  */ return {
2862
2876
  defaultProps: defaultProps,
2863
2877
  generateCalloutClass: props => {
2864
- const {variant: variant = defaultProps.variant, oneLine: oneLine = defaultProps.oneLine, toast: toast = defaultProps.toast, glass: glass = defaultProps.glass, className: className = ""} = props;
2865
- return `c-callout ${variant ? `c-callout--${variant}` : ""} ${oneLine ? "c-callout--oneline" : ""} ${toast ? "c-callout--toast" : ""} ${glass ? "c-callout--glass" : ""} ${className}`.trim();
2878
+ const {variant: variant = defaultProps.variant, compact: compact = defaultProps.compact, isToast: isToast = defaultProps.isToast, glass: glass = defaultProps.glass, className: className = ""} = props;
2879
+ return `c-callout ${variant ? `c-callout--${variant}` : ""} ${compact ? "c-callout--compact" : ""} ${isToast ? "c-callout--toast" : ""} ${glass ? "c-callout--glass" : ""} ${className}`.trim();
2866
2880
  },
2867
2881
  handleClose: handler => () => {
2868
2882
  handler && handler();
@@ -2873,8 +2887,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
2873
2887
  * Callout component for displaying important messages, notifications, or alerts
2874
2888
  */ ({
2875
2889
  variant: variant,
2876
- oneLine: oneLine,
2877
- toast: toast,
2890
+ compact: compact,
2891
+ isToast: isToast,
2878
2892
  glass: glass,
2879
2893
  className: className,
2880
2894
  style: style
@@ -2884,7 +2898,7 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
2884
2898
  role: "region"
2885
2899
  };
2886
2900
  // For toast notifications or alerts, use appropriate role and live region
2887
- return toast ? (baseAttributes.role = "alert", baseAttributes["aria-live"] = "polite") : _includesInstanceProperty(_context = [ "warning", "error" ]).call(_context, variant) ? (baseAttributes.role = "alert",
2901
+ return isToast ? (baseAttributes.role = "alert", baseAttributes["aria-live"] = "polite") : _includesInstanceProperty(_context = [ "warning", "error" ]).call(_context, variant) ? (baseAttributes.role = "alert",
2888
2902
  baseAttributes["aria-live"] = "assertive") : _includesInstanceProperty(_context2 = [ "info", "success" ]).call(_context2, variant) && (baseAttributes.role = "status",
2889
2903
  baseAttributes["aria-live"] = "polite"), baseAttributes;
2890
2904
  }, calloutContent = jsxs(Fragment, {
@@ -2930,8 +2944,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
2930
2944
  return jsx("div", {
2931
2945
  className: generateCalloutClass({
2932
2946
  variant: variant,
2933
- oneLine: oneLine,
2934
- toast: toast,
2947
+ compact: compact,
2948
+ isToast: isToast,
2935
2949
  glass: glass,
2936
2950
  className: className
2937
2951
  }),
@@ -2953,8 +2967,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
2953
2967
  return jsx("div", {
2954
2968
  className: generateCalloutClass({
2955
2969
  variant: variant,
2956
- oneLine: oneLine,
2957
- toast: toast,
2970
+ compact: compact,
2971
+ isToast: isToast,
2958
2972
  glass: glass,
2959
2973
  className: className
2960
2974
  }),