@shohojdhara/atomix 0.3.12 → 0.3.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +2 -0
  3. package/dist/atomix.css +101 -88
  4. package/dist/atomix.css.map +1 -1
  5. package/dist/atomix.min.css +5 -15258
  6. package/dist/atomix.min.css.map +1 -1
  7. package/dist/charts.d.ts +1 -1
  8. package/dist/charts.js +17 -19
  9. package/dist/charts.js.map +1 -1
  10. package/dist/core.d.ts +41 -11
  11. package/dist/core.js +55 -41
  12. package/dist/core.js.map +1 -1
  13. package/dist/forms.d.ts +28 -11
  14. package/dist/forms.js +25 -24
  15. package/dist/forms.js.map +1 -1
  16. package/dist/heavy.d.ts +1 -1
  17. package/dist/heavy.js +32 -25
  18. package/dist/heavy.js.map +1 -1
  19. package/dist/index.d.ts +122 -46
  20. package/dist/index.esm.js +865 -200
  21. package/dist/index.esm.js.map +1 -1
  22. package/dist/index.js +870 -204
  23. package/dist/index.js.map +1 -1
  24. package/dist/index.min.js +1 -1
  25. package/dist/index.min.js.map +1 -1
  26. package/dist/theme.d.ts +27 -2
  27. package/dist/theme.js +721 -108
  28. package/dist/theme.js.map +1 -1
  29. package/package.json +1 -1
  30. package/scripts/atomix-cli.js +610 -1111
  31. package/scripts/cli/component-generator.js +610 -0
  32. package/scripts/cli/documentation-sync.js +542 -0
  33. package/scripts/cli/interactive-init.js +84 -288
  34. package/scripts/cli/mappings.js +211 -0
  35. package/scripts/cli/migration-tools.js +95 -288
  36. package/scripts/cli/template-manager.js +107 -0
  37. package/scripts/cli/templates/README.md +123 -0
  38. package/scripts/cli/templates/composable-templates.js +149 -0
  39. package/scripts/cli/templates/config-templates.js +126 -0
  40. package/scripts/cli/templates/index.js +95 -0
  41. package/scripts/cli/templates/project-templates.js +214 -0
  42. package/scripts/cli/templates/react-templates.js +261 -0
  43. package/scripts/cli/templates/scss-templates.js +156 -0
  44. package/scripts/cli/templates/storybook-templates.js +236 -0
  45. package/scripts/cli/templates/testing-templates.js +45 -0
  46. package/scripts/cli/templates/token-templates.js +447 -0
  47. package/scripts/cli/templates/types-templates.js +133 -0
  48. package/scripts/cli/templates-original-backup.js +1655 -0
  49. package/scripts/cli/templates.js +35 -0
  50. package/scripts/cli/templates_backup.js +684 -0
  51. package/scripts/cli/theme-bridge.js +20 -14
  52. package/scripts/cli/token-manager.js +150 -77
  53. package/scripts/cli/utils.js +37 -25
  54. package/src/components/Accordion/Accordion.stories.tsx +5 -5
  55. package/src/components/Accordion/Accordion.test.tsx +57 -0
  56. package/src/components/Accordion/Accordion.tsx +4 -0
  57. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +41 -44
  58. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +1 -1
  59. package/src/components/AtomixGlass/stories/Examples.stories.tsx +37 -37
  60. package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -2
  61. package/src/components/AtomixGlass/stories/Playground.stories.tsx +50 -51
  62. package/src/components/Avatar/Avatar.stories.tsx +26 -26
  63. package/src/components/Badge/Badge.stories.tsx +31 -31
  64. package/src/components/Badge/Badge.test.tsx +51 -0
  65. package/src/components/Badge/Badge.tsx +20 -1
  66. package/src/components/Block/Block.stories.tsx +5 -5
  67. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +1 -1
  68. package/src/components/Breadcrumb/Breadcrumb.tsx +2 -2
  69. package/src/components/Button/Button.stories.tsx +13 -13
  70. package/src/components/Button/Button.tsx +4 -4
  71. package/src/components/Button/ButtonGroup.stories.tsx +2 -2
  72. package/src/components/Button/README.md +5 -0
  73. package/src/components/Callout/Callout.stories.tsx +11 -11
  74. package/src/components/Callout/Callout.test.tsx +10 -10
  75. package/src/components/Callout/Callout.tsx +7 -7
  76. package/src/components/Callout/README.md +9 -8
  77. package/src/components/Card/Card.tsx +2 -2
  78. package/src/components/Chart/Chart.stories.tsx +6 -6
  79. package/src/components/Chart/Chart.tsx +1 -1
  80. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +1 -1
  81. package/src/components/DataTable/DataTable.tsx +14 -12
  82. package/src/components/DatePicker/DatePicker.stories.tsx +6 -6
  83. package/src/components/Dropdown/Dropdown.stories.tsx +4 -4
  84. package/src/components/Form/Checkbox.stories.tsx +3 -3
  85. package/src/components/Form/Checkbox.tsx +4 -2
  86. package/src/components/Form/Form.stories.tsx +3 -3
  87. package/src/components/Form/FormGroup.stories.tsx +1 -1
  88. package/src/components/Form/Input.stories.tsx +28 -16
  89. package/src/components/Form/Input.test.tsx +59 -0
  90. package/src/components/Form/Input.tsx +97 -95
  91. package/src/components/Form/Radio.stories.tsx +94 -94
  92. package/src/components/Form/Radio.tsx +2 -2
  93. package/src/components/Form/Select.stories.tsx +4 -4
  94. package/src/components/Form/Select.tsx +2 -2
  95. package/src/components/Form/Textarea.stories.tsx +22 -7
  96. package/src/components/Form/Textarea.test.tsx +45 -0
  97. package/src/components/Form/Textarea.tsx +88 -86
  98. package/src/components/List/List.stories.tsx +2 -2
  99. package/src/components/Modal/Modal.stories.tsx +4 -4
  100. package/src/components/Navigation/Navbar/Navbar.stories.tsx +5 -5
  101. package/src/components/Navigation/Navbar/Navbar.tsx +1 -1
  102. package/src/components/Navigation/README.md +1 -1
  103. package/src/components/Pagination/Pagination.stories.tsx +5 -2
  104. package/src/components/Pagination/Pagination.tsx +1 -1
  105. package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -10
  106. package/src/components/Popover/Popover.stories.tsx +1 -1
  107. package/src/components/ProductReview/ProductReview.tsx +1 -1
  108. package/src/components/Progress/Progress.tsx +46 -46
  109. package/src/components/Rating/Rating.stories.tsx +4 -4
  110. package/src/components/Rating/Rating.tsx +8 -8
  111. package/src/components/Slider/Slider.stories.tsx +63 -63
  112. package/src/components/Spinner/Spinner.stories.tsx +2 -2
  113. package/src/components/Spinner/Spinner.test.tsx +35 -0
  114. package/src/components/Spinner/Spinner.tsx +9 -2
  115. package/src/components/Testimonial/Testimonial.stories.tsx +1 -1
  116. package/src/components/Toggle/Toggle.stories.tsx +32 -9
  117. package/src/components/Toggle/Toggle.test.tsx +91 -0
  118. package/src/components/Toggle/Toggle.tsx +44 -27
  119. package/src/components/Tooltip/Tooltip.tsx +1 -1
  120. package/src/layouts/Grid/Grid.stories.tsx +49 -49
  121. package/src/layouts/MasonryGrid/MasonryGrid.stories.tsx +2 -2
  122. package/src/lib/composables/useAccordion.ts +12 -3
  123. package/src/lib/composables/useBreadcrumb.ts +2 -2
  124. package/src/lib/composables/useCallout.ts +7 -7
  125. package/src/lib/composables/useNavbar.ts +1 -1
  126. package/src/lib/constants/components.ts +1 -1
  127. package/src/lib/storybook/InteractiveDemo.tsx +113 -0
  128. package/src/lib/storybook/PreviewContainer.tsx +36 -0
  129. package/src/lib/storybook/VariantsGrid.tsx +21 -0
  130. package/src/lib/storybook/index.ts +3 -0
  131. package/src/lib/theme/core/createThemeObject.ts +9 -5
  132. package/src/lib/theme/devtools/CLI.ts +155 -0
  133. package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +213 -0
  134. package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +566 -0
  135. package/src/lib/theme/devtools/LiveEditor.tsx +2 -1
  136. package/src/lib/theme/devtools/index.ts +3 -0
  137. package/src/lib/theme/errors/errors.ts +8 -0
  138. package/src/lib/theme/runtime/ThemeProvider.tsx +117 -57
  139. package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +305 -0
  140. package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +588 -0
  141. package/src/lib/theme/utils/__tests__/themeValidation.test.ts +264 -0
  142. package/src/lib/theme/utils/index.ts +1 -0
  143. package/src/lib/theme/utils/themeValidation.ts +501 -0
  144. package/src/lib/theme-tools.ts +32 -3
  145. package/src/lib/types/components.ts +81 -26
  146. package/src/lib/utils/themeNaming.ts +1 -1
  147. package/src/styles/06-components/_components.atomix-glass.scss +14 -15
  148. package/src/styles/06-components/_components.callout.scss +29 -33
  149. package/src/styles/06-components/_index.scss +1 -1
  150. package/src/styles/99-utilities/_utilities.display.scss +14 -3
  151. package/src/styles/99-utilities/_utilities.flex.scss +10 -10
  152. package/src/styles/99-utilities/_utilities.text.scss +28 -8
  153. package/scripts/cli/__tests__/cli-commands.test.js +0 -204
  154. package/scripts/cli/__tests__/utils.test.js +0 -201
  155. package/scripts/cli/__tests__/vitest.config.js +0 -26
package/dist/theme.js CHANGED
@@ -406,6 +406,14 @@ import { createContext, useRef, useEffect, useCallback, useMemo, useState, useCo
406
406
  ThemeErrorCode.INVALID_THEME_NAME = "INVALID_THEME_NAME",
407
407
  /** CSS injection failed */
408
408
  ThemeErrorCode.CSS_INJECTION_FAILED = "CSS_INJECTION_FAILED",
409
+ /** Invalid color format */
410
+ ThemeErrorCode.INVALID_COLOR_FORMAT = "INVALID_COLOR_FORMAT",
411
+ /** Missing required token */
412
+ ThemeErrorCode.MISSING_REQUIRED_TOKEN = "MISSING_REQUIRED_TOKEN",
413
+ /** Accessibility contrast violation */
414
+ ThemeErrorCode.CONTRAST_VIOLATION = "CONTRAST_VIOLATION",
415
+ /** Invalid token type */
416
+ ThemeErrorCode.INVALID_TOKEN_TYPE = "INVALID_TOKEN_TYPE",
409
417
  /** Unknown error */
410
418
  ThemeErrorCode.UNKNOWN_ERROR = "UNKNOWN_ERROR";
411
419
  }(ThemeErrorCode || (ThemeErrorCode = {}));
@@ -707,29 +715,6 @@ class ThemeLogger {
707
715
  return Object.keys(registry).length;
708
716
  }
709
717
 
710
- /**
711
- * Core Theme Engine
712
- *
713
- * Core theme creation, composition, and registry functionality
714
- */ const index = Object.freeze( Object.defineProperty({
715
- __proto__: null,
716
- clearThemes: clearThemes,
717
- createTheme: createTheme,
718
- createThemeRegistry: createThemeRegistry,
719
- deepMerge: deepMerge,
720
- extendTheme: extendTheme,
721
- getAllThemes: getAllThemes,
722
- getTheme: getTheme,
723
- getThemeCount: getThemeCount,
724
- getThemeIds: getThemeIds,
725
- hasTheme: hasTheme,
726
- mergeTheme: mergeTheme,
727
- registerTheme: registerTheme,
728
- unregisterTheme: unregisterTheme
729
- }, Symbol.toStringTag, {
730
- value: "Module"
731
- }));
732
-
733
718
  /**
734
719
  * CSS Injection Utilities
735
720
  *
@@ -1276,7 +1261,7 @@ const isBrowser = () => "undefined" != typeof window && "undefined" != typeof do
1276
1261
  /**
1277
1262
  * Convert hex color to RGB object
1278
1263
  */
1279
- function hexToRgb(hex) {
1264
+ function hexToRgb$1(hex) {
1280
1265
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1281
1266
  return result ? {
1282
1267
  r: parseInt(result[1], 16),
@@ -1296,7 +1281,7 @@ function hexToRgb(hex) {
1296
1281
  * Calculate relative luminance of a color
1297
1282
  * Used for determining contrast ratios
1298
1283
  */ function getLuminance(color) {
1299
- const rgb = hexToRgb(color);
1284
+ const rgb = hexToRgb$1(color);
1300
1285
  if (!rgb) return 0;
1301
1286
  const {r: r, g: g, b: b} = rgb, [rs, gs, bs] = [ r ?? 0, g ?? 0, b ?? 0 ].map((c => {
1302
1287
  const val = c / 255;
@@ -1326,7 +1311,7 @@ function hexToRgb(hex) {
1326
1311
  * @param amount - Amount to lighten (0-1), default 0.2
1327
1312
  * @returns Lightened hex color
1328
1313
  */ function lighten(color, amount = .2) {
1329
- const rgb = hexToRgb(color);
1314
+ const rgb = hexToRgb$1(color);
1330
1315
  if (!rgb) return color;
1331
1316
  const {r: r, g: g, b: b} = rgb, lightenValue = val => Math.min(255, Math.round(val + (255 - val) * amount));
1332
1317
  return rgbToHex(lightenValue(r), lightenValue(g), lightenValue(b));
@@ -1339,7 +1324,7 @@ function hexToRgb(hex) {
1339
1324
  * @param amount - Amount to darken (0-1), default 0.2
1340
1325
  * @returns Darkened hex color
1341
1326
  */ function darken(color, amount = .2) {
1342
- const rgb = hexToRgb(color);
1327
+ const rgb = hexToRgb$1(color);
1343
1328
  if (!rgb) return color;
1344
1329
  const {r: r, g: g, b: b} = rgb, darkenValue = val => Math.max(0, Math.round(val * (1 - amount)));
1345
1330
  return rgbToHex(darkenValue(r), darkenValue(g), darkenValue(b));
@@ -1352,7 +1337,7 @@ function hexToRgb(hex) {
1352
1337
  * @param opacity - Opacity value (0-1)
1353
1338
  * @returns RGBA color string
1354
1339
  */ function alpha(color, opacity) {
1355
- const rgb = hexToRgb(color);
1340
+ const rgb = hexToRgb$1(color);
1356
1341
  if (!rgb) return color;
1357
1342
  const {r: r, g: g, b: b} = rgb;
1358
1343
  return `rgba(${r}, ${g}, ${b}, ${Math.max(0, Math.min(1, opacity))})`;
@@ -1371,7 +1356,7 @@ function hexToRgb(hex) {
1371
1356
  */
1372
1357
  function generateColorScale(baseColor, prefix, colorName) {
1373
1358
  const vars = {};
1374
- if (!hexToRgb(baseColor)) return vars;
1359
+ if (!hexToRgb$1(baseColor)) return vars;
1375
1360
  // Generate 10-step scale
1376
1361
  // Steps 1-5: lighter variations
1377
1362
  // Step 6: base color
@@ -1417,7 +1402,7 @@ function generateCSSVariables(theme, options = {}) {
1417
1402
  // Main color (flat structure, matches SCSS: --atomix-primary)
1418
1403
  vars[`${prefix}-${key}`] = color.main;
1419
1404
  // Generate RGB for transparency support (matches SCSS: --atomix-primary-rgb)
1420
- const rgb = hexToRgb(color.main);
1405
+ const rgb = hexToRgb$1(color.main);
1421
1406
  // Generate full color scale (1-10) - matches SCSS: --atomix-primary-1 through --atomix-primary-10
1422
1407
  // Only for primary, secondary, error, warning, info, success (not for light/dark)
1423
1408
  if (rgb && (vars[`${prefix}-${key}-rgb`] = `${rgb.r}, ${rgb.g}, ${rgb.b}`), "light" !== key && "dark" !== key) {
@@ -1500,11 +1485,11 @@ function generateCSSVariables(theme, options = {}) {
1500
1485
  // Heading color (defaults to text primary) - matches SCSS: --atomix-heading-color
1501
1486
  palette.text && (vars[`${prefix}-heading-color`] = palette.text.primary), palette.primary) {
1502
1487
  vars[`${prefix}-link-color`] = palette.primary.main;
1503
- const linkRgb = hexToRgb(palette.primary.main);
1488
+ const linkRgb = hexToRgb$1(palette.primary.main);
1504
1489
  linkRgb && (vars[`${prefix}-link-color-rgb`] = `${linkRgb.r}, ${linkRgb.g}, ${linkRgb.b}`),
1505
1490
  // Link hover color (slightly darker)
1506
1491
  vars[`${prefix}-link-hover-color`] = palette.primary.dark || darken(palette.primary.main, .1);
1507
- const linkHoverRgb = hexToRgb(palette.primary.dark || darken(palette.primary.main, .1));
1492
+ const linkHoverRgb = hexToRgb$1(palette.primary.dark || darken(palette.primary.main, .1));
1508
1493
  linkHoverRgb && (vars[`${prefix}-link-hover-color-rgb`] = `${linkHoverRgb.r}, ${linkHoverRgb.g}, ${linkHoverRgb.b}`),
1509
1494
  // Link decoration (default: none, matching tokens list)
1510
1495
  vars[`${prefix}-link-decoration`] = "none";
@@ -1962,17 +1947,292 @@ function generateClassName(block, element, modifiers) {
1962
1947
  ThemeContext.displayName = "ThemeContext";
1963
1948
 
1964
1949
  /**
1965
- * Theme Provider
1950
+ * Theme Validation Utilities
1966
1951
  *
1967
- * React context provider for theme management with separated concerns.
1968
- * Simplified version focusing on core functionality:
1969
- * - String-based themes (CSS files)
1970
- * - DesignTokens (dynamic themes)
1971
- * - Persistence via localStorage
1972
- *
1973
- * Falls back to 'default' theme if no configuration is found.
1952
+ * Comprehensive validation utilities for DesignTokens objects.
1953
+ * Includes color format validation, accessibility checks, and required properties verification.
1974
1954
  */
1975
- const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes: themes = {}, basePath: basePath = "/themes", cdnPath: cdnPath = null, useMinified: useMinified = !1, storageKey: storageKey = "atomix-theme", dataAttribute: dataAttribute = "data-theme", enablePersistence: enablePersistence = !0, onThemeChange: onThemeChange, onError: onError}) => {
1955
+ const logger$1 = getLogger(), COLOR_PATTERNS = {
1956
+ /** Hex color: #RGB, #RRGGBB, #RRGGBBAA */
1957
+ hex: /^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$/,
1958
+ /** RGB color: rgb(r, g, b) or rgb(r, g, b, a) */
1959
+ rgb: /^rgb\(\s*(\d{1,3}(?:\.\d+)?)\s*,\s*(\d{1,3}(?:\.\d+)?)\s*,\s*(\d{1,3}(?:\.\d+)?)\s*(?:,\s*([01]?\.?\d+))?\s*\)$/,
1960
+ /** RGBA color: rgba(r, g, b, a) */
1961
+ rgba: /^rgba\(\s*(\d{1,3}(?:\.\d+)?)\s*,\s*(\d{1,3}(?:\.\d+)?)\s*,\s*(\d{1,3}(?:\.\d+)?)\s*,\s*([01]?\.?\d+)\s*\)$/,
1962
+ /** HSL color: hsl(h, s%, l%) */
1963
+ hsl: /^hsl\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*\)$/,
1964
+ /** HSLA color: hsla(h, s%, l%, a) */
1965
+ hsla: /^hsla\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*,\s*([01]?\.?\d+)\s*\)$/
1966
+ }, REQUIRED_COLOR_TOKENS = [ "primary", "secondary", "success", "info", "warning", "error", "light", "dark" ], REQUIRED_TEXT_EMPHASIS_TOKENS = [ "primary-text-emphasis", "secondary-text-emphasis", "tertiary-text-emphasis", "disabled-text-emphasis" ], ACCESSIBILITY_CHECKS = [ {
1967
+ text: "primary-text-emphasis",
1968
+ background: "primary-bg-subtle",
1969
+ name: "Primary text on subtle background"
1970
+ }, {
1971
+ text: "secondary-text-emphasis",
1972
+ background: "secondary-bg-subtle",
1973
+ name: "Secondary text on subtle background"
1974
+ }, {
1975
+ text: "error-text-emphasis",
1976
+ background: "error-bg-subtle",
1977
+ name: "Error text on subtle background"
1978
+ }, {
1979
+ text: "success-text-emphasis",
1980
+ background: "success-bg-subtle",
1981
+ name: "Success text on subtle background"
1982
+ } ];
1983
+
1984
+ /**
1985
+ * Color format validation patterns
1986
+ */
1987
+ /**
1988
+ * Parse RGB/RGBA color string to RGB values
1989
+ */
1990
+ function rgbToRgb(rgb) {
1991
+ const match = rgb.match(COLOR_PATTERNS.rgb) || rgb.match(COLOR_PATTERNS.rgba);
1992
+ if (!match) return null;
1993
+ const r = parseInt(match[1] ?? "0", 10), g = parseInt(match[2] ?? "0", 10), b = parseInt(match[3] ?? "0", 10);
1994
+ // Validate RGB ranges
1995
+ return r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255 ? null : {
1996
+ r: r,
1997
+ g: g,
1998
+ b: b
1999
+ };
2000
+ }
2001
+
2002
+ /**
2003
+ * Parse HSL/HSLA color string to RGB values
2004
+ */ function hslToRgb(hsl) {
2005
+ const match = hsl.match(COLOR_PATTERNS.hsl) || hsl.match(COLOR_PATTERNS.hsla);
2006
+ if (!match) return null;
2007
+ let h = parseInt(match[1] ?? "0", 10) / 360, s = parseInt(match[2] ?? "0", 10) / 100, l = parseInt(match[3] ?? "0", 10) / 100;
2008
+ // Validate HSL ranges
2009
+ if (h < 0 || h > 1 || s < 0 || s > 1 || l < 0 || l > 1) return null;
2010
+ const hue2rgb = (p, q, t) => (t < 0 && (t += 1), t > 1 && (t -= 1), t < 1 / 6 ? p + 6 * (q - p) * t : t < .5 ? q : t < 2 / 3 ? p + (q - p) * (2 / 3 - t) * 6 : p);
2011
+ let r, g, b;
2012
+ if (0 === s) r = g = b = l; // achromatic
2013
+ else {
2014
+ const q = l < .5 ? l * (1 + s) : l + s - l * s, p = 2 * l - q;
2015
+ r = hue2rgb(p, q, h + 1 / 3), g = hue2rgb(p, q, h), b = hue2rgb(p, q, h - 1 / 3);
2016
+ }
2017
+ return {
2018
+ r: Math.round(255 * r),
2019
+ g: Math.round(255 * g),
2020
+ b: Math.round(255 * b)
2021
+ };
2022
+ }
2023
+
2024
+ /**
2025
+ * Convert any valid color format to RGB values
2026
+ */ function colorToRgb(color) {
2027
+ // Try hex first
2028
+ return COLOR_PATTERNS.hex.test(color) ?
2029
+ /**
2030
+ * Convert hex color to RGB values
2031
+ */
2032
+ function(hex) {
2033
+ const result = COLOR_PATTERNS.hex.exec(hex);
2034
+ if (!result || !result[1]) return null;
2035
+ const digits = result[1];
2036
+ let r, g, b;
2037
+ switch (digits.length) {
2038
+ case 3:
2039
+ case 4:
2040
+ // #RGBA (ignore alpha)
2041
+ r = parseInt((digits[0] ?? "0") + (digits[0] ?? "0"), 16), g = parseInt((digits[1] ?? "0") + (digits[1] ?? "0"), 16),
2042
+ b = parseInt((digits[2] ?? "0") + (digits[2] ?? "0"), 16);
2043
+ break;
2044
+
2045
+ case 6:
2046
+ case 8:
2047
+ // #RRGGBBAA (ignore alpha)
2048
+ r = parseInt(digits.slice(0, 2), 16), g = parseInt(digits.slice(2, 4), 16), b = parseInt(digits.slice(4, 6), 16);
2049
+ break;
2050
+
2051
+ default:
2052
+ return null;
2053
+ }
2054
+ return {
2055
+ r: r,
2056
+ g: g,
2057
+ b: b
2058
+ };
2059
+ }(color) :
2060
+ // Try RGB/RGBA
2061
+ color.startsWith("rgb") ? rgbToRgb(color) :
2062
+ // Try HSL/HSLA
2063
+ color.startsWith("hsl") ? hslToRgb(color) : null;
2064
+ }
2065
+
2066
+ /**
2067
+ * Validate that a color string is in a valid format (hex, rgb, hsl, etc.)
2068
+ * Includes validation of value ranges for RGB and HSL
2069
+ */
2070
+ /**
2071
+ * Calculate relative luminance of a color
2072
+ * Based on WCAG guidelines: https://www.w3.org/TR/WCAG20-TECHS/G17.html
2073
+ */
2074
+ function getRelativeLuminance(r, g, b) {
2075
+ const normalize = val => (val /= 255) <= .03928 ? val / 12.92 : Math.pow((val + .055) / 1.055, 2.4);
2076
+ return .2126 * normalize(r) + .7152 * normalize(g) + .0722 * normalize(b);
2077
+ }
2078
+
2079
+ /**
2080
+ * Calculate contrast ratio between two colors (supports multiple formats)
2081
+ */
2082
+ /**
2083
+ * Check if contrast ratio meets WCAG AA standards
2084
+ * AA requires 4.5:1 for normal text, 3:1 for large text
2085
+ */
2086
+ function validateContrastRatio(foreground, background, isLargeText = !1) {
2087
+ const ratio = function(color1, color2) {
2088
+ const rgb1 = colorToRgb(color1), rgb2 = colorToRgb(color2);
2089
+ if (!rgb1 || !rgb2) return null;
2090
+ const lum1 = getRelativeLuminance(rgb1.r, rgb1.g, rgb1.b), lum2 = getRelativeLuminance(rgb2.r, rgb2.g, rgb2.b);
2091
+ return (Math.max(lum1, lum2) + .05) / (Math.min(lum1, lum2) + .05);
2092
+ }(foreground, background);
2093
+ if (null === ratio) return {
2094
+ valid: !1,
2095
+ ratio: 0,
2096
+ requiredRatio: isLargeText ? 3 : 4.5
2097
+ };
2098
+ const requiredRatio = isLargeText ? 3 : 4.5;
2099
+ return {
2100
+ valid: ratio >= requiredRatio,
2101
+ ratio: ratio,
2102
+ requiredRatio: requiredRatio
2103
+ };
2104
+ }
2105
+
2106
+ /**
2107
+ * Validate all color formats in DesignTokens
2108
+ */
2109
+ /**
2110
+ * Comprehensive validation of DesignTokens
2111
+ */
2112
+ function validateDesignTokens(tokens, options = {}) {
2113
+ const results = [];
2114
+ options.skipRequiredTokens || results.push(
2115
+ /**
2116
+ * Validate that all required tokens are present
2117
+ */
2118
+ function(tokens) {
2119
+ const errors = [], warnings = [];
2120
+ // Check required color tokens
2121
+ for (const token of REQUIRED_COLOR_TOKENS) token in tokens || errors.push(`Required color token '${token}' is missing`);
2122
+ // Check required text emphasis tokens
2123
+ for (const token of REQUIRED_TEXT_EMPHASIS_TOKENS) token in tokens || errors.push(`Required text emphasis token '${token}' is missing`);
2124
+ // Check for RGB versions of base colors
2125
+ for (const token of REQUIRED_COLOR_TOKENS) {
2126
+ const rgbToken = `${token}-rgb`;
2127
+ rgbToken in tokens || warnings.push(`RGB version of '${token}' token '${rgbToken}' is missing`);
2128
+ }
2129
+ return {
2130
+ valid: 0 === errors.length,
2131
+ errors: errors,
2132
+ warnings: warnings
2133
+ };
2134
+ }
2135
+ /**
2136
+ * Validate accessibility contrast ratios
2137
+ */ (tokens)), options.skipColorValidation || results.push(function(tokens) {
2138
+ const errors = [], colorTokenKeys = new Set([
2139
+ // Base colors
2140
+ "primary", "secondary", "success", "info", "warning", "error", "light", "dark",
2141
+ // Text emphasis
2142
+ "primary-text-emphasis", "secondary-text-emphasis", "tertiary-text-emphasis", "disabled-text-emphasis", "invert-text-emphasis", "brand-text-emphasis", "error-text-emphasis", "success-text-emphasis", "warning-text-emphasis", "info-text-emphasis", "light-text-emphasis", "dark-text-emphasis",
2143
+ // Background subtle
2144
+ "primary-bg-subtle", "secondary-bg-subtle", "tertiary-bg-subtle", "invert-bg-subtle", "brand-bg-subtle", "error-bg-subtle", "success-bg-subtle", "warning-bg-subtle", "info-bg-subtle", "light-bg-subtle", "dark-bg-subtle",
2145
+ // Border subtle
2146
+ "primary-border-subtle", "secondary-border-subtle", "success-border-subtle", "error-border-subtle", "warning-border-subtle", "info-border-subtle", "brand-border-subtle", "light-border-subtle", "dark-border-subtle",
2147
+ // Hover states
2148
+ "primary-hover", "secondary-hover", "light-hover", "dark-hover", "error-hover", "success-hover", "warning-hover", "info-hover",
2149
+ // Colors from scales (primary, red, green, blue, yellow)
2150
+ ...Array.from({
2151
+ length: 10
2152
+ }, ((_, i) => [ `primary-${i + 1}`, `red-${i + 1}`, `green-${i + 1}`, `blue-${i + 1}`, `yellow-${i + 1}` ])).flat(),
2153
+ // Gray scale
2154
+ ...Array.from({
2155
+ length: 10
2156
+ }, ((_, i) => `gray-${i + 1}`)),
2157
+ // Body colors
2158
+ "body-color", "heading-color",
2159
+ // Link colors
2160
+ "link-color", "link-hover-color",
2161
+ // Highlight & code
2162
+ "highlight-bg", "code-color",
2163
+ // Border colors
2164
+ "border-color", "border-color-translucent",
2165
+ // Focus ring
2166
+ "focus-border-color",
2167
+ // Form validation
2168
+ "form-valid-color", "form-valid-border-color", "form-invalid-color", "form-invalid-border-color" ]);
2169
+ for (const key of colorTokenKeys) {
2170
+ if (!(key in tokens)) continue;
2171
+ // Skip if token not present
2172
+ const value = tokens[key];
2173
+ "string" == typeof value ? (color = value,
2174
+ // Check hex first (regex is sufficient)
2175
+ COLOR_PATTERNS.hex.test(color) || (
2176
+ // Check RGB/RGBA with value validation
2177
+ COLOR_PATTERNS.rgb.test(color) || COLOR_PATTERNS.rgba.test(color) ? null !== rgbToRgb(color) :
2178
+ // Check HSL/HSLA with value validation
2179
+ (COLOR_PATTERNS.hsl.test(color) || COLOR_PATTERNS.hsla.test(color)) && null !== hslToRgb(color)) || errors.push(`Token '${key}' has invalid color format: '${value}'`)) : errors.push(`Token '${key}' must be a string, got ${typeof value}`);
2180
+ }
2181
+ var color;
2182
+ return {
2183
+ valid: 0 === errors.length,
2184
+ errors: errors,
2185
+ warnings: []
2186
+ };
2187
+ }(tokens)), options.skipAccessibility || results.push(function(tokens) {
2188
+ const errors = [], warnings = [];
2189
+ for (const check of ACCESSIBILITY_CHECKS) {
2190
+ const textColor = tokens[check.text], bgColor = tokens[check.background];
2191
+ if (!textColor || !bgColor) {
2192
+ warnings.push(`Cannot validate contrast for ${check.name}: missing tokens`);
2193
+ continue;
2194
+ }
2195
+ const contrast = validateContrastRatio(textColor, bgColor);
2196
+ if (!contrast.valid) {
2197
+ const level = 3 === contrast.requiredRatio ? "large text (AA)" : "normal text (AA)";
2198
+ errors.push(`${check.name}: contrast ratio ${contrast.ratio.toFixed(2)}:1 is below required ${contrast.requiredRatio}:1 for ${level}`);
2199
+ }
2200
+ }
2201
+ return {
2202
+ valid: 0 === errors.length,
2203
+ errors: errors,
2204
+ warnings: warnings
2205
+ };
2206
+ }(tokens));
2207
+ const allErrors = results.flatMap((r => r.errors)), allWarnings = results.flatMap((r => r.warnings)), valid = 0 === allErrors.length;
2208
+ // Log validation results
2209
+ return valid ? allWarnings.length > 0 ? logger$1.warn(`DesignTokens validation passed with ${allWarnings.length} warnings`, {
2210
+ warnings: allWarnings
2211
+ }) : logger$1.debug("DesignTokens validation passed") : logger$1.error("DesignTokens validation failed", new Error(`Validation failed with ${allErrors.length} errors and ${allWarnings.length} warnings`), {
2212
+ errors: allErrors,
2213
+ warnings: allWarnings,
2214
+ tokenCount: Object.keys(tokens).length
2215
+ }), {
2216
+ valid: valid,
2217
+ errors: allErrors,
2218
+ warnings: allWarnings
2219
+ };
2220
+ }
2221
+
2222
+ /**
2223
+ * Safely validate and merge partial tokens with defaults
2224
+ */ function validateAndMergeTokens(partialTokens) {
2225
+ const merged = {
2226
+ ...defaultTokens,
2227
+ ...partialTokens
2228
+ };
2229
+ return {
2230
+ tokens: merged,
2231
+ validation: validateDesignTokens(merged)
2232
+ };
2233
+ }
2234
+
2235
+ const logger = getLogger(), ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes: themes = {}, basePath: basePath = "/themes", cdnPath: cdnPath = null, useMinified: useMinified = !1, storageKey: storageKey = "atomix-theme", dataAttribute: dataAttribute = "data-theme", enablePersistence: enablePersistence = !0, onThemeChange: onThemeChange, onError: onError}) => {
1976
2236
  // Store callbacks in refs to avoid recreating when they change
1977
2237
  const onThemeChangeRef = useRef(onThemeChange), onErrorRef = useRef(onError);
1978
2238
  // Update ref when callback changes
@@ -1993,12 +2253,20 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
1993
2253
  // If defaultTheme is provided, use it
1994
2254
  return null != defaultTheme ? defaultTheme : "default";
1995
2255
  // Default fallback
1996
- }), [ defaultTheme, enablePersistence, storageKey ]), [currentTheme, setCurrentTheme] = useState((() => "string" == typeof initialDefaultTheme ? initialDefaultTheme : "tokens-theme")), [activeTokens, setActiveTokens] = useState((() =>
1997
- // If defaultTheme is DesignTokens, store them
1998
- defaultTheme && "string" != typeof defaultTheme ? createTokens(defaultTheme) : null)), [isLoading, setIsLoading] = useState(!1), [error, setError] = useState(null), loadedThemesRef = useRef(new Set), themePromisesRef = useRef({}), abortControllerRef = useRef(null);
2256
+ }), [ defaultTheme, enablePersistence, storageKey ]), [currentTheme, setCurrentTheme] = useState((() => "string" == typeof initialDefaultTheme ? initialDefaultTheme : "tokens-theme")), [activeTokens, setActiveTokens] = useState((() => {
2257
+ // If defaultTheme is DesignTokens, validate and store them
2258
+ if (defaultTheme && "string" != typeof defaultTheme) {
2259
+ const {tokens: tokens, validation: validation} = validateAndMergeTokens(defaultTheme);
2260
+ return validation.valid ? tokens : (logger.warn("Invalid default theme tokens, using defaults", {
2261
+ errors: validation.errors,
2262
+ warnings: validation.warnings
2263
+ }), createTokens({}));
2264
+ }
2265
+ return null;
2266
+ })), [isLoading, setIsLoading] = useState(!1), [error, setError] = useState(null), loadedThemesRef = useRef(new Set), themePromisesRef = useRef({}), abortControllerRef = useRef(null);
1999
2267
  // Handle initial DesignTokens defaultTheme
2000
2268
  useEffect((() => {
2001
- defaultTheme && "string" != typeof defaultTheme && activeTokens && !isServer() && injectCSS$1(createTheme(defaultTheme), "theme-tokens-theme");
2269
+ defaultTheme && "string" != typeof defaultTheme && activeTokens && !isServer() && injectCSS$1(createTheme(activeTokens), "theme-tokens-theme");
2002
2270
  }), [ defaultTheme, activeTokens ]), // Run when defaultTheme or activeTokens change
2003
2271
  // Apply initial theme attributes to document element
2004
2272
  useEffect((() => {
@@ -2028,19 +2296,42 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
2028
2296
  if ("string" != typeof theme) {
2029
2297
  // Check if aborted before processing
2030
2298
  if (abortController.signal.aborted) return;
2031
- // For DesignTokens, create CSS and inject it
2032
- const {createTheme: createTheme} = await Promise.resolve().then((() => index)), css = createTheme(theme), themeId = "tokens-theme";
2299
+ // Validate and merge DesignTokens
2300
+ const {tokens: validatedTokens, validation: validation} = validateAndMergeTokens(theme);
2301
+ if (!validation.valid) {
2302
+ const errorMsg = `Invalid DesignTokens provided: ${validation.errors.join(", ")}`, validationError = new Error(errorMsg);
2303
+ // Default to true
2304
+ if (logger.error("Theme validation failed", validationError, {
2305
+ errors: validation.errors,
2306
+ warnings: validation.warnings
2307
+ }), !1 !== options?.fallbackOnError) {
2308
+ logger.warn("Falling back to default theme due to validation errors");
2309
+ // Use default tokens instead
2310
+ const {tokens: defaultTokens} = validateAndMergeTokens({}), css = createTheme(defaultTokens), themeId = "tokens-theme-fallback";
2311
+ // Check if aborted before state update
2312
+ if (abortController.signal.aborted) return;
2313
+ // Remove any previously loaded theme CSS
2314
+ return removeCSS(`theme-${currentTheme}`),
2315
+ // Inject new theme CSS
2316
+ injectCSS$1(css, `theme-${themeId}`),
2317
+ // Store default tokens
2318
+ setActiveTokens(defaultTokens), setCurrentTheme(themeId), handleThemeChange(defaultTokens),
2319
+ handleError(validationError, themeId), void setIsLoading(!1);
2320
+ }
2321
+ // No fallback, throw the error
2322
+ throw validationError;
2323
+ }
2324
+ // For valid DesignTokens, create CSS and inject it
2325
+ const css = createTheme(validatedTokens), themeId = "tokens-theme";
2033
2326
  // Check if aborted after async operation
2034
2327
  if (abortController.signal.aborted) return;
2035
2328
  // Remove any previously loaded theme CSS
2036
- removeCSS(`theme-${currentTheme}`),
2037
- // Inject new theme CSS
2038
- injectCSS$1(css, `theme-${themeId}`);
2039
- // Store tokens for reference
2040
- const fullTokens = createTokens(theme);
2329
+ // Store validated tokens for reference
2041
2330
  // Check if aborted before state update
2042
- if (abortController.signal.aborted) return;
2043
- return setActiveTokens(fullTokens), setCurrentTheme(themeId), handleThemeChange(fullTokens),
2331
+ if (removeCSS(`theme-${currentTheme}`),
2332
+ // Inject new theme CSS
2333
+ injectCSS$1(css, `theme-${themeId}`), abortController.signal.aborted) return;
2334
+ return setActiveTokens(validatedTokens), setCurrentTheme(themeId), handleThemeChange(validatedTokens),
2044
2335
  void setIsLoading(!1);
2045
2336
  }
2046
2337
  // If it's a string theme name, load the associated CSS
@@ -2055,30 +2346,33 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
2055
2346
  // If previous load failed, continue with new load
2056
2347
  }
2057
2348
  // Load CSS theme
2058
- const themeLoadPromise = new Promise((async (resolve, reject) => {
2059
- try {
2060
- // Check if aborted
2061
- if (abortController.signal.aborted) return void resolve();
2062
- if (!themes[theme]) throw new Error(`Theme metadata not found for theme: ${theme}`);
2063
- {
2064
- // Build CSS path using utility function
2065
- const cssPath = buildThemePath(theme, basePath, useMinified, cdnPath);
2349
+ const themeLoadPromise = new Promise(((resolve, reject) => {
2350
+ // Start the async operation
2351
+ (async () => {
2352
+ try {
2066
2353
  // Check if aborted
2067
- if (abortController.signal.aborted) return void resolve();
2068
- // Load CSS file (using loadThemeCSS from domUtils)
2069
- const {loadThemeCSS: loadThemeCSS} = await Promise.resolve().then((() => domUtils));
2070
- // Check if aborted after async operation
2071
- if (await loadThemeCSS(cssPath, `theme-${theme}`), abortController.signal.aborted) return void resolve();
2072
- // Remove any previously loaded theme CSS
2073
- removeCSS(`theme-${String(currentTheme)}`), loadedThemesRef.current.add(theme),
2074
- setCurrentTheme(theme), setActiveTokens(null), handleThemeChange(theme), resolve();
2354
+ if (abortController.signal.aborted) return void resolve();
2355
+ if (!themes[theme]) throw new Error(`Theme metadata not found for theme: ${theme}`);
2356
+ {
2357
+ // Build CSS path using utility function
2358
+ const cssPath = buildThemePath(theme, basePath, useMinified, cdnPath);
2359
+ // Check if aborted
2360
+ if (abortController.signal.aborted) return void resolve();
2361
+ // Load CSS file (using loadThemeCSS from domUtils)
2362
+ const {loadThemeCSS: loadThemeCSS} = await Promise.resolve().then((() => domUtils));
2363
+ // Check if aborted after async operation
2364
+ if (await loadThemeCSS(cssPath, `theme-${theme}`), abortController.signal.aborted) return void resolve();
2365
+ // Remove any previously loaded theme CSS
2366
+ removeCSS(`theme-${String(currentTheme)}`), loadedThemesRef.current.add(theme),
2367
+ setCurrentTheme(theme), setActiveTokens(null), handleThemeChange(theme), resolve();
2368
+ }
2369
+ } catch (err) {
2370
+ // Don't reject if aborted
2371
+ if (abortController.signal.aborted) return void resolve();
2372
+ const error = err instanceof Error ? err : new Error(String(err));
2373
+ setError(error), handleError(error, String(theme)), reject(error);
2075
2374
  }
2076
- } catch (err) {
2077
- // Don't reject if aborted
2078
- if (abortController.signal.aborted) return void resolve();
2079
- const error = err instanceof Error ? err : new Error(String(err));
2080
- setError(error), handleError(error, String(theme)), reject(error);
2081
- }
2375
+ })();
2082
2376
  }));
2083
2377
  themePromisesRef.current[theme] = themeLoadPromise;
2084
2378
  try {
@@ -2143,6 +2437,17 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
2143
2437
  });
2144
2438
  };
2145
2439
 
2440
+ /**
2441
+ * Theme Provider
2442
+ *
2443
+ * React context provider for theme management with separated concerns.
2444
+ * Simplified version focusing on core functionality:
2445
+ * - String-based themes (CSS files)
2446
+ * - DesignTokens (dynamic themes)
2447
+ * - Persistence via localStorage
2448
+ *
2449
+ * Falls back to 'default' theme if no configuration is found.
2450
+ */
2146
2451
  /**
2147
2452
  * useTheme Hook
2148
2453
  *
@@ -2168,7 +2473,8 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
2168
2473
  * );
2169
2474
  * }
2170
2475
  * ```
2171
- */ function useTheme() {
2476
+ */
2477
+ function useTheme() {
2172
2478
  const context = useContext(ThemeContext);
2173
2479
  if (!context) throw new Error("useTheme must be used within a ThemeProvider");
2174
2480
  return {
@@ -4241,8 +4547,8 @@ function createPaletteColor(color) {
4241
4547
  * @returns Complete theme object
4242
4548
  */
4243
4549
  function createThemeObject(...options) {
4244
- // Merge all options
4245
- const mergedOptions = _reduceInstanceProperty(options).call(options, ((acc, option) => deepMerge(acc, option)), {}), palette = {
4550
+ // Merge all options by spreading them into a single object
4551
+ const mergedOptions = _reduceInstanceProperty(options).call(options, ((acc, option) => deepMerge(acc, option || {})), {}), palette = {
4246
4552
  primary: createPaletteColor(mergedOptions.palette?.primary || DEFAULT_PALETTE.primary),
4247
4553
  secondary: createPaletteColor(mergedOptions.palette?.secondary || DEFAULT_PALETTE.secondary),
4248
4554
  error: createPaletteColor(mergedOptions.palette?.error || DEFAULT_PALETTE.error),
@@ -4427,43 +4733,45 @@ function createThemeObject(...options) {
4427
4733
 
4428
4734
  case "hsl":
4429
4735
  case "hsla":
4430
- // Convert RGB to HSL (simplified)
4431
- const hsl =
4432
- /**
4736
+ {
4737
+ // Convert RGB to HSL (simplified)
4738
+ const hsl =
4739
+ /**
4433
4740
  * Convert RGB to HSL
4434
4741
  */
4435
- function(r, g, b) {
4436
- r /= 255, g /= 255, b /= 255;
4437
- const max = Math.max(r, g, b), min = Math.min(r, g, b);
4438
- let h = 0, s = 0;
4439
- const l = (max + min) / 2;
4440
- if (max !== min) {
4441
- const d = max - min;
4442
- switch (s = l > .5 ? d / (2 - max - min) : d / (max + min), max) {
4443
- case r:
4444
- h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
4445
- break;
4742
+ function(r, g, b) {
4743
+ r /= 255, g /= 255, b /= 255;
4744
+ const max = Math.max(r, g, b), min = Math.min(r, g, b);
4745
+ let h = 0, s = 0;
4746
+ const l = (max + min) / 2;
4747
+ if (max !== min) {
4748
+ const d = max - min;
4749
+ switch (s = l > .5 ? d / (2 - max - min) : d / (max + min), max) {
4750
+ case r:
4751
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
4752
+ break;
4446
4753
 
4447
- case g:
4448
- h = ((b - r) / d + 2) / 6;
4449
- break;
4754
+ case g:
4755
+ h = ((b - r) / d + 2) / 6;
4756
+ break;
4450
4757
 
4451
- case b:
4452
- h = ((r - g) / d + 4) / 6;
4758
+ case b:
4759
+ h = ((r - g) / d + 4) / 6;
4760
+ }
4453
4761
  }
4762
+ return {
4763
+ h: Math.round(360 * h),
4764
+ s: Math.round(100 * s),
4765
+ l: Math.round(100 * l)
4766
+ };
4454
4767
  }
4455
- return {
4456
- h: Math.round(360 * h),
4457
- s: Math.round(100 * s),
4458
- l: Math.round(100 * l)
4459
- };
4460
- }
4461
- /**
4768
+ /**
4462
4769
  * Theme Live Editor Component
4463
4770
  *
4464
4771
  * Allows live editing of theme properties with instant preview
4465
4772
  */ (r, g, b);
4466
- return "hsl" === format ? `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)` : `hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${a})`;
4773
+ return "hsl" === format ? `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)` : `hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${a})`;
4774
+ }
4467
4775
 
4468
4776
  default:
4469
4777
  return color;
@@ -4789,8 +5097,312 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
4789
5097
  children: "\n .atomix-theme-live-editor {\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n background: white;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n\n .editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 24px;\n border-bottom: 1px solid #e0e0e0;\n background: #f5f5f5;\n border-radius: 8px 8px 0 0;\n }\n\n .editor-header h2 {\n margin: 0;\n font-size: 20px;\n color: #333;\n }\n\n .editor-controls {\n display: flex;\n gap: 12px;\n align-items: center;\n }\n\n .history-controls,\n .mode-controls,\n .action-controls {\n display: flex;\n gap: 8px;\n }\n\n .history-button,\n .mode-button,\n .export-button,\n .copy-button {\n padding: 8px 16px;\n border: 1px solid #e0e0e0;\n background: white;\n border-radius: 4px;\n cursor: pointer;\n font-size: 14px;\n transition: all 0.2s;\n }\n\n .history-button:hover:not(:disabled),\n .mode-button:hover,\n .export-button:hover,\n .copy-button:hover {\n background: #f5f5f5;\n }\n\n .history-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .mode-button.active {\n background: #2196f3;\n color: white;\n border-color: #2196f3;\n }\n\n .export-button {\n background: #4caf50;\n color: white;\n border-color: #4caf50;\n }\n\n .copy-button {\n background: #ff9800;\n color: white;\n border-color: #ff9800;\n }\n\n .editor-content {\n display: flex;\n position: relative;\n min-height: 600px;\n }\n\n .editor-panel,\n .preview-panel {\n overflow-y: auto;\n padding: 24px;\n }\n\n .resizer {\n width: 4px;\n background: #e0e0e0;\n cursor: col-resize;\n position: relative;\n flex-shrink: 0;\n transition: background 0.2s;\n }\n\n .resizer:hover,\n .resizer.resizing {\n background: #2196f3;\n }\n\n .resizer::before {\n content: '';\n position: absolute;\n left: -2px;\n right: -2px;\n top: 0;\n bottom: 0;\n }\n\n .editor-panel h3,\n .preview-panel h3 {\n margin: 0 0 16px 0;\n font-size: 16px;\n color: #333;\n border-bottom: 2px solid #2196f3;\n padding-bottom: 8px;\n }\n\n .visual-editor {\n display: flex;\n flex-direction: column;\n gap: 24px;\n }\n\n .editor-section {\n display: flex;\n flex-direction: column;\n gap: 16px;\n }\n\n .color-format-selector {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n }\n\n .color-format-selector label {\n font-size: 14px;\n font-weight: 500;\n color: #666;\n }\n\n .color-format-selector select {\n padding: 6px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n font-size: 14px;\n background: white;\n cursor: pointer;\n }\n\n .editor-field {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .editor-field label {\n font-size: 14px;\n font-weight: 500;\n color: #666;\n }\n\n .color-input-group {\n display: flex;\n gap: 8px;\n align-items: center;\n }\n\n .color-input-group input[type=\"color\"] {\n width: 50px;\n height: 40px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n cursor: pointer;\n }\n\n .color-input-group input[type=\"text\"],\n .editor-field input[type=\"text\"],\n .editor-field input[type=\"number\"] {\n flex: 1;\n padding: 8px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n font-size: 14px;\n font-family: 'Monaco', 'Menlo', monospace;\n }\n\n .json-editor {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n\n .json-editor textarea {\n flex: 1;\n padding: 16px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n font-family: 'Monaco', 'Menlo', monospace;\n font-size: 12px;\n line-height: 1.5;\n resize: none;\n }\n\n .error-message {\n padding: 12px;\n background: #ffebee;\n color: #d32f2f;\n border-radius: 4px;\n margin-top: 8px;\n font-size: 14px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .error-dismiss {\n background: none;\n border: none;\n color: #d32f2f;\n font-size: 20px;\n cursor: pointer;\n padding: 0;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .error-dismiss:hover {\n background: rgba(211, 47, 47, 0.1);\n border-radius: 50%;\n }\n\n .preview-panel {\n border-left: 1px solid #e0e0e0;\n }\n "
4790
5098
  }) ]
4791
5099
  });
5100
+ }, DesignTokensCustomizer = ({initialTokens: initialTokens = {}, onTokensChange: onTokensChange, className: className, style: style}) => {
5101
+ // Current tokens state
5102
+ const [tokens, setTokens] = useState((() => createTokens(initialTokens))), [colorFormat, setColorFormat] = useState("hex"), [activeCategory, setActiveCategory] = useState("colors"), [cssPreview, setCssPreview] = useState("");
5103
+ // Generate CSS when tokens change
5104
+ useEffect((() => {
5105
+ const css = createTheme(tokens, {
5106
+ selector: ":root",
5107
+ prefix: "atomix-preview"
5108
+ });
5109
+ setCssPreview(css), onTokensChange?.(tokens);
5110
+ }), [ tokens, onTokensChange ]);
5111
+ // Create theme object for preview
5112
+ const previewTheme = useMemo((() => createThemeObject({
5113
+ palette: {
5114
+ primary: {
5115
+ main: tokens.primary
5116
+ },
5117
+ secondary: {
5118
+ main: tokens.secondary
5119
+ },
5120
+ error: {
5121
+ main: tokens.error
5122
+ },
5123
+ warning: {
5124
+ main: tokens.warning
5125
+ },
5126
+ info: {
5127
+ main: tokens.info
5128
+ },
5129
+ success: {
5130
+ main: tokens.success
5131
+ },
5132
+ background: {
5133
+ default: "#ffffff",
5134
+ subtle: tokens["secondary-bg-subtle"] || "#f3f4f6"
5135
+ },
5136
+ text: {
5137
+ primary: tokens["primary-text-emphasis"] || "#111827",
5138
+ secondary: tokens["secondary-text-emphasis"] || "#374151",
5139
+ disabled: tokens["disabled-text-emphasis"] || "#9ca3af"
5140
+ }
5141
+ },
5142
+ typography: {
5143
+ fontFamily: tokens["body-font-family"] || '"Roboto", sans-serif',
5144
+ fontSize: parseInt(tokens["body-font-size"] || "16")
5145
+ },
5146
+ spacing: factor => .25 * factor + "rem"
5147
+ })), [ tokens ]), updateToken = useCallback(((key, value) => {
5148
+ setTokens((prev => ({
5149
+ ...prev,
5150
+ [key]: value
5151
+ })));
5152
+ }), []), convertColorFormat = useCallback(((color, format) => {
5153
+ // Parse current color
5154
+ const temp = document.createElement("div");
5155
+ temp.style.color = color, document.body.appendChild(temp);
5156
+ const computed = window.getComputedStyle(temp).color;
5157
+ document.body.removeChild(temp);
5158
+ const rgbMatch = computed.match(/\d+/g);
5159
+ if (!rgbMatch || rgbMatch.length < 3) return color;
5160
+ const r = parseInt(rgbMatch[0] || "0", 10), g = parseInt(rgbMatch[1] || "0", 10), b = parseInt(rgbMatch[2] || "0", 10), a = rgbMatch[3] ? parseFloat(rgbMatch[3]) : 1;
5161
+ switch (format) {
5162
+ case "hex":
5163
+ return `#${[ r, g, b ].map((x => x.toString(16).padStart(2, "0"))).join("")}`;
5164
+
5165
+ case "rgb":
5166
+ return `rgb(${r}, ${g}, ${b})`;
5167
+
5168
+ case "rgba":
5169
+ return `rgba(${r}, ${g}, ${b}, ${a})`;
5170
+
5171
+ case "hsl":
5172
+ case "hsla":
5173
+ {
5174
+ const hsl =
5175
+ // RGB to HSL conversion
5176
+ function(r, g, b) {
5177
+ r /= 255, g /= 255, b /= 255;
5178
+ const max = Math.max(r, g, b), min = Math.min(r, g, b);
5179
+ let h = 0, s = 0;
5180
+ const l = (max + min) / 2;
5181
+ if (max !== min) {
5182
+ const d = max - min;
5183
+ switch (s = l > .5 ? d / (2 - max - min) : d / (max + min), max) {
5184
+ case r:
5185
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
5186
+ break;
5187
+
5188
+ case g:
5189
+ h = ((b - r) / d + 2) / 6;
5190
+ break;
5191
+
5192
+ case b:
5193
+ h = ((r - g) / d + 4) / 6;
5194
+ }
5195
+ }
5196
+ return {
5197
+ h: Math.round(360 * h),
5198
+ s: Math.round(100 * s),
5199
+ l: Math.round(100 * l)
5200
+ };
5201
+ }
5202
+ // Export functions
5203
+ (r, g, b);
5204
+ return "hsl" === format ? `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)` : `hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${a})`;
5205
+ }
5206
+
5207
+ default:
5208
+ return color;
5209
+ }
5210
+ }), []), exportTokens = useCallback((() => {
5211
+ const dataStr = JSON.stringify(tokens, null, 2), dataUri = "data:application/json;charset=utf-8," + encodeURIComponent(dataStr), linkElement = document.createElement("a");
5212
+ linkElement.setAttribute("href", dataUri), linkElement.setAttribute("download", "design-tokens.json"),
5213
+ linkElement.click();
5214
+ }), [ tokens ]), exportTheme = useCallback((() => {
5215
+ const themeCss = createTheme(tokens), dataUri = "data:text/css;charset=utf-8," + encodeURIComponent(themeCss), linkElement = document.createElement("a");
5216
+ linkElement.setAttribute("href", dataUri), linkElement.setAttribute("download", "theme.css"),
5217
+ linkElement.click();
5218
+ }), [ tokens ]), copyToClipboard = useCallback((() => {
5219
+ navigator.clipboard?.writeText(JSON.stringify(tokens, null, 2));
5220
+ }), [ tokens ]), resetToDefaults = useCallback((() => {
5221
+ setTokens(defaultTokens);
5222
+ }), []), loadTokensFromFile = useCallback((event => {
5223
+ const file = event.target.files?.[0];
5224
+ if (!file) return;
5225
+ const reader = new FileReader;
5226
+ reader.onload = e => {
5227
+ try {
5228
+ const content = e.target?.result, mergedTokens = createTokens(JSON.parse(content));
5229
+ setTokens(mergedTokens);
5230
+ } catch (error) {
5231
+ console.error("Failed to load tokens:", error), alert("Invalid JSON file. Please select a valid design tokens JSON file.");
5232
+ }
5233
+ }, reader.readAsText(file);
5234
+ }), []), tokenCategories = {
5235
+ colors: {
5236
+ label: "Colors",
5237
+ tokens: [
5238
+ // Base colors
5239
+ "primary", "secondary", "success", "info", "warning", "error", "light", "dark",
5240
+ // RGB versions
5241
+ "primary-rgb", "secondary-rgb", "success-rgb", "info-rgb", "warning-rgb", "error-rgb", "light-rgb", "dark-rgb",
5242
+ // Gray scale
5243
+ "gray-1", "gray-2", "gray-3", "gray-4", "gray-5", "gray-6", "gray-7", "gray-8", "gray-9", "gray-10",
5244
+ // Primary scale
5245
+ "primary-1", "primary-2", "primary-3", "primary-4", "primary-5", "primary-6", "primary-7", "primary-8", "primary-9", "primary-10",
5246
+ // Text emphasis
5247
+ "primary-text-emphasis", "secondary-text-emphasis", "tertiary-text-emphasis", "disabled-text-emphasis", "invert-text-emphasis", "brand-text-emphasis", "error-text-emphasis", "success-text-emphasis", "warning-text-emphasis", "info-text-emphasis", "light-text-emphasis", "dark-text-emphasis",
5248
+ // Background subtle
5249
+ "primary-bg-subtle", "secondary-bg-subtle", "tertiary-bg-subtle", "invert-bg-subtle", "brand-bg-subtle", "error-bg-subtle", "success-bg-subtle", "warning-bg-subtle", "info-bg-subtle", "light-bg-subtle", "dark-bg-subtle",
5250
+ // Border subtle
5251
+ "primary-border-subtle", "secondary-border-subtle", "success-border-subtle", "error-border-subtle", "warning-border-subtle", "info-border-subtle", "brand-border-subtle", "light-border-subtle", "dark-border-subtle",
5252
+ // Hover states
5253
+ "primary-hover", "secondary-hover", "light-hover", "dark-hover", "error-hover", "success-hover", "warning-hover", "info-hover",
5254
+ // Gradients
5255
+ "primary-gradient", "secondary-gradient", "light-gradient", "dark-gradient", "success-gradient", "info-gradient", "warning-gradient", "error-gradient", "gradient" ]
5256
+ },
5257
+ typography: {
5258
+ label: "Typography",
5259
+ tokens: [ "font-sans-serif", "font-monospace", "body-font-family", "body-font-size", "body-font-weight", "body-line-height", "body-color", "body-bg", "heading-color", "font-size-xl", "font-size-2xl", "display-1", "font-weight-light", "font-weight-normal", "font-weight-medium", "font-weight-semibold", "font-weight-bold", "font-weight-heavy", "font-weight-black", "line-height-base", "line-height-sm", "line-height-lg", "letter-spacing-h1", "letter-spacing-h2", "letter-spacing-h3", "letter-spacing-h4", "letter-spacing-h5", "letter-spacing-h6", "link-color", "link-color-rgb", "link-decoration", "link-hover-color", "link-hover-color-rgb", "highlight-bg", "code-color" ]
5260
+ },
5261
+ spacing: {
5262
+ label: "Spacing",
5263
+ tokens: [ "spacing-0", "spacing-1", "spacing-px-6", "spacing-2", "spacing-px-10", "spacing-3", "spacing-px-14", "spacing-4", "spacing-5", "spacing-px-22", "spacing-6", "spacing-7", "spacing-px-30", "spacing-8", "spacing-9", "spacing-10", "spacing-11", "spacing-12", "spacing-14", "spacing-16", "spacing-20", "spacing-24", "spacing-28", "spacing-32", "spacing-36", "spacing-40", "spacing-44", "spacing-48", "spacing-52", "spacing-56", "spacing-60", "spacing-64", "spacing-72", "spacing-80", "spacing-90", "spacing-200" ]
5264
+ },
5265
+ shadows: {
5266
+ label: "Shadows",
5267
+ tokens: [ "box-shadow", "box-shadow-xs", "box-shadow-sm", "box-shadow-lg", "box-shadow-xl", "box-shadow-inset" ]
5268
+ },
5269
+ borders: {
5270
+ label: "Borders",
5271
+ tokens: [ "border-width", "border-style", "border-color", "border-color-translucent", "border-radius", "border-radius-sm", "border-radius-lg", "border-radius-xl", "border-radius-xxl", "border-radius-2xl", "border-radius-3xl", "border-radius-4xl", "border-radius-pill", "focus-border-color", "focus-ring-width", "focus-ring-offset", "focus-ring-opacity", "form-valid-color", "form-valid-border-color", "form-invalid-color", "form-invalid-border-color" ]
5272
+ },
5273
+ transitions: {
5274
+ label: "Transitions",
5275
+ tokens: [ "transition-duration-fast", "transition-duration-base", "transition-duration-slow", "transition-duration-slower", "easing-base", "easing-ease-in-out", "easing-ease-out", "easing-ease-in", "easing-ease-linear", "transition-fast", "transition-base", "transition-slow" ]
5276
+ },
5277
+ zindex: {
5278
+ label: "Z-Index",
5279
+ tokens: [ "z-n1", "z-0", "z-1", "z-2", "z-3", "z-4", "z-5", "z-dropdown", "z-sticky", "z-fixed", "z-modal", "z-popover", "z-tooltip", "z-drawer" ]
5280
+ },
5281
+ breakpoints: {
5282
+ label: "Breakpoints",
5283
+ tokens: [ "breakpoint-xs", "breakpoint-sm", "breakpoint-md", "breakpoint-lg", "breakpoint-xl", "breakpoint-xxl" ]
5284
+ }
5285
+ };
5286
+ // Update token value
5287
+ return jsxs("div", {
5288
+ className: `design-tokens-customizer ${className || ""}`,
5289
+ style: style,
5290
+ children: [ jsxs("div", {
5291
+ className: "customizer-header",
5292
+ children: [ jsx("h2", {
5293
+ children: "Interactive Theme Customizer"
5294
+ }), jsxs("div", {
5295
+ className: "customizer-controls",
5296
+ children: [ jsxs("select", {
5297
+ value: colorFormat,
5298
+ onChange: e => setColorFormat(e.target.value),
5299
+ children: [ jsx("option", {
5300
+ value: "hex",
5301
+ children: "HEX"
5302
+ }), jsx("option", {
5303
+ value: "rgb",
5304
+ children: "RGB"
5305
+ }), jsx("option", {
5306
+ value: "rgba",
5307
+ children: "RGBA"
5308
+ }), jsx("option", {
5309
+ value: "hsl",
5310
+ children: "HSL"
5311
+ }), jsx("option", {
5312
+ value: "hsla",
5313
+ children: "HSLA"
5314
+ }) ]
5315
+ }), jsx("button", {
5316
+ onClick: resetToDefaults,
5317
+ children: "Reset to Defaults"
5318
+ }), jsxs("label", {
5319
+ className: "file-input-button",
5320
+ children: [ "Load Tokens", jsx("input", {
5321
+ type: "file",
5322
+ accept: ".json",
5323
+ onChange: loadTokensFromFile,
5324
+ style: {
5325
+ display: "none"
5326
+ }
5327
+ }) ]
5328
+ }), jsx("button", {
5329
+ onClick: copyToClipboard,
5330
+ children: "Copy Tokens"
5331
+ }), jsx("button", {
5332
+ onClick: exportTokens,
5333
+ children: "Export Tokens"
5334
+ }), jsx("button", {
5335
+ onClick: exportTheme,
5336
+ children: "Export Theme CSS"
5337
+ }) ]
5338
+ }) ]
5339
+ }), jsxs("div", {
5340
+ className: "customizer-content",
5341
+ children: [ jsx("div", {
5342
+ className: "customizer-sidebar",
5343
+ children: Object.entries(tokenCategories).map((([key, category]) => jsx("button", {
5344
+ className: "category-button " + (activeCategory === key ? "active" : ""),
5345
+ onClick: () => setActiveCategory(key),
5346
+ children: category.label
5347
+ }, key)))
5348
+ }), jsxs("div", {
5349
+ className: "customizer-editor",
5350
+ children: [ jsx("h3", {
5351
+ children: tokenCategories[activeCategory].label
5352
+ }), jsx("div", {
5353
+ className: "tokens-grid",
5354
+ children: tokenCategories[activeCategory].tokens.map((tokenKey => {
5355
+ var _context;
5356
+ const value = tokens[tokenKey] || "", isColor = _includesInstanceProperty(tokenKey).call(tokenKey, "color") || _includesInstanceProperty(tokenKey).call(tokenKey, "bg") || _includesInstanceProperty(tokenKey).call(tokenKey, "gradient") || _includesInstanceProperty(_context = [ "primary", "secondary", "success", "info", "warning", "error", "light", "dark" ]).call(_context, tokenKey) || tokenKey.match(/^(gray|primary|red|green|blue|yellow)-\d+$/);
5357
+ return jsxs("div", {
5358
+ className: "token-item",
5359
+ children: [ jsx("label", {
5360
+ children: tokenKey
5361
+ }), isColor ? jsxs("div", {
5362
+ className: "color-input-group",
5363
+ children: [ jsx("input", {
5364
+ type: "color",
5365
+ value: value.startsWith("#") ? value : convertColorFormat(value, "hex"),
5366
+ onChange: e => updateToken(tokenKey, e.target.value)
5367
+ }), jsx("input", {
5368
+ type: "text",
5369
+ value: convertColorFormat(value, colorFormat),
5370
+ onChange: e => {
5371
+ const converted = convertColorFormat(e.target.value, "hex");
5372
+ updateToken(tokenKey, converted);
5373
+ }
5374
+ }) ]
5375
+ }) : jsx("input", {
5376
+ type: "text",
5377
+ value: value,
5378
+ onChange: e => updateToken(tokenKey, e.target.value)
5379
+ }) ]
5380
+ }, tokenKey);
5381
+ }))
5382
+ }) ]
5383
+ }), jsxs("div", {
5384
+ className: "customizer-preview",
5385
+ children: [ jsx("h3", {
5386
+ children: "Live Preview"
5387
+ }), jsx("style", {
5388
+ children: cssPreview
5389
+ }), jsx(ThemePreview, {
5390
+ theme: previewTheme,
5391
+ showDetails: !1,
5392
+ showPalette: !0,
5393
+ showTypography: !0,
5394
+ showSpacing: !0
5395
+ }) ]
5396
+ }) ]
5397
+ }), jsx("style", {
5398
+ children: "\n .design-tokens-customizer {\n display: flex;\n flex-direction: column;\n height: 100vh;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n\n .customizer-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 24px;\n border-bottom: 1px solid #e0e0e0;\n background: #f5f5f5;\n }\n\n .customizer-header h2 {\n margin: 0;\n font-size: 24px;\n color: #333;\n }\n\n .customizer-controls {\n display: flex;\n gap: 8px;\n align-items: center;\n }\n\n .customizer-controls select,\n .customizer-controls button {\n padding: 8px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n }\n\n .customizer-controls button:hover,\n .file-input-button:hover {\n background: #f0f0f0;\n }\n\n .file-input-button {\n padding: 8px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n font-size: 14px;\n display: inline-block;\n }\n\n .customizer-content {\n display: flex;\n flex: 1;\n overflow: hidden;\n }\n\n .customizer-sidebar {\n width: 200px;\n border-right: 1px solid #e0e0e0;\n padding: 16px;\n background: #fafafa;\n overflow-y: auto;\n }\n\n .category-button {\n display: block;\n width: 100%;\n padding: 12px;\n margin-bottom: 8px;\n border: none;\n background: white;\n border-radius: 4px;\n cursor: pointer;\n text-align: left;\n font-size: 14px;\n }\n\n .category-button:hover,\n .category-button.active {\n background: #e0e0e0;\n }\n\n .customizer-editor {\n flex: 1;\n padding: 24px;\n overflow-y: auto;\n }\n\n .customizer-editor h3 {\n margin-top: 0;\n margin-bottom: 16px;\n color: #333;\n }\n\n .tokens-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 16px;\n }\n\n .token-item {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .token-item label {\n font-size: 14px;\n font-weight: 500;\n color: #666;\n }\n\n .color-input-group {\n display: flex;\n gap: 8px;\n align-items: center;\n }\n\n .color-input-group input[type=\"color\"] {\n width: 50px;\n height: 40px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n cursor: pointer;\n }\n\n .color-input-group input[type=\"text\"],\n .token-item input[type=\"text\"] {\n flex: 1;\n padding: 8px 12px;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n font-size: 14px;\n font-family: 'Monaco', 'Menlo', monospace;\n }\n\n .customizer-preview {\n width: 400px;\n border-left: 1px solid #e0e0e0;\n padding: 24px;\n overflow-y: auto;\n background: #fafafa;\n }\n\n .customizer-preview h3 {\n margin-top: 0;\n margin-bottom: 16px;\n color: #333;\n }\n "
5399
+ }) ]
5400
+ });
4792
5401
  };
4793
5402
 
5403
+ /**
5404
+ * Design Tokens Customizer Component
5405
+ */
4794
5406
  /**
4795
5407
  * Theme Adapter
4796
5408
  *
@@ -4801,7 +5413,8 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
4801
5413
  *
4802
5414
  * @param tokens - DesignTokens object
4803
5415
  * @returns CSS variables object compatible with Theme.cssVars
4804
- */ function designTokensToCSSVars(tokens) {
5416
+ */
5417
+ function designTokensToCSSVars(tokens) {
4805
5418
  const cssVars = {};
4806
5419
  return Object.entries(tokens).forEach((([key, value]) => {
4807
5420
  void 0 !== value && (cssVars[`--atomix-${key}`] = String(value));
@@ -5149,5 +5762,5 @@ class RTLManager {
5149
5762
  removeCSS(id);
5150
5763
  }
5151
5764
 
5152
- export { RTLManager, ThemeApplicator, ThemeComparator, ThemeContext, ThemeErrorBoundary, ThemeInspector, ThemeLiveEditor, ThemePreview, ThemeProvider, ThemeValidator, applyCSSVariables, applyComponentTheme, applyTheme, camelToKebab, clearThemes, createTheme, createThemeRegistry, createTokens, cssVarsToStyle, deepMerge, defaultTokens, designTokensToCSSVars, extendTheme, extractComponentName, generateCSSVariableName, generateCSSVariables$1 as generateCSSVariables, generateCSSVariablesForSelector, generateClassName, generateComponentCSSVars, getAllThemes, getCSSVariable, getComponentThemeValue, getTheme, getThemeApplicator, getThemeCount, getThemeIds, hasTheme, injectCSS$1 as injectCSS, injectTheme, isCSSInjected, isDesignTokens, isValidCSSVariableName, mapSCSSTokensToCSSVars, mergeCSSVars, mergeTheme, normalizeThemeTokens, registerTheme, removeCSS, removeCSSVariables, removeTheme, themePropertyToCSSVar, unregisterTheme, useComponentTheme, useHistory, useTheme, useThemeTokens };
5765
+ export { DesignTokensCustomizer, RTLManager, ThemeApplicator, ThemeComparator, ThemeContext, ThemeErrorBoundary, ThemeInspector, ThemeLiveEditor, ThemePreview, ThemeProvider, ThemeValidator, applyCSSVariables, applyComponentTheme, applyTheme, camelToKebab, clearThemes, createTheme, createThemeRegistry, createTokens, cssVarsToStyle, deepMerge, defaultTokens, designTokensToCSSVars, extendTheme, extractComponentName, generateCSSVariableName, generateCSSVariables$1 as generateCSSVariables, generateCSSVariablesForSelector, generateClassName, generateComponentCSSVars, getAllThemes, getCSSVariable, getComponentThemeValue, getTheme, getThemeApplicator, getThemeCount, getThemeIds, hasTheme, injectCSS$1 as injectCSS, injectTheme, isCSSInjected, isDesignTokens, isValidCSSVariableName, mapSCSSTokensToCSSVars, mergeCSSVars, mergeTheme, normalizeThemeTokens, registerTheme, removeCSS, removeCSSVariables, removeTheme, themePropertyToCSSVar, unregisterTheme, useComponentTheme, useHistory, useTheme, useThemeTokens };
5153
5766
  //# sourceMappingURL=theme.js.map