@shohojdhara/atomix 0.5.2 → 0.5.4

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