@shohojdhara/atomix 0.5.2 → 0.5.5

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 (61) hide show
  1. package/atomix.config.ts +33 -33
  2. package/dist/atomix.css +3213 -159
  3. package/dist/atomix.css.map +1 -1
  4. package/dist/atomix.min.css +5 -5
  5. package/dist/atomix.min.css.map +1 -1
  6. package/dist/config.d.ts +187 -112
  7. package/dist/config.js +2 -47
  8. package/dist/config.js.map +1 -1
  9. package/dist/index.d.ts +1958 -900
  10. package/dist/index.esm.js +2279 -382
  11. package/dist/index.esm.js.map +1 -1
  12. package/dist/index.js +2332 -413
  13. package/dist/index.js.map +1 -1
  14. package/dist/index.min.js +1 -1
  15. package/dist/index.min.js.map +1 -1
  16. package/dist/theme.d.ts +1390 -276
  17. package/dist/theme.js +2125 -621
  18. package/dist/theme.js.map +1 -1
  19. package/package.json +1 -1
  20. package/scripts/cli/internal/config-loader.js +30 -20
  21. package/src/lib/config/index.ts +38 -362
  22. package/src/lib/config/loader.ts +422 -0
  23. package/src/lib/config/public-api.ts +43 -0
  24. package/src/lib/config/types.ts +389 -0
  25. package/src/lib/config/validator.ts +305 -0
  26. package/src/lib/theme/adapters/index.ts +1 -1
  27. package/src/lib/theme/adapters/themeAdapter.ts +358 -229
  28. package/src/lib/theme/components/ThemeToggle.tsx +276 -0
  29. package/src/lib/theme/config/configLoader.ts +351 -0
  30. package/src/lib/theme/config/loader.ts +221 -0
  31. package/src/lib/theme/core/createTheme.ts +126 -50
  32. package/src/lib/theme/core/createThemeObject.ts +7 -4
  33. package/src/lib/theme/hooks/useThemeSwitcher.ts +164 -0
  34. package/src/lib/theme/index.ts +322 -38
  35. package/src/lib/theme/runtime/ThemeProvider.tsx +44 -10
  36. package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +44 -393
  37. package/src/lib/theme/runtime/useTheme.ts +1 -0
  38. package/src/lib/theme/tokens/tokens.ts +101 -1
  39. package/src/lib/theme/types.ts +91 -0
  40. package/src/lib/theme/utils/performanceMonitor.ts +315 -0
  41. package/src/lib/theme/utils/responsive.ts +280 -0
  42. package/src/lib/theme/utils/themeUtils.ts +531 -117
  43. package/src/styles/01-settings/_settings.background.scss +34 -5
  44. package/src/styles/02-tools/_tools.background.scss +330 -52
  45. package/src/styles/05-objects/_objects.masonry-grid.scss +3 -3
  46. package/src/styles/06-components/_components.accordion.scss +2 -2
  47. package/src/styles/06-components/_components.badge.scss +1 -1
  48. package/src/styles/06-components/_components.button.scss +2 -2
  49. package/src/styles/06-components/_components.callout.scss +2 -2
  50. package/src/styles/06-components/_components.card.scss +1 -1
  51. package/src/styles/06-components/_components.dropdown.scss +1 -1
  52. package/src/styles/06-components/_components.dynamic-background.scss +69 -0
  53. package/src/styles/06-components/_components.edge-panel.scss +2 -2
  54. package/src/styles/06-components/_components.input.scss +3 -3
  55. package/src/styles/06-components/_components.messages.scss +6 -6
  56. package/src/styles/06-components/_components.modal.scss +1 -1
  57. package/src/styles/06-components/_components.navbar.scss +1 -1
  58. package/src/styles/06-components/_components.popover.scss +1 -1
  59. package/src/styles/06-components/_components.toggle.scss +1 -1
  60. package/src/styles/06-components/_components.tooltip.scss +3 -3
  61. package/src/styles/06-components/_index.scss +1 -0
package/dist/index.esm.js CHANGED
@@ -3562,7 +3562,7 @@ function useResponsiveGlass({baseParams: baseParams, breakpoints: breakpoints =
3562
3562
  * @param config Monitor configuration
3563
3563
  * @returns Performance metrics and controls
3564
3564
  */
3565
- function usePerformanceMonitor(config = {}) {
3565
+ function usePerformanceMonitor$1(config = {}) {
3566
3566
  const {enabled: enabled = !0, targetFps: targetFps = 60, minFps: minFps = 45, scaleUpThreshold: scaleUpThreshold = 58, lowFpsFrames: lowFpsFrames = 3, highFpsFrames: highFpsFrames = 10, debug: debug = !1, showOverlay: showOverlay = !1} = config, [metrics, setMetrics] = useState({
3567
3567
  fps: 0,
3568
3568
  frameTime: 0,
@@ -4118,7 +4118,7 @@ function getDevicePreset(presetName) {
4118
4118
  debug: !1
4119
4119
  });
4120
4120
  // Performance monitoring - tracks FPS, frame time, memory usage
4121
- const {metrics: performanceMetrics, toggleMonitoring: toggleMonitoring} = usePerformanceMonitor({
4121
+ const {metrics: performanceMetrics, toggleMonitoring: toggleMonitoring} = usePerformanceMonitor$1({
4122
4122
  enabled: debugPerformance,
4123
4123
  // Enable when debugPerformance is true
4124
4124
  debug: !1,
@@ -5111,7 +5111,7 @@ const BreadcrumbItem = forwardRef((({children: children, href: href, active: ac
5111
5111
 
5112
5112
  BreadcrumbItem.displayName = "BreadcrumbItem";
5113
5113
 
5114
- const Breadcrumb = memo((function({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", linkComponent: linkComponent, style: style, children: children}) {
5114
+ const BreadcrumbComponent = memo((function({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", linkComponent: linkComponent, style: style, children: children}) {
5115
5115
  const breadcrumbClasses = [ BREADCRUMB.CLASSES.BASE, className ].filter(Boolean).join(" ");
5116
5116
  let content;
5117
5117
  if (items && items.length > 0)
@@ -5151,7 +5151,7 @@ const Breadcrumb = memo((function({items: items, divider: divider, className: c
5151
5151
  children: content
5152
5152
  })
5153
5153
  });
5154
- }));
5154
+ })), Breadcrumb = BreadcrumbComponent;
5155
5155
 
5156
5156
  /**
5157
5157
  * Spinner state and functionality
@@ -13502,21 +13502,21 @@ function useTodo(initialProps) {
13502
13502
  const [interaction, setInteraction] = useState({
13503
13503
  hoveredIndex: null,
13504
13504
  selectedIndex: null
13505
- });
13505
+ }), handlePointHover = useCallback((index => {
13506
+ setInteraction((prev => ({
13507
+ ...prev,
13508
+ hoveredIndex: index
13509
+ })));
13510
+ }), []), handlePointClick = useCallback((index => {
13511
+ setInteraction((prev => ({
13512
+ ...prev,
13513
+ selectedIndex: prev.selectedIndex === index ? null : index
13514
+ })));
13515
+ }), []);
13506
13516
  return {
13507
13517
  interaction: interaction,
13508
- handlePointHover: useCallback((index => {
13509
- setInteraction((prev => ({
13510
- ...prev,
13511
- hoveredIndex: index
13512
- })));
13513
- }), []),
13514
- handlePointClick: useCallback((index => {
13515
- setInteraction((prev => ({
13516
- ...prev,
13517
- selectedIndex: prev.selectedIndex === index ? null : index
13518
- })));
13519
- }), []),
13518
+ handlePointHover: handlePointHover,
13519
+ handlePointClick: handlePointClick,
13520
13520
  clearInteraction: useCallback((() => {
13521
13521
  setInteraction({
13522
13522
  hoveredIndex: null,
@@ -13559,7 +13559,7 @@ const composablesImport = Object.freeze( Object.defineProperty({
13559
13559
  useNavDropdown: useNavDropdown,
13560
13560
  useNavItem: useNavItem,
13561
13561
  useNavbar: useNavbar,
13562
- usePerformanceMonitor: usePerformanceMonitor,
13562
+ usePerformanceMonitor: usePerformanceMonitor$1,
13563
13563
  usePieChart: usePieChart,
13564
13564
  useRadio: useRadio,
13565
13565
  useResponsiveGlass: useResponsiveGlass,
@@ -18819,7 +18819,7 @@ const TabsPanel = forwardRef((({children: children, className: className = "",
18819
18819
 
18820
18820
  TabsPanel.displayName = "TabsPanel";
18821
18821
 
18822
- const Tabs = memo((({items: items, activeIndex: activeIndex = TAB.DEFAULTS.ACTIVE_INDEX, onTabChange: onTabChange, className: className = "", style: style, glass: glass, children: children}) => {
18822
+ const TabsComponentBase = ({items: items, activeIndex: activeIndex = TAB.DEFAULTS.ACTIVE_INDEX, onTabChange: onTabChange, className: className = "", style: style, glass: glass, children: children}) => {
18823
18823
  const [currentTab, setCurrentTab] = useState(activeIndex), handleTabClick = index => {
18824
18824
  setCurrentTab(index), onTabChange && onTabChange(index);
18825
18825
  }, handleKeyDown = (event, totalTabs) => {
@@ -18935,7 +18935,7 @@ const Tabs = memo((({items: items, activeIndex: activeIndex = TAB.DEFAULTS.ACTI
18935
18935
  });
18936
18936
  }
18937
18937
  return wrapper;
18938
- }));
18938
+ }, Tabs = memo(TabsComponentBase);
18939
18939
 
18940
18940
  Tabs.displayName = "Tabs", Tabs.List = TabsList, Tabs.Trigger = TabsTrigger, Tabs.Panels = TabsPanels,
18941
18941
  Tabs.Panel = TabsPanel;
@@ -20853,7 +20853,51 @@ const components = Object.freeze( Object.defineProperty({
20853
20853
  "breakpoint-md": "768px",
20854
20854
  "breakpoint-lg": "992px",
20855
20855
  "breakpoint-xl": "1200px",
20856
- "breakpoint-xxl": "1440px"
20856
+ "breakpoint-xxl": "1440px",
20857
+ // Advanced Features - Interactive Effects (Phase 2)
20858
+ "interactive-vortex-enabled": "false",
20859
+ "interactive-vortex-strength": "0.5",
20860
+ "interactive-vortex-radius": "100",
20861
+ "interactive-vortex-decay": "0.8",
20862
+ "interactive-chromatic-enabled": "false",
20863
+ "interactive-chromatic-mode": "lateral",
20864
+ "interactive-chromatic-red-shift": "0.02",
20865
+ "interactive-chromatic-green-shift": "0",
20866
+ "interactive-chromatic-blue-shift": "-0.02",
20867
+ "interactive-chromatic-edge-only": "false",
20868
+ "interactive-chromatic-edge-threshold": "0.5",
20869
+ "interactive-mouse-sensitivity": "1.0",
20870
+ "interactive-mouse-trail-effect": "false",
20871
+ "interactive-animation-speed-base": "1.0",
20872
+ "interactive-animation-speed-multiplier": "1.0",
20873
+ // Advanced Features - Optimization (Phase 3)
20874
+ "optimization-breakpoint-mobile": "0px",
20875
+ "optimization-breakpoint-tablet": "768px",
20876
+ "optimization-breakpoint-desktop": "1024px",
20877
+ "optimization-breakpoint-wide": "1440px",
20878
+ "optimization-device-scaling-mobile": "0.5",
20879
+ "optimization-device-scaling-tablet": "0.75",
20880
+ "optimization-device-scaling-desktop": "1.0",
20881
+ "optimization-performance-fps-target": "60",
20882
+ "optimization-auto-scaling-enabled": "false",
20883
+ "optimization-auto-scaling-low-end": "0.5",
20884
+ "optimization-auto-scaling-mid-range": "0.75",
20885
+ "optimization-auto-scaling-high-end": "1.0",
20886
+ // Advanced Features - Visual Polish (Phase 4)
20887
+ "visual-polish-border-iridescent-glow": "false",
20888
+ "visual-polish-border-shimmer-effect": "false",
20889
+ "visual-polish-border-beveled-edges": "false",
20890
+ "visual-polish-border-pulsing-glow": "false",
20891
+ "visual-polish-content-aware-blur-enabled": "false",
20892
+ "visual-polish-content-aware-depth-detection": "false",
20893
+ "visual-polish-content-aware-edge-preservation": "false",
20894
+ "visual-polish-content-aware-variable-radius": "false",
20895
+ "visual-polish-holographic-enabled": "false",
20896
+ "visual-polish-holographic-rainbow-diffraction": "false",
20897
+ "visual-polish-holographic-scanline-animation": "false",
20898
+ "visual-polish-holographic-grid-overlay": "false",
20899
+ "visual-polish-holographic-data-stream": "false",
20900
+ "visual-polish-holographic-pulse-rings": "false"
20857
20901
  };
20858
20902
 
20859
20903
  // Export all component types
@@ -20935,158 +20979,501 @@ function createTokens(overrides) {
20935
20979
  }
20936
20980
 
20937
20981
  /**
20938
- * Theme System Error Handling
20982
+ * Theme Adapter
20939
20983
  *
20940
- * Centralized error handling for the Atomix theme system.
20941
- * Provides custom error classes and logging utilities.
20984
+ * Converts between Theme objects and DesignTokens
20942
20985
  */
20943
20986
  /**
20944
- * Theme error codes
20945
- */ var ThemeErrorCode, LogLevel;
20946
-
20947
- !function(ThemeErrorCode) {
20948
- /** Theme not found in registry */
20949
- ThemeErrorCode.THEME_NOT_FOUND = "THEME_NOT_FOUND",
20950
- /** Theme failed to load */
20951
- ThemeErrorCode.THEME_LOAD_FAILED = "THEME_LOAD_FAILED",
20952
- /** Theme validation failed */
20953
- ThemeErrorCode.THEME_VALIDATION_FAILED = "THEME_VALIDATION_FAILED",
20954
- /** Configuration loading failed */
20955
- ThemeErrorCode.CONFIG_LOAD_FAILED = "CONFIG_LOAD_FAILED",
20956
- /** Configuration validation failed */
20957
- ThemeErrorCode.CONFIG_VALIDATION_FAILED = "CONFIG_VALIDATION_FAILED",
20958
- /** Circular dependency detected */
20959
- ThemeErrorCode.CIRCULAR_DEPENDENCY = "CIRCULAR_DEPENDENCY",
20960
- /** Missing dependency */
20961
- ThemeErrorCode.MISSING_DEPENDENCY = "MISSING_DEPENDENCY",
20962
- /** Storage operation failed */
20963
- ThemeErrorCode.STORAGE_ERROR = "STORAGE_ERROR",
20964
- /** Invalid theme name */
20965
- ThemeErrorCode.INVALID_THEME_NAME = "INVALID_THEME_NAME",
20966
- /** CSS injection failed */
20967
- ThemeErrorCode.CSS_INJECTION_FAILED = "CSS_INJECTION_FAILED",
20968
- /** Invalid color format */
20969
- ThemeErrorCode.INVALID_COLOR_FORMAT = "INVALID_COLOR_FORMAT",
20970
- /** Missing required token */
20971
- ThemeErrorCode.MISSING_REQUIRED_TOKEN = "MISSING_REQUIRED_TOKEN",
20972
- /** Accessibility contrast violation */
20973
- ThemeErrorCode.CONTRAST_VIOLATION = "CONTRAST_VIOLATION",
20974
- /** Invalid token type */
20975
- ThemeErrorCode.INVALID_TOKEN_TYPE = "INVALID_TOKEN_TYPE",
20976
- /** Unknown error */
20977
- ThemeErrorCode.UNKNOWN_ERROR = "UNKNOWN_ERROR";
20978
- }(ThemeErrorCode || (ThemeErrorCode = {}));
20987
+ * Convert a Theme object to DesignTokens
20988
+ */ function themeToDesignTokens(theme) {
20989
+ const tokens = {};
20990
+ // Convert colors
20991
+ if (theme.palette) {
20992
+ // Primary color
20993
+ if (theme.palette.primary) {
20994
+ const primaryMain = theme.palette.primary.main;
20995
+ tokens.primary = primaryMain;
20996
+ const rgb = hexToRgb$2(primaryMain);
20997
+ rgb && (tokens["primary-rgb"] = rgb);
20998
+ }
20999
+ // Secondary color
21000
+ if (theme.palette.secondary) {
21001
+ const secondaryMain = theme.palette.secondary.main;
21002
+ tokens.secondary = secondaryMain;
21003
+ const rgb = hexToRgb$2(secondaryMain);
21004
+ rgb && (tokens["secondary-rgb"] = rgb);
21005
+ }
21006
+ // Other colors
21007
+ const colorKeys = [ "error", "warning", "info", "success" ];
21008
+ for (const key of colorKeys) if (theme.palette[key]) {
21009
+ const colorMain = theme.palette[key].main;
21010
+ tokens[key] = colorMain;
21011
+ const rgb = hexToRgb$2(colorMain);
21012
+ rgb && (tokens[`${key}-rgb`] = rgb);
21013
+ }
21014
+ // Background colors
21015
+ theme.palette.background && (tokens["body-bg"] = theme.palette.background.default),
21016
+ // Text colors
21017
+ theme.palette.text && (tokens["body-color"] = theme.palette.text.primary);
21018
+ }
21019
+ // Convert typography
21020
+ // Convert border radius
21021
+ if (theme.typography && (tokens["body-font-family"] = theme.typography.fontFamily,
21022
+ tokens["body-font-size"] = `${theme.typography.fontSize}px`, tokens["font-weight-normal"] = `${theme.typography.fontWeightRegular}`,
21023
+ tokens["font-weight-bold"] = `${theme.typography.fontWeightBold}`),
21024
+ // Convert spacing
21025
+ "function" == typeof theme.spacing && (
21026
+ // If spacing is a function, call it with some values to get results
21027
+ tokens["spacing-1"] = theme.spacing(1), tokens["spacing-2"] = theme.spacing(2),
21028
+ tokens["spacing-4"] = theme.spacing(4)),
21029
+ // Convert breakpoints
21030
+ theme.breakpoints?.values && (tokens["breakpoint-xs"] = `${theme.breakpoints.values.xs}px`,
21031
+ tokens["breakpoint-sm"] = `${theme.breakpoints.values.sm}px`, tokens["breakpoint-md"] = `${theme.breakpoints.values.md}px`,
21032
+ tokens["breakpoint-lg"] = `${theme.breakpoints.values.lg}px`, tokens["breakpoint-xl"] = `${theme.breakpoints.values.xl}px`),
21033
+ // Convert shadows
21034
+ theme.shadows && (tokens["box-shadow"] = theme.shadows[2], // Use a moderate shadow
21035
+ tokens["box-shadow-sm"] = theme.shadows[1], tokens["box-shadow-lg"] = theme.shadows[3]),
21036
+ // Convert transitions
21037
+ theme.transitions && (tokens["transition-duration-base"] = `${theme.transitions.duration.standard}ms`),
21038
+ // Convert z-index
21039
+ theme.zIndex && (tokens["z-modal"] = `${theme.zIndex.modal}`, tokens["z-popover"] = `${theme.zIndex.popover}`,
21040
+ tokens["z-tooltip"] = `${theme.zIndex.tooltip}`), theme.borderRadius) {
21041
+ const baseRadius = theme.borderRadius.base;
21042
+ tokens["border-radius"] = "number" == typeof baseRadius ? `${baseRadius}px` : baseRadius;
21043
+ }
21044
+ // Add advanced feature tokens if available in theme
21045
+ if (theme.custom) {
21046
+ // Interactive Effects (Phase 2)
21047
+ if (theme.custom.interactiveEffects) {
21048
+ const ie = theme.custom.interactiveEffects;
21049
+ // Vortex effects
21050
+ ie.vortex && (tokens["interactive-vortex-enabled"] = String(ie.vortex.enabled ?? !1),
21051
+ tokens["interactive-vortex-strength"] = String(ie.vortex.strength ?? .5), tokens["interactive-vortex-radius"] = String(ie.vortex.radius ?? 100),
21052
+ tokens["interactive-vortex-decay"] = String(ie.vortex.decay ?? .8)),
21053
+ // Chromatic aberration
21054
+ ie.chromaticAberration && (tokens["interactive-chromatic-enabled"] = String(ie.chromaticAberration.enabled ?? !1),
21055
+ tokens["interactive-chromatic-mode"] = ie.chromaticAberration.mode ?? "lateral",
21056
+ tokens["interactive-chromatic-red-shift"] = String(ie.chromaticAberration.redShift ?? .02),
21057
+ tokens["interactive-chromatic-green-shift"] = String(ie.chromaticAberration.greenShift ?? 0),
21058
+ tokens["interactive-chromatic-blue-shift"] = String(ie.chromaticAberration.blueShift ?? -.02),
21059
+ tokens["interactive-chromatic-edge-only"] = String(ie.chromaticAberration.edgeOnly ?? !1),
21060
+ tokens["interactive-chromatic-edge-threshold"] = String(ie.chromaticAberration.edgeThreshold ?? .5)),
21061
+ // Mouse interaction
21062
+ ie.mouseInteraction && (tokens["interactive-mouse-sensitivity"] = String(ie.mouseInteraction.sensitivity ?? 1),
21063
+ tokens["interactive-mouse-trail-effect"] = String(ie.mouseInteraction.trailEffect ?? !1)),
21064
+ // Animation speed
21065
+ ie.animationSpeed && (tokens["interactive-animation-speed-base"] = String(ie.animationSpeed.base ?? 1),
21066
+ tokens["interactive-animation-speed-multiplier"] = String(ie.animationSpeed.timeMultiplier ?? 1));
21067
+ }
21068
+ // Optimization (Phase 3)
21069
+ if (theme.custom.optimization) {
21070
+ const opt = theme.custom.optimization;
21071
+ // Responsive breakpoints
21072
+ opt.responsive && (opt.responsive.breakpoints && (tokens["optimization-breakpoint-mobile"] = opt.responsive.breakpoints.mobile ?? "0px",
21073
+ tokens["optimization-breakpoint-tablet"] = opt.responsive.breakpoints.tablet ?? "768px",
21074
+ tokens["optimization-breakpoint-desktop"] = opt.responsive.breakpoints.desktop ?? "1024px",
21075
+ tokens["optimization-breakpoint-wide"] = opt.responsive.breakpoints.wide ?? "1440px"),
21076
+ opt.responsive.deviceScaling && (tokens["optimization-device-scaling-mobile"] = String(opt.responsive.deviceScaling.mobile ?? .5),
21077
+ tokens["optimization-device-scaling-tablet"] = String(opt.responsive.deviceScaling.tablet ?? .75),
21078
+ tokens["optimization-device-scaling-desktop"] = String(opt.responsive.deviceScaling.desktop ?? 1))),
21079
+ // Performance settings
21080
+ opt.performance && (tokens["optimization-performance-fps-target"] = String(opt.performance.fpsTarget ?? 60),
21081
+ tokens["optimization-auto-scaling-enabled"] = String(opt.performance.autoScaling ?? !1)),
21082
+ // Auto-scaling settings
21083
+ opt.autoScaling && (tokens["optimization-auto-scaling-enabled"] = String(opt.autoScaling.enabled ?? !1),
21084
+ tokens["optimization-auto-scaling-low-end"] = String(opt.autoScaling.qualityThresholds?.lowEnd ?? .5),
21085
+ tokens["optimization-auto-scaling-mid-range"] = String(opt.autoScaling.qualityThresholds?.midRange ?? .75),
21086
+ tokens["optimization-auto-scaling-high-end"] = String(opt.autoScaling.qualityThresholds?.highEnd ?? 1));
21087
+ }
21088
+ // Visual Polish (Phase 4)
21089
+ if (theme.custom.visualPolish) {
21090
+ const vp = theme.custom.visualPolish;
21091
+ vp.borders && (tokens["visual-polish-border-iridescent-glow"] = String(vp.borders.iridescentGlow ?? !1),
21092
+ tokens["visual-polish-border-shimmer-effect"] = String(vp.borders.shimmerEffect ?? !1),
21093
+ tokens["visual-polish-border-beveled-edges"] = String(vp.borders.beveledEdges ?? !1),
21094
+ tokens["visual-polish-border-pulsing-glow"] = String(vp.borders.pulsingGlow ?? !1)),
21095
+ vp.contentAwareBlur && (tokens["visual-polish-content-aware-blur-enabled"] = String(vp.contentAwareBlur.enabled ?? !1),
21096
+ tokens["visual-polish-content-aware-depth-detection"] = String(vp.contentAwareBlur.depthDetection ?? !1),
21097
+ tokens["visual-polish-content-aware-edge-preservation"] = String(vp.contentAwareBlur.edgePreservation ?? !1),
21098
+ tokens["visual-polish-content-aware-variable-radius"] = String(vp.contentAwareBlur.variableRadius ?? !1)),
21099
+ vp.holographicEffects && (tokens["visual-polish-holographic-enabled"] = String(vp.holographicEffects.enabled ?? !1),
21100
+ tokens["visual-polish-holographic-rainbow-diffraction"] = String(vp.holographicEffects.rainbowDiffraction ?? !1),
21101
+ tokens["visual-polish-holographic-scanline-animation"] = String(vp.holographicEffects.scanlineAnimation ?? !1),
21102
+ tokens["visual-polish-holographic-grid-overlay"] = String(vp.holographicEffects.gridOverlay ?? !1),
21103
+ tokens["visual-polish-holographic-data-stream"] = String(vp.holographicEffects.dataStream ?? !1),
21104
+ tokens["visual-polish-holographic-pulse-rings"] = String(vp.holographicEffects.pulseRings ?? !1));
21105
+ }
21106
+ }
21107
+ // Create full tokens object with defaults
21108
+ return createTokens(tokens);
21109
+ }
20979
21110
 
20980
21111
  /**
20981
- * Custom error class for theme-related errors
20982
- */
20983
- class ThemeError extends Error {
20984
- constructor(message, code = ThemeErrorCode.UNKNOWN_ERROR, context) {
20985
- super(message), this.name = "ThemeError", this.code = code, this.context = context,
20986
- this.timestamp = Date.now(),
20987
- // Maintains proper stack trace for where our error was thrown (only available on V8)
20988
- Error.captureStackTrace && Error.captureStackTrace(this, ThemeError);
20989
- }
20990
- /**
20991
- * Convert error to JSON for logging
20992
- */ toJSON() {
20993
- return {
20994
- name: this.name,
20995
- message: this.message,
20996
- code: this.code,
20997
- context: this.context,
20998
- timestamp: this.timestamp,
20999
- stack: this.stack
21000
- };
21112
+ * Converts an AtomixConfig to DesignTokens
21113
+ *
21114
+ * This function maps the configuration from the user-facing format
21115
+ * to the internal DesignTokens format used by the theme system.
21116
+ *
21117
+ * @param config - The configuration object to convert
21118
+ * @returns DesignTokens object ready for theme generation
21119
+ *
21120
+ * @example
21121
+ * ```typescript
21122
+ * import { configToTokens } from '@shohojdhara/atomix/theme';
21123
+ *
21124
+ * const config = {
21125
+ * prefix: 'myapp',
21126
+ * theme: { extend: { colors: { primary: { main: '#7AFFD7' } } } }
21127
+ * };
21128
+ * const tokens = configToTokens(config);
21129
+ * ```
21130
+ */ function configToTokens(config) {
21131
+ const prefix = config.prefix || "atomix", theme = config.theme || {};
21132
+ // Start with default tokens
21133
+ let tokens = {
21134
+ ...defaultTokens
21135
+ };
21136
+ // Apply theme extensions
21137
+ // Apply advanced features if available in config
21138
+ if (theme.extend &&
21139
+ // Apply extensions to tokens
21140
+ Object.entries(theme.extend).forEach((([category, values]) => {
21141
+ "object" == typeof values && null !== values && Object.entries(values).forEach((([key, value]) => {
21142
+ // Map theme categories to token names
21143
+ const tokenName = `${category}-${key}`;
21144
+ "string" == typeof value || "number" == typeof value ? tokens[tokenName] = String(value) : "object" == typeof value && null !== value &&
21145
+ // Handle nested objects like color scales
21146
+ Object.entries(value).forEach((([nestedKey, nestedValue]) => {
21147
+ "string" != typeof nestedValue && "number" != typeof nestedValue || (tokens[`${tokenName}-${nestedKey}`] = String(nestedValue));
21148
+ }));
21149
+ }));
21150
+ })),
21151
+ // Apply theme tokens if provided (completely replacing defaults)
21152
+ theme.tokens && (tokens = {
21153
+ ...tokens,
21154
+ ...theme.tokens
21155
+ }), config) {
21156
+ // Interactive Effects (Phase 2)
21157
+ if (config.interactiveEffects) {
21158
+ const ie = config.interactiveEffects;
21159
+ // Vortex effects
21160
+ ie.vortex && (tokens["interactive-vortex-enabled"] = String(ie.vortex.enabled ?? !1),
21161
+ tokens["interactive-vortex-strength"] = String(ie.vortex.strength ?? .5), tokens["interactive-vortex-radius"] = String(ie.vortex.radius ?? 100),
21162
+ tokens["interactive-vortex-decay"] = String(ie.vortex.decay ?? .8), tokens["interactive-vortex-curl-noise"] = String(ie.vortex.curlNoise ?? !1),
21163
+ tokens["interactive-vortex-velocity-tracking"] = String(ie.vortex.velocityTracking ?? !1)),
21164
+ // Chromatic aberration
21165
+ ie.chromaticAberration && (tokens["interactive-chromatic-enabled"] = String(ie.chromaticAberration.enabled ?? !1),
21166
+ tokens["interactive-chromatic-mode"] = ie.chromaticAberration.mode ?? "lateral",
21167
+ tokens["interactive-chromatic-red-shift"] = String(ie.chromaticAberration.redShift ?? .02),
21168
+ tokens["interactive-chromatic-green-shift"] = String(ie.chromaticAberration.greenShift ?? 0),
21169
+ tokens["interactive-chromatic-blue-shift"] = String(ie.chromaticAberration.blueShift ?? -.02),
21170
+ tokens["interactive-chromatic-edge-only"] = String(ie.chromaticAberration.edgeOnly ?? !1),
21171
+ tokens["interactive-chromatic-edge-threshold"] = String(ie.chromaticAberration.edgeThreshold ?? .5)),
21172
+ // Mouse interaction
21173
+ ie.mouseInteraction && (tokens["interactive-mouse-sensitivity"] = String(ie.mouseInteraction.sensitivity ?? 1),
21174
+ tokens["interactive-mouse-trail-effect"] = String(ie.mouseInteraction.trailEffect ?? !1),
21175
+ tokens["interactive-mouse-pressure-sensitivity"] = String(ie.mouseInteraction.pressureSensitivity ?? !1)),
21176
+ // Animation speed
21177
+ ie.animationSpeed && (tokens["interactive-animation-speed-base"] = String(ie.animationSpeed.base ?? 1),
21178
+ tokens["interactive-animation-speed-multiplier"] = String(ie.animationSpeed.timeMultiplier ?? 1));
21179
+ }
21180
+ // Optimization (Phase 3)
21181
+ if (config.optimization) {
21182
+ const opt = config.optimization;
21183
+ // Responsive breakpoints
21184
+ opt.responsive && (opt.responsive.breakpoints && (tokens["optimization-breakpoint-mobile"] = opt.responsive.breakpoints.mobile ?? "0px",
21185
+ tokens["optimization-breakpoint-tablet"] = opt.responsive.breakpoints.tablet ?? "768px",
21186
+ tokens["optimization-breakpoint-desktop"] = opt.responsive.breakpoints.desktop ?? "1024px",
21187
+ tokens["optimization-breakpoint-wide"] = opt.responsive.breakpoints.wide ?? "1440px"),
21188
+ opt.responsive.deviceScaling && (tokens["optimization-device-scaling-mobile"] = String(opt.responsive.deviceScaling.mobile ?? .5),
21189
+ tokens["optimization-device-scaling-tablet"] = String(opt.responsive.deviceScaling.tablet ?? .75),
21190
+ tokens["optimization-device-scaling-desktop"] = String(opt.responsive.deviceScaling.desktop ?? 1))),
21191
+ // Performance settings
21192
+ opt.performance && (tokens["optimization-performance-fps-target"] = String(opt.performance.fpsTarget ?? 60),
21193
+ tokens["optimization-auto-scaling-enabled"] = String(opt.performance.autoScaling ?? !1),
21194
+ tokens["optimization-monitor-dashboard-enabled"] = String(opt.performance.monitorDashboard ?? !1)),
21195
+ // Auto-scaling settings
21196
+ opt.autoScaling && (tokens["optimization-auto-scaling-enabled"] = String(opt.autoScaling.enabled ?? !1),
21197
+ tokens["optimization-auto-scaling-low-end"] = String(opt.autoScaling.qualityThresholds?.lowEnd ?? .5),
21198
+ tokens["optimization-auto-scaling-mid-range"] = String(opt.autoScaling.qualityThresholds?.midRange ?? .75),
21199
+ tokens["optimization-auto-scaling-high-end"] = String(opt.autoScaling.qualityThresholds?.highEnd ?? 1));
21200
+ }
21201
+ // Visual Polish (Phase 4)
21202
+ if (config.visualPolish) {
21203
+ const vp = config.visualPolish;
21204
+ vp.borders && (tokens["visual-polish-border-iridescent-glow"] = String(vp.borders.iridescentGlow ?? !1),
21205
+ tokens["visual-polish-border-shimmer-effect"] = String(vp.borders.shimmerEffect ?? !1),
21206
+ tokens["visual-polish-border-beveled-edges"] = String(vp.borders.beveledEdges ?? !1),
21207
+ tokens["visual-polish-border-pulsing-glow"] = String(vp.borders.pulsingGlow ?? !1)),
21208
+ vp.contentAwareBlur && (tokens["visual-polish-content-aware-blur-enabled"] = String(vp.contentAwareBlur.enabled ?? !1),
21209
+ tokens["visual-polish-content-aware-depth-detection"] = String(vp.contentAwareBlur.depthDetection ?? !1),
21210
+ tokens["visual-polish-content-aware-edge-preservation"] = String(vp.contentAwareBlur.edgePreservation ?? !1),
21211
+ tokens["visual-polish-content-aware-variable-radius"] = String(vp.contentAwareBlur.variableRadius ?? !1)),
21212
+ vp.holographicEffects && (tokens["visual-polish-holographic-enabled"] = String(vp.holographicEffects.enabled ?? !1),
21213
+ tokens["visual-polish-holographic-rainbow-diffraction"] = String(vp.holographicEffects.rainbowDiffraction ?? !1),
21214
+ tokens["visual-polish-holographic-scanline-animation"] = String(vp.holographicEffects.scanlineAnimation ?? !1),
21215
+ tokens["visual-polish-holographic-grid-overlay"] = String(vp.holographicEffects.gridOverlay ?? !1),
21216
+ tokens["visual-polish-holographic-data-stream"] = String(vp.holographicEffects.dataStream ?? !1),
21217
+ tokens["visual-polish-holographic-pulse-rings"] = String(vp.holographicEffects.pulseRings ?? !1));
21218
+ }
21001
21219
  }
21220
+ // Apply prefix to all tokens
21221
+ const prefixedTokens = {};
21222
+ return Object.entries(tokens).forEach((([key, value]) => {
21223
+ // If the token key already starts with the prefix, use as-is
21224
+ // Otherwise, add the prefix
21225
+ const prefixedKey = key.startsWith(prefix) ? key : `${prefix}-${key}`;
21226
+ prefixedTokens[prefixedKey] = value;
21227
+ })), prefixedTokens;
21002
21228
  }
21003
21229
 
21004
21230
  /**
21005
- * Log level
21006
- */ !function(LogLevel) {
21007
- LogLevel[LogLevel.ERROR = 0] = "ERROR", LogLevel[LogLevel.WARN = 1] = "WARN", LogLevel[LogLevel.INFO = 2] = "INFO",
21008
- LogLevel[LogLevel.DEBUG = 3] = "DEBUG";
21009
- }(LogLevel || (LogLevel = {}));
21231
+ * Convert hex color to RGB
21232
+ */ function hexToRgb$2(hex) {
21233
+ hex = hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, ((m, r, g, b) => r + r + g + g + b + b));
21234
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
21235
+ return result && result[1] && result[2] && result[3] ? `${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}` : "0, 0, 0";
21236
+ }
21010
21237
 
21011
21238
  /**
21012
- * Theme Logger
21239
+ * Converts DesignTokens to CSS variables
21013
21240
  *
21014
- * Centralized logging for the theme system.
21015
- * Replaces console statements with structured logging.
21241
+ * @param tokens - The tokens to convert
21242
+ * @returns A record of CSS variable names and values
21243
+ */ function designTokensToCSSVars(tokens) {
21244
+ const cssVars = {};
21245
+ return Object.entries(tokens).forEach((([key, value]) => {
21246
+ void 0 !== value && (cssVars[`--atomix-${key}`] = String(value));
21247
+ })), cssVars;
21248
+ }
21249
+
21250
+ /**
21251
+ * Load theme from config file (synchronous, Node.js only)
21252
+ * @param configPath - Path to config file (default: atomix.config.ts)
21253
+ * @returns DesignTokens from theme configuration
21254
+ * @throws Error if config loading is not available in browser environment
21016
21255
  */
21017
- class ThemeLogger {
21018
- constructor(config = {}) {
21019
- this.config = {
21020
- level: config.level ?? ("undefined" != typeof process && "production" === process.env?.NODE_ENV ? LogLevel.WARN : LogLevel.INFO),
21021
- enableConsole: config.enableConsole ?? !0,
21022
- onError: config.onError,
21023
- onWarn: config.onWarn,
21024
- onInfo: config.onInfo,
21025
- onDebug: config.onDebug
21026
- };
21256
+ /**
21257
+ * Atomix Config Loader
21258
+ *
21259
+ * Helper functions to load atomix.config.ts from external projects.
21260
+ * Now also supports atomix.config.js and atomix.config.json
21261
+ */
21262
+ /**
21263
+ * Validate Atomix configuration structure
21264
+ *
21265
+ * Performs basic validation to catch common configuration errors early.
21266
+ * Returns warnings for potential issues.
21267
+ *
21268
+ * @param config - Configuration object to validate
21269
+ * @returns Array of validation warnings (empty if valid)
21270
+ *
21271
+ * @example
21272
+ * ```typescript
21273
+ * import { loadAtomixConfig, validateConfig } from '@shohojdhara/atomix/config';
21274
+ *
21275
+ * const config = loadAtomixConfig();
21276
+ * const warnings = validateConfig(config);
21277
+ * warnings.forEach(w => console.warn(w));
21278
+ * ```
21279
+ */
21280
+ function validateConfig$1(config) {
21281
+ const warnings = [];
21282
+ // Check prefix format
21283
+ // Check theme structure
21284
+ if (config.prefix && (/^[a-zA-Z][a-zA-Z0-9-]*$/.test(config.prefix) || warnings.push(`Invalid prefix "${config.prefix}". Prefix should start with a letter and contain only letters, numbers, and hyphens.\nExample: "myapp", "brand-ui", "enterprise"`),
21285
+ config.prefix.length < 2 && warnings.push(`Prefix "${config.prefix}" is too short. Use at least 2 characters for clarity.\nExample: "app" instead of "a"`)),
21286
+ config.theme && (
21287
+ // Warn if both extend and tokens are provided
21288
+ config.theme.extend && config.theme.tokens && warnings.push("Both theme.extend and theme.tokens are defined. theme.tokens will take precedence and completely replace the default token system.\nIf you want to extend defaults, remove theme.tokens and use only theme.extend."),
21289
+ config.theme.extend)) {
21290
+ const extend = config.theme.extend, validThemeKeys = [ "colors", "typography", "spacing", "borderRadius", "shadows", "zIndex", "transitions", "breakpoints" ];
21291
+ // Check for common typos in theme properties
21292
+ Object.keys(extend).forEach((key => {
21293
+ _includesInstanceProperty(validThemeKeys).call(validThemeKeys, key) || warnings.push(`Unknown theme property: "${key}"\nValid properties: ${validThemeKeys.join(", ")}\nDid you mean one of these? Check for typos.`);
21294
+ }));
21027
21295
  }
21028
- /**
21029
- * Log an error
21030
- */ error(message, error, context) {
21031
- if (this.config.level < LogLevel.ERROR) return;
21032
- const errorObj = error instanceof Error ? error : new Error(message), themeError = error instanceof ThemeError ? error : new ThemeError(message, ThemeErrorCode.UNKNOWN_ERROR, context);
21033
- this.config.enableConsole && console.error(`[ThemeError] ${message}`, {
21034
- error: errorObj,
21035
- context: {
21036
- ...context,
21037
- ...themeError.context
21038
- },
21039
- code: themeError.code
21040
- }), this.config.onError?.(themeError, context);
21296
+ // Validate advanced features
21297
+ if (config.interactiveEffects) {
21298
+ const ie = config.interactiveEffects;
21299
+ // Validate vortex settings
21300
+ ie.vortex && (ie.vortex.strength && (ie.vortex.strength < 0 || ie.vortex.strength > 10) && warnings.push("Vortex strength should be between 0 and 10 for optimal performance"),
21301
+ ie.vortex.radius && ie.vortex.radius < 0 && warnings.push("Vortex radius should be a positive number"),
21302
+ ie.vortex.decay && (ie.vortex.decay <= 0 || ie.vortex.decay > 1) && warnings.push("Vortex decay should be between 0 and 1")),
21303
+ // Validate chromatic aberration settings
21304
+ ie.chromaticAberration && (ie.chromaticAberration.redShift && Math.abs(ie.chromaticAberration.redShift) > .1 && warnings.push("Chromatic red shift value seems unusually high (>0.1), verify this is intended"),
21305
+ ie.chromaticAberration.blueShift && Math.abs(ie.chromaticAberration.blueShift) > .1 && warnings.push("Chromatic blue shift value seems unusually high (>0.1), verify this is intended"),
21306
+ ie.chromaticAberration.edgeThreshold && (ie.chromaticAberration.edgeThreshold < 0 || ie.chromaticAberration.edgeThreshold > 1) && warnings.push("Chromatic edge threshold should be between 0 and 1")),
21307
+ // Validate mouse interaction settings
21308
+ ie.mouseInteraction && ie.mouseInteraction.sensitivity && ie.mouseInteraction.sensitivity < 0 && warnings.push("Mouse sensitivity should be a positive number"),
21309
+ // Validate animation speed settings
21310
+ ie.animationSpeed && (ie.animationSpeed.base && ie.animationSpeed.base <= 0 && warnings.push("Animation base speed should be greater than 0"),
21311
+ ie.animationSpeed.timeMultiplier && ie.animationSpeed.timeMultiplier <= 0 && warnings.push("Animation time multiplier should be greater than 0"));
21041
21312
  }
21042
- /**
21043
- * Log a warning
21044
- */ warn(message, context) {
21045
- this.config.level < LogLevel.WARN || (this.config.enableConsole && console.warn(`[ThemeWarning] ${message}`, context || {}),
21046
- this.config.onWarn?.(message, context));
21313
+ // Validate optimization settings
21314
+ if (config.optimization) {
21315
+ const opt = config.optimization;
21316
+ // Validate responsive breakpoints
21317
+ if (opt.responsive && opt.responsive.breakpoints) {
21318
+ const breakpoints = opt.responsive.breakpoints;
21319
+ breakpoints.mobile && !isValidCSSLength(breakpoints.mobile) && warnings.push("Mobile breakpoint value is not a valid CSS length"),
21320
+ breakpoints.tablet && !isValidCSSLength(breakpoints.tablet) && warnings.push("Tablet breakpoint value is not a valid CSS length"),
21321
+ breakpoints.desktop && !isValidCSSLength(breakpoints.desktop) && warnings.push("Desktop breakpoint value is not a valid CSS length"),
21322
+ breakpoints.wide && !isValidCSSLength(breakpoints.wide) && warnings.push("Wide breakpoint value is not a valid CSS length");
21323
+ }
21324
+ // Validate device scaling
21325
+ if (opt.responsive && opt.responsive.deviceScaling) {
21326
+ const scaling = opt.responsive.deviceScaling;
21327
+ scaling.mobile && (scaling.mobile <= 0 || scaling.mobile > 1) && warnings.push("Mobile device scaling should be between 0 and 1"),
21328
+ scaling.tablet && (scaling.tablet <= 0 || scaling.tablet > 1) && warnings.push("Tablet device scaling should be between 0 and 1"),
21329
+ scaling.desktop && (scaling.desktop <= 0 || scaling.desktop > 1) && warnings.push("Desktop device scaling should be between 0 and 1");
21330
+ }
21331
+ // Validate performance settings
21332
+ // Validate auto-scaling thresholds
21333
+ if (opt.performance && opt.performance.fpsTarget && (opt.performance.fpsTarget <= 0 || opt.performance.fpsTarget > 240) && warnings.push("FPS target should be a reasonable value (typically 30-120)"),
21334
+ opt.autoScaling && opt.autoScaling.qualityThresholds) {
21335
+ const thresholds = opt.autoScaling.qualityThresholds;
21336
+ thresholds.lowEnd && (thresholds.lowEnd < 0 || thresholds.lowEnd > 1) && warnings.push("Auto-scaling low-end threshold should be between 0 and 1"),
21337
+ thresholds.midRange && (thresholds.midRange < 0 || thresholds.midRange > 1) && warnings.push("Auto-scaling mid-range threshold should be between 0 and 1"),
21338
+ thresholds.highEnd && (thresholds.highEnd < 0 || thresholds.highEnd > 1) && warnings.push("Auto-scaling high-end threshold should be between 0 and 1");
21339
+ }
21047
21340
  }
21048
- /**
21049
- * Log an info message
21050
- */ info(message, context) {
21051
- this.config.level < LogLevel.INFO || (this.config.enableConsole && console.info(`[ThemeInfo] ${message}`, context || {}),
21052
- this.config.onInfo?.(message, context));
21341
+ // Validate visual polish settings
21342
+ if (config.visualPolish) {
21343
+ const vp = config.visualPolish;
21344
+ // Validate content aware blur settings
21345
+ vp.contentAwareBlur && (void 0 !== vp.contentAwareBlur.edgePreservation && "boolean" != typeof vp.contentAwareBlur.edgePreservation && warnings.push("Content-aware blur edge preservation should be a boolean value"),
21346
+ void 0 !== vp.contentAwareBlur.depthDetection && "boolean" != typeof vp.contentAwareBlur.depthDetection && warnings.push("Content-aware blur depth detection should be a boolean value")),
21347
+ // Validate holographic effects settings
21348
+ vp.holographicEffects && (void 0 !== vp.holographicEffects.enabled && "boolean" != typeof vp.holographicEffects.enabled && warnings.push("Holographic effects enabled should be a boolean value"),
21349
+ void 0 !== vp.holographicEffects.rainbowDiffraction && "boolean" != typeof vp.holographicEffects.rainbowDiffraction && warnings.push("Holographic rainbow diffraction should be a boolean value"));
21053
21350
  }
21054
- /**
21055
- * Log a debug message
21056
- */ debug(message, context) {
21057
- this.config.level < LogLevel.DEBUG || (this.config.enableConsole, this.config.onDebug?.(message, context));
21351
+ // Validate AI settings
21352
+ var _context;
21353
+ return config.ai && (config.ai.provider && !_includesInstanceProperty(_context = [ "openai", "anthropic" ]).call(_context, config.ai.provider) && warnings.push(`Unknown AI provider: "${config.ai.provider}". Supported: openai, anthropic`),
21354
+ config.ai.temperature && (config.ai.temperature < 0 || config.ai.temperature > 1) && warnings.push("AI temperature should be between 0 and 1"),
21355
+ config.ai.maxTokens && config.ai.maxTokens < 100 && warnings.push("AI maxTokens should typically be 100 or more"),
21356
+ config.ai.rateLimit && (config.ai.rateLimit.requests <= 0 && warnings.push("AI rate limit requests should be greater than 0"),
21357
+ config.ai.rateLimit.windowMs <= 0 && warnings.push("AI rate limit window should be greater than 0"))),
21358
+ // Validate telemetry settings
21359
+ config.telemetry && config.telemetry.path && !config.telemetry.path.endsWith(".json") && warnings.push("Telemetry path should typically end with .json"),
21360
+ warnings;
21361
+ }
21362
+
21363
+ /**
21364
+ * Helper function to validate CSS length values
21365
+ */ function isValidCSSLength(value) {
21366
+ return /^(\d+(\.\d+)?)(px|em|rem|%|vw|vh|vmin|vmax|cm|mm|in|pt|pc|ex|ch)?$/.test(value);
21367
+ }
21368
+
21369
+ /**
21370
+ * Load Atomix configuration from project root
21371
+ *
21372
+ * Attempts to load atomix.config.ts, atomix.config.js, or atomix.config.json from the current working directory.
21373
+ * Falls back to default config if file doesn't exist.
21374
+ *
21375
+ * @param options - Loader options
21376
+ * @returns Loaded configuration or default
21377
+ *
21378
+ * @example
21379
+ * ```typescript
21380
+ * import { loadAtomixConfig } from '@shohojdhara/atomix/config';
21381
+ * import { createTheme } from '@shohojdhara/atomix/theme';
21382
+ *
21383
+ * const config = loadAtomixConfig();
21384
+ * const theme = createTheme(config.theme?.tokens || {});
21385
+ * ```
21386
+ */ function loadAtomixConfig(options = {}) {
21387
+ const {configPath: configPath, required: required = !1} = options, defaultConfig = {
21388
+ prefix: "atomix",
21389
+ theme: {
21390
+ extend: {}
21391
+ }
21392
+ };
21393
+ // Default config
21394
+ // In browser environments, config loading is not supported
21395
+ if ("undefined" != typeof window) {
21396
+ if (required) throw new Error('Config loading requires Node.js file system access.\n\nSolutions:\n1. Provide tokens explicitly to createTheme():\n const css = createTheme({ "--brand-primary": "#6366f1" });\n\n2. Use SSR framework (Next.js, Remix, Astro)\n\n3. Load config on server and pass to client\n\nSee examples/config-examples/browser-only.config.ts');
21397
+ return defaultConfig;
21398
+ }
21399
+ // If a specific config path is provided, try to load it directly
21400
+ if (configPath) return loadConfigAtPath(configPath, required, defaultConfig);
21401
+ // Otherwise, try standard locations in order of preference
21402
+ const possiblePaths = [ "atomix.config.ts", "atomix.config.js", "atomix.config.json" ];
21403
+ for (const path of possiblePaths) {
21404
+ const config = loadConfigAtPath(path, !1, defaultConfig);
21405
+ // If we found a valid config, return it
21406
+ if (JSON.stringify(config) !== JSON.stringify(defaultConfig)) return config;
21058
21407
  }
21408
+ // If no config file was found or all contained only defaults, return default config
21409
+ if (required) throw new Error('No Atomix configuration file found in project root.\n\nExpected one of:\n - atomix.config.ts (recommended)\n - atomix.config.js\n - atomix.config.json\n\nQuick Fix:\n1. Create a config file in your project root:\n touch atomix.config.ts\n\n2. Add basic configuration:\n import { defineConfig } from "@shohojdhara/atomix/config";\n export default defineConfig({ prefix: "myapp" });\n\n3. Or copy an example:\n cp node_modules/@shohojdhara/atomix/examples/config-examples/standard.config.ts ./atomix.config.ts');
21410
+ return defaultConfig;
21059
21411
  }
21060
21412
 
21061
21413
  /**
21062
- * Default logger instance
21063
- */ let defaultLogger = null;
21414
+ * Helper function to load config from a specific path
21415
+ */ function loadConfigAtPath(path, required, defaultConfig) {
21416
+ try {
21417
+ // Use dynamic import for ESM compatibility
21418
+ const configModule = require(path), config = configModule.default || configModule;
21419
+ // Validate it's an AtomixConfig
21420
+ if (config && "object" == typeof config) return config;
21421
+ throw new Error("Invalid config format");
21422
+ } catch (error) {
21423
+ if (required) throw new Error(`Failed to load config from ${path}: ${error.message}`);
21424
+ // Return default config if not required
21425
+ return defaultConfig;
21426
+ }
21427
+ }
21064
21428
 
21065
21429
  /**
21066
- * Get or create default logger
21067
- */ function getLogger() {
21068
- return defaultLogger || (defaultLogger = new ThemeLogger), defaultLogger;
21430
+ * Resolve config path
21431
+ *
21432
+ * Finds atomix.config.ts in the project, checking common locations.
21433
+ * Returns null in browser environments where file system access is not available.
21434
+ *
21435
+ * This function is designed to help tools identify if a config exists without loading it.
21436
+ *
21437
+ * @param configPath - Optional custom path to check
21438
+ * @returns Absolute path to config file or null if not found
21439
+ */ function resolveConfigPath(configPath) {
21440
+ // In browser environments, config resolution is not possible
21441
+ if ("undefined" != typeof window) return null;
21442
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
21443
+ const {existsSync: existsSync} = require("fs"), {join: join} = require("path");
21444
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
21445
+ // If a specific config path is provided, check if it exists
21446
+ if (configPath) {
21447
+ const absPath = join(process.cwd(), configPath);
21448
+ return existsSync(absPath) ? absPath : null;
21449
+ }
21450
+ // Otherwise, check standard locations
21451
+ const possiblePaths = [ join(process.cwd(), "atomix.config.ts"), join(process.cwd(), "atomix.config.js"), join(process.cwd(), "atomix.config.json") ];
21452
+ for (const path of possiblePaths) if (existsSync(path)) return path;
21453
+ return null;
21069
21454
  }
21070
21455
 
21071
21456
  /**
21072
21457
  * Core Theme Functions
21073
21458
  *
21074
- * Simplified theme system using DesignTokens only.
21459
+ * Unified theme system that handles both DesignTokens and Theme objects.
21075
21460
  * Config-first approach: loads from atomix.config.ts when no input is provided.
21461
+ * Config-first approach: loads advanced features from config when available.
21076
21462
  */
21077
21463
  /**
21078
- * Create theme CSS from DesignTokens
21464
+ * Create theme CSS from tokens or Theme object
21079
21465
  *
21080
21466
  * **Config-First Approach**: If no input is provided, loads from `atomix.config.ts`.
21467
+ * Config file is required for automatic loading.
21081
21468
  *
21082
- * @param input - DesignTokens (partial) or undefined (loads from config)
21469
+ * @param input - DesignTokens (partial), Theme object, or undefined (loads from config)
21083
21470
  * @param options - CSS generation options (prefix is automatically read from config if not provided)
21084
21471
  * @returns CSS string with custom properties
21085
21472
  * @throws Error if config loading fails when no input is provided
21086
21473
  *
21087
21474
  * @example
21088
21475
  * ```typescript
21089
- * // Loads from atomix.config.ts
21476
+ * // Loads from atomix.config.ts (config file required)
21090
21477
  * const css = createTheme();
21091
21478
  *
21092
21479
  * // Using DesignTokens
@@ -21095,42 +21482,150 @@ class ThemeLogger {
21095
21482
  * 'spacing-4': '1rem',
21096
21483
  * });
21097
21484
  *
21485
+ * // Using Theme object
21486
+ * const theme = createThemeObject({ palette: { primary: { main: '#7c3aed' } } });
21487
+ * const css = createTheme(theme);
21488
+ *
21098
21489
  * // With custom options
21099
21490
  * const css = createTheme(undefined, { prefix: 'myapp', selector: ':root' });
21100
21491
  * ```
21101
21492
  */ function createTheme(input, options) {
21102
- // Validate options if provided
21103
- if (options?.prefix) {
21104
- const prefixPattern = /^[a-z][a-z0-9-]*$/;
21105
- if (!prefixPattern.test(options.prefix)) throw new ThemeError(`Invalid CSS variable prefix: "${options.prefix}". Prefix must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens (e.g., "atomix", "my-app").`, ThemeErrorCode.THEME_VALIDATION_FAILED, {
21106
- prefix: options.prefix,
21107
- pattern: prefixPattern.toString()
21108
- });
21109
- }
21110
- // Validate selector if provided
21111
- if (options?.selector && ("string" != typeof options.selector || 0 === options.selector.trim().length)) throw new ThemeError(`Invalid CSS selector: "${options.selector}". Selector must be a non-empty string (e.g., ":root", ".my-theme").`, ThemeErrorCode.THEME_VALIDATION_FAILED, {
21112
- selector: options.selector
21113
- });
21114
- // Determine tokens based on input
21115
- let tokens;
21116
- if (input) {
21117
- // Validate input tokens structure
21118
- if ("object" != typeof input || null === input || Array.isArray(input)) throw new ThemeError(`Invalid tokens input. Expected an object with DesignTokens, but received: ${typeof input}.`, ThemeErrorCode.THEME_VALIDATION_FAILED, {
21119
- inputType: typeof input
21120
- });
21121
- // Use DesignTokens directly
21122
- tokens = input;
21493
+ let tokens, configPrefix;
21494
+ // If no input provided, load from config (required)
21495
+ if (input)
21496
+ // Convert Theme object to DesignTokens
21497
+ tokens = !0 === input.__isJSTheme || input.palette && input.typography ? themeToDesignTokens(input) : input; else {
21498
+ const configTokens = function() {
21499
+ // Check if we're in a browser environment
21500
+ if ("undefined" != typeof window) throw new Error("loadThemeFromConfigSync: Not available in browser environment. Config loading requires Node.js/SSR environment.");
21501
+ // Use dynamic import to load the config loader
21502
+ // This allows bundlers to handle external dependencies properly
21503
+ let loadAtomixConfig;
21504
+ try {
21505
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
21506
+ const {loadAtomixConfig: loader} = require("../../config/loader");
21507
+ loadAtomixConfig = loader;
21508
+ } catch (error) {
21509
+ throw new Error("Config loader module not available");
21510
+ }
21511
+ const config = loadAtomixConfig({
21512
+ configPath: undefined,
21513
+ required: !0
21514
+ });
21515
+ if (!config?.theme) return createTokens({});
21516
+ if ((obj = config.theme) && "object" == typeof obj && (obj.palette || obj.typography || obj.spacing || obj.breakpoints || obj.colors)) return themeToDesignTokens(config.theme);
21517
+ // Handle the config.theme object which has extend/tokens/themes properties
21518
+ // Extract the actual tokens from the theme configuration
21519
+ // Helper type guard function
21520
+ var obj;
21521
+ const themeConfig = config.theme;
21522
+ let tokensToApply = {};
21523
+ return themeConfig.tokens ?
21524
+ // If tokens is provided, use it as the base
21525
+ tokensToApply = themeConfig.tokens : themeConfig.extend && (
21526
+ // If only extend is provided, use it as overrides
21527
+ tokensToApply = themeConfig.extend),
21528
+ // Apply advanced feature configurations as tokens
21529
+ config.interactiveEffects && (
21530
+ // Vortex effects
21531
+ config.interactiveEffects.vortex && (tokensToApply = {
21532
+ ...tokensToApply,
21533
+ "interactive-vortex-enabled": String(config.interactiveEffects.vortex.enabled ?? !1),
21534
+ "interactive-vortex-strength": String(config.interactiveEffects.vortex.strength ?? .5),
21535
+ "interactive-vortex-radius": String(config.interactiveEffects.vortex.radius ?? 100),
21536
+ "interactive-vortex-decay": String(config.interactiveEffects.vortex.decay ?? .8)
21537
+ }),
21538
+ // Chromatic aberration
21539
+ config.interactiveEffects.chromaticAberration && (tokensToApply = {
21540
+ ...tokensToApply,
21541
+ "interactive-chromatic-enabled": String(config.interactiveEffects.chromaticAberration.enabled ?? !1),
21542
+ "interactive-chromatic-mode": config.interactiveEffects.chromaticAberration.mode ?? "lateral",
21543
+ "interactive-chromatic-red-shift": String(config.interactiveEffects.chromaticAberration.redShift ?? .02),
21544
+ "interactive-chromatic-green-shift": String(config.interactiveEffects.chromaticAberration.greenShift ?? 0),
21545
+ "interactive-chromatic-blue-shift": String(config.interactiveEffects.chromaticAberration.blueShift ?? -.02),
21546
+ "interactive-chromatic-edge-only": String(config.interactiveEffects.chromaticAberration.edgeOnly ?? !1),
21547
+ "interactive-chromatic-edge-threshold": String(config.interactiveEffects.chromaticAberration.edgeThreshold ?? .5)
21548
+ }),
21549
+ // Mouse interaction
21550
+ config.interactiveEffects.mouseInteraction && (tokensToApply = {
21551
+ ...tokensToApply,
21552
+ "interactive-mouse-sensitivity": String(config.interactiveEffects.mouseInteraction.sensitivity ?? 1),
21553
+ "interactive-mouse-trail-effect": String(config.interactiveEffects.mouseInteraction.trailEffect ?? !1)
21554
+ }),
21555
+ // Animation speed
21556
+ config.interactiveEffects.animationSpeed && (tokensToApply = {
21557
+ ...tokensToApply,
21558
+ "interactive-animation-speed-base": String(config.interactiveEffects.animationSpeed.base ?? 1),
21559
+ "interactive-animation-speed-multiplier": String(config.interactiveEffects.animationSpeed.timeMultiplier ?? 1)
21560
+ })),
21561
+ // Apply optimization configurations as tokens
21562
+ config.optimization && (
21563
+ // Responsive breakpoints
21564
+ config.optimization.responsive && (config.optimization.responsive.breakpoints && (tokensToApply = {
21565
+ ...tokensToApply,
21566
+ "optimization-breakpoint-mobile": config.optimization.responsive.breakpoints.mobile ?? "0px",
21567
+ "optimization-breakpoint-tablet": config.optimization.responsive.breakpoints.tablet ?? "768px",
21568
+ "optimization-breakpoint-desktop": config.optimization.responsive.breakpoints.desktop ?? "1024px",
21569
+ "optimization-breakpoint-wide": config.optimization.responsive.breakpoints.wide ?? "1440px"
21570
+ }), config.optimization.responsive.deviceScaling && (tokensToApply = {
21571
+ ...tokensToApply,
21572
+ "optimization-device-scaling-mobile": String(config.optimization.responsive.deviceScaling.mobile ?? .5),
21573
+ "optimization-device-scaling-tablet": String(config.optimization.responsive.deviceScaling.tablet ?? .75),
21574
+ "optimization-device-scaling-desktop": String(config.optimization.responsive.deviceScaling.desktop ?? 1)
21575
+ })),
21576
+ // Performance settings
21577
+ config.optimization.performance && (tokensToApply = {
21578
+ ...tokensToApply,
21579
+ "optimization-performance-fps-target": String(config.optimization.performance.fpsTarget ?? 60),
21580
+ "optimization-auto-scaling-enabled": String(config.optimization.performance.autoScaling ?? !1)
21581
+ }),
21582
+ // Auto-scaling settings
21583
+ config.optimization.autoScaling && (tokensToApply = {
21584
+ ...tokensToApply,
21585
+ "optimization-auto-scaling-enabled": String(config.optimization.autoScaling.enabled ?? !1),
21586
+ "optimization-auto-scaling-low-end": String(config.optimization.autoScaling.qualityThresholds?.lowEnd ?? .5),
21587
+ "optimization-auto-scaling-mid-range": String(config.optimization.autoScaling.qualityThresholds?.midRange ?? .75),
21588
+ "optimization-auto-scaling-high-end": String(config.optimization.autoScaling.qualityThresholds?.highEnd ?? 1)
21589
+ })),
21590
+ // Apply visual polish configurations as tokens
21591
+ config.visualPolish && (config.visualPolish.borders && (tokensToApply = {
21592
+ ...tokensToApply,
21593
+ "visual-polish-border-iridescent-glow": String(config.visualPolish.borders.iridescentGlow ?? !1),
21594
+ "visual-polish-border-shimmer-effect": String(config.visualPolish.borders.shimmerEffect ?? !1),
21595
+ "visual-polish-border-beveled-edges": String(config.visualPolish.borders.beveledEdges ?? !1),
21596
+ "visual-polish-border-pulsing-glow": String(config.visualPolish.borders.pulsingGlow ?? !1)
21597
+ }), config.visualPolish.contentAwareBlur && (tokensToApply = {
21598
+ ...tokensToApply,
21599
+ "visual-polish-content-aware-blur-enabled": String(config.visualPolish.contentAwareBlur.enabled ?? !1),
21600
+ "visual-polish-content-aware-depth-detection": String(config.visualPolish.contentAwareBlur.depthDetection ?? !1),
21601
+ "visual-polish-content-aware-edge-preservation": String(config.visualPolish.contentAwareBlur.edgePreservation ?? !1),
21602
+ "visual-polish-content-aware-variable-radius": String(config.visualPolish.contentAwareBlur.variableRadius ?? !1)
21603
+ }), config.visualPolish.holographicEffects && (tokensToApply = {
21604
+ ...tokensToApply,
21605
+ "visual-polish-holographic-enabled": String(config.visualPolish.holographicEffects.enabled ?? !1),
21606
+ "visual-polish-holographic-rainbow-diffraction": String(config.visualPolish.holographicEffects.rainbowDiffraction ?? !1),
21607
+ "visual-polish-holographic-scanline-animation": String(config.visualPolish.holographicEffects.scanlineAnimation ?? !1),
21608
+ "visual-polish-holographic-grid-overlay": String(config.visualPolish.holographicEffects.gridOverlay ?? !1),
21609
+ "visual-polish-holographic-data-stream": String(config.visualPolish.holographicEffects.dataStream ?? !1),
21610
+ "visual-polish-holographic-pulse-rings": String(config.visualPolish.holographicEffects.pulseRings ?? !1)
21611
+ })), createTokens(tokensToApply);
21612
+ }();
21613
+ // Get prefix from config
21614
+ try {
21615
+ // Use the imported function directly instead of require to avoid bundling issues
21616
+ const config = loadAtomixConfig({
21617
+ configPath: "atomix.config.ts",
21618
+ required: !0
21619
+ });
21620
+ configPrefix = config?.prefix;
21621
+ } catch (error) {
21622
+ // Prefix loading failed, but tokens were loaded, so continue
21623
+ }
21624
+ tokens = configTokens;
21123
21625
  }
21124
21626
  // Merge with defaults and generate CSS
21125
- else
21126
- // Auto-loading config from file system is removed for browser compatibility.
21127
- // If no input is provided, we return an empty theme (using defaults only) or user must provide tokens.
21128
- // This allows createTheme to be isomorphic.
21129
- // Warn in development if no input provided
21130
- "production" !== process.env.NODE_ENV && "undefined" != typeof window && console.warn("Atomix: createTheme() called without tokens. Using default tokens only."),
21131
- tokens = {};
21132
- const allTokens = createTokens(tokens), prefix = options?.prefix ?? "atomix";
21133
- // Get prefix from options or use default
21627
+ const allTokens = createTokens(tokens), prefix = options?.prefix ?? configPrefix ?? "atomix";
21628
+ // Get prefix from options, config, or use default
21134
21629
  return generateCSSVariables$1(allTokens, {
21135
21630
  ...options,
21136
21631
  prefix: prefix
@@ -21344,42 +21839,175 @@ class ThemeLogger {
21344
21839
  */
21345
21840
  /**
21346
21841
  * Default storage key for theme persistence
21347
- */ "undefined" != typeof process && process.env;
21348
-
21842
+ */
21349
21843
  /**
21350
- * Check if code is running in a browser environment
21844
+ * Theme System Error Handling
21845
+ *
21846
+ * Centralized error handling for the Atomix theme system.
21847
+ * Provides custom error classes and logging utilities.
21351
21848
  */
21352
- const isBrowser = () => "undefined" != typeof window && "undefined" != typeof document, isServer = () => !isBrowser(), sanitizePath = path => path.replace(/[<>"']/g, "").replace(/\.\./g, "").replace(/\/+/g, "/").replace(/^\/+|\/+$/g, "") // Trim leading/trailing slashes
21353
- , buildThemePath = (themeName, basePath = "/themes", useMinified = !1, cdnPath = null) => {
21354
- // Validate theme name to prevent path injection
21355
- if (!isValidThemeName(themeName)) throw new ThemeError(`Invalid theme name: "${themeName}". Theme names must be lowercase alphanumeric with hyphens (e.g., "my-theme").`, ThemeErrorCode.INVALID_THEME_NAME, {
21356
- themeName: themeName,
21357
- pattern: /^[a-z0-9]+(-[a-z0-9]+)*$/
21358
- });
21359
- const fileName = `${themeName}${useMinified ? ".min.css" : ".css"}`;
21360
- return cdnPath ? `${sanitizePath(cdnPath)}/${fileName}` : `${sanitizePath(basePath)}/${fileName.replace(/^\//, "")}`;
21361
- // Sanitize basePath to prevent path injection
21362
- }, applyThemeAttributes = (dataAttribute, themeName) => {
21363
- isServer() || (
21364
- // Set data attribute on body (with null check)
21365
- document.body && document.body.setAttribute(dataAttribute, themeName),
21366
- // Also set on documentElement for broader compatibility
21367
- document.documentElement.setAttribute(dataAttribute, themeName));
21368
- }, isValidThemeName = themeName => !(!themeName || "string" != typeof themeName) && /^[a-z0-9]+(-[a-z0-9]+)*$/.test(themeName), createLocalStorageAdapter = () => ({
21369
- getItem: key => {
21370
- if (isServer()) return null;
21371
- try {
21372
- return localStorage.getItem(key);
21373
- } catch {
21374
- return null;
21375
- }
21376
- },
21377
- setItem: (key, value) => {
21378
- if (!isServer()) try {
21379
- localStorage.setItem(key, value);
21380
- } catch {
21381
- // Silently fail if localStorage is not available
21382
- }
21849
+ /**
21850
+ * Theme error codes
21851
+ */
21852
+ var ThemeErrorCode, LogLevel;
21853
+
21854
+ "undefined" != typeof process && process.env, function(ThemeErrorCode) {
21855
+ /** Theme not found in registry */
21856
+ ThemeErrorCode.THEME_NOT_FOUND = "THEME_NOT_FOUND",
21857
+ /** Theme failed to load */
21858
+ ThemeErrorCode.THEME_LOAD_FAILED = "THEME_LOAD_FAILED",
21859
+ /** Theme validation failed */
21860
+ ThemeErrorCode.THEME_VALIDATION_FAILED = "THEME_VALIDATION_FAILED",
21861
+ /** Configuration loading failed */
21862
+ ThemeErrorCode.CONFIG_LOAD_FAILED = "CONFIG_LOAD_FAILED",
21863
+ /** Configuration validation failed */
21864
+ ThemeErrorCode.CONFIG_VALIDATION_FAILED = "CONFIG_VALIDATION_FAILED",
21865
+ /** Circular dependency detected */
21866
+ ThemeErrorCode.CIRCULAR_DEPENDENCY = "CIRCULAR_DEPENDENCY",
21867
+ /** Missing dependency */
21868
+ ThemeErrorCode.MISSING_DEPENDENCY = "MISSING_DEPENDENCY",
21869
+ /** Storage operation failed */
21870
+ ThemeErrorCode.STORAGE_ERROR = "STORAGE_ERROR",
21871
+ /** Invalid theme name */
21872
+ ThemeErrorCode.INVALID_THEME_NAME = "INVALID_THEME_NAME",
21873
+ /** CSS injection failed */
21874
+ ThemeErrorCode.CSS_INJECTION_FAILED = "CSS_INJECTION_FAILED",
21875
+ /** Invalid color format */
21876
+ ThemeErrorCode.INVALID_COLOR_FORMAT = "INVALID_COLOR_FORMAT",
21877
+ /** Missing required token */
21878
+ ThemeErrorCode.MISSING_REQUIRED_TOKEN = "MISSING_REQUIRED_TOKEN",
21879
+ /** Accessibility contrast violation */
21880
+ ThemeErrorCode.CONTRAST_VIOLATION = "CONTRAST_VIOLATION",
21881
+ /** Invalid token type */
21882
+ ThemeErrorCode.INVALID_TOKEN_TYPE = "INVALID_TOKEN_TYPE",
21883
+ /** Unknown error */
21884
+ ThemeErrorCode.UNKNOWN_ERROR = "UNKNOWN_ERROR";
21885
+ }(ThemeErrorCode || (ThemeErrorCode = {}));
21886
+
21887
+ /**
21888
+ * Custom error class for theme-related errors
21889
+ */
21890
+ class ThemeError extends Error {
21891
+ constructor(message, code = ThemeErrorCode.UNKNOWN_ERROR, context) {
21892
+ super(message), this.name = "ThemeError", this.code = code, this.context = context,
21893
+ this.timestamp = Date.now(),
21894
+ // Maintains proper stack trace for where our error was thrown (only available on V8)
21895
+ Error.captureStackTrace && Error.captureStackTrace(this, ThemeError);
21896
+ }
21897
+ /**
21898
+ * Convert error to JSON for logging
21899
+ */ toJSON() {
21900
+ return {
21901
+ name: this.name,
21902
+ message: this.message,
21903
+ code: this.code,
21904
+ context: this.context,
21905
+ timestamp: this.timestamp,
21906
+ stack: this.stack
21907
+ };
21908
+ }
21909
+ }
21910
+
21911
+ /**
21912
+ * Log level
21913
+ */ !function(LogLevel) {
21914
+ LogLevel[LogLevel.ERROR = 0] = "ERROR", LogLevel[LogLevel.WARN = 1] = "WARN", LogLevel[LogLevel.INFO = 2] = "INFO",
21915
+ LogLevel[LogLevel.DEBUG = 3] = "DEBUG";
21916
+ }(LogLevel || (LogLevel = {}));
21917
+
21918
+ /**
21919
+ * Theme Logger
21920
+ *
21921
+ * Centralized logging for the theme system.
21922
+ * Replaces console statements with structured logging.
21923
+ */
21924
+ class ThemeLogger {
21925
+ constructor(config = {}) {
21926
+ this.config = {
21927
+ level: config.level ?? ("undefined" != typeof process && "production" === process.env?.NODE_ENV ? LogLevel.WARN : LogLevel.INFO),
21928
+ enableConsole: config.enableConsole ?? !0,
21929
+ onError: config.onError,
21930
+ onWarn: config.onWarn,
21931
+ onInfo: config.onInfo,
21932
+ onDebug: config.onDebug
21933
+ };
21934
+ }
21935
+ /**
21936
+ * Log an error
21937
+ */ error(message, error, context) {
21938
+ if (this.config.level < LogLevel.ERROR) return;
21939
+ const errorObj = error instanceof Error ? error : new Error(message), themeError = error instanceof ThemeError ? error : new ThemeError(message, ThemeErrorCode.UNKNOWN_ERROR, context);
21940
+ this.config.enableConsole && console.error(`[ThemeError] ${message}`, {
21941
+ error: errorObj,
21942
+ context: {
21943
+ ...context,
21944
+ ...themeError.context
21945
+ },
21946
+ code: themeError.code
21947
+ }), this.config.onError?.(themeError, context);
21948
+ }
21949
+ /**
21950
+ * Log a warning
21951
+ */ warn(message, context) {
21952
+ this.config.level < LogLevel.WARN || (this.config.enableConsole && console.warn(`[ThemeWarning] ${message}`, context || {}),
21953
+ this.config.onWarn?.(message, context));
21954
+ }
21955
+ /**
21956
+ * Log an info message
21957
+ */ info(message, context) {
21958
+ this.config.level < LogLevel.INFO || (this.config.enableConsole && console.info(`[ThemeInfo] ${message}`, context || {}),
21959
+ this.config.onInfo?.(message, context));
21960
+ }
21961
+ /**
21962
+ * Log a debug message
21963
+ */ debug(message, context) {
21964
+ this.config.level < LogLevel.DEBUG || (this.config.enableConsole, this.config.onDebug?.(message, context));
21965
+ }
21966
+ }
21967
+
21968
+ /**
21969
+ * Default logger instance
21970
+ */ let defaultLogger = null;
21971
+
21972
+ /**
21973
+ * Get or create default logger
21974
+ */ function getLogger() {
21975
+ return defaultLogger || (defaultLogger = new ThemeLogger), defaultLogger;
21976
+ }
21977
+
21978
+ /**
21979
+ * Check if code is running in a browser environment
21980
+ */ const isBrowser = () => "undefined" != typeof window && "undefined" != typeof document, isServer = () => !isBrowser(), sanitizePath = path => path.replace(/[<>"']/g, "").replace(/\.\./g, "").replace(/\/+/g, "/").replace(/^\/+|\/+$/g, "") // Trim leading/trailing slashes
21981
+ , buildThemePath = (themeName, basePath = "/themes", useMinified = !1, cdnPath = null) => {
21982
+ // Validate theme name to prevent path injection
21983
+ if (!isValidThemeName(themeName)) throw new ThemeError(`Invalid theme name: "${themeName}". Theme names must be lowercase alphanumeric with hyphens (e.g., "my-theme").`, ThemeErrorCode.INVALID_THEME_NAME, {
21984
+ themeName: themeName,
21985
+ pattern: /^[a-z0-9]+(-[a-z0-9]+)*$/
21986
+ });
21987
+ const fileName = `${themeName}${useMinified ? ".min.css" : ".css"}`;
21988
+ return cdnPath ? `${sanitizePath(cdnPath)}/${fileName}` : `${sanitizePath(basePath)}/${fileName.replace(/^\//, "")}`;
21989
+ // Sanitize basePath to prevent path injection
21990
+ }, applyThemeAttributes = (dataAttribute, themeName) => {
21991
+ isServer() || (
21992
+ // Set data attribute on body (with null check)
21993
+ document.body && document.body.setAttribute(dataAttribute, themeName),
21994
+ // Also set on documentElement for broader compatibility
21995
+ document.documentElement.setAttribute(dataAttribute, themeName));
21996
+ }, isValidThemeName = themeName => !(!themeName || "string" != typeof themeName) && /^[a-z0-9]+(-[a-z0-9]+)*$/.test(themeName), createLocalStorageAdapter = () => ({
21997
+ getItem: key => {
21998
+ if (isServer()) return null;
21999
+ try {
22000
+ return localStorage.getItem(key);
22001
+ } catch {
22002
+ return null;
22003
+ }
22004
+ },
22005
+ setItem: (key, value) => {
22006
+ if (!isServer()) try {
22007
+ localStorage.setItem(key, value);
22008
+ } catch {
22009
+ // Silently fail if localStorage is not available
22010
+ }
21383
22011
  },
21384
22012
  removeItem: key => {
21385
22013
  if (!isServer()) try {
@@ -21434,106 +22062,428 @@ const isBrowser = () => "undefined" != typeof window && "undefined" != typeof do
21434
22062
  /**
21435
22063
  * Check if code is running on the server (SSR)
21436
22064
  */
22065
+ // ============================================================================
22066
+ // Theme Mode Switching
22067
+ // ============================================================================
21437
22068
  /**
21438
- * Theme Utilities
22069
+ * Switch between light and dark themes
22070
+ *
22071
+ * Automatically toggles a class on the root element and persists the choice.
22072
+ *
22073
+ * @param mode - Theme mode ('light', 'dark', or 'system')
22074
+ * @param options - Configuration options
22075
+ *
22076
+ * @example
22077
+ * ```typescript
22078
+ * import { switchTheme } from '@shohojdhara/atomix/theme/utils';
22079
+ *
22080
+ * // Switch to dark mode
22081
+ * switchTheme('dark');
21439
22082
  *
21440
- * Helper utilities for working with themes, including color manipulation,
21441
- * spacing helpers, and theme value accessors.
22083
+ * // Toggle between light/dark
22084
+ * const current = getCurrentTheme();
22085
+ * switchTheme(current === 'dark' ? 'light' : 'dark');
22086
+ * ```
21442
22087
  */
22088
+ function switchTheme(mode, options = {}) {
22089
+ const {selector: selector = ":root", storageKey: storageKey = "atomix-theme", enableTransition: enableTransition = !0, transitionDuration: transitionDuration = 300} = options, resolvedMode = "system" === mode ? getSystemTheme() : mode, root = ":root" === selector ? document.documentElement : document.querySelector(selector);
22090
+ // Determine actual mode (resolve 'system')
22091
+ if (root) {
22092
+ // Add transition class if enabled
22093
+ if (enableTransition) {
22094
+ const htmlRoot = root;
22095
+ htmlRoot.style.transition = `all ${transitionDuration}ms ease-in-out`,
22096
+ // Remove transition after it completes
22097
+ setTimeout((() => {
22098
+ htmlRoot.style.transition = "";
22099
+ }), transitionDuration);
22100
+ }
22101
+ // Apply theme class
22102
+ root.classList.remove("atomix-theme-light", "atomix-theme-dark"), root.classList.add(`atomix-theme-${resolvedMode}`),
22103
+ // Set data attribute for CSS selectors
22104
+ root.setAttribute("data-theme", resolvedMode),
22105
+ // Persist choice
22106
+ persistTheme(resolvedMode, {
22107
+ storageKey: storageKey
22108
+ }),
22109
+ // Dispatch custom event for listeners
22110
+ window.dispatchEvent(new CustomEvent("atomix-theme-change", {
22111
+ detail: {
22112
+ mode: resolvedMode
22113
+ }
22114
+ }));
22115
+ }
22116
+ }
22117
+
22118
+ /**
22119
+ * Toggle between light and dark themes
22120
+ *
22121
+ * @param options - Configuration options
22122
+ * @returns The new theme mode
22123
+ *
22124
+ * @example
22125
+ * ```typescript
22126
+ * const newMode = toggleTheme();
22127
+ * console.log('Switched to:', newMode);
22128
+ * ```
22129
+ */ function toggleTheme(options = {}) {
22130
+ const next = "dark" === getCurrentTheme(options.storageKey) ? "light" : "dark";
22131
+ return switchTheme(next, options), next;
22132
+ }
22133
+
22134
+ /**
22135
+ * Get current theme mode
22136
+ *
22137
+ * @param storageKey - Storage key (default: 'atomix-theme')
22138
+ * @returns Current theme mode or 'light' if not set
22139
+ */ function getCurrentTheme(storageKey = "atomix-theme") {
22140
+ return "undefined" == typeof window ? "light" : localStorage.getItem(storageKey) || "light";
22141
+ }
22142
+
22143
+ /**
22144
+ * Get system theme preference
22145
+ *
22146
+ * @returns 'dark' if system prefers dark mode, 'light' otherwise
22147
+ */ function getSystemTheme() {
22148
+ return "undefined" == typeof window ? "light" : window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
22149
+ }
22150
+
22151
+ /**
22152
+ * Initialize theme based on saved preference or system preference
22153
+ *
22154
+ * Call this once at app startup.
22155
+ *
22156
+ * @param options - Configuration options
22157
+ * @returns The initialized theme mode
22158
+ *
22159
+ * @example
22160
+ * ```typescript
22161
+ * // In your app entry point
22162
+ * import { initializeTheme } from '@shohojdhara/atomix/theme/utils';
22163
+ *
22164
+ * const theme = initializeTheme();
22165
+ * console.log('Theme initialized:', theme);
22166
+ * ```
22167
+ */ function initializeTheme(options = {}) {
22168
+ const saved = getCurrentTheme(options.storageKey);
22169
+ // If no saved preference, use system preference
22170
+ if (!saved || "system" === saved) {
22171
+ const system = getSystemTheme();
22172
+ return switchTheme(system, options), system;
22173
+ }
22174
+ // Use saved preference
22175
+ return switchTheme(saved, options), saved;
22176
+ }
22177
+
22178
+ /**
22179
+ * Listen for system theme changes
22180
+ *
22181
+ * @param callback - Function to call when system theme changes
22182
+ * @returns Cleanup function to stop listening
22183
+ *
22184
+ * @example
22185
+ * ```typescript
22186
+ * const cleanup = listenToSystemTheme((mode) => {
22187
+ * console.log('System theme changed to:', mode);
22188
+ * switchTheme(mode);
22189
+ * });
22190
+ *
22191
+ * // Later, when component unmounts
22192
+ * cleanup();
22193
+ * ```
22194
+ */ function listenToSystemTheme(callback) {
22195
+ if ("undefined" == typeof window) return () => {};
22196
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"), handler = e => {
22197
+ callback(e.matches ? "dark" : "light");
22198
+ };
22199
+ // Modern browsers
22200
+ return mediaQuery.addEventListener ? (mediaQuery.addEventListener("change", handler),
22201
+ () => mediaQuery.removeEventListener("change", handler)) : (
22202
+ // Fallback for older browsers
22203
+ mediaQuery.addListener(handler), () => mediaQuery.removeListener(handler));
22204
+ }
22205
+
21443
22206
  // ============================================================================
21444
- // Color Manipulation Utilities
22207
+ // Theme Persistence
21445
22208
  // ============================================================================
21446
22209
  /**
21447
- * Convert hex color to RGB object
21448
- */
21449
- function hexToRgb$1(hex) {
21450
- const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
21451
- return result ? {
21452
- r: parseInt(result[1], 16),
21453
- g: parseInt(result[2], 16),
21454
- b: parseInt(result[3], 16)
21455
- } : null;
22210
+ * Save theme preference to storage
22211
+ *
22212
+ * @param mode - Theme mode to save
22213
+ * @param options - Persistence options
22214
+ */ function persistTheme(mode, options = {}) {
22215
+ if ("undefined" == typeof window) return;
22216
+ const {storageKey: storageKey = "atomix-theme", storageType: storageType = "localStorage"} = options;
22217
+ ("localStorage" === storageType ? localStorage : sessionStorage).setItem(storageKey, mode);
22218
+ }
22219
+
22220
+ /**
22221
+ * Clear saved theme preference
22222
+ *
22223
+ * @param options - Persistence options
22224
+ */ function clearThemePreference(options = {}) {
22225
+ if ("undefined" == typeof window) return;
22226
+ const {storageKey: storageKey = "atomix-theme", storageType: storageType = "localStorage"} = options;
22227
+ ("localStorage" === storageType ? localStorage : sessionStorage).removeItem(storageKey);
22228
+ }
22229
+
22230
+ // ============================================================================
22231
+ // Theme Tokens Manipulation
22232
+ // ============================================================================
22233
+ /**
22234
+ * Merge multiple token sets
22235
+ *
22236
+ * Deep merges token objects, with later tokens overriding earlier ones.
22237
+ *
22238
+ * @param tokens - Token objects to merge
22239
+ * @returns Merged tokens
22240
+ *
22241
+ * @example
22242
+ * ```typescript
22243
+ * const merged = mergeTokens(
22244
+ * baseTokens,
22245
+ * { colors: { primary: { main: '#custom' } } }
22246
+ * );
22247
+ * ```
22248
+ */ function mergeTokens(...tokens) {
22249
+ return _reduceInstanceProperty(tokens).call(tokens, ((acc, current) => deepMerge(acc, current)), {});
22250
+ }
22251
+
22252
+ /**
22253
+ * Override specific tokens
22254
+ *
22255
+ * Creates a new token object with specific overrides.
22256
+ *
22257
+ * @param base - Base tokens
22258
+ * @param overrides - Tokens to override
22259
+ * @returns New tokens with overrides applied
22260
+ *
22261
+ * @example
22262
+ * ```typescript
22263
+ * const customized = overrideTokens(defaultTokens, {
22264
+ * colors: {
22265
+ * primary: { main: '#ff0000' }
22266
+ * }
22267
+ * });
22268
+ * ```
22269
+ */ function overrideTokens(base, overrides) {
22270
+ return deepMerge({
22271
+ ...base
22272
+ }, overrides);
21456
22273
  }
21457
22274
 
21458
22275
  /**
21459
- * Convert RGB to hex color
22276
+ * Pick specific token categories
22277
+ *
22278
+ * Extracts only the specified categories from tokens.
22279
+ *
22280
+ * @param tokens - Source tokens
22281
+ * @param categories - Categories to pick
22282
+ * @returns Tokens with only selected categories
22283
+ *
22284
+ * @example
22285
+ * ```typescript
22286
+ * const colorTokens = pickTokens(allTokens, ['colors']);
22287
+ * ```
22288
+ */ function pickTokens(tokens, categories) {
22289
+ const result = {};
22290
+ return categories.forEach((category => {
22291
+ tokens[category] && (result[category] = tokens[category]);
22292
+ })), result;
22293
+ }
22294
+
22295
+ /**
22296
+ * Omit specific token categories
22297
+ *
22298
+ * Removes specified categories from tokens.
22299
+ *
22300
+ * @param tokens - Source tokens
22301
+ * @param categories - Categories to omit
22302
+ * @returns Tokens without omitted categories
22303
+ *
22304
+ * @example
22305
+ * ```typescript
22306
+ * const withoutColors = omitTokens(allTokens, ['colors']);
22307
+ * ```
22308
+ */ function omitTokens(tokens, categories) {
22309
+ const result = {
22310
+ ...tokens
22311
+ };
22312
+ return categories.forEach((category => {
22313
+ delete result[category];
22314
+ })), result;
22315
+ }
22316
+
22317
+ // ============================================================================
22318
+ // Color Utilities
22319
+ // ============================================================================
22320
+ /**
22321
+ * Convert hex color to RGB
22322
+ *
22323
+ * @param hex - Hex color (with or without #)
22324
+ * @returns RGB object { r, g, b }
22325
+ */ function hexToRgb$1(hex) {
22326
+ // Validate
22327
+ if (
22328
+ // Remove # if present
22329
+ // Handle shorthand hex
22330
+ 3 === (hex = hex.replace(/^#/, "")).length && (hex = hex.split("").map((c => c + c)).join("")),
22331
+ 6 !== hex.length) return null;
22332
+ const num = parseInt(hex, 16);
22333
+ return {
22334
+ r: num >> 16 & 255,
22335
+ g: num >> 8 & 255,
22336
+ b: 255 & num
22337
+ };
22338
+ }
22339
+
22340
+ /**
22341
+ * Convert RGB to hex
22342
+ *
22343
+ * @param r - Red (0-255)
22344
+ * @param g - Green (0-255)
22345
+ * @param b - Blue (0-255)
22346
+ * @returns Hex color with #
21460
22347
  */ function rgbToHex(r, g, b) {
21461
- const toHex = val => Math.round(Math.max(0, Math.min(255, val))).toString(16).padStart(2, "0");
21462
- return `#${toHex(r ?? 0)}${toHex(g ?? 0)}${toHex(b ?? 0)}`;
22348
+ return "#" + [ r, g, b ].map((x => {
22349
+ const hex = x.toString(16);
22350
+ return 1 === hex.length ? "0" + hex : hex;
22351
+ })).join("");
21463
22352
  }
21464
22353
 
21465
22354
  /**
21466
- * Calculate relative luminance of a color
21467
- * Used for determining contrast ratios
21468
- */ function getLuminance(color) {
21469
- const rgb = hexToRgb$1(color);
22355
+ * Calculate luminance of a color
22356
+ *
22357
+ * Used for determining contrast ratios.
22358
+ *
22359
+ * @param hex - Hex color
22360
+ * @returns Luminance value (0-1)
22361
+ */ function getLuminance(hex) {
22362
+ const rgb = hexToRgb$1(hex);
21470
22363
  if (!rgb) return 0;
21471
- const {r: r, g: g, b: b} = rgb, [rs, gs, bs] = [ r ?? 0, g ?? 0, b ?? 0 ].map((c => {
21472
- const val = c / 255;
21473
- return val <= .03928 ? val / 12.92 : Math.pow((val + .055) / 1.055, 2.4);
21474
- }));
21475
- return .2126 * (rs ?? 0) + .7152 * (gs ?? 0) + .0722 * (bs ?? 0);
22364
+ const [r, g, b] = [ rgb.r, rgb.g, rgb.b ].map((v => (v /= 255) <= .03928 ? v / 12.92 : Math.pow((v + .055) / 1.055, 2.4)));
22365
+ return .2126 * (r ?? 0) + .7152 * (g ?? 0) + .0722 * (b ?? 0);
21476
22366
  }
21477
22367
 
21478
22368
  /**
21479
22369
  * Calculate contrast ratio between two colors
21480
- */ function getContrastRatio(foreground, background) {
21481
- const lumA = getLuminance(foreground), lumB = getLuminance(background);
21482
- return (Math.max(lumA, lumB) + .05) / (Math.min(lumA, lumB) + .05);
22370
+ *
22371
+ * @param hex1 - First hex color
22372
+ * @param hex2 - Second hex color
22373
+ * @returns Contrast ratio (1-21)
22374
+ */ function getContrastRatio(hex1, hex2) {
22375
+ const lum1 = getLuminance(hex1), lum2 = getLuminance(hex2);
22376
+ return (Math.max(lum1, lum2) + .05) / (Math.min(lum1, lum2) + .05);
21483
22377
  }
21484
22378
 
21485
22379
  /**
21486
- * Get appropriate contrast text color (black or white) for a background color
21487
- */ function getContrastText(background, threshold = 3) {
21488
- const contrastWithWhite = getContrastRatio("#FFFFFF", background), contrastWithBlack = getContrastRatio("#000000", background);
21489
- return contrastWithWhite >= threshold ? "#FFFFFF" : contrastWithBlack >= threshold ? "#000000" : contrastWithWhite > contrastWithBlack ? "#FFFFFF" : "#000000";
22380
+ * Check if text color passes WCAG AA standard
22381
+ *
22382
+ * @param textColor - Text color hex
22383
+ * @param backgroundColor - Background color hex
22384
+ * @param size - Font size ('small' or 'large')
22385
+ * @returns true if passes WCAG AA
22386
+ */ function isAccessible(textColor, backgroundColor, size = "small") {
22387
+ return getContrastRatio(textColor, backgroundColor) >= ("large" === size ? 3 : 4.5);
21490
22388
  }
21491
22389
 
21492
22390
  /**
21493
- * Lighten a color by a given amount
22391
+ * Get appropriate text color (black or white) for a background
21494
22392
  *
21495
- * @param color - Hex color string
21496
- * @param amount - Amount to lighten (0-1), default 0.2
22393
+ * @param backgroundColor - Background hex color
22394
+ * @param threshold - Contrast threshold (default: 3)
22395
+ * @returns '#000000' or '#FFFFFF'
22396
+ */ function getContrastText(backgroundColor, threshold = 3) {
22397
+ return getContrastRatio(backgroundColor, "#FFFFFF") >= threshold ? "#FFFFFF" : "#000000";
22398
+ }
22399
+
22400
+ /**
22401
+ * Lighten a color
22402
+ *
22403
+ * @param hex - Base hex color
22404
+ * @param amount - Amount to lighten (0-1)
21497
22405
  * @returns Lightened hex color
21498
- */ function lighten(color, amount = .2) {
21499
- const rgb = hexToRgb$1(color);
21500
- if (!rgb) return color;
21501
- const {r: r, g: g, b: b} = rgb, lightenValue = val => Math.min(255, Math.round(val + (255 - val) * amount));
21502
- return rgbToHex(lightenValue(r), lightenValue(g), lightenValue(b));
22406
+ */ function lighten(hex, amount = 0) {
22407
+ const rgb = hexToRgb$1(hex);
22408
+ if (!rgb) return hex;
22409
+ // Use amount directly as factor (0-1)
22410
+ const factor = Math.max(0, Math.min(1, amount)), r = Math.round(rgb.r + (255 - rgb.r) * factor), g = Math.round(rgb.g + (255 - rgb.g) * factor), b = Math.round(rgb.b + (255 - rgb.b) * factor);
22411
+ return rgbToHex(Math.min(255, r), Math.min(255, g), Math.min(255, b));
21503
22412
  }
21504
22413
 
21505
22414
  /**
21506
- * Darken a color by a given amount
22415
+ * Darken a color
21507
22416
  *
21508
- * @param color - Hex color string
21509
- * @param amount - Amount to darken (0-1), default 0.2
22417
+ * @param hex - Base hex color
22418
+ * @param amount - Amount to darken (0-1)
21510
22419
  * @returns Darkened hex color
21511
- */ function darken(color, amount = .2) {
21512
- const rgb = hexToRgb$1(color);
21513
- if (!rgb) return color;
21514
- const {r: r, g: g, b: b} = rgb, darkenValue = val => Math.max(0, Math.round(val * (1 - amount)));
21515
- return rgbToHex(darkenValue(r), darkenValue(g), darkenValue(b));
22420
+ */ function darken(hex, amount = 0) {
22421
+ const rgb = hexToRgb$1(hex);
22422
+ if (!rgb) return hex;
22423
+ // Use amount directly as factor (0-1)
22424
+ const factor = Math.max(0, Math.min(1, amount)), r = Math.round(rgb.r * (1 - factor)), g = Math.round(rgb.g * (1 - factor)), b = Math.round(rgb.b * (1 - factor));
22425
+ return rgbToHex(Math.max(0, r), Math.max(0, g), Math.max(0, b));
21516
22426
  }
21517
22427
 
21518
22428
  /**
21519
- * Add alpha (opacity) to a color
22429
+ * Add alpha to a color
21520
22430
  *
21521
- * @param color - Hex color string
22431
+ * @param hex - Hex color
21522
22432
  * @param opacity - Opacity value (0-1)
21523
22433
  * @returns RGBA color string
21524
- */ function alpha(color, opacity) {
21525
- const rgb = hexToRgb$1(color);
21526
- if (!rgb) return color;
21527
- const {r: r, g: g, b: b} = rgb;
21528
- return `rgba(${r}, ${g}, ${b}, ${Math.max(0, Math.min(1, opacity))})`;
22434
+ */ function alpha(hex, opacity) {
22435
+ const rgb = hexToRgb$1(hex);
22436
+ if (!rgb) return hex;
22437
+ const validOpacity = Math.max(0, Math.min(1, opacity));
22438
+ return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${validOpacity})`;
21529
22439
  }
21530
22440
 
21531
22441
  /**
21532
22442
  * Emphasize a color (lighten if dark, darken if light)
21533
22443
  *
21534
- * @param color - Hex color string
21535
- * @param coefficient - Amount to emphasize (0-1), default 0.15
22444
+ * @param hex - Hex color
22445
+ * @param amount - Amount to emphasize (0-1)
21536
22446
  * @returns Emphasized hex color
22447
+ */ function emphasize(hex, amount = .15) {
22448
+ return getLuminance(hex) > .5 ? darken(hex, amount) : lighten(hex, amount);
22449
+ }
22450
+
22451
+ /**
22452
+ * Create a spacing utility
22453
+ *
22454
+ * @param spacingInput - Spacing configuration
22455
+ * @returns Spacing function
22456
+ */ function createSpacing(spacingInput = 4) {
22457
+ return (...values) => 0 === values.length ? "0px" : "function" == typeof spacingInput ? spacingInput(...values) : values.map((value => {
22458
+ if ("number" == typeof spacingInput) return value * spacingInput + "px";
22459
+ if (Array.isArray(spacingInput)) {
22460
+ const scaled = spacingInput[value];
22461
+ return "number" == typeof scaled ? `${scaled}px` : `${value}px`;
22462
+ }
22463
+ return `${value}px`;
22464
+ })).join(" ");
22465
+ }
22466
+
22467
+ /**
22468
+ * CSS Variable Generator
22469
+ *
22470
+ * Generates CSS custom properties from theme objects and injects them into the DOM.
22471
+ *
22472
+ * **Token Naming Alignment:**
22473
+ * This generator produces CSS variables that match the SCSS token naming pattern exactly:
22474
+ * - Colors: --atomix-primary, --atomix-primary-1 through --atomix-primary-10
22475
+ * - Spacing: --atomix-spacing-1, --atomix-spacing-4, etc.
22476
+ * - Typography: --atomix-font-size-base, --atomix-font-weight-normal, etc.
22477
+ * - Shadows: --atomix-box-shadow, --atomix-box-shadow-sm, etc.
22478
+ *
22479
+ * All tokens follow the flat structure pattern used in SCSS (not nested like --atomix-palette-primary-main).
22480
+ * This ensures compatibility between SCSS themes and JavaScript themes.
22481
+ *
22482
+ * @see src/styles/03-generic/_generic.root.scss for SCSS token definitions
22483
+ */
22484
+ /**
22485
+ * Convert a nested object to flat CSS variable declarations
22486
+ * Uses iterative approach for better performance with large objects
21537
22487
  */
21538
22488
  /**
21539
22489
  * Generate a color scale from a base color (1-10 steps)
@@ -21601,18 +22551,7 @@ function generateCSSVariables(theme, options = {}) {
21601
22551
  color.dark && (vars[`${prefix}-${key}-hover`] = color.dark),
21602
22552
  // Generate semantic color variants (matches SCSS patterns)
21603
22553
  // Text emphasis: emphasized version of the color for text (--atomix-primary-text-emphasis)
21604
- vars[`${prefix}-${key}-text-emphasis`] = function(color, coefficient = .15) {
21605
- return getLuminance(color) > .5 ? darken(color, coefficient) : lighten(color, coefficient);
21606
- }
21607
- // ============================================================================
21608
- // Spacing Utilities
21609
- // ============================================================================
21610
- /**
21611
- * Create a spacing function from various input types
21612
- *
21613
- * @param spacingInput - Spacing configuration (number, array, or function), default 4
21614
- * @returns Spacing function
21615
- */ (color.main, .15),
22554
+ vars[`${prefix}-${key}-text-emphasis`] = emphasize(color.main, .15),
21616
22555
  // Background subtle: very light version for backgrounds (--atomix-primary-bg-subtle)
21617
22556
  vars[`${prefix}-${key}-bg-subtle`] = alpha(color.main, .1),
21618
22557
  // Border subtle: light version for borders (--atomix-primary-border-subtle)
@@ -21957,29 +22896,7 @@ function generateCSSVariables(theme, options = {}) {
21957
22896
  return vars[`${prefix}-focus-ring-width`] = "3px", vars[`${prefix}-focus-ring-offset`] = "2px",
21958
22897
  vars[`${prefix}-focus-ring-opacity`] = "0.25", vars;
21959
22898
  }(theme.palette, prefix)), theme.custom && Object.keys(theme.custom).length > 0) {
21960
- const customVars =
21961
- /**
21962
- * CSS Variable Generator
21963
- *
21964
- * Generates CSS custom properties from theme objects and injects them into the DOM.
21965
- *
21966
- * **Token Naming Alignment:**
21967
- * This generator produces CSS variables that match the SCSS token naming pattern exactly:
21968
- * - Colors: --atomix-primary, --atomix-primary-1 through --atomix-primary-10
21969
- * - Spacing: --atomix-spacing-1, --atomix-spacing-4, etc.
21970
- * - Typography: --atomix-font-size-base, --atomix-font-weight-normal, etc.
21971
- * - Shadows: --atomix-box-shadow, --atomix-box-shadow-sm, etc.
21972
- *
21973
- * All tokens follow the flat structure pattern used in SCSS (not nested like --atomix-palette-primary-main).
21974
- * This ensures compatibility between SCSS themes and JavaScript themes.
21975
- *
21976
- * @see src/styles/03-generic/_generic.root.scss for SCSS token definitions
21977
- */
21978
- /**
21979
- * Convert a nested object to flat CSS variable declarations
21980
- * Uses iterative approach for better performance with large objects
21981
- */
21982
- function(obj, prefix = "", result = {}) {
22899
+ const customVars = function(obj, prefix = "", result = {}) {
21983
22900
  // Use iterative approach with stack to avoid deep recursion
21984
22901
  const stack = [ {
21985
22902
  obj: obj,
@@ -22433,19 +23350,29 @@ const logger = getLogger(), ThemeProvider = ({children: children, defaultTheme:
22433
23350
  // Check storage first
22434
23351
  if (enablePersistence && storageAdapter.isAvailable()) {
22435
23352
  const stored = storageAdapter.getItem(storageKey);
22436
- if (stored) return stored;
23353
+ if (stored) {
23354
+ // If it looks like a JSON object, parse it
23355
+ if (stored.trim().startsWith("{")) try {
23356
+ return JSON.parse(stored);
23357
+ } catch (e) {
23358
+ return logger.error("Failed to parse stored theme tokens", e), stored;
23359
+ }
23360
+ return stored;
23361
+ }
22437
23362
  }
22438
23363
  // If defaultTheme is provided, use it
22439
23364
  return null != defaultTheme ? defaultTheme : "default";
22440
23365
  // Default fallback
22441
23366
  }), [ defaultTheme, enablePersistence, storageKey, storageAdapter ]), [currentTheme, setCurrentTheme] = useState((() => "string" == typeof initialDefaultTheme ? initialDefaultTheme : "tokens-theme")), [activeTokens, setActiveTokens] = useState((() => {
22442
- // If defaultTheme is DesignTokens, validate and store them
22443
- if (defaultTheme && "string" != typeof defaultTheme) {
23367
+ // 1. Check if initialDefaultTheme (from storage) is an object
23368
+ if (initialDefaultTheme && "string" != typeof initialDefaultTheme) {
23369
+ const {tokens: tokens, validation: validation} = validateAndMergeTokens(initialDefaultTheme);
23370
+ if (validation.valid) return tokens;
23371
+ }
23372
+ // 2. Check if defaultTheme prop is an object
23373
+ if (defaultTheme && "string" != typeof defaultTheme) {
22444
23374
  const {tokens: tokens, validation: validation} = validateAndMergeTokens(defaultTheme);
22445
- return validation.valid ? tokens : (logger.warn("Invalid default theme tokens, using defaults", {
22446
- errors: validation.errors,
22447
- warnings: validation.warnings
22448
- }), createTokens({}));
23375
+ if (validation.valid) return tokens;
22449
23376
  }
22450
23377
  return null;
22451
23378
  })), [isLoading, setIsLoading] = useState(!1), [error, setError] = useState(null), loadedThemesRef = useRef(new Set), themePromisesRef = useRef({}), abortControllerRef = useRef(null);
@@ -22457,10 +23384,14 @@ const logger = getLogger(), ThemeProvider = ({children: children, defaultTheme:
22457
23384
  useEffect((() => {
22458
23385
  isServer() || applyThemeAttributes(String(currentTheme), dataAttribute);
22459
23386
  }), [ currentTheme, dataAttribute ]),
22460
- // Handle theme persistence
23387
+ // Handle persistence
22461
23388
  useEffect((() => {
22462
- enablePersistence && storageAdapter.isAvailable() && storageAdapter.setItem(storageKey, String(currentTheme));
22463
- }), [ currentTheme, storageKey, enablePersistence, storageAdapter ]),
23389
+ enablePersistence && storageAdapter.isAvailable() && ("tokens-theme" === currentTheme ?
23390
+ // Only persist if we have actual tokens to store
23391
+ activeTokens && storageAdapter.setItem(storageKey, JSON.stringify(activeTokens)) :
23392
+ // Persist named theme string
23393
+ storageAdapter.setItem(storageKey, String(currentTheme)));
23394
+ }), [ currentTheme, activeTokens, enablePersistence, storageKey, storageAdapter ]),
22464
23395
  // Cleanup: Remove completed promises and abort controllers on unmount
22465
23396
  useEffect((() => () => {
22466
23397
  // Cancel any in-flight theme loads
@@ -22599,20 +23530,21 @@ const logger = getLogger(), ThemeProvider = ({children: children, defaultTheme:
22599
23530
  setIsLoading(!1);
22600
23531
  }
22601
23532
  }
22602
- }), [ themes, isThemeLoaded, handleError, basePath, useMinified, cdnPath ]), themeManager = useMemo((() => ({})), []), availableThemes = useMemo((() => Object.entries(themes).map((([name, metadata]) => ({
23533
+ }), [ themes, isThemeLoaded, handleError, basePath, useMinified, cdnPath ]), updateTheme = useCallback((async (sectionOrTokens, values) => setTheme("string" == typeof sectionOrTokens && values ? values : sectionOrTokens)), [ setTheme ]), themeManager = useMemo((() => ({})), []), availableThemes = useMemo((() => Object.entries(themes).map((([name, metadata]) => ({
22603
23534
  ...metadata,
22604
23535
  name: name
22605
23536
  })))), [ themes ]), contextValue = useMemo((() => ({
22606
23537
  theme: currentTheme,
22607
23538
  activeTokens: activeTokens,
22608
23539
  setTheme: setTheme,
23540
+ updateTheme: updateTheme,
22609
23541
  availableThemes: availableThemes,
22610
23542
  isLoading: isLoading,
22611
23543
  error: error,
22612
23544
  isThemeLoaded: isThemeLoaded,
22613
23545
  preloadTheme: preloadTheme,
22614
23546
  themeManager: themeManager
22615
- })), [ currentTheme, activeTokens, setTheme, availableThemes,
23547
+ })), [ currentTheme, activeTokens, setTheme, updateTheme, availableThemes,
22616
23548
  // Use memoized value
22617
23549
  isLoading, error, isThemeLoaded, preloadTheme, themeManager ]);
22618
23550
  // Check if theme is loaded
@@ -22666,6 +23598,7 @@ function useTheme() {
22666
23598
  theme: context.theme,
22667
23599
  activeTokens: context.activeTokens,
22668
23600
  setTheme: context.setTheme,
23601
+ updateTheme: context.updateTheme,
22669
23602
  availableThemes: context.availableThemes,
22670
23603
  isLoading: context.isLoading,
22671
23604
  error: context.error,
@@ -22901,6 +23834,389 @@ function useThemeTokens() {
22901
23834
  }
22902
23835
  }
22903
23836
 
23837
+ /**
23838
+ * useThemeSwitcher Hook
23839
+ *
23840
+ * React hook for managing theme switching with persistence and system preference detection.
23841
+ * Provides an easy-to-use API for dark/light mode toggling.
23842
+ *
23843
+ * @example
23844
+ * ```tsx
23845
+ * import { useThemeSwitcher } from '@shohojdhara/atomix/theme';
23846
+ *
23847
+ * function ThemeToggle() {
23848
+ * const { mode, toggle, setMode, isDark } = useThemeSwitcher();
23849
+ *
23850
+ * return (
23851
+ * <button onClick={toggle}>
23852
+ * {isDark ? '☀️ Light' : '🌙 Dark'}
23853
+ * </button>
23854
+ * );
23855
+ * }
23856
+ * ```
23857
+ */
23858
+ /**
23859
+ * Hook for managing theme switching
23860
+ *
23861
+ * @param options - Configuration options
23862
+ * @returns Theme switcher controls
23863
+ */ function useThemeSwitcher(options = {}) {
23864
+ const {initialMode: initialMode = "system", syncWithSystem: syncWithSystem = !1, storageKey: storageKey = "atomix-theme", enableTransition: enableTransition = !0, transitionDuration: transitionDuration = 300} = options, [mode, setModeState] = useState((() => {
23865
+ if ("undefined" == typeof window) return initialMode;
23866
+ // Check for saved preference first
23867
+ const saved = getCurrentTheme(storageKey);
23868
+ return saved && "system" !== saved ? saved : "system" === initialMode ? getSystemTheme() : initialMode;
23869
+ // Fall back to initial mode or system
23870
+ }));
23871
+ // State for current mode
23872
+ // Initialize theme on mount
23873
+ return useEffect((() => {
23874
+ "undefined" != typeof window && (
23875
+ // Initialize with proper theme application
23876
+ initializeTheme({
23877
+ storageKey: storageKey,
23878
+ enableTransition: enableTransition,
23879
+ transitionDuration: transitionDuration
23880
+ }),
23881
+ // Update state to match initialized theme
23882
+ setModeState(getCurrentTheme(storageKey)));
23883
+ }), [ storageKey, enableTransition, transitionDuration ]),
23884
+ // Listen for system theme changes if enabled
23885
+ useEffect((() => {
23886
+ if (syncWithSystem) return listenToSystemTheme((newMode => {
23887
+ setModeState(newMode), switchTheme(newMode, {
23888
+ storageKey: storageKey,
23889
+ enableTransition: enableTransition,
23890
+ transitionDuration: transitionDuration
23891
+ });
23892
+ }));
23893
+ }), [ syncWithSystem, storageKey, enableTransition, transitionDuration ]), {
23894
+ mode: mode,
23895
+ isDark: "dark" === mode,
23896
+ isLight: "light" === mode,
23897
+ toggle: useCallback((() => {
23898
+ const newMode = toggleTheme({
23899
+ storageKey: storageKey,
23900
+ enableTransition: enableTransition,
23901
+ transitionDuration: transitionDuration
23902
+ });
23903
+ return setModeState(newMode), newMode;
23904
+ }), [ storageKey, enableTransition, transitionDuration ]),
23905
+ setMode: useCallback((newMode => {
23906
+ switchTheme(newMode, {
23907
+ storageKey: storageKey,
23908
+ enableTransition: enableTransition,
23909
+ transitionDuration: transitionDuration
23910
+ }), setModeState(newMode);
23911
+ }), [ storageKey, enableTransition, transitionDuration ]),
23912
+ resetToSystem: useCallback((() => {
23913
+ const systemMode = getSystemTheme();
23914
+ switchTheme(systemMode, {
23915
+ storageKey: storageKey,
23916
+ enableTransition: enableTransition,
23917
+ transitionDuration: transitionDuration
23918
+ }), setModeState(systemMode);
23919
+ }), [ storageKey, enableTransition, transitionDuration ]),
23920
+ clearPreference: useCallback((() => {
23921
+ "undefined" != typeof window && localStorage.removeItem(storageKey);
23922
+ }), [ storageKey ])
23923
+ };
23924
+ }
23925
+
23926
+ /**
23927
+ * ThemeToggle component with multiple variants
23928
+ */ const ThemeToggle = ({className: className = "", showLabel: showLabel = !1, lightLabel: lightLabel = "Light", darkLabel: darkLabel = "Dark", iconSize: iconSize = 20, variant: variant = "icon", render: render, ariaLabel: ariaLabel = "Toggle theme", ...hookOptions}) => {
23929
+ const {mode: mode, isDark: isDark, toggle: toggle} = useThemeSwitcher(hookOptions);
23930
+ // Custom render
23931
+ return render ? jsx(Fragment, {
23932
+ children: render({
23933
+ isDark: isDark,
23934
+ toggle: toggle,
23935
+ mode: mode
23936
+ })
23937
+ }) :
23938
+ // Icon-only variant (default)
23939
+ "icon" === variant ? jsx("button", {
23940
+ onClick: toggle,
23941
+ className: `theme-toggle theme-toggle-icon ${className}`,
23942
+ "aria-label": ariaLabel,
23943
+ title: isDark ? darkLabel : lightLabel,
23944
+ style: {
23945
+ background: "none",
23946
+ border: "none",
23947
+ cursor: "pointer",
23948
+ padding: "8px",
23949
+ borderRadius: "50%",
23950
+ display: "flex",
23951
+ alignItems: "center",
23952
+ justifyContent: "center",
23953
+ transition: "all 0.3s ease-in-out"
23954
+ },
23955
+ children: isDark ? jsxs("svg", {
23956
+ width: iconSize,
23957
+ height: iconSize,
23958
+ viewBox: "0 0 24 24",
23959
+ fill: "none",
23960
+ stroke: "currentColor",
23961
+ strokeWidth: "2",
23962
+ strokeLinecap: "round",
23963
+ strokeLinejoin: "round",
23964
+ children: [ jsx("circle", {
23965
+ cx: "12",
23966
+ cy: "12",
23967
+ r: "5"
23968
+ }), jsx("line", {
23969
+ x1: "12",
23970
+ y1: "1",
23971
+ x2: "12",
23972
+ y2: "3"
23973
+ }), jsx("line", {
23974
+ x1: "12",
23975
+ y1: "21",
23976
+ x2: "12",
23977
+ y2: "23"
23978
+ }), jsx("line", {
23979
+ x1: "4.22",
23980
+ y1: "4.22",
23981
+ x2: "5.64",
23982
+ y2: "5.64"
23983
+ }), jsx("line", {
23984
+ x1: "18.36",
23985
+ y1: "18.36",
23986
+ x2: "19.78",
23987
+ y2: "19.78"
23988
+ }), jsx("line", {
23989
+ x1: "1",
23990
+ y1: "12",
23991
+ x2: "3",
23992
+ y2: "12"
23993
+ }), jsx("line", {
23994
+ x1: "21",
23995
+ y1: "12",
23996
+ x2: "23",
23997
+ y2: "12"
23998
+ }), jsx("line", {
23999
+ x1: "4.22",
24000
+ y1: "19.78",
24001
+ x2: "5.64",
24002
+ y2: "18.36"
24003
+ }), jsx("line", {
24004
+ x1: "18.36",
24005
+ y1: "5.64",
24006
+ x2: "19.78",
24007
+ y2: "4.22"
24008
+ }) ]
24009
+ }) : jsx("svg", {
24010
+ width: iconSize,
24011
+ height: iconSize,
24012
+ viewBox: "0 0 24 24",
24013
+ fill: "none",
24014
+ stroke: "currentColor",
24015
+ strokeWidth: "2",
24016
+ strokeLinecap: "round",
24017
+ strokeLinejoin: "round",
24018
+ children: jsx("path", {
24019
+ d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"
24020
+ })
24021
+ })
24022
+ }) :
24023
+ // Button variant with text
24024
+ "button" === variant ? jsxs("button", {
24025
+ onClick: toggle,
24026
+ className: `theme-toggle theme-toggle-button ${className}`,
24027
+ "aria-label": ariaLabel,
24028
+ style: {
24029
+ display: "flex",
24030
+ alignItems: "center",
24031
+ gap: "8px",
24032
+ padding: "8px 16px",
24033
+ borderRadius: "8px",
24034
+ border: "1px solid currentColor",
24035
+ background: "transparent",
24036
+ color: "inherit",
24037
+ cursor: "pointer",
24038
+ fontSize: "14px",
24039
+ fontWeight: "500",
24040
+ transition: "all 0.3s ease-in-out"
24041
+ },
24042
+ children: [ isDark ? jsxs("svg", {
24043
+ width: iconSize,
24044
+ height: iconSize,
24045
+ viewBox: "0 0 24 24",
24046
+ fill: "none",
24047
+ stroke: "currentColor",
24048
+ strokeWidth: "2",
24049
+ strokeLinecap: "round",
24050
+ strokeLinejoin: "round",
24051
+ children: [ jsx("circle", {
24052
+ cx: "12",
24053
+ cy: "12",
24054
+ r: "5"
24055
+ }), jsx("line", {
24056
+ x1: "12",
24057
+ y1: "1",
24058
+ x2: "12",
24059
+ y2: "3"
24060
+ }), jsx("line", {
24061
+ x1: "12",
24062
+ y1: "21",
24063
+ x2: "12",
24064
+ y2: "23"
24065
+ }), jsx("line", {
24066
+ x1: "4.22",
24067
+ y1: "4.22",
24068
+ x2: "5.64",
24069
+ y2: "5.64"
24070
+ }), jsx("line", {
24071
+ x1: "18.36",
24072
+ y1: "18.36",
24073
+ x2: "19.78",
24074
+ y2: "19.78"
24075
+ }), jsx("line", {
24076
+ x1: "1",
24077
+ y1: "12",
24078
+ x2: "3",
24079
+ y2: "12"
24080
+ }), jsx("line", {
24081
+ x1: "21",
24082
+ y1: "12",
24083
+ x2: "23",
24084
+ y2: "12"
24085
+ }), jsx("line", {
24086
+ x1: "4.22",
24087
+ y1: "19.78",
24088
+ x2: "5.64",
24089
+ y2: "18.36"
24090
+ }), jsx("line", {
24091
+ x1: "18.36",
24092
+ y1: "5.64",
24093
+ x2: "19.78",
24094
+ y2: "4.22"
24095
+ }) ]
24096
+ }) : jsx("svg", {
24097
+ width: iconSize,
24098
+ height: iconSize,
24099
+ viewBox: "0 0 24 24",
24100
+ fill: "none",
24101
+ stroke: "currentColor",
24102
+ strokeWidth: "2",
24103
+ strokeLinecap: "round",
24104
+ strokeLinejoin: "round",
24105
+ children: jsx("path", {
24106
+ d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"
24107
+ })
24108
+ }), showLabel && jsx("span", {
24109
+ children: isDark ? darkLabel : lightLabel
24110
+ }) ]
24111
+ }) :
24112
+ // Switch/toggle variant
24113
+ "switch" === variant ? jsx("div", {
24114
+ className: `theme-toggle theme-toggle-switch ${className}`,
24115
+ role: "button",
24116
+ tabIndex: 0,
24117
+ onClick: toggle,
24118
+ onKeyDown: e => "Enter" === e.key && toggle(),
24119
+ "aria-label": ariaLabel,
24120
+ style: {
24121
+ position: "relative",
24122
+ width: "56px",
24123
+ height: "28px",
24124
+ borderRadius: "14px",
24125
+ background: isDark ? "#4b5563" : "#d1d5db",
24126
+ cursor: "pointer",
24127
+ transition: "background 0.3s ease-in-out",
24128
+ display: "flex",
24129
+ alignItems: "center",
24130
+ padding: "2px"
24131
+ },
24132
+ children: jsx("div", {
24133
+ style: {
24134
+ position: "absolute",
24135
+ left: isDark ? "auto" : "2px",
24136
+ right: isDark ? "2px" : "auto",
24137
+ width: "24px",
24138
+ height: "24px",
24139
+ borderRadius: "50%",
24140
+ background: "white",
24141
+ boxShadow: "0 2px 4px rgba(0, 0, 0, 0.2)",
24142
+ transition: "all 0.3s ease-in-out",
24143
+ display: "flex",
24144
+ alignItems: "center",
24145
+ justifyContent: "center"
24146
+ },
24147
+ children: isDark ? jsx("svg", {
24148
+ width: "14",
24149
+ height: "14",
24150
+ viewBox: "0 0 24 24",
24151
+ fill: "none",
24152
+ stroke: "#4b5563",
24153
+ strokeWidth: "2",
24154
+ strokeLinecap: "round",
24155
+ strokeLinejoin: "round",
24156
+ children: jsx("path", {
24157
+ d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"
24158
+ })
24159
+ }) : jsxs("svg", {
24160
+ width: "14",
24161
+ height: "14",
24162
+ viewBox: "0 0 24 24",
24163
+ fill: "none",
24164
+ stroke: "#f59e0b",
24165
+ strokeWidth: "2",
24166
+ strokeLinecap: "round",
24167
+ strokeLinejoin: "round",
24168
+ children: [ jsx("circle", {
24169
+ cx: "12",
24170
+ cy: "12",
24171
+ r: "5"
24172
+ }), jsx("line", {
24173
+ x1: "12",
24174
+ y1: "1",
24175
+ x2: "12",
24176
+ y2: "3"
24177
+ }), jsx("line", {
24178
+ x1: "12",
24179
+ y1: "21",
24180
+ x2: "12",
24181
+ y2: "23"
24182
+ }), jsx("line", {
24183
+ x1: "4.22",
24184
+ y1: "4.22",
24185
+ x2: "5.64",
24186
+ y2: "5.64"
24187
+ }), jsx("line", {
24188
+ x1: "18.36",
24189
+ y1: "18.36",
24190
+ x2: "19.78",
24191
+ y2: "19.78"
24192
+ }), jsx("line", {
24193
+ x1: "1",
24194
+ y1: "12",
24195
+ x2: "3",
24196
+ y2: "12"
24197
+ }), jsx("line", {
24198
+ x1: "21",
24199
+ y1: "12",
24200
+ x2: "23",
24201
+ y2: "12"
24202
+ }), jsx("line", {
24203
+ x1: "4.22",
24204
+ y1: "19.78",
24205
+ x2: "5.64",
24206
+ y2: "18.36"
24207
+ }), jsx("line", {
24208
+ x1: "18.36",
24209
+ y1: "5.64",
24210
+ x2: "19.78",
24211
+ y2: "4.22"
24212
+ }) ]
24213
+ })
24214
+ })
24215
+ }) : null;
24216
+ };
24217
+
24218
+ ThemeToggle.displayName = "ThemeToggle";
24219
+
22904
24220
  /**
22905
24221
  * Theme Applicator
22906
24222
  *
@@ -22913,7 +24229,8 @@ function useThemeTokens() {
22913
24229
  * Theme applicator class for runtime theme application
22914
24230
  *
22915
24231
  * Uses the unified theme system for efficient CSS variable generation and injection.
22916
- */ class ThemeApplicator {
24232
+ */
24233
+ class ThemeApplicator {
22917
24234
  constructor(root = document.documentElement) {
22918
24235
  this.styleId = "atomix-theme-applicator", this.root = root;
22919
24236
  }
@@ -24652,13 +25969,13 @@ class ThemeValidator {
24652
25969
  function createPaletteColor(color) {
24653
25970
  return "string" == typeof color ? {
24654
25971
  main: color,
24655
- light: lighten(color),
24656
- dark: darken(color),
25972
+ light: lighten(color, .15),
25973
+ dark: darken(color, .15),
24657
25974
  contrastText: getContrastText(color)
24658
25975
  } : {
24659
25976
  main: color.main || "#000000",
24660
- light: color.light || lighten(color.main || "#000000"),
24661
- dark: color.dark || darken(color.main || "#000000"),
25977
+ light: color.light || lighten(color.main || "#000000", .15),
25978
+ dark: color.dark || darken(color.main || "#000000", .15),
24662
25979
  contrastText: color.contrastText || getContrastText(color.main || "#000000")
24663
25980
  };
24664
25981
  }
@@ -24693,23 +26010,19 @@ function createThemeObject(...options) {
24693
26010
  },
24694
26011
  background: {
24695
26012
  default: mergedOptions.palette?.background?.default || DEFAULT_PALETTE.background.default,
26013
+ paper: mergedOptions.palette?.background?.paper || DEFAULT_PALETTE.background.paper,
24696
26014
  subtle: mergedOptions.palette?.background?.subtle || DEFAULT_PALETTE.background.subtle
24697
26015
  },
24698
26016
  text: {
24699
26017
  primary: mergedOptions.palette?.text?.primary || DEFAULT_PALETTE.text.primary,
24700
26018
  secondary: mergedOptions.palette?.text?.secondary || DEFAULT_PALETTE.text.secondary,
24701
26019
  disabled: mergedOptions.palette?.text?.disabled || DEFAULT_PALETTE.text.disabled
24702
- }
26020
+ },
26021
+ // Spread other palette properties
26022
+ ...mergedOptions.palette
24703
26023
  }, typography = deepMerge({
24704
26024
  ...DEFAULT_TYPOGRAPHY
24705
- }, mergedOptions.typography || {}), spacing = function(spacingInput = 4) {
24706
- // If it's already a function, return it
24707
- return "function" == typeof spacingInput ? spacingInput :
24708
- // If it's a number, create a function that multiplies by that number
24709
- "number" == typeof spacingInput ? (...values) => 0 === values.length ? "0px" : values.map((value => value * spacingInput + "px")).join(" ") :
24710
- // If it's an array, use it as a scale
24711
- Array.isArray(spacingInput) ? (...values) => 0 === values.length ? "0px" : values.map((value => `${spacingInput[value] || value}px`)).join(" ") : (...values) => 0 === values.length ? "0px" : values.map((value => 4 * value + "px")).join(" ");
24712
- }(mergedOptions.spacing), breakpoints = function(breakpointsInput) {
26025
+ }, mergedOptions.typography || {}), spacing = createSpacing(mergedOptions.spacing), breakpoints = function(breakpointsInput) {
24713
26026
  const values = {
24714
26027
  xs: 0,
24715
26028
  sm: 576,
@@ -25532,24 +26845,6 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
25532
26845
  /**
25533
26846
  * Design Tokens Customizer Component
25534
26847
  */
25535
- /**
25536
- * Theme Adapter
25537
- *
25538
- * Converts between Theme objects and DesignTokens.
25539
- */
25540
- /**
25541
- * Convert DesignTokens to Theme-compatible CSS variables
25542
- *
25543
- * @param tokens - DesignTokens object
25544
- * @returns CSS variables object compatible with Theme.cssVars
25545
- */
25546
- function designTokensToCSSVars(tokens) {
25547
- const cssVars = {};
25548
- return Object.entries(tokens).forEach((([key, value]) => {
25549
- void 0 !== value && (cssVars[`--atomix-${key}`] = String(value));
25550
- })), cssVars;
25551
- }
25552
-
25553
26848
  /**
25554
26849
  * Theme Helper Functions
25555
26850
  *
@@ -25562,7 +26857,8 @@ function designTokensToCSSVars(tokens) {
25562
26857
  *
25563
26858
  * @param value - Value to check
25564
26859
  * @returns True if value is DesignTokens
25565
- */ function isDesignTokens(value) {
26860
+ */
26861
+ function isDesignTokens(value) {
25566
26862
  if (!value || "object" != typeof value) return !1;
25567
26863
  // DesignTokens is a flat object with string keys, no nested structures
25568
26864
  const obj = value;
@@ -25574,6 +26870,335 @@ function designTokensToCSSVars(tokens) {
25574
26870
  // Check if keys look like DesignTokens (kebab-case, no nesting)
25575
26871
  }
25576
26872
 
26873
+ /**
26874
+ * Performance monitor class
26875
+ */ class PerformanceMonitor {
26876
+ /**
26877
+ * Create a new performance monitor
26878
+ *
26879
+ * @param config Configuration options
26880
+ */
26881
+ constructor(config) {
26882
+ this.frameCount = 0, this.lastSampleTime = 0, this.lastFpsUpdate = 0, this.frameTimes = [],
26883
+ this.animationFrameId = null, this.isActive = !1, this.startTime = 0, this.config = {
26884
+ fpsTarget: config?.fpsTarget ?? 60,
26885
+ sampleInterval: config?.sampleInterval ?? 500,
26886
+ onUpdate: config?.onUpdate ?? (() => {}),
26887
+ onDegraded: config?.onDegraded ?? (() => {}),
26888
+ enableMemoryMonitoring: config?.enableMemoryMonitoring ?? ("undefined" != typeof window && window.performance && window.performance.memory)
26889
+ };
26890
+ }
26891
+ /**
26892
+ * Start monitoring performance
26893
+ */ start() {
26894
+ this.isActive || (this.isActive = !0, this.frameCount = 0, this.lastSampleTime = performance.now(),
26895
+ this.lastFpsUpdate = this.lastSampleTime, this.frameTimes = [], this.startTime = this.lastSampleTime,
26896
+ this.animationFrameId = requestAnimationFrame(this.onFrame.bind(this)));
26897
+ }
26898
+ /**
26899
+ * Stop monitoring performance
26900
+ */ stop() {
26901
+ this.animationFrameId && (cancelAnimationFrame(this.animationFrameId), this.animationFrameId = null),
26902
+ this.isActive = !1;
26903
+ }
26904
+ /**
26905
+ * Get current performance metrics
26906
+ */ getMetrics() {
26907
+ var _context;
26908
+ const now = performance.now(), elapsed = now - this.lastFpsUpdate, fps = elapsed > 0 ? Math.round(this.frameCount / elapsed * 1e3) : 0, avgFrameTime = this.frameTimes.length > 0 ? _reduceInstanceProperty(_context = this.frameTimes).call(_context, ((a, b) => a + b), 0) / this.frameTimes.length : 0, peakFrameTime = this.frameTimes.length > 0 ? Math.max(...this.frameTimes) : 0;
26909
+ // Get memory stats if available
26910
+ let memory;
26911
+ if (this.config.enableMemoryMonitoring) {
26912
+ const perf = window.performance;
26913
+ perf && perf.memory && (memory = {
26914
+ usedJSHeapSize: perf.memory.usedJSHeapSize,
26915
+ totalJSHeapSize: perf.memory.totalJSHeapSize,
26916
+ jsHeapSizeLimit: perf.memory.jsHeapSizeLimit
26917
+ });
26918
+ }
26919
+ return {
26920
+ fps: fps,
26921
+ frameTime: avgFrameTime,
26922
+ peakFrameTime: peakFrameTime,
26923
+ memory: memory,
26924
+ timestamp: now,
26925
+ isDegraded: fps < .7 * this.config.fpsTarget
26926
+ };
26927
+ }
26928
+ /**
26929
+ * Get the current FPS
26930
+ */ getFps() {
26931
+ return this.getMetrics().fps;
26932
+ }
26933
+ /**
26934
+ * Check if performance is degraded
26935
+ */ isPerformanceDegraded() {
26936
+ return this.getMetrics().isDegraded;
26937
+ }
26938
+ /**
26939
+ * Private method called on each animation frame
26940
+ */ onFrame(timestamp) {
26941
+ if (!this.isActive) return;
26942
+ // Calculate frame time
26943
+ const frameTime = timestamp - this.lastSampleTime;
26944
+ // Check if we need to update metrics
26945
+ if (this.frameTimes.push(frameTime),
26946
+ // Keep only the last 60 frame times for averaging
26947
+ this.frameTimes.length > 60 && this.frameTimes.shift(), this.frameCount++, this.lastSampleTime = timestamp,
26948
+ timestamp - this.lastFpsUpdate >= this.config.sampleInterval) {
26949
+ const metrics = this.getMetrics();
26950
+ // Call update callback
26951
+ this.config.onUpdate(metrics),
26952
+ // Check for degradation
26953
+ metrics.isDegraded && this.config.onDegraded(metrics),
26954
+ // Reset counters
26955
+ this.frameCount = 0, this.lastFpsUpdate = timestamp;
26956
+ }
26957
+ this.animationFrameId = requestAnimationFrame(this.onFrame.bind(this));
26958
+ }
26959
+ /**
26960
+ * Run a performance test for a specific function
26961
+ *
26962
+ * @param fn Function to test
26963
+ * @param iterations Number of iterations (default: 100)
26964
+ * @returns Average execution time in ms
26965
+ */ async testFunctionPerformance(fn, iterations = 100) {
26966
+ const times = [];
26967
+ for (let i = 0; i < iterations; i++) {
26968
+ const start = performance.now();
26969
+ fn();
26970
+ const end = performance.now();
26971
+ times.push(end - start);
26972
+ }
26973
+ return _reduceInstanceProperty(times).call(times, ((a, b) => a + b), 0) / times.length;
26974
+ }
26975
+ }
26976
+
26977
+ /**
26978
+ * Create a performance monitor instance
26979
+ *
26980
+ * @param config Configuration options
26981
+ * @returns PerformanceMonitor instance
26982
+ *
26983
+ * @example
26984
+ * ```typescript
26985
+ * import { createPerformanceMonitor } from '@shohojdhara/atomix/theme';
26986
+ *
26987
+ * const monitor = createPerformanceMonitor({
26988
+ * fpsTarget: 60,
26989
+ * onUpdate: (metrics) => console.log('FPS:', metrics.fps),
26990
+ * onDegraded: (metrics) => console.warn('Performance degraded!', metrics),
26991
+ * });
26992
+ *
26993
+ * monitor.start();
26994
+ *
26995
+ * // Later...
26996
+ * monitor.stop();
26997
+ * ```
26998
+ */ function createPerformanceMonitor(config) {
26999
+ return new PerformanceMonitor(config);
27000
+ }
27001
+
27002
+ /**
27003
+ * Hook for React components to monitor performance
27004
+ *
27005
+ * @param config Configuration options
27006
+ * @returns Performance metrics and monitor controls
27007
+ *
27008
+ * @example
27009
+ * ```typescript
27010
+ * import { usePerformanceMonitor } from '@shohojdhara/atomix/theme';
27011
+ *
27012
+ * function MyComponent() {
27013
+ * const { metrics, start, stop } = usePerformanceMonitor({ fpsTarget: 60 });
27014
+ *
27015
+ * useEffect(() => {
27016
+ * start();
27017
+ * return () => stop();
27018
+ * }, []);
27019
+ *
27020
+ * return <div>FPS: {metrics.fps}</div>;
27021
+ * }
27022
+ * ```
27023
+ */ function usePerformanceMonitor(config) {
27024
+ const [monitor] = React.useState((() => createPerformanceMonitor(config))), [metrics, setMetrics] = React.useState((() => "undefined" != typeof window ? monitor.getMetrics() : {
27025
+ fps: 0,
27026
+ frameTime: 0,
27027
+ peakFrameTime: 0,
27028
+ timestamp: 0,
27029
+ isDegraded: !1
27030
+ })), start = React.useCallback((() => {
27031
+ "undefined" != typeof window && monitor.start();
27032
+ }), [ monitor ]), stop = React.useCallback((() => {
27033
+ "undefined" != typeof window && monitor.stop();
27034
+ }), [ monitor ]);
27035
+ return React.useEffect((() => {
27036
+ if ("undefined" == typeof window) return;
27037
+ // Update metrics when monitor callbacks fire
27038
+ const originalOnUpdate = config?.onUpdate;
27039
+ return monitor.config.onUpdate = newMetrics => {
27040
+ setMetrics(newMetrics), originalOnUpdate?.(newMetrics);
27041
+ }, () => {
27042
+ monitor.stop();
27043
+ };
27044
+ }), [ monitor, config?.onUpdate ]), {
27045
+ metrics: metrics,
27046
+ start: start,
27047
+ stop: stop
27048
+ };
27049
+ }
27050
+
27051
+ /**
27052
+ * Responsive Utility for Atomix Theme System
27053
+ *
27054
+ * Provides responsive breakpoint detection and device-aware parameter scaling
27055
+ * based on configuration from the advanced optimization features.
27056
+ */
27057
+ /**
27058
+ * Responsive utility class
27059
+ */ class ResponsiveUtil {
27060
+ constructor(config) {
27061
+ this.currentDevice = "desktop", // Default
27062
+ this.resizeHandler = null, this.observer = null, this.config = config, this.currentDevice = this.getCurrentDeviceType(),
27063
+ // Set up resize listener
27064
+ this.setupResizeListener();
27065
+ }
27066
+ /**
27067
+ * Get the current device type based on viewport width
27068
+ */ getCurrentDeviceType() {
27069
+ if ("undefined" == typeof window) return "desktop";
27070
+ // SSR fallback
27071
+ const width = window.innerWidth;
27072
+ // Parse breakpoint values to numbers
27073
+ this.parsePxValue(this.config.breakpoints.mobile);
27074
+ const tabletWidth = this.parsePxValue(this.config.breakpoints.tablet), desktopWidth = this.parsePxValue(this.config.breakpoints.desktop), wideWidth = this.parsePxValue(this.config.breakpoints.wide);
27075
+ return width < tabletWidth ? "mobile" : width < desktopWidth ? "tablet" : width < wideWidth ? "desktop" : "wide";
27076
+ }
27077
+ /**
27078
+ * Get the scaling factor for the current device
27079
+ */ getCurrentScalingFactor() {
27080
+ // 'wide' devices use the same scaling as 'desktop'
27081
+ const scalingKey = "wide" === this.currentDevice ? "desktop" : this.currentDevice;
27082
+ return this.config.deviceScaling[scalingKey] || 1;
27083
+ }
27084
+ /**
27085
+ * Scale a value based on the current device's scaling factor
27086
+ */ scaleValue(value) {
27087
+ return value * this.getCurrentScalingFactor();
27088
+ }
27089
+ /**
27090
+ * Check if the current device matches a specific type
27091
+ */ isDevice(device) {
27092
+ return this.currentDevice === device;
27093
+ }
27094
+ /**
27095
+ * Check if the current device is mobile or smaller
27096
+ */ isMobileOrSmaller() {
27097
+ return "mobile" === this.currentDevice;
27098
+ }
27099
+ /**
27100
+ * Check if the current device is tablet or smaller
27101
+ */ isTabletOrSmaller() {
27102
+ return "mobile" === this.currentDevice || "tablet" === this.currentDevice;
27103
+ }
27104
+ /**
27105
+ * Check if the current device is desktop or larger
27106
+ */ isDesktopOrLarger() {
27107
+ return "desktop" === this.currentDevice || "wide" === this.currentDevice;
27108
+ }
27109
+ /**
27110
+ * Update the responsive configuration
27111
+ */ updateConfig(config) {
27112
+ this.config = config, this.currentDevice = this.getCurrentDeviceType();
27113
+ }
27114
+ /**
27115
+ * Destroy the responsive utility and clean up listeners
27116
+ */ destroy() {
27117
+ this.resizeHandler && (window.removeEventListener("resize", this.resizeHandler),
27118
+ this.resizeHandler = null), this.observer && (this.observer.disconnect(), this.observer = null);
27119
+ }
27120
+ /**
27121
+ * Parse a CSS value to pixels
27122
+ */ parsePxValue(value) {
27123
+ return value.endsWith("px") ? parseFloat(value.slice(0, -2)) :
27124
+ // For other units, we'll use a rough conversion assuming 16px base
27125
+ value.endsWith("rem") ? 16 * parseFloat(value.slice(0, -3)) : value.endsWith("em") ? 16 * parseFloat(value.slice(0, -2)) : parseFloat(value) || 0;
27126
+ }
27127
+ /**
27128
+ * Set up the resize listener
27129
+ */ setupResizeListener() {
27130
+ if ("undefined" == typeof window) return;
27131
+ // Throttled resize handler
27132
+ let resizeTimeout = null;
27133
+ const handleResize = () => {
27134
+ resizeTimeout && window.clearTimeout(resizeTimeout), resizeTimeout = window.setTimeout((() => {
27135
+ const newDeviceType = this.getCurrentDeviceType();
27136
+ newDeviceType !== this.currentDevice && (this.currentDevice = newDeviceType);
27137
+ }), 150);
27138
+ } // Throttle to 150ms
27139
+ ;
27140
+ this.resizeHandler = handleResize, window.addEventListener("resize", handleResize),
27141
+ // Also observe the document body for size changes
27142
+ "undefined" != typeof ResizeObserver && (this.observer = new ResizeObserver(handleResize),
27143
+ this.observer.observe(document.body));
27144
+ }
27145
+ }
27146
+
27147
+ /**
27148
+ * Create a responsive utility instance
27149
+ *
27150
+ * @param config Responsive configuration
27151
+ * @returns ResponsiveUtil instance
27152
+ */ function createResponsiveUtil(config) {
27153
+ return new ResponsiveUtil(config);
27154
+ }
27155
+
27156
+ /**
27157
+ * Hook for React components to use responsive features
27158
+ *
27159
+ * @param config Responsive configuration
27160
+ * @returns Current device type and utility functions
27161
+ */ function useResponsive(config) {
27162
+ const [util] = React.useState((() => createResponsiveUtil(config))), [deviceType, setDeviceType] = React.useState((() => "undefined" != typeof window ? util.getCurrentDeviceType() : "desktop"));
27163
+ return React.useEffect((() => {
27164
+ if ("undefined" == typeof window) return;
27165
+ const handleResize = () => {
27166
+ const newDeviceType = util.getCurrentDeviceType();
27167
+ newDeviceType !== deviceType && setDeviceType(newDeviceType);
27168
+ };
27169
+ // Update device type on mount
27170
+ return setDeviceType(util.getCurrentDeviceType()),
27171
+ // Listen for resize events
27172
+ window.addEventListener("resize", handleResize), () => {
27173
+ window.removeEventListener("resize", handleResize), util.destroy();
27174
+ };
27175
+ }), [ util, deviceType ]), "undefined" == typeof window ? {
27176
+ deviceType: "desktop",
27177
+ isMobile: !1,
27178
+ isTablet: !1,
27179
+ isDesktop: !0,
27180
+ isWide: !1,
27181
+ scaleValue: value => value,
27182
+ getCurrentDeviceType: () => "desktop",
27183
+ getCurrentScalingFactor: () => 1,
27184
+ isMobileOrSmaller: () => !1,
27185
+ isTabletOrSmaller: () => !0,
27186
+ isDesktopOrLarger: () => !0
27187
+ } : {
27188
+ deviceType: deviceType,
27189
+ isMobile: "mobile" === deviceType,
27190
+ isTablet: "tablet" === deviceType,
27191
+ isDesktop: "desktop" === deviceType,
27192
+ isWide: "wide" === deviceType,
27193
+ scaleValue: value => util.scaleValue(value),
27194
+ getCurrentDeviceType: () => util.getCurrentDeviceType(),
27195
+ getCurrentScalingFactor: () => util.getCurrentScalingFactor(),
27196
+ isMobileOrSmaller: () => util.isMobileOrSmaller(),
27197
+ isTabletOrSmaller: () => util.isTabletOrSmaller(),
27198
+ isDesktopOrLarger: () => util.isDesktopOrLarger()
27199
+ };
27200
+ }
27201
+
25577
27202
  /**
25578
27203
  * RTL (Right-to-Left) Support Utilities
25579
27204
  *
@@ -25759,6 +27384,32 @@ class RTLManager {
25759
27384
  }
25760
27385
  }
25761
27386
 
27387
+ /**
27388
+ * Create RTL manager instance
27389
+ */ function createRTLManager(config) {
27390
+ return new RTLManager(config);
27391
+ }
27392
+
27393
+ /**
27394
+ * Check if locale is RTL
27395
+ */ function isRTLLocale(locale) {
27396
+ return RTL_LOCALES.has(locale.toLowerCase());
27397
+ }
27398
+
27399
+ /**
27400
+ * Get direction from locale
27401
+ */ function getDirectionFromLocale(locale) {
27402
+ return isRTLLocale(locale) ? "rtl" : "ltr";
27403
+ }
27404
+
27405
+ /**
27406
+ * RTL-aware CSS helper
27407
+ *
27408
+ * Returns appropriate CSS based on direction
27409
+ */ function rtlCSS(ltrCSS, rtlCSS, direction = "ltr") {
27410
+ return "rtl" === direction ? rtlCSS : ltrCSS;
27411
+ }
27412
+
25762
27413
  /**
25763
27414
  * Theme System Exports
25764
27415
  *
@@ -25781,8 +27432,6 @@ class RTLManager {
25781
27432
  // ============================================================================
25782
27433
  // Core Theme Functions
25783
27434
  // ============================================================================
25784
- // Create theme CSS from DesignTokens
25785
- // File saving utilities removed to prevent bundling Node.js modules in browser
25786
27435
  /**
25787
27436
  * Inject theme CSS into DOM
25788
27437
  */ function injectTheme(css, id = "atomix-theme") {
@@ -25795,7 +27444,114 @@ class RTLManager {
25795
27444
  removeCSS(id);
25796
27445
  }
25797
27446
 
25798
- const themeImport = Object.freeze( Object.defineProperty({
27447
+ /**
27448
+ * Main theme module interface
27449
+ */ const index = {
27450
+ // Core
27451
+ createTheme: createTheme,
27452
+ injectTheme: injectTheme,
27453
+ removeTheme: removeTheme,
27454
+ // Context and Provider
27455
+ ThemeProvider: ThemeProvider,
27456
+ useTheme: useTheme,
27457
+ useThemeTokens: useThemeTokens,
27458
+ ThemeContext: ThemeContext,
27459
+ ThemeErrorBoundary: ThemeErrorBoundary,
27460
+ // Adapters
27461
+ configToTokens: configToTokens,
27462
+ designTokensToCSSVars: designTokensToCSSVars,
27463
+ // Theme Utils
27464
+ switchTheme: switchTheme,
27465
+ toggleTheme: toggleTheme,
27466
+ getCurrentTheme: getCurrentTheme,
27467
+ getSystemTheme: getSystemTheme,
27468
+ initializeTheme: initializeTheme,
27469
+ listenToSystemTheme: listenToSystemTheme,
27470
+ persistTheme: persistTheme,
27471
+ clearThemePreference: clearThemePreference,
27472
+ // Token Manipulation
27473
+ mergeTokens: mergeTokens,
27474
+ overrideTokens: overrideTokens,
27475
+ pickTokens: pickTokens,
27476
+ omitTokens: omitTokens,
27477
+ // Color Utilities
27478
+ hexToRgb: hexToRgb$1,
27479
+ rgbToHex: rgbToHex,
27480
+ getLuminance: getLuminance,
27481
+ getContrastRatio: getContrastRatio,
27482
+ isAccessible: isAccessible,
27483
+ getContrastText: getContrastText,
27484
+ lighten: lighten,
27485
+ darken: darken,
27486
+ alpha: alpha,
27487
+ emphasize: emphasize,
27488
+ createSpacing: createSpacing,
27489
+ // Performance utilities
27490
+ createPerformanceMonitor: createPerformanceMonitor,
27491
+ usePerformanceMonitor: usePerformanceMonitor,
27492
+ // Responsive utilities
27493
+ createResponsiveUtil: createResponsiveUtil,
27494
+ useResponsive: useResponsive,
27495
+ // Components
27496
+ ThemeToggle: ThemeToggle,
27497
+ ThemeApplicator: ThemeApplicator,
27498
+ applyTheme: applyTheme,
27499
+ getThemeApplicator: getThemeApplicator,
27500
+ // Registry
27501
+ createThemeRegistry: createThemeRegistry,
27502
+ registerTheme: registerTheme,
27503
+ unregisterTheme: unregisterTheme,
27504
+ hasTheme: hasTheme,
27505
+ getTheme: getTheme,
27506
+ getAllThemes: getAllThemes,
27507
+ getThemeIds: getThemeIds,
27508
+ clearThemes: clearThemes,
27509
+ getThemeCount: getThemeCount,
27510
+ // Composition
27511
+ deepMerge: deepMerge,
27512
+ mergeTheme: mergeTheme,
27513
+ extendTheme: extendTheme,
27514
+ // Tokens
27515
+ createTokens: createTokens,
27516
+ defaultTokens: defaultTokens,
27517
+ // Generators
27518
+ generateCSSVariables: generateCSSVariables$1,
27519
+ generateCSSVariablesForSelector: generateCSSVariablesForSelector,
27520
+ // Naming
27521
+ generateClassName: generateClassName,
27522
+ generateCSSVariableName: generateCSSVariableName,
27523
+ normalizeThemeTokens: normalizeThemeTokens,
27524
+ camelToKebab: camelToKebab,
27525
+ themePropertyToCSSVar: themePropertyToCSSVar,
27526
+ // Component Theming
27527
+ getComponentThemeValue: getComponentThemeValue,
27528
+ generateComponentCSSVars: generateComponentCSSVars,
27529
+ applyComponentTheme: applyComponentTheme,
27530
+ useComponentTheme: useComponentTheme,
27531
+ // Hooks
27532
+ useThemeSwitcher: useThemeSwitcher,
27533
+ // Helpers
27534
+ isDesignTokens: isDesignTokens,
27535
+ // CSS Variable Mapper
27536
+ mapSCSSTokensToCSSVars: mapSCSSTokensToCSSVars,
27537
+ applyCSSVariables: applyCSSVariables,
27538
+ removeCSSVariables: removeCSSVariables,
27539
+ getCSSVariable: getCSSVariable,
27540
+ cssVarsToStyle: cssVarsToStyle,
27541
+ mergeCSSVars: mergeCSSVars,
27542
+ isValidCSSVariableName: isValidCSSVariableName,
27543
+ extractComponentName: extractComponentName,
27544
+ // Injection Utils
27545
+ injectCSS: injectCSS$1,
27546
+ removeCSS: removeCSS,
27547
+ isCSSInjected: isCSSInjected,
27548
+ // I18n
27549
+ RTLManager: RTLManager,
27550
+ createRTLManager: createRTLManager,
27551
+ isRTLLocale: isRTLLocale,
27552
+ getDirectionFromLocale: getDirectionFromLocale,
27553
+ rtlCSS: rtlCSS
27554
+ }, themeImport = Object.freeze( Object.defineProperty({
25799
27555
  __proto__: null,
25800
27556
  DesignTokensCustomizer: DesignTokensCustomizer,
25801
27557
  RTLManager: RTLManager,
@@ -25807,19 +27563,30 @@ const themeImport = Object.freeze( Object.defineProperty({
25807
27563
  ThemeLiveEditor: ThemeLiveEditor,
25808
27564
  ThemePreview: ThemePreview,
25809
27565
  ThemeProvider: ThemeProvider,
27566
+ ThemeToggle: ThemeToggle,
25810
27567
  ThemeValidator: ThemeValidator,
27568
+ alpha: alpha,
25811
27569
  applyCSSVariables: applyCSSVariables,
25812
27570
  applyComponentTheme: applyComponentTheme,
25813
27571
  applyTheme: applyTheme,
25814
27572
  camelToKebab: camelToKebab,
27573
+ clearThemePreference: clearThemePreference,
25815
27574
  clearThemes: clearThemes,
27575
+ configToTokens: configToTokens,
27576
+ createPerformanceMonitor: createPerformanceMonitor,
27577
+ createRTLManager: createRTLManager,
27578
+ createResponsiveUtil: createResponsiveUtil,
27579
+ createSpacing: createSpacing,
25816
27580
  createTheme: createTheme,
25817
27581
  createThemeRegistry: createThemeRegistry,
25818
27582
  createTokens: createTokens,
25819
27583
  cssVarsToStyle: cssVarsToStyle,
27584
+ darken: darken,
25820
27585
  deepMerge: deepMerge,
27586
+ default: index,
25821
27587
  defaultTokens: defaultTokens,
25822
27588
  designTokensToCSSVars: designTokensToCSSVars,
27589
+ emphasize: emphasize,
25823
27590
  extendTheme: extendTheme,
25824
27591
  extractComponentName: extractComponentName,
25825
27592
  generateCSSVariableName: generateCSSVariableName,
@@ -25830,29 +27597,53 @@ const themeImport = Object.freeze( Object.defineProperty({
25830
27597
  getAllThemes: getAllThemes,
25831
27598
  getCSSVariable: getCSSVariable,
25832
27599
  getComponentThemeValue: getComponentThemeValue,
27600
+ getContrastRatio: getContrastRatio,
27601
+ getContrastText: getContrastText,
27602
+ getCurrentTheme: getCurrentTheme,
27603
+ getDirectionFromLocale: getDirectionFromLocale,
27604
+ getLuminance: getLuminance,
27605
+ getSystemTheme: getSystemTheme,
25833
27606
  getTheme: getTheme,
25834
27607
  getThemeApplicator: getThemeApplicator,
25835
27608
  getThemeCount: getThemeCount,
25836
27609
  getThemeIds: getThemeIds,
25837
27610
  hasTheme: hasTheme,
27611
+ hexToRgb: hexToRgb$1,
27612
+ initializeTheme: initializeTheme,
25838
27613
  injectCSS: injectCSS$1,
25839
27614
  injectTheme: injectTheme,
27615
+ isAccessible: isAccessible,
25840
27616
  isCSSInjected: isCSSInjected,
25841
27617
  isDesignTokens: isDesignTokens,
27618
+ isRTLLocale: isRTLLocale,
25842
27619
  isValidCSSVariableName: isValidCSSVariableName,
27620
+ lighten: lighten,
27621
+ listenToSystemTheme: listenToSystemTheme,
25843
27622
  mapSCSSTokensToCSSVars: mapSCSSTokensToCSSVars,
25844
27623
  mergeCSSVars: mergeCSSVars,
25845
27624
  mergeTheme: mergeTheme,
27625
+ mergeTokens: mergeTokens,
25846
27626
  normalizeThemeTokens: normalizeThemeTokens,
27627
+ omitTokens: omitTokens,
27628
+ overrideTokens: overrideTokens,
27629
+ persistTheme: persistTheme,
27630
+ pickTokens: pickTokens,
25847
27631
  registerTheme: registerTheme,
25848
27632
  removeCSS: removeCSS,
25849
27633
  removeCSSVariables: removeCSSVariables,
25850
27634
  removeTheme: removeTheme,
27635
+ rgbToHex: rgbToHex,
27636
+ rtlCSS: rtlCSS,
27637
+ switchTheme: switchTheme,
25851
27638
  themePropertyToCSSVar: themePropertyToCSSVar,
27639
+ toggleTheme: toggleTheme,
25852
27640
  unregisterTheme: unregisterTheme,
25853
27641
  useComponentTheme: useComponentTheme,
25854
27642
  useHistory: useHistory,
27643
+ usePerformanceMonitor: usePerformanceMonitor,
27644
+ useResponsive: useResponsive,
25855
27645
  useTheme: useTheme,
27646
+ useThemeSwitcher: useThemeSwitcher,
25856
27647
  useThemeTokens: useThemeTokens
25857
27648
  }, Symbol.toStringTag, {
25858
27649
  value: "Module"
@@ -26114,15 +27905,6 @@ const themeImport = Object.freeze( Object.defineProperty({
26114
27905
  Radio: RADIO_CSS_VARS
26115
27906
  };
26116
27907
 
26117
- /**
26118
- * CSS Variables Constants
26119
- *
26120
- * Comprehensive CSS custom property definitions for all components.
26121
- * These provide type-safe access to component styling variables.
26122
- */
26123
- /**
26124
- * Button CSS Variables
26125
- */
26126
27908
  /**
26127
27909
  * Get CSS variables for a component
26128
27910
  */
@@ -26215,59 +27997,174 @@ function getComponentCSSVars(component) {
26215
27997
  }
26216
27998
 
26217
27999
  /**
26218
- * Atomix Configuration System
28000
+ * Configuration Types
28001
+ *
28002
+ * Type definitions for the Atomix configuration system.
28003
+ */
28004
+ /**
28005
+ * Helper function to define Atomix configuration with type safety
28006
+ */ function defineConfig(config) {
28007
+ return config;
28008
+ }
28009
+
28010
+ /**
28011
+ * Configuration Validator
26219
28012
  *
26220
- * Tailwind-like configuration for customizing the Atomix Design System.
28013
+ * Provides detailed validation and feedback for Atomix configurations,
28014
+ * especially for advanced features (Phases 2, 3, and 4).
28015
+ */
28016
+ /**
28017
+ * Validate an Atomix configuration with detailed feedback
26221
28018
  *
26222
- * External developers can create `atomix.config.ts` in their project root
26223
- * to customize design tokens, similar to Tailwind's tailwind.config.js
28019
+ * @param config - The configuration to validate
28020
+ * @param options - Validation options
28021
+ * @returns Detailed validation result
26224
28022
  *
26225
28023
  * @example
26226
28024
  * ```typescript
26227
- * // atomix.config.ts (in your project)
26228
- * import { defineConfig } from '@shohojdhara/atomix/config';
28025
+ * import { validateConfiguration } from '@shohojdhara/atomix/config';
26229
28026
  *
26230
- * export default defineConfig({
26231
- * theme: {
26232
- * extend: {
26233
- * colors: {
26234
- * primary: { main: '#7AFFD7' },
26235
- * },
26236
- * },
26237
- * },
26238
- * });
28027
+ * const config = { /* your config *\/ };
28028
+ * const result = validateConfiguration(config);
28029
+ *
28030
+ * if (!result.isValid) {
28031
+ * console.warn('Warnings:', result.warnings);
28032
+ * console.info('Suggestions:', result.suggestions);
28033
+ * }
26239
28034
  * ```
28035
+ */ function validateConfiguration(config, options) {
28036
+ const {performanceAnalysis: performanceAnalysis = !0, compatibilityReport: compatibilityReport = !0} = options || {}, warnings = [], suggestions = [];
28037
+ let performanceImpact = "low";
28038
+ // Use the existing validation
28039
+ const baseWarnings = validateConfig$1(config);
28040
+ warnings.push(...baseWarnings),
28041
+ // Analyze advanced features for performance impact
28042
+ performanceAnalysis && (performanceImpact =
28043
+ /**
28044
+ * Analyze the performance impact of a configuration
26240
28045
  */
28046
+ function(config) {
28047
+ let impactScore = 0;
28048
+ // Analyze interactive effects
28049
+ if (config.interactiveEffects) {
28050
+ const ie = config.interactiveEffects;
28051
+ ie.vortex?.enabled && (impactScore += 2), ie.chromaticAberration?.enabled && (impactScore += 1),
28052
+ ie.mouseInteraction?.trailEffect && (impactScore += 1), ie.mouseInteraction?.pressureSensitivity && (impactScore += 1);
28053
+ }
28054
+ // Analyze visual polish effects
28055
+ if (config.visualPolish) {
28056
+ const vp = config.visualPolish;
28057
+ vp.borders?.iridescentGlow && (impactScore += 1), vp.borders?.shimmerEffect && (impactScore += 1),
28058
+ vp.contentAwareBlur?.enabled && (impactScore += 2), vp.holographicEffects?.enabled && (impactScore += 2),
28059
+ vp.holographicEffects?.scanlineAnimation && (impactScore += 1), vp.holographicEffects?.dataStream && (impactScore += 1),
28060
+ vp.holographicEffects?.pulseRings && (impactScore += 1);
28061
+ }
28062
+ // Analyze optimization settings
28063
+ return config.optimization?.autoScaling?.enabled && (impactScore -= 1),
28064
+ impactScore >= 6 ? "high" : impactScore >= 3 ? "medium" : "low";
28065
+ }
28066
+ /**
28067
+ * Generate suggestions based on the configuration
28068
+ */ (config)),
28069
+ // Generate suggestions based on configuration
28070
+ function(config, suggestions) {
28071
+ // Suggest enabling performance optimizations if heavy effects are used
28072
+ (config.interactiveEffects || config.visualPolish?.holographicEffects?.enabled) && (config.optimization?.autoScaling?.enabled || suggestions.push("Consider enabling auto-scaling in optimization settings to adjust effects based on device performance: optimization.autoScaling.enabled = true"),
28073
+ config.optimization?.performance?.fpsTarget || suggestions.push("Set a target FPS in optimization.performance.fpsTarget to ensure smooth performance when using interactive effects")),
28074
+ // Suggest responsive breakpoints if optimization is partially configured
28075
+ config.optimization && !config.optimization.responsive && suggestions.push("Consider adding responsive breakpoints in optimization.responsive.breakpoints to adapt advanced effects based on device type"),
28076
+ // Suggest disabling heavy effects on lower-end devices
28077
+ config.visualPolish?.holographicEffects?.enabled && suggestions.push("For better performance on lower-end devices, consider conditionally disabling holographic effects based on device capabilities"),
28078
+ // Suggest using content-aware blur with performance considerations
28079
+ config.visualPolish?.contentAwareBlur?.enabled && suggestions.push("Content-aware blur can be expensive; consider setting a maximum blur radius or using simpler blur techniques for mobile devices"),
28080
+ // Suggest using chromatic aberration适度
28081
+ config.interactiveEffects?.chromaticAberration?.enabled && (config.interactiveEffects.chromaticAberration.redShift && Math.abs(config.interactiveEffects.chromaticAberration.redShift) > .05 && suggestions.push("High chromatic aberration red shift values (>0.05) may cause discomfort for some users; consider reducing to improve accessibility"),
28082
+ config.interactiveEffects.chromaticAberration.blueShift && Math.abs(config.interactiveEffects.chromaticAberration.blueShift) > .05 && suggestions.push("High chromatic aberration blue shift values (>0.05) may cause discomfort for some users; consider reducing to improve accessibility"));
28083
+ }
28084
+ /**
28085
+ * Generate a compatibility report for the configuration
28086
+ */ (config, suggestions);
28087
+ // Determine overall validity
28088
+ const isValid = 0 === warnings.length, compatibility = compatibilityReport ? function(config) {
28089
+ return {
28090
+ browsers: !(config.visualPolish?.holographicEffects?.enabled || config.visualPolish?.contentAwareBlur?.enabled || config.interactiveEffects?.vortex?.enabled || config.interactiveEffects?.chromaticAberration?.enabled),
28091
+ // May have issues on older browsers
28092
+ ssr: !0,
28093
+ // Works fine with SSR
28094
+ frameworks: [ "react", "vue", "angular", "svelte", "vanillajs" ]
28095
+ };
28096
+ }
28097
+ /**
28098
+ * Print a detailed configuration report to the console
28099
+ *
28100
+ * @param config - The configuration to analyze
28101
+ * @param title - Optional title for the report
28102
+ *
28103
+ * @example
28104
+ * ```typescript
28105
+ * import { printConfigReport } from '@shohojdhara/atomix/config';
28106
+ *
28107
+ * const config = { /* your config *\/ };
28108
+ * printConfigReport(config, 'My Application Config');
28109
+ * ```
28110
+ */ (config) : {
28111
+ browsers: !0,
28112
+ ssr: !0,
28113
+ frameworks: [ "react", "vue", "angular", "svelte", "vanillajs" ]
28114
+ };
28115
+ // Generate compatibility report
28116
+ return {
28117
+ isValid: isValid,
28118
+ warnings: warnings,
28119
+ suggestions: suggestions,
28120
+ performanceImpact: performanceImpact,
28121
+ compatibility: compatibility
28122
+ };
28123
+ }
28124
+
28125
+ function printConfigReport(config, title) {
28126
+ const result = validateConfiguration(config);
28127
+ result.warnings.length > 0 && result.warnings.forEach((warning => {})), result.suggestions.length > 0 && result.suggestions.forEach((suggestion => {}));
28128
+ const featuresDetected = [];
28129
+ config.interactiveEffects && featuresDetected.push("Interactive Effects"), config.optimization && featuresDetected.push("Optimization"),
28130
+ config.visualPolish && featuresDetected.push("Visual Polish"), config.ai && featuresDetected.push("AI Integration"),
28131
+ config.tokenEngine && featuresDetected.push("Token Engine"), config.generator && featuresDetected.push("Component Generator"),
28132
+ featuresDetected.length > 0 && featuresDetected.forEach((feature => {}));
28133
+ }
28134
+
26241
28135
  /**
26242
- * Helper function to define Atomix configuration with type safety
28136
+ * Public API for loading and managing Atomix configuration
26243
28137
  *
26244
- * @param config - Atomix configuration object
26245
- * @returns The configuration object
28138
+ * This module provides the public-facing API for configuration loading
28139
+ * in external projects.
26246
28140
  */
26247
28141
  /**
26248
- * Helper function to define Atomix configuration with type safety
28142
+ * Load Atomix configuration from an external project.
26249
28143
  *
26250
- * Similar to Tailwind's defineConfig, provides autocomplete and type checking.
26251
- *
26252
- * @param config - Atomix configuration object
26253
- * @returns The configuration object
28144
+ * @param options - Loading options
28145
+ * @returns The loaded configuration
26254
28146
  *
26255
28147
  * @example
26256
28148
  * ```typescript
26257
- * import { defineConfig } from '@shohojdhara/atomix/config';
28149
+ * import { loadConfig } from '@shohojdhara/atomix/config';
26258
28150
  *
26259
- * export default defineConfig({
26260
- * theme: {
26261
- * extend: {
26262
- * colors: {
26263
- * primary: { main: '#7AFFD7' },
26264
- * },
26265
- * },
26266
- * },
26267
- * });
28151
+ * const config = loadConfig();
28152
+ * console.log(config.prefix); // 'atomix' or user's custom prefix
26268
28153
  * ```
26269
- */ function defineConfig(config) {
26270
- return config;
28154
+ */ function loadConfig(options) {
28155
+ return loadAtomixConfig({
28156
+ configPath: options?.configPath,
28157
+ required: options?.required ?? !1
28158
+ });
28159
+ }
28160
+
28161
+ /**
28162
+ * Validate Atomix configuration structure.
28163
+ *
28164
+ * @param config - Configuration object to validate
28165
+ * @returns Array of validation warnings (empty if valid)
28166
+ */ function validateConfig(config) {
28167
+ return validateConfig$1(config);
26271
28168
  }
26272
28169
 
26273
28170
  // Import and re-export as namespaces with proper typing
@@ -26416,5 +28313,5 @@ const atomix = {
26416
28313
  types: types
26417
28314
  };
26418
28315
 
26419
- export { ACCORDION, ATOMIX_GLASS, AVATAR, AVATAR_GROUP, Accordion, AreaChart, AtomixGlass, AtomixLogo, Avatar, AvatarGroup, BADGE, BADGE_CSS_VARS, BALANCED_PRESET, 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, DEFAULT_BREAKPOINTS, DROPDOWN, DROPDOWN_CSS_VARS, DataTable, DatePicker, DesignTokensCustomizer, DeviceDetector, DonutChart, Dropdown, EDGE_PANEL, EdgePanel, ElevationCard, FOOTER, FORM, FORM_GROUP, Footer, FooterLink, FooterSection, FooterSocialLink, Form, FormGroup, FunnelChart, GaugeChart, Grid, GridCol, HERO, HeatmapChart, Hero, INPUT, INPUT_CSS_VARS, Icon, Input, LIST, LIST_GROUP, LineChart, List, ListGroup, MESSAGES, MOBILE_OPTIMIZED_BREAKPOINTS, MODAL, MODAL_CSS_VARS, MasonryGrid, MasonryGridItem, MegaMenu, MegaMenuColumn, MegaMenuLink, Menu, MenuDivider, MenuItem, Messages, Modal, MultiAxisChart, NAV, NAVBAR, Nav, NavDropdown, NavItem, Navbar, PAGINATION_DEFAULTS, PERFORMANCE_PRESET, PHOTOVIEWER, POPOVER, PROGRESS, PROGRESS_CSS_VARS, Pagination, PerformanceOverlay, PhotoViewer, PieChart, Popover, ProductReview, Progress, QUALITY_PRESET, 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, TYPEDBUTTON, 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, createBreakpoints$1 as createBreakpoints, 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, getDefaultBreakpoints, getDevicePreset, getMobileOptimizedParams, getPartStyles, getQualityMultipliers, 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, useChartData, useChartInteraction, useChartScale, useComponentCustomization, useComponentDefaultProps, useComponentTheme, useEdgePanel, useForm, useFormGroup, useHero, useHistory, useInput, useLineChart, useMergedProps, useNav, useNavDropdown, useNavItem, useNavbar, usePerformanceMonitor, usePieChart, useRadio, useResponsiveGlass, useRiver, useSelect, useSideMenu, useSideMenuItem, useSlot, useSpinner, useTextarea, useTheme, useThemeTokens, useTodo, utils, validateTheme };
28316
+ export { ACCORDION, ATOMIX_GLASS, AVATAR, AVATAR_GROUP, Accordion, AreaChart, AtomixGlass, AtomixLogo, Avatar, AvatarGroup, BADGE, BADGE_CSS_VARS, BALANCED_PRESET, 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, DEFAULT_BREAKPOINTS, DROPDOWN, DROPDOWN_CSS_VARS, DataTable, DatePicker, DesignTokensCustomizer, DeviceDetector, DonutChart, Dropdown, EDGE_PANEL, EdgePanel, ElevationCard, FOOTER, FORM, FORM_GROUP, Footer, FooterLink, FooterSection, FooterSocialLink, Form, FormGroup, FunnelChart, GaugeChart, Grid, GridCol, HERO, HeatmapChart, Hero, INPUT, INPUT_CSS_VARS, Icon, Input, LIST, LIST_GROUP, LineChart, List, ListGroup, MESSAGES, MOBILE_OPTIMIZED_BREAKPOINTS, MODAL, MODAL_CSS_VARS, MasonryGrid, MasonryGridItem, MegaMenu, MegaMenuColumn, MegaMenuLink, Menu, MenuDivider, MenuItem, Messages, Modal, MultiAxisChart, NAV, NAVBAR, Nav, NavDropdown, NavItem, Navbar, PAGINATION_DEFAULTS, PERFORMANCE_PRESET, PHOTOVIEWER, POPOVER, PROGRESS, PROGRESS_CSS_VARS, Pagination, PerformanceOverlay, PhotoViewer, PieChart, Popover, ProductReview, Progress, QUALITY_PRESET, 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, TYPEDBUTTON, Tabs, Testimonial, Textarea, ThemeApplicator, ThemeComparator, ThemeContext, ThemeErrorBoundary, ThemeInspector, ThemeLiveEditor, ThemePreview, ThemeProvider, ThemeToggle, ThemeValidator, Todo, Toggle, Tooltip, TreemapChart, UPLOAD, Upload, VIDEO_PLAYER, VideoPlayer, WaterfallChart, alpha, applyCSSVariables, applyCSSVarsToStyle, applyComponentTheme, applyPartStyles, applyTheme, camelToKebab, clearThemePreference, clearThemes, composables, configToTokens, constants, createBreakpoints$1 as createBreakpoints, createCSSVarStyle, createDarkVariant, createDebugAttrs, createFontPreloadLink, createPartProps, createPerformanceMonitor, createRTLManager, createResponsiveUtil, createSlotComponent, createSlotProps, createSpacing, createTheme, createThemeRegistry, createTokens, cssVarsToStyle, darken, deepMerge, atomix as default, defaultTokens, defineConfig, designTokensToCSSVars, emphasize, exportTheme, extendTheme, extractComponentName, extractYouTubeId, generateCSSVariableName, generateCSSVariables$1 as generateCSSVariables, generateCSSVariablesForSelector, generateClassName, generateComponentCSSVars, generateFontPreloadTags, generateUUID, getAllThemes, getCSSVariable, getComponentCSSVars, getComponentThemeValue, getContrastRatio, getContrastText, getCurrentTheme, getDefaultBreakpoints, getDevicePreset, getDirectionFromLocale, getLuminance, getMobileOptimizedParams, getPartStyles, getQualityMultipliers, getSystemTheme, getTheme, getThemeApplicator, getThemeCount, getThemeIds, getThemeMetadata, hasCustomization, hasTheme, hexToRgb$1 as hexToRgb, importTheme, initializeTheme, injectCSS$1 as injectCSS, injectTheme, isAccessible, isCSSInjected, isDesignTokens, isRTLLocale, isSlot, isValidCSSVariableName, isYouTubeUrl, lighten, listenToSystemTheme, loadAtomixConfig, loadConfig, mapSCSSTokensToCSSVars, mergeCSSVars, mergeClassNames, mergeComponentProps, mergePartStyles, mergeSlots, mergeTheme, mergeTokens, normalizeThemeTokens, omitTokens, overrideTokens, persistTheme, pickTokens, preloadFonts, printConfigReport, quickTheme, registerTheme, removeCSS, removeCSSVariables, removeTheme, renderSlot, resolveConfigPath, rgbToHex, rtlCSS, sliderConstants, supportsDarkMode, switchTheme, theme, themePropertyToCSSVar, themeToCSS, toggleTheme, types, unregisterTheme, useAccordion, useAtomixGlass, useBadge, useBarChart, useBlock, useChartData, useChartInteraction, useChartScale, useComponentCustomization, useComponentDefaultProps, useComponentTheme, useEdgePanel, useForm, useFormGroup, useHero, useHistory, useInput, useLineChart, useMergedProps, useNav, useNavDropdown, useNavItem, useNavbar, usePieChart, useRadio, useResponsive, useResponsiveGlass, useRiver, useSelect, useSideMenu, useSideMenuItem, useSlot, useSpinner, useTextarea, useTheme, useThemeSwitcher, useThemeTokens, useTodo, utils, validateConfig, validateConfiguration, validateTheme };
26420
28317
  //# sourceMappingURL=index.esm.js.map