@shohojdhara/atomix 0.3.7 → 0.3.9

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 (53) hide show
  1. package/CHANGELOG.md +19 -1
  2. package/dist/atomix.css +77 -0
  3. package/dist/atomix.css.map +1 -1
  4. package/dist/atomix.min.css +77 -0
  5. package/dist/atomix.min.css.map +1 -1
  6. package/dist/charts.js.map +1 -1
  7. package/dist/core.js.map +1 -1
  8. package/dist/forms.js.map +1 -1
  9. package/dist/heavy.js.map +1 -1
  10. package/dist/index.d.ts +578 -515
  11. package/dist/index.esm.js +3150 -2632
  12. package/dist/index.esm.js.map +1 -1
  13. package/dist/index.js +10485 -9973
  14. package/dist/index.js.map +1 -1
  15. package/dist/index.min.js +1 -1
  16. package/dist/index.min.js.map +1 -1
  17. package/dist/theme.d.ts +237 -420
  18. package/dist/theme.js +1616 -1701
  19. package/dist/theme.js.map +1 -1
  20. package/package.json +1 -1
  21. package/src/components/DataTable/DataTable.stories.tsx +238 -0
  22. package/src/components/DataTable/DataTable.test.tsx +450 -0
  23. package/src/components/DataTable/DataTable.tsx +384 -61
  24. package/src/components/DatePicker/DatePicker.tsx +29 -38
  25. package/src/components/Upload/Upload.tsx +539 -40
  26. package/src/lib/composables/useDataTable.ts +355 -15
  27. package/src/lib/composables/useDatePicker.ts +19 -0
  28. package/src/lib/constants/components.ts +10 -0
  29. package/src/lib/theme/adapters/cssVariableMapper.ts +29 -14
  30. package/src/lib/theme/adapters/index.ts +1 -4
  31. package/src/lib/theme/config/configLoader.ts +53 -35
  32. package/src/lib/theme/core/composeTheme.ts +22 -30
  33. package/src/lib/theme/core/createTheme.ts +49 -26
  34. package/src/lib/theme/core/index.ts +0 -1
  35. package/src/lib/theme/generators/generateCSSNested.ts +4 -3
  36. package/src/lib/theme/generators/generateCSSVariables.ts +24 -16
  37. package/src/lib/theme/index.ts +10 -17
  38. package/src/lib/theme/runtime/ThemeApplicator.ts +6 -109
  39. package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +3 -3
  40. package/src/lib/theme/runtime/ThemeProvider.tsx +205 -64
  41. package/src/lib/theme/runtime/useTheme.ts +1 -1
  42. package/src/lib/theme/runtime/useThemeTokens.ts +7 -16
  43. package/src/lib/theme/test/testTheme.ts +2 -1
  44. package/src/lib/theme/types.ts +14 -14
  45. package/src/lib/theme/utils/componentTheming.ts +35 -27
  46. package/src/lib/theme/utils/domUtils.ts +57 -15
  47. package/src/lib/theme/utils/injectCSS.ts +0 -1
  48. package/src/lib/theme/utils/themeHelpers.ts +1 -39
  49. package/src/lib/theme/utils/themeUtils.ts +1 -170
  50. package/src/lib/types/components.ts +145 -0
  51. package/src/lib/utils/dataTableExport.ts +143 -0
  52. package/src/styles/06-components/_components.data-table.scss +95 -0
  53. package/src/lib/hooks/useThemeTokens.ts +0 -105
package/dist/theme.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { loadAtomixConfig } from "../lib/config/loader";
2
+
1
3
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
4
 
3
5
  import { createContext, useRef, useEffect, useCallback, useMemo, useState, useContext, Component } from "react";
@@ -375,1386 +377,1046 @@ import { createContext, useRef, useEffect, useCallback, useMemo, useState, useCo
375
377
  });
376
378
  }
377
379
 
378
- var commonjsGlobal = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {};
380
+ /**
381
+ * Theme System Error Handling
382
+ *
383
+ * Centralized error handling for the Atomix theme system.
384
+ * Provides custom error classes and logging utilities.
385
+ */
386
+ /**
387
+ * Theme error codes
388
+ */ var ThemeErrorCode, LogLevel;
379
389
 
380
- function getDefaultExportFromCjs(x) {
381
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x.default : x;
382
- }
390
+ !function(ThemeErrorCode) {
391
+ /** Theme not found in registry */
392
+ ThemeErrorCode.THEME_NOT_FOUND = "THEME_NOT_FOUND",
393
+ /** Theme failed to load */
394
+ ThemeErrorCode.THEME_LOAD_FAILED = "THEME_LOAD_FAILED",
395
+ /** Theme validation failed */
396
+ ThemeErrorCode.THEME_VALIDATION_FAILED = "THEME_VALIDATION_FAILED",
397
+ /** Configuration loading failed */
398
+ ThemeErrorCode.CONFIG_LOAD_FAILED = "CONFIG_LOAD_FAILED",
399
+ /** Configuration validation failed */
400
+ ThemeErrorCode.CONFIG_VALIDATION_FAILED = "CONFIG_VALIDATION_FAILED",
401
+ /** Circular dependency detected */
402
+ ThemeErrorCode.CIRCULAR_DEPENDENCY = "CIRCULAR_DEPENDENCY",
403
+ /** Missing dependency */
404
+ ThemeErrorCode.MISSING_DEPENDENCY = "MISSING_DEPENDENCY",
405
+ /** Storage operation failed */
406
+ ThemeErrorCode.STORAGE_ERROR = "STORAGE_ERROR",
407
+ /** Invalid theme name */
408
+ ThemeErrorCode.INVALID_THEME_NAME = "INVALID_THEME_NAME",
409
+ /** CSS injection failed */
410
+ ThemeErrorCode.CSS_INJECTION_FAILED = "CSS_INJECTION_FAILED",
411
+ /** Unknown error */
412
+ ThemeErrorCode.UNKNOWN_ERROR = "UNKNOWN_ERROR";
413
+ }(ThemeErrorCode || (ThemeErrorCode = {}));
383
414
 
384
- var fails$9 = function(exec) {
385
- try {
386
- return !!exec();
387
- } catch (error) {
388
- return !0;
415
+ /**
416
+ * Custom error class for theme-related errors
417
+ */
418
+ class ThemeError extends Error {
419
+ constructor(message, code = ThemeErrorCode.UNKNOWN_ERROR, context) {
420
+ super(message), this.name = "ThemeError", this.code = code, this.context = context,
421
+ this.timestamp = Date.now(),
422
+ // Maintains proper stack trace for where our error was thrown (only available on V8)
423
+ Error.captureStackTrace && Error.captureStackTrace(this, ThemeError);
389
424
  }
390
- }, functionBindNative = !fails$9((function() {
391
- // eslint-disable-next-line es/no-function-prototype-bind -- safe
392
- var test = function() {/* empty */}.bind();
393
- // eslint-disable-next-line no-prototype-builtins -- safe
394
- return "function" != typeof test || test.hasOwnProperty("prototype");
395
- })), NATIVE_BIND$3 = functionBindNative, FunctionPrototype$1 = Function.prototype, call$5 = FunctionPrototype$1.call, uncurryThisWithBind = NATIVE_BIND$3 && FunctionPrototype$1.bind.bind(call$5, call$5), functionUncurryThis = NATIVE_BIND$3 ? uncurryThisWithBind : function(fn) {
396
- return function() {
397
- return call$5.apply(fn, arguments);
398
- };
399
- }, objectIsPrototypeOf = functionUncurryThis({}.isPrototypeOf), check = function(it) {
400
- return it && it.Math === Math && it;
401
- }, globalThis_1 =
402
- // eslint-disable-next-line es/no-global-this -- safe
403
- check("object" == typeof globalThis && globalThis) || check("object" == typeof window && window) ||
404
- // eslint-disable-next-line no-restricted-globals -- safe
405
- check("object" == typeof self && self) || check("object" == typeof commonjsGlobal && commonjsGlobal) || check("object" == typeof commonjsGlobal && commonjsGlobal) ||
406
- // eslint-disable-next-line no-new-func -- fallback
407
- function() {
408
- return this;
409
- }() || Function("return this")(), NATIVE_BIND$2 = functionBindNative, FunctionPrototype = Function.prototype, apply$1 = FunctionPrototype.apply, call$4 = FunctionPrototype.call, functionApply = "object" == typeof Reflect && Reflect.apply || (NATIVE_BIND$2 ? call$4.bind(apply$1) : function() {
410
- return call$4.apply(apply$1, arguments);
411
- }), uncurryThis$7 = functionUncurryThis, toString$3 = uncurryThis$7({}.toString), stringSlice = uncurryThis$7("".slice), classofRaw$2 = function(it) {
412
- return stringSlice(toString$3(it), 8, -1);
413
- }, classofRaw$1 = classofRaw$2, uncurryThis$6 = functionUncurryThis, functionUncurryThisClause = function(fn) {
414
- // Nashorn bug:
415
- // https://github.com/zloirock/core-js/issues/1128
416
- // https://github.com/zloirock/core-js/issues/1130
417
- if ("Function" === classofRaw$1(fn)) return uncurryThis$6(fn);
418
- }, documentAll = "object" == typeof document && document.all, isCallable$8 = void 0 === documentAll && void 0 !== documentAll ? function(argument) {
419
- return "function" == typeof argument || argument === documentAll;
420
- } : function(argument) {
421
- return "function" == typeof argument;
422
- }, objectGetOwnPropertyDescriptor = {}, descriptors = !fails$9((function() {
423
- // eslint-disable-next-line es/no-object-defineproperty -- required for testing
424
- return 7 !== Object.defineProperty({}, 1, {
425
- get: function() {
426
- return 7;
427
- }
428
- })[1];
429
- })), NATIVE_BIND$1 = functionBindNative, call$3 = Function.prototype.call, functionCall = NATIVE_BIND$1 ? call$3.bind(call$3) : function() {
430
- return call$3.apply(call$3, arguments);
431
- }, objectPropertyIsEnumerable = {}, $propertyIsEnumerable = {}.propertyIsEnumerable, getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor, NASHORN_BUG = getOwnPropertyDescriptor$1 && !$propertyIsEnumerable.call({
432
- 1: 2
433
- }, 1);
434
-
435
- // `Object.prototype.propertyIsEnumerable` method implementation
436
- // https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
437
- objectPropertyIsEnumerable.f = NASHORN_BUG ? function(V) {
438
- var descriptor = getOwnPropertyDescriptor$1(this, V);
439
- return !!descriptor && descriptor.enumerable;
440
- } : $propertyIsEnumerable;
441
-
442
- var match, version, createPropertyDescriptor$2 = function(bitmap, value) {
443
- return {
444
- enumerable: !(1 & bitmap),
445
- configurable: !(2 & bitmap),
446
- writable: !(4 & bitmap),
447
- value: value
448
- };
449
- }, fails$6 = fails$9, classof$4 = classofRaw$2, $Object$3 = Object, split = functionUncurryThis("".split), indexedObject = fails$6((function() {
450
- // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
451
- // eslint-disable-next-line no-prototype-builtins -- safe
452
- return !$Object$3("z").propertyIsEnumerable(0);
453
- })) ? function(it) {
454
- return "String" === classof$4(it) ? split(it, "") : $Object$3(it);
455
- } : $Object$3, isNullOrUndefined$2 = function(it) {
456
- return null == it;
457
- }, isNullOrUndefined$1 = isNullOrUndefined$2, $TypeError$7 = TypeError, requireObjectCoercible$3 = function(it) {
458
- if (isNullOrUndefined$1(it)) throw new $TypeError$7("Can't call method on " + it);
459
- return it;
460
- }, IndexedObject$1 = indexedObject, requireObjectCoercible$2 = requireObjectCoercible$3, toIndexedObject$2 = function(it) {
461
- return IndexedObject$1(requireObjectCoercible$2(it));
462
- }, isCallable$7 = isCallable$8, isObject$6 = function(it) {
463
- return "object" == typeof it ? null !== it : isCallable$7(it);
464
- }, path$3 = {}, path$2 = path$3, globalThis$b = globalThis_1, isCallable$6 = isCallable$8, aFunction = function(variable) {
465
- return isCallable$6(variable) ? variable : void 0;
466
- }, navigator$1 = globalThis_1.navigator, userAgent$2 = navigator$1 && navigator$1.userAgent, environmentUserAgent = userAgent$2 ? String(userAgent$2) : "", globalThis$9 = globalThis_1, userAgent$1 = environmentUserAgent, process$1 = globalThis$9.process, Deno$1 = globalThis$9.Deno, versions = process$1 && process$1.versions || Deno$1 && Deno$1.version, v8 = versions && versions.v8;
425
+ /**
426
+ * Convert error to JSON for logging
427
+ */ toJSON() {
428
+ return {
429
+ name: this.name,
430
+ message: this.message,
431
+ code: this.code,
432
+ context: this.context,
433
+ timestamp: this.timestamp,
434
+ stack: this.stack
435
+ };
436
+ }
437
+ }
467
438
 
468
- v8 && (
469
- // in old Chrome, versions of V8 isn't V8 = Chrome / 10
470
- // but their correct versions are not interesting for us
471
- version = (match = v8.split("."))[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1])),
472
- // BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
473
- // so check `userAgent` even if `.v8` exists, but 0
474
- !version && userAgent$1 && (!(match = userAgent$1.match(/Edge\/(\d+)/)) || match[1] >= 74) && (match = userAgent$1.match(/Chrome\/(\d+)/)) && (version = +match[1]);
439
+ /**
440
+ * Log level
441
+ */ !function(LogLevel) {
442
+ LogLevel[LogLevel.ERROR = 0] = "ERROR", LogLevel[LogLevel.WARN = 1] = "WARN", LogLevel[LogLevel.INFO = 2] = "INFO",
443
+ LogLevel[LogLevel.DEBUG = 3] = "DEBUG";
444
+ }(LogLevel || (LogLevel = {}));
475
445
 
476
- var environmentV8Version = version, V8_VERSION = environmentV8Version, fails$5 = fails$9, $String$3 = globalThis_1.String, symbolConstructorDetection = !!Object.getOwnPropertySymbols && !fails$5((function() {
477
- var symbol = Symbol("symbol detection");
478
- // Chrome 38 Symbol has incorrect toString conversion
479
- // `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
480
- // nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will,
481
- // of course, fail.
482
- return !$String$3(symbol) || !(Object(symbol) instanceof Symbol) ||
483
- // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
484
- !Symbol.sham && V8_VERSION && V8_VERSION < 41;
485
- })), useSymbolAsUid = symbolConstructorDetection && !Symbol.sham && "symbol" == typeof Symbol.iterator, isCallable$5 = isCallable$8, isPrototypeOf$2 = objectIsPrototypeOf, $Object$2 = Object, isSymbol$2 = useSymbolAsUid ? function(it) {
486
- return "symbol" == typeof it;
487
- } : function(it) {
488
- var $Symbol = function(namespace, method) {
489
- return arguments.length < 2 ? aFunction(path$2[namespace]) || aFunction(globalThis$b[namespace]) : path$2[namespace] && path$2[namespace][method] || globalThis$b[namespace] && globalThis$b[namespace][method];
490
- }("Symbol");
491
- return isCallable$5($Symbol) && isPrototypeOf$2($Symbol.prototype, $Object$2(it));
492
- }, $String$2 = String, isCallable$4 = isCallable$8, $TypeError$6 = TypeError, aCallable$3 = function(argument) {
493
- if (isCallable$4(argument)) return argument;
494
- throw new $TypeError$6(function(argument) {
495
- try {
496
- return $String$2(argument);
497
- } catch (error) {
498
- return "Object";
499
- }
500
- }(argument) + " is not a function");
501
- }, aCallable$2 = aCallable$3, isNullOrUndefined = isNullOrUndefined$2, call$2 = functionCall, isCallable$3 = isCallable$8, isObject$5 = isObject$6, $TypeError$5 = TypeError, sharedStore = {
502
- exports: {}
503
- }, globalThis$7 = globalThis_1, defineProperty = Object.defineProperty, globalThis$6 = globalThis_1, store$1 = sharedStore.exports = globalThis$6["__core-js_shared__"] || function(key, value) {
504
- try {
505
- defineProperty(globalThis$7, key, {
506
- value: value,
507
- configurable: !0,
508
- writable: !0
509
- });
510
- } catch (error) {
511
- globalThis$7[key] = value;
446
+ /**
447
+ * Theme Logger
448
+ *
449
+ * Centralized logging for the theme system.
450
+ * Replaces console statements with structured logging.
451
+ */
452
+ class ThemeLogger {
453
+ constructor(config = {}) {
454
+ this.config = {
455
+ level: config.level ?? ("undefined" != typeof process && "production" === process.env?.NODE_ENV ? LogLevel.WARN : LogLevel.INFO),
456
+ enableConsole: config.enableConsole ?? !0,
457
+ onError: config.onError,
458
+ onWarn: config.onWarn,
459
+ onInfo: config.onInfo,
460
+ onDebug: config.onDebug
461
+ };
512
462
  }
513
- return value;
514
- }("__core-js_shared__", {});
463
+ /**
464
+ * Log an error
465
+ */ error(message, error, context) {
466
+ if (this.config.level < LogLevel.ERROR) return;
467
+ const errorObj = error instanceof Error ? error : new Error(message), themeError = error instanceof ThemeError ? error : new ThemeError(message, ThemeErrorCode.UNKNOWN_ERROR, context);
468
+ this.config.enableConsole && console.error(`[ThemeError] ${message}`, {
469
+ error: errorObj,
470
+ context: {
471
+ ...context,
472
+ ...themeError.context
473
+ },
474
+ code: themeError.code
475
+ }), this.config.onError?.(themeError, context);
476
+ }
477
+ /**
478
+ * Log a warning
479
+ */ warn(message, context) {
480
+ this.config.level < LogLevel.WARN || (this.config.enableConsole && console.warn(`[ThemeWarning] ${message}`, context || {}),
481
+ this.config.onWarn?.(message, context));
482
+ }
483
+ /**
484
+ * Log an info message
485
+ */ info(message, context) {
486
+ this.config.level < LogLevel.INFO || (this.config.enableConsole && console.info(`[ThemeInfo] ${message}`, context || {}),
487
+ this.config.onInfo?.(message, context));
488
+ }
489
+ /**
490
+ * Log a debug message
491
+ */ debug(message, context) {
492
+ this.config.level < LogLevel.DEBUG || (this.config.enableConsole, this.config.onDebug?.(message, context));
493
+ }
494
+ }
515
495
 
516
- /* eslint-disable es/no-symbol -- required for testing */ (store$1.versions || (store$1.versions = [])).push({
517
- version: "3.43.0",
518
- mode: "pure",
519
- copyright: "© 2014-2025 Denis Pushkarev (zloirock.ru)",
520
- license: "https://github.com/zloirock/core-js/blob/v3.43.0/LICENSE",
521
- source: "https://github.com/zloirock/core-js"
522
- });
496
+ /**
497
+ * Default logger instance
498
+ */ let defaultLogger = null;
523
499
 
524
- var key, value, store = sharedStore.exports, requireObjectCoercible$1 = requireObjectCoercible$3, $Object$1 = Object, toObject$2 = function(argument) {
525
- return $Object$1(requireObjectCoercible$1(argument));
526
- }, toObject$1 = toObject$2, hasOwnProperty = functionUncurryThis({}.hasOwnProperty), hasOwnProperty_1 = Object.hasOwn || function(it, key) {
527
- return hasOwnProperty(toObject$1(it), key);
528
- }, uncurryThis$3 = functionUncurryThis, id = 0, postfix = Math.random(), toString$2 = uncurryThis$3(1.1.toString), hasOwn$2 = hasOwnProperty_1, NATIVE_SYMBOL = symbolConstructorDetection, USE_SYMBOL_AS_UID = useSymbolAsUid, Symbol$1 = globalThis_1.Symbol, WellKnownSymbolsStore = store[key = "wks"] || (store[key] = value || {}), createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol$1.for || Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || function(key) {
529
- return "Symbol(" + (void 0 === key ? "" : key) + ")_" + toString$2(++id + postfix, 36);
530
- }, wellKnownSymbol$5 = function(name) {
531
- return hasOwn$2(WellKnownSymbolsStore, name) || (WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn$2(Symbol$1, name) ? Symbol$1[name] : createWellKnownSymbol("Symbol." + name)),
532
- WellKnownSymbolsStore[name];
533
- }, call$1 = functionCall, isObject$4 = isObject$6, isSymbol$1 = isSymbol$2, $TypeError$4 = TypeError, TO_PRIMITIVE = wellKnownSymbol$5("toPrimitive"), toPrimitive = function(input, pref) {
534
- if (!isObject$4(input) || isSymbol$1(input)) return input;
535
- var result, func, exoticToPrim = (func = input[TO_PRIMITIVE], isNullOrUndefined(func) ? void 0 : aCallable$2(func));
536
- if (exoticToPrim) {
537
- if (void 0 === pref && (pref = "default"), result = call$1(exoticToPrim, input, pref),
538
- !isObject$4(result) || isSymbol$1(result)) return result;
539
- throw new $TypeError$4("Can't convert object to primitive value");
540
- }
541
- return void 0 === pref && (pref = "number"), function(input, pref) {
542
- var fn, val;
543
- if ("string" === pref && isCallable$3(fn = input.toString) && !isObject$5(val = call$2(fn, input))) return val;
544
- if (isCallable$3(fn = input.valueOf) && !isObject$5(val = call$2(fn, input))) return val;
545
- if ("string" !== pref && isCallable$3(fn = input.toString) && !isObject$5(val = call$2(fn, input))) return val;
546
- throw new $TypeError$5("Can't convert object to primitive value");
547
- }(input, pref);
548
- }, isSymbol = isSymbol$2, toPropertyKey$2 = function(argument) {
549
- var key = toPrimitive(argument, "string");
550
- return isSymbol(key) ? key : key + "";
551
- }, isObject$3 = isObject$6, document$1 = globalThis_1.document, EXISTS = isObject$3(document$1) && isObject$3(document$1.createElement), ie8DomDefine = !descriptors && !fails$9((function() {
552
- // eslint-disable-next-line es/no-object-defineproperty -- required for testing
553
- return 7 !== Object.defineProperty((it = "div", EXISTS ? document$1.createElement(it) : {}), "a", {
554
- get: function() {
555
- return 7;
556
- }
557
- }).a;
558
- var it;
559
- })), DESCRIPTORS$3 = descriptors, call = functionCall, propertyIsEnumerableModule = objectPropertyIsEnumerable, createPropertyDescriptor$1 = createPropertyDescriptor$2, toIndexedObject$1 = toIndexedObject$2, toPropertyKey$1 = toPropertyKey$2, hasOwn$1 = hasOwnProperty_1, IE8_DOM_DEFINE$1 = ie8DomDefine, $getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor;
560
-
561
- // `Object.getOwnPropertyDescriptor` method
562
- // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
563
- objectGetOwnPropertyDescriptor.f = DESCRIPTORS$3 ? $getOwnPropertyDescriptor$1 : function(O, P) {
564
- if (O = toIndexedObject$1(O), P = toPropertyKey$1(P), IE8_DOM_DEFINE$1) try {
565
- return $getOwnPropertyDescriptor$1(O, P);
566
- } catch (error) {/* empty */}
567
- if (hasOwn$1(O, P)) return createPropertyDescriptor$1(!call(propertyIsEnumerableModule.f, O, P), O[P]);
568
- };
569
-
570
- var fails$3 = fails$9, isCallable$2 = isCallable$8, replacement = /#|\.prototype\./, isForced$1 = function(feature, detection) {
571
- var value = data[normalize(feature)];
572
- return value === POLYFILL || value !== NATIVE && (isCallable$2(detection) ? fails$3(detection) : !!detection);
573
- }, normalize = isForced$1.normalize = function(string) {
574
- return String(string).replace(replacement, ".").toLowerCase();
575
- }, data = isForced$1.data = {}, NATIVE = isForced$1.NATIVE = "N", POLYFILL = isForced$1.POLYFILL = "P", isForced_1 = isForced$1, aCallable$1 = aCallable$3, NATIVE_BIND = functionBindNative, bind$1 = functionUncurryThisClause(functionUncurryThisClause.bind), objectDefineProperty = {}, v8PrototypeDefineBug = descriptors && fails$9((function() {
576
- // eslint-disable-next-line es/no-object-defineproperty -- required for testing
577
- return 42 !== Object.defineProperty((function() {/* empty */}), "prototype", {
578
- value: 42,
579
- writable: !1
580
- }).prototype;
581
- })), isObject$2 = isObject$6, $String$1 = String, $TypeError$3 = TypeError, DESCRIPTORS$1 = descriptors, IE8_DOM_DEFINE = ie8DomDefine, V8_PROTOTYPE_DEFINE_BUG = v8PrototypeDefineBug, anObject = function(argument) {
582
- if (isObject$2(argument)) return argument;
583
- throw new $TypeError$3($String$1(argument) + " is not an object");
584
- }, toPropertyKey = toPropertyKey$2, $TypeError$2 = TypeError, $defineProperty = Object.defineProperty, $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
500
+ /**
501
+ * Get or create default logger
502
+ */ function getLogger() {
503
+ return defaultLogger || (defaultLogger = new ThemeLogger), defaultLogger;
504
+ }
585
505
 
586
- // `Object.defineProperty` method
587
- // https://tc39.es/ecma262/#sec-object.defineproperty
588
- objectDefineProperty.f = DESCRIPTORS$1 ? V8_PROTOTYPE_DEFINE_BUG ? function(O, P, Attributes) {
589
- if (anObject(O), P = toPropertyKey(P), anObject(Attributes), "function" == typeof O && "prototype" === P && "value" in Attributes && "writable" in Attributes && !Attributes.writable) {
590
- var current = $getOwnPropertyDescriptor(O, P);
591
- current && current.writable && (O[P] = Attributes.value, Attributes = {
592
- configurable: "configurable" in Attributes ? Attributes.configurable : current.configurable,
593
- enumerable: "enumerable" in Attributes ? Attributes.enumerable : current.enumerable,
594
- writable: !1
506
+ /**
507
+ * Core Theme Functions
508
+ *
509
+ * Simplified theme system using DesignTokens only.
510
+ * Config-first approach: loads from atomix.config.ts when no input is provided.
511
+ */
512
+ /**
513
+ * Create theme CSS from DesignTokens
514
+ *
515
+ * **Config-First Approach**: If no input is provided, loads from `atomix.config.ts`.
516
+ *
517
+ * @param input - DesignTokens (partial) or undefined (loads from config)
518
+ * @param options - CSS generation options (prefix is automatically read from config if not provided)
519
+ * @returns CSS string with custom properties
520
+ * @throws Error if config loading fails when no input is provided
521
+ *
522
+ * @example
523
+ * ```typescript
524
+ * // Loads from atomix.config.ts
525
+ * const css = createTheme();
526
+ *
527
+ * // Using DesignTokens
528
+ * const css = createTheme({
529
+ * 'primary': '#7c3aed',
530
+ * 'spacing-4': '1rem',
531
+ * });
532
+ *
533
+ * // With custom options
534
+ * const css = createTheme(undefined, { prefix: 'myapp', selector: ':root' });
535
+ * ```
536
+ */ function createTheme(input, options) {
537
+ // Validate options if provided
538
+ if (options?.prefix) {
539
+ const prefixPattern = /^[a-z][a-z0-9-]*$/;
540
+ 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, {
541
+ prefix: options.prefix,
542
+ pattern: prefixPattern.toString()
595
543
  });
596
544
  }
597
- return $defineProperty(O, P, Attributes);
598
- } : $defineProperty : function(O, P, Attributes) {
599
- if (anObject(O), P = toPropertyKey(P), anObject(Attributes), IE8_DOM_DEFINE) try {
600
- return $defineProperty(O, P, Attributes);
601
- } catch (error) {/* empty */}
602
- if ("get" in Attributes || "set" in Attributes) throw new $TypeError$2("Accessors not supported");
603
- return "value" in Attributes && (O[P] = Attributes.value), O;
604
- };
605
-
606
- var definePropertyModule = objectDefineProperty, createPropertyDescriptor = createPropertyDescriptor$2, createNonEnumerableProperty$1 = descriptors ? function(object, key, value) {
607
- return definePropertyModule.f(object, key, createPropertyDescriptor(1, value));
608
- } : function(object, key, value) {
609
- return object[key] = value, object;
610
- }, globalThis$3 = globalThis_1, apply = functionApply, uncurryThis$1 = functionUncurryThisClause, isCallable$1 = isCallable$8, getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f, isForced = isForced_1, path$1 = path$3, bind = function(fn, that) {
611
- return aCallable$1(fn), void 0 === that ? fn : NATIVE_BIND ? bind$1(fn, that) : function() {
612
- return fn.apply(that, arguments);
613
- };
614
- }, createNonEnumerableProperty = createNonEnumerableProperty$1, hasOwn = hasOwnProperty_1, wrapConstructor = function(NativeConstructor) {
615
- var Wrapper = function(a, b, c) {
616
- if (this instanceof Wrapper) {
617
- switch (arguments.length) {
618
- case 0:
619
- return new NativeConstructor;
620
-
621
- case 1:
622
- return new NativeConstructor(a);
623
-
624
- case 2:
625
- return new NativeConstructor(a, b);
545
+ // Validate selector if provided
546
+ 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, {
547
+ selector: options.selector
548
+ });
549
+ // Determine tokens based on input
550
+ let tokens;
551
+ if (input) {
552
+ // Validate input tokens structure
553
+ 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, {
554
+ inputType: typeof input
555
+ });
556
+ // Use DesignTokens directly
557
+ tokens = input;
558
+ }
559
+ // Merge with defaults and generate CSS
560
+ else {
561
+ // Check if we're in a browser environment
562
+ if ("undefined" != typeof window) throw new ThemeError("No input provided and config loading is not available in browser environment. Please provide tokens explicitly or use Node.js/SSR environment.", ThemeErrorCode.CONFIG_LOAD_FAILED, {
563
+ environment: "browser"
564
+ });
565
+ // Load from config when no input provided
566
+ let loadThemeFromConfigSync, loadAtomixConfig;
567
+ try {
568
+ const configLoaderModule = require("../config/configLoader"), loaderModule = require("../../config/loader");
569
+ // Get prefix from config if needed
570
+ if (loadThemeFromConfigSync = configLoaderModule.loadThemeFromConfigSync, loadAtomixConfig = loaderModule.loadAtomixConfig,
571
+ tokens = loadThemeFromConfigSync(), !options?.prefix) try {
572
+ const config = loadAtomixConfig({
573
+ configPath: "atomix.config.ts",
574
+ required: !1
575
+ });
576
+ options = {
577
+ ...options,
578
+ prefix: config?.prefix || "atomix"
579
+ };
580
+ } catch (error) {
581
+ // If config loading fails, use default prefix
582
+ options = {
583
+ ...options,
584
+ prefix: "atomix"
585
+ };
626
586
  }
627
- return new NativeConstructor(a, b, c);
587
+ } catch (error) {
588
+ throw new ThemeError("No input provided and config loading is not available in this environment. Please provide tokens explicitly.", ThemeErrorCode.CONFIG_LOAD_FAILED, {
589
+ error: error instanceof Error ? error.message : String(error)
590
+ });
628
591
  }
629
- return apply(NativeConstructor, this, arguments);
630
- };
631
- return Wrapper.prototype = NativeConstructor.prototype, Wrapper;
632
- }, _export = function(options, source) {
633
- var FORCED, USE_NATIVE, VIRTUAL_PROTOTYPE, key, sourceProperty, targetProperty, nativeProperty, resultProperty, descriptor, TARGET = options.target, GLOBAL = options.global, STATIC = options.stat, PROTO = options.proto, nativeSource = GLOBAL ? globalThis$3 : STATIC ? globalThis$3[TARGET] : globalThis$3[TARGET] && globalThis$3[TARGET].prototype, target = GLOBAL ? path$1 : path$1[TARGET] || createNonEnumerableProperty(path$1, TARGET, {})[TARGET], targetPrototype = target.prototype;
634
- for (key in source)
635
- // contains in native
636
- USE_NATIVE = !(FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? "." : "#") + key, options.forced)) && nativeSource && hasOwn(nativeSource, key),
637
- targetProperty = target[key], USE_NATIVE && (nativeProperty = options.dontCallGetSet ? (descriptor = getOwnPropertyDescriptor(nativeSource, key)) && descriptor.value : nativeSource[key]),
638
- // export native or implementation
639
- sourceProperty = USE_NATIVE && nativeProperty ? nativeProperty : source[key], (FORCED || PROTO || typeof targetProperty != typeof sourceProperty) && (
640
- // bind methods to global for calling from export context
641
- resultProperty = options.bind && USE_NATIVE ? bind(sourceProperty, globalThis$3) : options.wrap && USE_NATIVE ? wrapConstructor(sourceProperty) : PROTO && isCallable$1(sourceProperty) ? uncurryThis$1(sourceProperty) : sourceProperty,
642
- // add a flag to not completely full polyfills
643
- (options.sham || sourceProperty && sourceProperty.sham || targetProperty && targetProperty.sham) && createNonEnumerableProperty(resultProperty, "sham", !0),
644
- createNonEnumerableProperty(target, key, resultProperty), PROTO && (hasOwn(path$1, VIRTUAL_PROTOTYPE = TARGET + "Prototype") || createNonEnumerableProperty(path$1, VIRTUAL_PROTOTYPE, {}),
645
- // export virtual prototype methods
646
- createNonEnumerableProperty(path$1[VIRTUAL_PROTOTYPE], key, sourceProperty),
647
- // export real prototype methods
648
- options.real && targetPrototype && (FORCED || !targetPrototype[key]) && createNonEnumerableProperty(targetPrototype, key, sourceProperty)));
649
- }, ceil = Math.ceil, floor = Math.floor, trunc = Math.trunc || function(x) {
650
- var n = +x;
651
- return (n > 0 ? floor : ceil)(n);
652
- }, toIntegerOrInfinity$2 = function(argument) {
653
- var number = +argument;
654
- // eslint-disable-next-line no-self-compare -- NaN check
655
- return number != number || 0 === number ? 0 : trunc(number);
656
- }, toIntegerOrInfinity$1 = toIntegerOrInfinity$2, max = Math.max, min$1 = Math.min, toIntegerOrInfinity = toIntegerOrInfinity$2, min = Math.min, lengthOfArrayLike$2 = function(obj) {
657
- return argument = obj.length, (len = toIntegerOrInfinity(argument)) > 0 ? min(len, 9007199254740991) : 0;
658
- var argument, len;
659
- }, toIndexedObject = toIndexedObject$2, lengthOfArrayLike$1 = lengthOfArrayLike$2, createMethod$1 = function(IS_INCLUDES) {
660
- return function($this, el, fromIndex) {
661
- var O = toIndexedObject($this), length = lengthOfArrayLike$1(O);
662
- if (0 === length) return !IS_INCLUDES && -1;
663
- var value, index = function(index, length) {
664
- var integer = toIntegerOrInfinity$1(index);
665
- return integer < 0 ? max(integer + length, 0) : min$1(integer, length);
666
- }(fromIndex, length);
667
- // Array#includes uses SameValueZero equality algorithm
668
- // eslint-disable-next-line no-self-compare -- NaN check
669
- if (IS_INCLUDES && el != el) {
670
- for (;length > index; )
671
- // eslint-disable-next-line no-self-compare -- NaN check
672
- if ((value = O[index++]) != value) return !0;
673
- // Array#indexOf ignores holes, Array#includes - not
674
- } else for (;length > index; index++) if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
675
- return !IS_INCLUDES && -1;
676
- };
677
- }, $includes = [ createMethod$1(!0), createMethod$1(!1) ][0];
678
-
679
- // `Array.prototype.includes` method
680
- // https://tc39.es/ecma262/#sec-array.prototype.includes
681
- _export({
682
- target: "Array",
683
- proto: !0,
684
- forced: fails$9((function() {
685
- // eslint-disable-next-line es/no-array-prototype-includes -- detection
686
- return !Array(1).includes();
687
- }))
688
- }, {
689
- includes: function(el /* , fromIndex = 0 */) {
690
- return $includes(this, el, arguments.length > 1 ? arguments[1] : void 0);
691
592
  }
692
- });
593
+ const allTokens = createTokens(tokens), prefix = options?.prefix ?? "atomix";
594
+ // Get prefix from options or use default
595
+ return generateCSSVariables$1(allTokens, {
596
+ ...options,
597
+ prefix: prefix
598
+ });
599
+ }
693
600
 
694
- var globalThis$2 = globalThis_1, path = path$3, getBuiltInPrototypeMethod$3 = function(CONSTRUCTOR, METHOD) {
695
- var Namespace = path[CONSTRUCTOR + "Prototype"], pureMethod = Namespace && Namespace[METHOD];
696
- if (pureMethod) return pureMethod;
697
- var NativeConstructor = globalThis$2[CONSTRUCTOR], NativePrototype = NativeConstructor && NativeConstructor.prototype;
698
- return NativePrototype && NativePrototype[METHOD];
699
- }, includes$4 = getBuiltInPrototypeMethod$3("Array", "includes"), isObject$1 = isObject$6, classof$3 = classofRaw$2, MATCH$1 = wellKnownSymbol$5("match"), $TypeError$1 = TypeError, test = {};
601
+ /**
602
+ * Theme Composition Utilities
603
+ *
604
+ * Simplified utilities for composing and merging DesignTokens.
605
+ */
606
+ // ============================================================================
607
+ // Deep Merge Utility
608
+ // ============================================================================
609
+ /**
610
+ * Check if value is an object
611
+ */ function isObject$6(item) {
612
+ return item && "object" == typeof item && !Array.isArray(item) && "function" != typeof item;
613
+ }
700
614
 
701
- test[wellKnownSymbol$5("toStringTag")] = "z";
615
+ /**
616
+ * Deep merge multiple objects
617
+ * Later objects override earlier ones
618
+ */ function deepMerge(...objects) {
619
+ if (0 === objects.length) return {};
620
+ if (1 === objects.length) return objects[0];
621
+ const [target, ...sources] = objects, result = {
622
+ ...target
623
+ };
624
+ for (const source of sources) if (source) for (const key in source) {
625
+ if (!Object.prototype.hasOwnProperty.call(source, key)) continue;
626
+ const targetValue = result[key], sourceValue = source[key];
627
+ isObject$6(targetValue) && isObject$6(sourceValue) ?
628
+ // Recursively merge objects
629
+ result[key] = deepMerge(targetValue, sourceValue) :
630
+ // Override with source value
631
+ result[key] = sourceValue;
632
+ }
633
+ return result;
634
+ }
702
635
 
703
- var TO_STRING_TAG_SUPPORT = "[object z]" === String(test), isCallable = isCallable$8, classofRaw = classofRaw$2, TO_STRING_TAG = wellKnownSymbol$5("toStringTag"), $Object = Object, CORRECT_ARGUMENTS = "Arguments" === classofRaw(function() {
704
- return arguments;
705
- }()), classof$1 = TO_STRING_TAG_SUPPORT ? classofRaw : function(it) {
706
- var O, tag, result;
707
- return void 0 === it ? "Undefined" : null === it ? "Null" : "string" == typeof (tag = function(it, key) {
708
- try {
709
- return it[key];
710
- } catch (error) {/* empty */}
711
- }(O = $Object(it), TO_STRING_TAG)) ? tag : CORRECT_ARGUMENTS ? classofRaw(O) : "Object" === (result = classofRaw(O)) && isCallable(O.callee) ? "Arguments" : result;
712
- }, $String = String, MATCH = wellKnownSymbol$5("match"), $$1 = _export, notARegExp = function(it) {
713
- if (function(it) {
714
- var isRegExp;
715
- return isObject$1(it) && (void 0 !== (isRegExp = it[MATCH$1]) ? !!isRegExp : "RegExp" === classof$3(it));
716
- }(it)) throw new $TypeError$1("The method doesn't accept regular expressions");
717
- return it;
718
- }, requireObjectCoercible = requireObjectCoercible$3, toString = function(argument) {
719
- if ("Symbol" === classof$1(argument)) throw new TypeError("Cannot convert a Symbol value to a string");
720
- return $String(argument);
721
- }, stringIndexOf = functionUncurryThis("".indexOf);
722
-
723
- // `String.prototype.includes` method
724
- // https://tc39.es/ecma262/#sec-string.prototype.includes
725
- $$1({
726
- target: "String",
727
- proto: !0,
728
- forced: !function(METHOD_NAME) {
729
- var regexp = /./;
730
- try {
731
- "/./"[METHOD_NAME](regexp);
732
- } catch (error1) {
733
- try {
734
- return regexp[MATCH] = !1, "/./"[METHOD_NAME](regexp);
735
- } catch (error2) {/* empty */}
736
- }
737
- return !1;
738
- }("includes")
739
- }, {
740
- includes: function(searchString /* , position = 0 */) {
741
- return !!~stringIndexOf(toString(requireObjectCoercible(this)), toString(notARegExp(searchString)), arguments.length > 1 ? arguments[1] : void 0);
742
- }
743
- });
744
-
745
- var includes$3 = getBuiltInPrototypeMethod$3("String", "includes"), isPrototypeOf$1 = objectIsPrototypeOf, arrayMethod = includes$4, stringMethod = includes$3, ArrayPrototype$1 = Array.prototype, StringPrototype = String.prototype;
746
-
747
- const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
748
- var own = it.includes;
749
- return it === ArrayPrototype$1 || isPrototypeOf$1(ArrayPrototype$1, it) && own === ArrayPrototype$1.includes ? arrayMethod : "string" == typeof it || it === StringPrototype || isPrototypeOf$1(StringPrototype, it) && own === StringPrototype.includes ? stringMethod : own;
750
- }));
636
+ /**
637
+ * Merge multiple DesignTokens objects into a single DesignTokens object
638
+ *
639
+ * @param tokens - DesignTokens objects to merge
640
+ * @returns Merged DesignTokens object
641
+ *
642
+ * @example
643
+ * ```typescript
644
+ * const baseTokens = { 'primary': '#000', 'spacing-4': '1rem' };
645
+ * const customTokens = { 'secondary': '#fff', 'spacing-4': '1.5rem' };
646
+ * const merged = mergeTheme(baseTokens, customTokens);
647
+ * // Returns: { 'primary': '#000', 'secondary': '#fff', 'spacing-4': '1.5rem' }
648
+ * ```
649
+ */ function mergeTheme(...tokens) {
650
+ return deepMerge({}, ...tokens);
651
+ }
751
652
 
752
653
  /**
753
- * Theme Utilities
654
+ * Extend DesignTokens with additional tokens
754
655
  *
755
- * Helper utilities for working with themes, including color manipulation,
756
- * spacing helpers, and theme value accessors.
757
- */
758
- // ============================================================================
759
- // Color Manipulation Utilities
760
- // ============================================================================
656
+ * @param baseTokens - Base DesignTokens to extend
657
+ * @param extension - Additional DesignTokens to merge
658
+ * @returns Extended DesignTokens object
659
+ *
660
+ * @example
661
+ * ```typescript
662
+ * const base = { 'primary': '#000' };
663
+ * const extended = extendTheme(base, { 'secondary': '#fff' });
664
+ * // Returns: { 'primary': '#000', 'secondary': '#fff' }
665
+ * ```
666
+ */ function extendTheme(baseTokens, extension) {
667
+ return mergeTheme(baseTokens, extension);
668
+ }
669
+
761
670
  /**
762
- * Convert hex color to RGB object
763
- */ function hexToRgb(hex) {
764
- const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
765
- return result ? {
766
- r: parseInt(result[1], 16),
767
- g: parseInt(result[2], 16),
768
- b: parseInt(result[3], 16)
769
- } : null;
671
+ * Create a new theme registry
672
+ */ function createThemeRegistry() {
673
+ return {};
770
674
  }
771
675
 
772
676
  /**
773
- * Convert RGB to hex color
774
- */ function rgbToHex(r, g, b) {
775
- const toHex = val => Math.round(Math.max(0, Math.min(255, val))).toString(16).padStart(2, "0");
776
- return `#${toHex(r ?? 0)}${toHex(g ?? 0)}${toHex(b ?? 0)}`;
677
+ * Register a theme
678
+ * @param registry - Theme registry object
679
+ * @param id - Theme identifier
680
+ * @param metadata - Theme metadata
681
+ */ function registerTheme(registry, id, metadata) {
682
+ registry[id] = metadata;
777
683
  }
778
684
 
779
685
  /**
780
- * Calculate relative luminance of a color
781
- * Used for determining contrast ratios
782
- */ function getLuminance(color) {
783
- const rgb = hexToRgb(color);
784
- if (!rgb) return 0;
785
- const {r: r, g: g, b: b} = rgb, [rs, gs, bs] = [ r ?? 0, g ?? 0, b ?? 0 ].map((c => {
786
- const val = c / 255;
787
- return val <= .03928 ? val / 12.92 : Math.pow((val + .055) / 1.055, 2.4);
788
- }));
789
- return .2126 * (rs ?? 0) + .7152 * (gs ?? 0) + .0722 * (bs ?? 0);
686
+ * Unregister a theme
687
+ * @param registry - Theme registry object
688
+ * @param id - Theme identifier
689
+ */ function unregisterTheme(registry, id) {
690
+ const exists = id in registry;
691
+ return delete registry[id], exists;
790
692
  }
791
693
 
792
694
  /**
793
- * Calculate contrast ratio between two colors
794
- */ function getContrastRatio(foreground, background) {
795
- const lumA = getLuminance(foreground), lumB = getLuminance(background);
796
- return (Math.max(lumA, lumB) + .05) / (Math.min(lumA, lumB) + .05);
695
+ * Check if a theme is registered
696
+ * @param registry - Theme registry object
697
+ * @param id - Theme identifier
698
+ */ function hasTheme(registry, id) {
699
+ return id in registry;
797
700
  }
798
701
 
799
702
  /**
800
- * Get appropriate contrast text color (black or white) for a background color
801
- */ function getContrastText(background, threshold = 3) {
802
- const contrastWithWhite = getContrastRatio("#FFFFFF", background), contrastWithBlack = getContrastRatio("#000000", background);
803
- return contrastWithWhite >= threshold ? "#FFFFFF" : contrastWithBlack >= threshold ? "#000000" : contrastWithWhite > contrastWithBlack ? "#FFFFFF" : "#000000";
703
+ * Get theme metadata
704
+ * @param registry - Theme registry object
705
+ * @param id - Theme identifier
706
+ */ function getTheme(registry, id) {
707
+ return registry[id];
804
708
  }
805
709
 
806
710
  /**
807
- * Lighten a color by a given amount
808
- *
809
- * @param color - Hex color string
810
- * @param amount - Amount to lighten (0-1), default 0.2
811
- * @returns Lightened hex color
812
- */ function lighten(color, amount = .2) {
813
- const rgb = hexToRgb(color);
814
- if (!rgb) return color;
815
- const {r: r, g: g, b: b} = rgb, lightenValue = val => Math.min(255, Math.round(val + (255 - val) * amount));
816
- return rgbToHex(lightenValue(r), lightenValue(g), lightenValue(b));
711
+ * Get all registered theme metadata
712
+ * @param registry - Theme registry object
713
+ */ function getAllThemes(registry) {
714
+ return Object.values(registry);
817
715
  }
818
716
 
819
717
  /**
820
- * Darken a color by a given amount
821
- *
822
- * @param color - Hex color string
823
- * @param amount - Amount to darken (0-1), default 0.2
824
- * @returns Darkened hex color
825
- */ function darken(color, amount = .2) {
826
- const rgb = hexToRgb(color);
827
- if (!rgb) return color;
828
- const {r: r, g: g, b: b} = rgb, darkenValue = val => Math.max(0, Math.round(val * (1 - amount)));
829
- return rgbToHex(darkenValue(r), darkenValue(g), darkenValue(b));
718
+ * Get all registered theme IDs
719
+ * @param registry - Theme registry object
720
+ */ function getThemeIds(registry) {
721
+ return Object.keys(registry);
830
722
  }
831
723
 
832
724
  /**
833
- * Add alpha (opacity) to a color
834
- *
835
- * @param color - Hex color string
836
- * @param opacity - Opacity value (0-1)
837
- * @returns RGBA color string
838
- */ function alpha(color, opacity) {
839
- const rgb = hexToRgb(color);
840
- if (!rgb) return color;
841
- const {r: r, g: g, b: b} = rgb;
842
- return `rgba(${r}, ${g}, ${b}, ${Math.max(0, Math.min(1, opacity))})`;
725
+ * Clear all registered themes
726
+ * @param registry - Theme registry object
727
+ */ function clearThemes(registry) {
728
+ Object.keys(registry).forEach((key => delete registry[key]));
843
729
  }
844
730
 
845
731
  /**
846
- * Emphasize a color (lighten if dark, darken if light)
732
+ * Get the number of registered themes
733
+ * @param registry - Theme registry object
734
+ */ function getThemeCount(registry) {
735
+ return Object.keys(registry).length;
736
+ }
737
+
738
+ /**
739
+ * Core Theme Engine
847
740
  *
848
- * @param color - Hex color string
849
- * @param coefficient - Amount to emphasize (0-1), default 0.15
850
- * @returns Emphasized hex color
851
- */
741
+ * Core theme creation, composition, and registry functionality
742
+ */ const index = Object.freeze( Object.defineProperty({
743
+ __proto__: null,
744
+ clearThemes: clearThemes,
745
+ createTheme: createTheme,
746
+ createThemeRegistry: createThemeRegistry,
747
+ deepMerge: deepMerge,
748
+ extendTheme: extendTheme,
749
+ getAllThemes: getAllThemes,
750
+ getTheme: getTheme,
751
+ getThemeCount: getThemeCount,
752
+ getThemeIds: getThemeIds,
753
+ hasTheme: hasTheme,
754
+ mergeTheme: mergeTheme,
755
+ registerTheme: registerTheme,
756
+ unregisterTheme: unregisterTheme
757
+ }, Symbol.toStringTag, {
758
+ value: "Module"
759
+ }));
760
+
852
761
  /**
853
- * Theme Adapter
762
+ * CSS Injection Utilities
854
763
  *
855
- * Converts between Theme objects and DesignTokens.
764
+ * Inject CSS into HTML head via <style> element.
856
765
  */
857
766
  /**
858
- * Convert Theme object to DesignTokens
767
+ * Check if running in browser environment
768
+ */ function isBrowser$1() {
769
+ return "undefined" != typeof document;
770
+ }
771
+
772
+ /**
773
+ * Inject CSS into HTML head via <style> element
859
774
  *
860
- * Extracts values from a Theme object and converts them to flat DesignTokens format.
775
+ * Creates or updates a style element in the document head.
776
+ * If an element with the same ID exists, it will be updated.
861
777
  *
862
- * @param theme - Theme object to convert
863
- * @returns Partial DesignTokens object
778
+ * @param css - CSS string to inject
779
+ * @param id - Style element ID (default: 'atomix-theme')
864
780
  *
865
781
  * @example
866
782
  * ```typescript
867
- * const theme = createTheme({ palette: { primary: { main: '#7c3aed' } } });
868
- * const tokens = themeToDesignTokens(theme);
869
- * // Returns: { 'primary': '#7c3aed', ... }
783
+ * const css = ':root { --atomix-color-primary: #7AFFD7; }';
784
+ * injectCSS(css);
785
+ *
786
+ * // With custom ID
787
+ * injectCSS(css, 'my-custom-theme');
870
788
  * ```
871
- */
872
- function themeToDesignTokens(theme) {
873
- const tokens = {};
874
- // Convert palette colors
875
- if (theme.palette) {
876
- // Primary colors
877
- if (theme.palette.primary && (tokens.primary = theme.palette.primary.main, theme.palette.primary.light && (tokens["primary-3"] = theme.palette.primary.light),
878
- theme.palette.primary.dark && (tokens["primary-9"] = theme.palette.primary.dark),
879
- theme.palette.primary.main)) {
880
- const rgb = hexToRgb(theme.palette.primary.main);
881
- rgb && (tokens["primary-rgb"] = `${rgb.r}, ${rgb.g}, ${rgb.b}`);
882
- }
883
- // Secondary colors
884
- if (theme.palette.secondary) {
885
- tokens.secondary = theme.palette.secondary.main, theme.palette.secondary.light && (tokens["gray-1"] = theme.palette.secondary.light),
886
- theme.palette.secondary.dark && (tokens["gray-3"] = theme.palette.secondary.dark);
887
- const rgb = hexToRgb(theme.palette.secondary.main);
888
- rgb && (tokens["secondary-rgb"] = `${rgb.r}, ${rgb.g}, ${rgb.b}`);
889
- }
890
- // Error colors
891
- if (theme.palette.error) {
892
- tokens.error = theme.palette.error.main, tokens["red-6"] = theme.palette.error.main,
893
- theme.palette.error.light && (tokens["red-4"] = theme.palette.error.light), theme.palette.error.dark && (tokens["red-9"] = theme.palette.error.dark);
894
- const rgb = hexToRgb(theme.palette.error.main);
895
- rgb && (tokens["error-rgb"] = `${rgb.r}, ${rgb.g}, ${rgb.b}`);
896
- }
897
- // Success colors
898
- if (theme.palette.success) {
899
- tokens.success = theme.palette.success.main, tokens["green-6"] = theme.palette.success.main,
900
- theme.palette.success.light && (tokens["green-4"] = theme.palette.success.light),
901
- theme.palette.success.dark && (tokens["green-9"] = theme.palette.success.dark);
902
- const rgb = hexToRgb(theme.palette.success.main);
903
- rgb && (tokens["success-rgb"] = `${rgb.r}, ${rgb.g}, ${rgb.b}`);
904
- }
905
- // Warning colors
906
- if (theme.palette.warning) {
907
- tokens.warning = theme.palette.warning.main, tokens["yellow-6"] = theme.palette.warning.main,
908
- theme.palette.warning.light && (tokens["yellow-4"] = theme.palette.warning.light),
909
- theme.palette.warning.dark && (tokens["yellow-9"] = theme.palette.warning.dark);
910
- const rgb = hexToRgb(theme.palette.warning.main);
911
- rgb && (tokens["warning-rgb"] = `${rgb.r}, ${rgb.g}, ${rgb.b}`);
912
- }
913
- // Info colors
914
- if (theme.palette.info) {
915
- tokens.info = theme.palette.info.main, tokens["blue-6"] = theme.palette.info.main,
916
- theme.palette.info.light && (tokens["blue-4"] = theme.palette.info.light), theme.palette.info.dark && (tokens["blue-9"] = theme.palette.info.dark);
917
- const rgb = hexToRgb(theme.palette.info.main);
918
- rgb && (tokens["info-rgb"] = `${rgb.r}, ${rgb.g}, ${rgb.b}`);
919
- }
920
- // Background colors
921
- theme.palette.background && (tokens["body-bg"] = theme.palette.background.default,
922
- tokens["primary-bg-subtle"] = theme.palette.background.default, tokens["secondary-bg-subtle"] = theme.palette.background.paper,
923
- tokens["tertiary-bg-subtle"] = theme.palette.background.subtle),
924
- // Text colors
925
- theme.palette.text && (tokens["body-color"] = theme.palette.text.primary, tokens["heading-color"] = theme.palette.text.primary,
926
- tokens["primary-text-emphasis"] = theme.palette.text.primary, tokens["secondary-text-emphasis"] = theme.palette.text.secondary,
927
- tokens["disabled-text-emphasis"] = theme.palette.text.disabled);
928
- }
929
- // Convert typography
930
- // Convert spacing (if available as object)
931
- if (theme.typography && (tokens["body-font-family"] = theme.typography.fontFamily,
932
- tokens["font-sans-serif"] = theme.typography.fontFamily, tokens["body-font-size"] = `${theme.typography.fontSize}px`,
933
- tokens["body-font-weight"] = String(theme.typography.fontWeightRegular),
934
- // Font weights
935
- tokens["font-weight-light"] = String(theme.typography.fontWeightLight), tokens["font-weight-normal"] = String(theme.typography.fontWeightRegular),
936
- tokens["font-weight-medium"] = String(theme.typography.fontWeightMedium), tokens["font-weight-semibold"] = String(theme.typography.fontWeightSemiBold),
937
- tokens["font-weight-bold"] = String(theme.typography.fontWeightBold),
938
- // Line heights
939
- theme.typography.h1?.lineHeight && (tokens["line-height-base"] = String(theme.typography.h1.lineHeight))),
940
- theme.spacing && "object" == typeof theme.spacing && !("__isSpacingFunction" in theme.spacing)) {
941
- const spacing = theme.spacing;
942
- Object.entries(spacing).forEach((([key, value]) => {
943
- tokens[`spacing-${key}`] = String(value);
944
- }));
945
- }
946
- // Convert border radius
947
- return theme.borderRadius && Object.entries(theme.borderRadius).forEach((([key, value]) => {
948
- tokens["sm" === key ? "border-radius-sm" : "md" === key ? "border-radius" : "lg" === key ? "border-radius-lg" : "xl" === key ? "border-radius-xl" : "xxl" === key ? "border-radius-xxl" : `border-radius-${key}`] = String(value);
949
- })),
950
- // Convert shadows
951
- theme.shadows && Object.entries(theme.shadows).forEach((([key, value]) => {
952
- tokens["xs" === key ? "box-shadow-xs" : "sm" === key ? "box-shadow-sm" : "md" === key ? "box-shadow" : "lg" === key ? "box-shadow-lg" : "xl" === key ? "box-shadow-xl" : `box-shadow-${key}`] = String(value);
953
- })),
954
- // Convert z-index
955
- theme.zIndex && Object.entries(theme.zIndex).forEach((([key, value]) => {
956
- tokens[`z-${key}`] = String(value);
957
- })),
958
- // Convert transitions
959
- theme.transitions && (theme.transitions.duration && Object.entries(theme.transitions.duration).forEach((([key, value]) => {
960
- tokens[`transition-duration-${key}`] = String(value);
961
- })), theme.transitions.easing && Object.entries(theme.transitions.easing).forEach((([key, value]) => {
962
- tokens[`easing-${key}`] = String(value);
963
- }))),
964
- // Convert breakpoints
965
- theme.breakpoints?.values && Object.entries(theme.breakpoints.values).forEach((([key, value]) => {
966
- tokens[`breakpoint-${key}`] = String(value);
967
- })),
968
- // Merge any existing cssVars from theme
969
- theme.cssVars && Object.entries(theme.cssVars).forEach((([key, value]) => {
970
- // Remove --atomix- prefix if present
971
- const cleanKey = key.replace(/^--atomix-/, "").replace(/^--/, "");
972
- tokens[cleanKey] = String(value);
973
- })), tokens;
789
+ */ function injectCSS$1(css, id = "atomix-theme") {
790
+ if (!isBrowser$1()) return;
791
+ let styleElement = document.getElementById(id);
792
+ styleElement || (styleElement = document.createElement("style"), styleElement.id = id,
793
+ styleElement.setAttribute("data-atomix-theme", "true"), document.head.appendChild(styleElement)),
794
+ styleElement.textContent = css;
974
795
  }
975
796
 
976
797
  /**
977
- * Convert DesignTokens to Theme-compatible CSS variables
798
+ * Remove injected CSS from DOM
978
799
  *
979
- * @param tokens - DesignTokens object
980
- * @returns CSS variables object compatible with Theme.cssVars
981
- */ function designTokensToCSSVars(tokens) {
982
- const cssVars = {};
983
- return Object.entries(tokens).forEach((([key, value]) => {
984
- void 0 !== value && (cssVars[`--atomix-${key}`] = String(value));
985
- })), cssVars;
986
- }
987
-
988
- /**
989
- * Create DesignTokens from Theme with defaults
800
+ * Removes the style element with the given ID from the document head.
990
801
  *
991
- * Converts a Theme to DesignTokens and merges with default tokens.
802
+ * @param id - Style element ID to remove (default: 'atomix-theme')
992
803
  *
993
- * @param theme - Theme object to convert
994
- * @returns Complete DesignTokens object
995
- */ function createDesignTokensFromTheme(theme) {
996
- return createTokens(themeToDesignTokens(theme));
804
+ * @example
805
+ * ```typescript
806
+ * removeCSS(); // Removes default 'atomix-theme'
807
+ * removeCSS('my-custom-theme'); // Removes custom ID
808
+ * ```
809
+ */ function removeCSS(id = "atomix-theme") {
810
+ if (!isBrowser$1()) return;
811
+ const styleElement = document.getElementById(id);
812
+ styleElement && styleElement.remove();
997
813
  }
998
814
 
999
815
  /**
1000
- * Create a minimal Theme object from DesignTokens
816
+ * Check if CSS is already injected
1001
817
  *
1002
- * @param tokens - DesignTokens to convert
1003
- * @returns Minimal Theme object with cssVars populated
1004
- */ function designTokensToTheme(tokens) {
1005
- return {
1006
- name: "Design Tokens Theme",
1007
- cssVars: designTokensToCSSVars(tokens),
1008
- __isJSTheme: !0
1009
- };
818
+ * @param id - Style element ID to check (default: 'atomix-theme')
819
+ * @returns True if style element exists
820
+ */ function isCSSInjected(id = "atomix-theme") {
821
+ return !!isBrowser$1() && null !== document.getElementById(id);
1010
822
  }
1011
823
 
1012
824
  /**
1013
- * Core Theme Functions
825
+ * CSS File Utilities
1014
826
  *
1015
- * Simplified theme system that handles both DesignTokens and Theme objects.
1016
- * Config-first approach: loads from atomix.config.ts when no input is provided.
1017
- * Config file is required for automatic loading.
827
+ * Save CSS to file system (Node.js only).
1018
828
  */
1019
829
  /**
1020
- * Create theme CSS from tokens or Theme object
830
+ * Save CSS to file
1021
831
  *
1022
- * **Config-First Approach**: If no input is provided, loads from `atomix.config.ts`.
1023
- * Config file is required for automatic loading.
832
+ * Writes CSS string to a file. Only works in Node.js environment.
1024
833
  *
1025
- * @param input - DesignTokens (partial), Theme object, or undefined (loads from config)
1026
- * @param options - CSS generation options (prefix is automatically read from config if not provided)
1027
- * @returns CSS string with custom properties
1028
- * @throws Error if config loading fails when no input is provided
834
+ * @param css - CSS string to save
835
+ * @param filePath - Output file path
836
+ * @throws Error if called in browser environment
1029
837
  *
1030
838
  * @example
1031
839
  * ```typescript
1032
- * // Loads from atomix.config.ts (config file required)
1033
- * const css = createTheme();
1034
- *
1035
- * // Using DesignTokens
1036
- * const css = createTheme({
1037
- * 'primary': '#7c3aed',
1038
- * 'spacing-4': '1rem',
1039
- * });
1040
- *
1041
- * // Using Theme object
1042
- * const theme = createThemeObject({ palette: { primary: { main: '#7c3aed' } } });
1043
- * const css = createTheme(theme);
1044
- *
1045
- * // With custom options
1046
- * const css = createTheme(undefined, { prefix: 'myapp', selector: ':root' });
840
+ * const css = ':root { --atomix-color-primary: #7AFFD7; }';
841
+ * await saveCSSFile(css, './themes/custom.css');
1047
842
  * ```
1048
- */ function createTheme(input, options) {
1049
- // Determine tokens based on input
1050
- let tokens;
1051
- if (input)
1052
- // Use DesignTokens directly
1053
- tokens =
1054
- // Helper functions to simplify main function
1055
- function(input) {
1056
- return !0 === input?.__isJSTheme || input?.palette && input?.typography;
1057
- }(input) ? themeToDesignTokens(input) : input;
1058
- // Merge with defaults and generate CSS
1059
- else {
1060
- // Check if we're in a browser environment
1061
- if ("undefined" != typeof window) throw new Error("createTheme: No input provided and config loading is not available in browser environment. Please provide tokens explicitly or use Node.js/SSR environment.");
1062
- // Load from config when no input provided
1063
- // Using dynamic import in a way that's more compatible with bundlers
1064
- let loadThemeFromConfigSync, loadAtomixConfig;
1065
- try {
1066
- // Use dynamic require but only in Node.js environments
1067
- // This approach allows bundlers to properly handle external dependencies
1068
- const configLoaderModule = require("../config/configLoader"), loaderModule = require("../../config/loader");
1069
- // Get prefix from config if needed
1070
- if (loadThemeFromConfigSync = configLoaderModule.loadThemeFromConfigSync, loadAtomixConfig = loaderModule.loadAtomixConfig,
1071
- tokens = loadThemeFromConfigSync(), !options?.prefix) try {
1072
- const config = loadAtomixConfig({
1073
- configPath: "atomix.config.ts",
1074
- required: !1
1075
- });
1076
- options = {
1077
- ...options,
1078
- prefix: config?.prefix || "atomix"
1079
- };
1080
- } catch (error) {
1081
- // If config loading fails, use default prefix
1082
- options = {
1083
- ...options,
1084
- prefix: "atomix"
1085
- };
1086
- }
1087
- } catch (error) {
1088
- throw new Error("createTheme: No input provided and config loading is not available in this environment. Please provide tokens explicitly.");
1089
- }
1090
- }
1091
- const allTokens = createTokens(tokens), prefix = options?.prefix ?? "atomix";
1092
- // Get prefix from options or use default
1093
- return generateCSSVariables$1(allTokens, {
1094
- ...options,
1095
- prefix: prefix
1096
- });
1097
- }
843
+ */ var commonjsGlobal = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {};
1098
844
 
1099
- var aCallable = aCallable$3, toObject = toObject$2, IndexedObject = indexedObject, lengthOfArrayLike = lengthOfArrayLike$2, $TypeError = TypeError, REDUCE_EMPTY = "Reduce of empty array with no initial value", createMethod = function(IS_RIGHT) {
1100
- return function(that, callbackfn, argumentsLength, memo) {
1101
- var O = toObject(that), self = IndexedObject(O), length = lengthOfArrayLike(O);
1102
- if (aCallable(callbackfn), 0 === length && argumentsLength < 2) throw new $TypeError(REDUCE_EMPTY);
1103
- var index = IS_RIGHT ? length - 1 : 0, i = IS_RIGHT ? -1 : 1;
1104
- if (argumentsLength < 2) for (;;) {
1105
- if (index in self) {
1106
- memo = self[index], index += i;
1107
- break;
1108
- }
1109
- if (index += i, IS_RIGHT ? index < 0 : length <= index) throw new $TypeError(REDUCE_EMPTY);
1110
- }
1111
- for (;IS_RIGHT ? index >= 0 : length > index; index += i) index in self && (memo = callbackfn(memo, self[index], index, O));
1112
- return memo;
1113
- };
1114
- }, arrayReduce = {
1115
- // `Array.prototype.reduce` method
1116
- // https://tc39.es/ecma262/#sec-array.prototype.reduce
1117
- left: createMethod(!1),
1118
- // `Array.prototype.reduceRight` method
1119
- // https://tc39.es/ecma262/#sec-array.prototype.reduceright
1120
- right: createMethod(!0)
1121
- }, fails = fails$9, globalThis$1 = globalThis_1, userAgent = environmentUserAgent, classof = classofRaw$2, userAgentStartsWith = function(string) {
1122
- return userAgent.slice(0, string.length) === string;
1123
- }, environment = userAgentStartsWith("Bun/") ? "BUN" : userAgentStartsWith("Cloudflare-Workers") ? "CLOUDFLARE" : userAgentStartsWith("Deno/") ? "DENO" : userAgentStartsWith("Node.js/") ? "NODE" : globalThis$1.Bun && "string" == typeof Bun.version ? "BUN" : globalThis$1.Deno && "object" == typeof Deno.version ? "DENO" : "process" === classof(globalThis$1.process) ? "NODE" : globalThis$1.window && globalThis$1.document ? "BROWSER" : "REST", $reduce = arrayReduce.left;
845
+ function getDefaultExportFromCjs(x) {
846
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x.default : x;
847
+ }
1124
848
 
1125
- // `Array.prototype.reduce` method
1126
- // https://tc39.es/ecma262/#sec-array.prototype.reduce
1127
- _export({
1128
- target: "Array",
1129
- proto: !0,
1130
- forced: !("NODE" === environment) && environmentV8Version > 79 && environmentV8Version < 83 || !function(METHOD_NAME, argument) {
1131
- var method = [][METHOD_NAME];
1132
- return !!method && fails((function() {
1133
- // eslint-disable-next-line no-useless-call -- required for testing
1134
- method.call(null, argument || function() {
1135
- return 1;
1136
- }, 1);
1137
- }));
1138
- }("reduce")
1139
- }, {
1140
- reduce: function(callbackfn /* , initialValue */) {
1141
- var length = arguments.length;
1142
- return $reduce(this, callbackfn, length, length > 1 ? arguments[1] : void 0);
849
+ var fails$9 = function(exec) {
850
+ try {
851
+ return !!exec();
852
+ } catch (error) {
853
+ return !0;
1143
854
  }
1144
- });
855
+ }, functionBindNative = !fails$9((function() {
856
+ // eslint-disable-next-line es/no-function-prototype-bind -- safe
857
+ var test = function() {/* empty */}.bind();
858
+ // eslint-disable-next-line no-prototype-builtins -- safe
859
+ return "function" != typeof test || test.hasOwnProperty("prototype");
860
+ })), NATIVE_BIND$3 = functionBindNative, FunctionPrototype$1 = Function.prototype, call$5 = FunctionPrototype$1.call, uncurryThisWithBind = NATIVE_BIND$3 && FunctionPrototype$1.bind.bind(call$5, call$5), functionUncurryThis = NATIVE_BIND$3 ? uncurryThisWithBind : function(fn) {
861
+ return function() {
862
+ return call$5.apply(fn, arguments);
863
+ };
864
+ }, objectIsPrototypeOf = functionUncurryThis({}.isPrototypeOf), check = function(it) {
865
+ return it && it.Math === Math && it;
866
+ }, globalThis_1 =
867
+ // eslint-disable-next-line es/no-global-this -- safe
868
+ check("object" == typeof globalThis && globalThis) || check("object" == typeof window && window) ||
869
+ // eslint-disable-next-line no-restricted-globals -- safe
870
+ check("object" == typeof self && self) || check("object" == typeof commonjsGlobal && commonjsGlobal) || check("object" == typeof commonjsGlobal && commonjsGlobal) ||
871
+ // eslint-disable-next-line no-new-func -- fallback
872
+ function() {
873
+ return this;
874
+ }() || Function("return this")(), NATIVE_BIND$2 = functionBindNative, FunctionPrototype = Function.prototype, apply$1 = FunctionPrototype.apply, call$4 = FunctionPrototype.call, functionApply = "object" == typeof Reflect && Reflect.apply || (NATIVE_BIND$2 ? call$4.bind(apply$1) : function() {
875
+ return call$4.apply(apply$1, arguments);
876
+ }), uncurryThis$7 = functionUncurryThis, toString$3 = uncurryThis$7({}.toString), stringSlice = uncurryThis$7("".slice), classofRaw$2 = function(it) {
877
+ return stringSlice(toString$3(it), 8, -1);
878
+ }, classofRaw$1 = classofRaw$2, uncurryThis$6 = functionUncurryThis, functionUncurryThisClause = function(fn) {
879
+ // Nashorn bug:
880
+ // https://github.com/zloirock/core-js/issues/1128
881
+ // https://github.com/zloirock/core-js/issues/1130
882
+ if ("Function" === classofRaw$1(fn)) return uncurryThis$6(fn);
883
+ }, documentAll = "object" == typeof document && document.all, isCallable$8 = void 0 === documentAll && void 0 !== documentAll ? function(argument) {
884
+ return "function" == typeof argument || argument === documentAll;
885
+ } : function(argument) {
886
+ return "function" == typeof argument;
887
+ }, objectGetOwnPropertyDescriptor = {}, descriptors = !fails$9((function() {
888
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
889
+ return 7 !== Object.defineProperty({}, 1, {
890
+ get: function() {
891
+ return 7;
892
+ }
893
+ })[1];
894
+ })), NATIVE_BIND$1 = functionBindNative, call$3 = Function.prototype.call, functionCall = NATIVE_BIND$1 ? call$3.bind(call$3) : function() {
895
+ return call$3.apply(call$3, arguments);
896
+ }, objectPropertyIsEnumerable = {}, $propertyIsEnumerable = {}.propertyIsEnumerable, getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor, NASHORN_BUG = getOwnPropertyDescriptor$1 && !$propertyIsEnumerable.call({
897
+ 1: 2
898
+ }, 1);
1145
899
 
1146
- var reduce$3 = getBuiltInPrototypeMethod$3("Array", "reduce"), isPrototypeOf = objectIsPrototypeOf, method = reduce$3, ArrayPrototype = Array.prototype;
900
+ // `Object.prototype.propertyIsEnumerable` method implementation
901
+ // https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
902
+ objectPropertyIsEnumerable.f = NASHORN_BUG ? function(V) {
903
+ var descriptor = getOwnPropertyDescriptor$1(this, V);
904
+ return !!descriptor && descriptor.enumerable;
905
+ } : $propertyIsEnumerable;
1147
906
 
1148
- const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
1149
- var own = it.reduce;
1150
- return it === ArrayPrototype || isPrototypeOf(ArrayPrototype, it) && own === ArrayPrototype.reduce ? method : own;
1151
- }));
907
+ var match, version, createPropertyDescriptor$2 = function(bitmap, value) {
908
+ return {
909
+ enumerable: !(1 & bitmap),
910
+ configurable: !(2 & bitmap),
911
+ writable: !(4 & bitmap),
912
+ value: value
913
+ };
914
+ }, fails$6 = fails$9, classof$4 = classofRaw$2, $Object$3 = Object, split = functionUncurryThis("".split), indexedObject = fails$6((function() {
915
+ // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
916
+ // eslint-disable-next-line no-prototype-builtins -- safe
917
+ return !$Object$3("z").propertyIsEnumerable(0);
918
+ })) ? function(it) {
919
+ return "String" === classof$4(it) ? split(it, "") : $Object$3(it);
920
+ } : $Object$3, isNullOrUndefined$2 = function(it) {
921
+ return null == it;
922
+ }, isNullOrUndefined$1 = isNullOrUndefined$2, $TypeError$7 = TypeError, requireObjectCoercible$3 = function(it) {
923
+ if (isNullOrUndefined$1(it)) throw new $TypeError$7("Can't call method on " + it);
924
+ return it;
925
+ }, IndexedObject$1 = indexedObject, requireObjectCoercible$2 = requireObjectCoercible$3, toIndexedObject$2 = function(it) {
926
+ return IndexedObject$1(requireObjectCoercible$2(it));
927
+ }, isCallable$7 = isCallable$8, isObject$5 = function(it) {
928
+ return "object" == typeof it ? null !== it : isCallable$7(it);
929
+ }, path$3 = {}, path$2 = path$3, globalThis$b = globalThis_1, isCallable$6 = isCallable$8, aFunction = function(variable) {
930
+ return isCallable$6(variable) ? variable : void 0;
931
+ }, navigator$1 = globalThis_1.navigator, userAgent$2 = navigator$1 && navigator$1.userAgent, environmentUserAgent = userAgent$2 ? String(userAgent$2) : "", globalThis$9 = globalThis_1, userAgent$1 = environmentUserAgent, process$1 = globalThis$9.process, Deno$1 = globalThis$9.Deno, versions = process$1 && process$1.versions || Deno$1 && Deno$1.version, v8 = versions && versions.v8;
1152
932
 
1153
- /**
1154
- * Theme Composition Utilities
1155
- *
1156
- * Simplified utilities for composing, merging, and extending themes.
1157
- */
1158
- // ============================================================================
1159
- // Deep Merge Utility
1160
- // ============================================================================
1161
- /**
1162
- * Check if value is an object
1163
- */ function isObject(item) {
1164
- return item && "object" == typeof item && !Array.isArray(item) && "function" != typeof item;
1165
- }
933
+ v8 && (
934
+ // in old Chrome, versions of V8 isn't V8 = Chrome / 10
935
+ // but their correct versions are not interesting for us
936
+ version = (match = v8.split("."))[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1])),
937
+ // BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
938
+ // so check `userAgent` even if `.v8` exists, but 0
939
+ !version && userAgent$1 && (!(match = userAgent$1.match(/Edge\/(\d+)/)) || match[1] >= 74) && (match = userAgent$1.match(/Chrome\/(\d+)/)) && (version = +match[1]);
1166
940
 
1167
- /**
1168
- * Deep merge multiple objects
1169
- * Later objects override earlier ones
1170
- */ function deepMerge(...objects) {
1171
- if (0 === objects.length) return {};
1172
- if (1 === objects.length) return objects[0];
1173
- const [target, ...sources] = objects, result = {
1174
- ...target
1175
- };
1176
- for (const source of sources) if (source) for (const key in source) {
1177
- if (!Object.prototype.hasOwnProperty.call(source, key)) continue;
1178
- const targetValue = result[key], sourceValue = source[key];
1179
- isObject(targetValue) && isObject(sourceValue) ?
1180
- // Recursively merge objects
1181
- result[key] = deepMerge(targetValue, sourceValue) :
1182
- // Override with source value
1183
- result[key] = sourceValue;
941
+ var environmentV8Version = version, V8_VERSION = environmentV8Version, fails$5 = fails$9, $String$3 = globalThis_1.String, symbolConstructorDetection = !!Object.getOwnPropertySymbols && !fails$5((function() {
942
+ var symbol = Symbol("symbol detection");
943
+ // Chrome 38 Symbol has incorrect toString conversion
944
+ // `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
945
+ // nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will,
946
+ // of course, fail.
947
+ return !$String$3(symbol) || !(Object(symbol) instanceof Symbol) ||
948
+ // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
949
+ !Symbol.sham && V8_VERSION && V8_VERSION < 41;
950
+ })), useSymbolAsUid = symbolConstructorDetection && !Symbol.sham && "symbol" == typeof Symbol.iterator, isCallable$5 = isCallable$8, isPrototypeOf$2 = objectIsPrototypeOf, $Object$2 = Object, isSymbol$2 = useSymbolAsUid ? function(it) {
951
+ return "symbol" == typeof it;
952
+ } : function(it) {
953
+ var $Symbol = function(namespace, method) {
954
+ return arguments.length < 2 ? aFunction(path$2[namespace]) || aFunction(globalThis$b[namespace]) : path$2[namespace] && path$2[namespace][method] || globalThis$b[namespace] && globalThis$b[namespace][method];
955
+ }("Symbol");
956
+ return isCallable$5($Symbol) && isPrototypeOf$2($Symbol.prototype, $Object$2(it));
957
+ }, $String$2 = String, isCallable$4 = isCallable$8, $TypeError$6 = TypeError, aCallable$3 = function(argument) {
958
+ if (isCallable$4(argument)) return argument;
959
+ throw new $TypeError$6(function(argument) {
960
+ try {
961
+ return $String$2(argument);
962
+ } catch (error) {
963
+ return "Object";
964
+ }
965
+ }(argument) + " is not a function");
966
+ }, aCallable$2 = aCallable$3, isNullOrUndefined = isNullOrUndefined$2, call$2 = functionCall, isCallable$3 = isCallable$8, isObject$4 = isObject$5, $TypeError$5 = TypeError, sharedStore = {
967
+ exports: {}
968
+ }, globalThis$7 = globalThis_1, defineProperty = Object.defineProperty, globalThis$6 = globalThis_1, store$1 = sharedStore.exports = globalThis$6["__core-js_shared__"] || function(key, value) {
969
+ try {
970
+ defineProperty(globalThis$7, key, {
971
+ value: value,
972
+ configurable: !0,
973
+ writable: !0
974
+ });
975
+ } catch (error) {
976
+ globalThis$7[key] = value;
1184
977
  }
1185
- return result;
1186
- }
978
+ return value;
979
+ }("__core-js_shared__", {});
1187
980
 
1188
- // ============================================================================
1189
- // Theme Merging
1190
- // ============================================================================
1191
- /**
1192
- * Merge multiple theme options into a single theme options object
1193
- *
1194
- * @param themes - Theme options to merge
1195
- * @returns Merged theme options
1196
- *
1197
- * @example
1198
- * ```typescript
1199
- * const baseTheme = { palette: { primary: { main: '#000' } } };
1200
- * const customTheme = { palette: { secondary: { main: '#fff' } } };
1201
- * const merged = mergeTheme(baseTheme, customTheme);
1202
- * ```
1203
- */ function mergeTheme(...themes) {
1204
- return deepMerge({}, ...themes);
1205
- }
1206
-
1207
- /**
1208
- * Extend an existing theme with new options
1209
- *
1210
- * @param baseTheme - Base theme to extend (can be Theme or ThemeOptions)
1211
- * @param extension - Theme options to extend with
1212
- * @returns New theme with extended options
1213
- *
1214
- * @example
1215
- * ```typescript
1216
- * const base = createTheme({ palette: { primary: { main: '#000' } } });
1217
- * const extended = extendTheme(base, {
1218
- * palette: { secondary: { main: '#fff' } }
1219
- * });
1220
- * ```
1221
- */ function extendTheme(baseTheme, extension) {
1222
- return createThemeObject(mergeTheme(baseTheme.__isJSTheme ? {
1223
- ...baseTheme
1224
- } : baseTheme, extension));
1225
- }
981
+ /* eslint-disable es/no-symbol -- required for testing */ (store$1.versions || (store$1.versions = [])).push({
982
+ version: "3.43.0",
983
+ mode: "pure",
984
+ copyright: "© 2014-2025 Denis Pushkarev (zloirock.ru)",
985
+ license: "https://github.com/zloirock/core-js/blob/v3.43.0/LICENSE",
986
+ source: "https://github.com/zloirock/core-js"
987
+ });
1226
988
 
1227
- // ============================================================================
1228
- // Default Theme Values
1229
- // ============================================================================
1230
- const DEFAULT_PALETTE = {
1231
- primary: {
1232
- main: "#7c3aed",
1233
- // Primary-6
1234
- light: "#d0b2f5",
1235
- // Primary-3
1236
- dark: "#3c1583",
1237
- // Primary-9
1238
- contrastText: "#ffffff"
1239
- },
1240
- secondary: {
1241
- main: "#f3f4f6",
1242
- // Gray-2
1243
- light: "#ffffff",
1244
- // Gray-1
1245
- dark: "#e5e7eb",
1246
- // Gray-3
1247
- contrastText: "#1f2937"
1248
- },
1249
- error: {
1250
- main: "#ef4444",
1251
- // Red-6
1252
- light: "#fca5a5",
1253
- // Red-4
1254
- dark: "#991b1b",
1255
- // Red-9
1256
- contrastText: "#ffffff"
1257
- },
1258
- warning: {
1259
- main: "#eab308",
1260
- // Yellow-6
1261
- light: "#fde047",
1262
- // Yellow-4
1263
- dark: "#854d0e",
1264
- // Yellow-9
1265
- contrastText: "#000000"
1266
- },
1267
- info: {
1268
- main: "#3b82f6",
1269
- // Blue-6
1270
- light: "#93c5fd",
1271
- // Blue-4
1272
- dark: "#1e40af",
1273
- // Blue-9
1274
- contrastText: "#ffffff"
1275
- },
1276
- success: {
1277
- main: "#22c55e",
1278
- // Green-6
1279
- light: "#86efac",
1280
- // Green-4
1281
- dark: "#166534",
1282
- // Green-9
1283
- contrastText: "#ffffff"
1284
- },
1285
- background: {
1286
- default: "#ffffff",
1287
- // Primary-bg
1288
- paper: "#f3f4f6",
1289
- // Secondary-bg
1290
- subtle: "#d1d5db"
1291
- },
1292
- text: {
1293
- primary: "#111827",
1294
- // Gray-10
1295
- secondary: "#374151",
1296
- // Gray-8
1297
- disabled: "#9ca3af"
1298
- }
1299
- }, DEFAULT_TYPOGRAPHY = {
1300
- fontFamily: '"Roboto", "Helvetica Neue", "Helvetica", "Arial", sans-serif',
1301
- fontSize: 16,
1302
- // 1rem
1303
- fontWeightLight: 300,
1304
- fontWeightRegular: 400,
1305
- fontWeightMedium: 500,
1306
- fontWeightSemiBold: 600,
1307
- fontWeightBold: 700,
1308
- fontWeightHeavy: 800,
1309
- fontWeightBlack: 900,
1310
- h1: {
1311
- fontSize: "2.5rem",
1312
- // 40px
1313
- fontWeight: 700,
1314
- lineHeight: 1.3,
1315
- letterSpacing: "-1px"
1316
- },
1317
- h2: {
1318
- fontSize: "2rem",
1319
- // 32px
1320
- fontWeight: 700,
1321
- lineHeight: 1.3,
1322
- letterSpacing: "-1px"
1323
- },
1324
- h3: {
1325
- fontSize: "1.5rem",
1326
- // 24px
1327
- fontWeight: 700,
1328
- lineHeight: 1.3,
1329
- letterSpacing: "-1px"
1330
- },
1331
- h4: {
1332
- fontSize: "1.25rem",
1333
- // 20px
1334
- fontWeight: 700,
1335
- lineHeight: 1.3,
1336
- letterSpacing: "-0.5px"
1337
- },
1338
- h5: {
1339
- fontSize: "1.125rem",
1340
- // 18px
1341
- fontWeight: 700,
1342
- lineHeight: 1.3,
1343
- letterSpacing: "-0.5px"
1344
- },
1345
- h6: {
1346
- fontSize: "1rem",
1347
- // 16px
1348
- fontWeight: 700,
1349
- lineHeight: 1.3,
1350
- letterSpacing: "-0.5px"
1351
- },
1352
- body1: {
1353
- fontSize: "1rem",
1354
- // 16px
1355
- fontWeight: 400,
1356
- lineHeight: 1.2
1357
- },
1358
- body2: {
1359
- fontSize: "0.875rem",
1360
- // 14px
1361
- fontWeight: 400,
1362
- lineHeight: 1.2
989
+ var key, value, store = sharedStore.exports, requireObjectCoercible$1 = requireObjectCoercible$3, $Object$1 = Object, toObject$2 = function(argument) {
990
+ return $Object$1(requireObjectCoercible$1(argument));
991
+ }, toObject$1 = toObject$2, hasOwnProperty = functionUncurryThis({}.hasOwnProperty), hasOwnProperty_1 = Object.hasOwn || function(it, key) {
992
+ return hasOwnProperty(toObject$1(it), key);
993
+ }, uncurryThis$3 = functionUncurryThis, id = 0, postfix = Math.random(), toString$2 = uncurryThis$3(1.1.toString), hasOwn$2 = hasOwnProperty_1, NATIVE_SYMBOL = symbolConstructorDetection, USE_SYMBOL_AS_UID = useSymbolAsUid, Symbol$1 = globalThis_1.Symbol, WellKnownSymbolsStore = store[key = "wks"] || (store[key] = value || {}), createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol$1.for || Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || function(key) {
994
+ return "Symbol(" + (void 0 === key ? "" : key) + ")_" + toString$2(++id + postfix, 36);
995
+ }, wellKnownSymbol$5 = function(name) {
996
+ return hasOwn$2(WellKnownSymbolsStore, name) || (WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn$2(Symbol$1, name) ? Symbol$1[name] : createWellKnownSymbol("Symbol." + name)),
997
+ WellKnownSymbolsStore[name];
998
+ }, call$1 = functionCall, isObject$3 = isObject$5, isSymbol$1 = isSymbol$2, $TypeError$4 = TypeError, TO_PRIMITIVE = wellKnownSymbol$5("toPrimitive"), toPrimitive = function(input, pref) {
999
+ if (!isObject$3(input) || isSymbol$1(input)) return input;
1000
+ var result, func, exoticToPrim = (func = input[TO_PRIMITIVE], isNullOrUndefined(func) ? void 0 : aCallable$2(func));
1001
+ if (exoticToPrim) {
1002
+ if (void 0 === pref && (pref = "default"), result = call$1(exoticToPrim, input, pref),
1003
+ !isObject$3(result) || isSymbol$1(result)) return result;
1004
+ throw new $TypeError$4("Can't convert object to primitive value");
1363
1005
  }
1364
- }, DEFAULT_SHADOWS = {
1365
- xs: "0px 1px 2px 0px rgba(45, 54, 67, 0.04), 0px 2px 4px 0px rgba(45, 54, 67, 0.08)",
1366
- sm: "0 2px 4px rgba(0, 0, 0, 0.075)",
1367
- md: "0 4px 8px rgba(0, 0, 0, 0.1)",
1368
- lg: "0 16px 48px rgba(0, 0, 0, 0.175)",
1369
- xl: "0px 16px 64px -8px rgba(45, 54, 67, 0.14)",
1370
- inset: "inset 0 1px 2px rgba(0, 0, 0, 0.075)"
1371
- }, DEFAULT_TRANSITIONS = {
1372
- duration: {
1373
- shortest: 150,
1374
- shorter: 200,
1375
- short: 250,
1376
- standard: 300,
1377
- complex: 375,
1378
- enteringScreen: 225,
1379
- leavingScreen: 195
1380
- },
1381
- easing: {
1382
- easeInOut: "cubic-bezier(0.4, 0, 0.2, 1)",
1383
- easeOut: "cubic-bezier(0.0, 0, 0.2, 1)",
1384
- easeIn: "cubic-bezier(0.4, 0, 1, 1)",
1385
- sharp: "cubic-bezier(0.4, 0, 0.6, 1)"
1006
+ return void 0 === pref && (pref = "number"), function(input, pref) {
1007
+ var fn, val;
1008
+ if ("string" === pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
1009
+ if (isCallable$3(fn = input.valueOf) && !isObject$4(val = call$2(fn, input))) return val;
1010
+ if ("string" !== pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
1011
+ throw new $TypeError$5("Can't convert object to primitive value");
1012
+ }(input, pref);
1013
+ }, isSymbol = isSymbol$2, toPropertyKey$2 = function(argument) {
1014
+ var key = toPrimitive(argument, "string");
1015
+ return isSymbol(key) ? key : key + "";
1016
+ }, isObject$2 = isObject$5, document$1 = globalThis_1.document, EXISTS = isObject$2(document$1) && isObject$2(document$1.createElement), ie8DomDefine = !descriptors && !fails$9((function() {
1017
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
1018
+ return 7 !== Object.defineProperty((it = "div", EXISTS ? document$1.createElement(it) : {}), "a", {
1019
+ get: function() {
1020
+ return 7;
1021
+ }
1022
+ }).a;
1023
+ var it;
1024
+ })), DESCRIPTORS$3 = descriptors, call = functionCall, propertyIsEnumerableModule = objectPropertyIsEnumerable, createPropertyDescriptor$1 = createPropertyDescriptor$2, toIndexedObject$1 = toIndexedObject$2, toPropertyKey$1 = toPropertyKey$2, hasOwn$1 = hasOwnProperty_1, IE8_DOM_DEFINE$1 = ie8DomDefine, $getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor;
1025
+
1026
+ // `Object.getOwnPropertyDescriptor` method
1027
+ // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
1028
+ objectGetOwnPropertyDescriptor.f = DESCRIPTORS$3 ? $getOwnPropertyDescriptor$1 : function(O, P) {
1029
+ if (O = toIndexedObject$1(O), P = toPropertyKey$1(P), IE8_DOM_DEFINE$1) try {
1030
+ return $getOwnPropertyDescriptor$1(O, P);
1031
+ } catch (error) {/* empty */}
1032
+ if (hasOwn$1(O, P)) return createPropertyDescriptor$1(!call(propertyIsEnumerableModule.f, O, P), O[P]);
1033
+ };
1034
+
1035
+ var fails$3 = fails$9, isCallable$2 = isCallable$8, replacement = /#|\.prototype\./, isForced$1 = function(feature, detection) {
1036
+ var value = data[normalize(feature)];
1037
+ return value === POLYFILL || value !== NATIVE && (isCallable$2(detection) ? fails$3(detection) : !!detection);
1038
+ }, normalize = isForced$1.normalize = function(string) {
1039
+ return String(string).replace(replacement, ".").toLowerCase();
1040
+ }, data = isForced$1.data = {}, NATIVE = isForced$1.NATIVE = "N", POLYFILL = isForced$1.POLYFILL = "P", isForced_1 = isForced$1, aCallable$1 = aCallable$3, NATIVE_BIND = functionBindNative, bind$1 = functionUncurryThisClause(functionUncurryThisClause.bind), objectDefineProperty = {}, v8PrototypeDefineBug = descriptors && fails$9((function() {
1041
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
1042
+ return 42 !== Object.defineProperty((function() {/* empty */}), "prototype", {
1043
+ value: 42,
1044
+ writable: !1
1045
+ }).prototype;
1046
+ })), isObject$1 = isObject$5, $String$1 = String, $TypeError$3 = TypeError, DESCRIPTORS$1 = descriptors, IE8_DOM_DEFINE = ie8DomDefine, V8_PROTOTYPE_DEFINE_BUG = v8PrototypeDefineBug, anObject = function(argument) {
1047
+ if (isObject$1(argument)) return argument;
1048
+ throw new $TypeError$3($String$1(argument) + " is not an object");
1049
+ }, toPropertyKey = toPropertyKey$2, $TypeError$2 = TypeError, $defineProperty = Object.defineProperty, $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
1050
+
1051
+ // `Object.defineProperty` method
1052
+ // https://tc39.es/ecma262/#sec-object.defineproperty
1053
+ objectDefineProperty.f = DESCRIPTORS$1 ? V8_PROTOTYPE_DEFINE_BUG ? function(O, P, Attributes) {
1054
+ if (anObject(O), P = toPropertyKey(P), anObject(Attributes), "function" == typeof O && "prototype" === P && "value" in Attributes && "writable" in Attributes && !Attributes.writable) {
1055
+ var current = $getOwnPropertyDescriptor(O, P);
1056
+ current && current.writable && (O[P] = Attributes.value, Attributes = {
1057
+ configurable: "configurable" in Attributes ? Attributes.configurable : current.configurable,
1058
+ enumerable: "enumerable" in Attributes ? Attributes.enumerable : current.enumerable,
1059
+ writable: !1
1060
+ });
1386
1061
  }
1387
- }, DEFAULT_ZINDEX = {
1388
- mobileStepper: 1e3,
1389
- speedDial: 1050,
1390
- appBar: 1020,
1391
- drawer: 1070,
1392
- modal: 1040,
1393
- snackbar: 1080,
1394
- tooltip: 1060
1395
- }, DEFAULT_BORDER_RADIUS = {
1396
- base: "0.5rem",
1397
- // 8px (spacing-2)
1398
- sm: "0.25rem",
1399
- // 4px (spacing-1)
1400
- md: "0.25rem",
1401
- // 4px (spacing-1)
1402
- lg: "0.625rem",
1403
- // 10px (spacing-2.5)
1404
- xl: "0.75rem",
1405
- // 12px (spacing-3)
1406
- xxl: "1rem",
1407
- // 16px (spacing-4)
1408
- "3xl": "1.5rem",
1409
- // 24px (spacing-6)
1410
- "4xl": "2rem",
1411
- // 32px (spacing-8)
1412
- pill: "50rem"
1062
+ return $defineProperty(O, P, Attributes);
1063
+ } : $defineProperty : function(O, P, Attributes) {
1064
+ if (anObject(O), P = toPropertyKey(P), anObject(Attributes), IE8_DOM_DEFINE) try {
1065
+ return $defineProperty(O, P, Attributes);
1066
+ } catch (error) {/* empty */}
1067
+ if ("get" in Attributes || "set" in Attributes) throw new $TypeError$2("Accessors not supported");
1068
+ return "value" in Attributes && (O[P] = Attributes.value), O;
1413
1069
  };
1414
1070
 
1415
- // ============================================================================
1416
- // Helper Functions
1417
- // ============================================================================
1418
- /**
1419
- * Create a complete palette color from partial configuration
1420
- */
1421
- function createPaletteColor(color) {
1422
- return "string" == typeof color ? {
1423
- main: color,
1424
- light: lighten(color),
1425
- dark: darken(color),
1426
- contrastText: getContrastText(color)
1427
- } : {
1428
- main: color.main || "#000000",
1429
- light: color.light || lighten(color.main || "#000000"),
1430
- dark: color.dark || darken(color.main || "#000000"),
1431
- contrastText: color.contrastText || getContrastText(color.main || "#000000")
1071
+ var definePropertyModule = objectDefineProperty, createPropertyDescriptor = createPropertyDescriptor$2, createNonEnumerableProperty$1 = descriptors ? function(object, key, value) {
1072
+ return definePropertyModule.f(object, key, createPropertyDescriptor(1, value));
1073
+ } : function(object, key, value) {
1074
+ return object[key] = value, object;
1075
+ }, globalThis$3 = globalThis_1, apply = functionApply, uncurryThis$1 = functionUncurryThisClause, isCallable$1 = isCallable$8, getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f, isForced = isForced_1, path$1 = path$3, bind = function(fn, that) {
1076
+ return aCallable$1(fn), void 0 === that ? fn : NATIVE_BIND ? bind$1(fn, that) : function() {
1077
+ return fn.apply(that, arguments);
1078
+ };
1079
+ }, createNonEnumerableProperty = createNonEnumerableProperty$1, hasOwn = hasOwnProperty_1, wrapConstructor = function(NativeConstructor) {
1080
+ var Wrapper = function(a, b, c) {
1081
+ if (this instanceof Wrapper) {
1082
+ switch (arguments.length) {
1083
+ case 0:
1084
+ return new NativeConstructor;
1085
+
1086
+ case 1:
1087
+ return new NativeConstructor(a);
1088
+
1089
+ case 2:
1090
+ return new NativeConstructor(a, b);
1091
+ }
1092
+ return new NativeConstructor(a, b, c);
1093
+ }
1094
+ return apply(NativeConstructor, this, arguments);
1432
1095
  };
1433
- }
1096
+ return Wrapper.prototype = NativeConstructor.prototype, Wrapper;
1097
+ }, _export = function(options, source) {
1098
+ var FORCED, USE_NATIVE, VIRTUAL_PROTOTYPE, key, sourceProperty, targetProperty, nativeProperty, resultProperty, descriptor, TARGET = options.target, GLOBAL = options.global, STATIC = options.stat, PROTO = options.proto, nativeSource = GLOBAL ? globalThis$3 : STATIC ? globalThis$3[TARGET] : globalThis$3[TARGET] && globalThis$3[TARGET].prototype, target = GLOBAL ? path$1 : path$1[TARGET] || createNonEnumerableProperty(path$1, TARGET, {})[TARGET], targetPrototype = target.prototype;
1099
+ for (key in source)
1100
+ // contains in native
1101
+ USE_NATIVE = !(FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? "." : "#") + key, options.forced)) && nativeSource && hasOwn(nativeSource, key),
1102
+ targetProperty = target[key], USE_NATIVE && (nativeProperty = options.dontCallGetSet ? (descriptor = getOwnPropertyDescriptor(nativeSource, key)) && descriptor.value : nativeSource[key]),
1103
+ // export native or implementation
1104
+ sourceProperty = USE_NATIVE && nativeProperty ? nativeProperty : source[key], (FORCED || PROTO || typeof targetProperty != typeof sourceProperty) && (
1105
+ // bind methods to global for calling from export context
1106
+ resultProperty = options.bind && USE_NATIVE ? bind(sourceProperty, globalThis$3) : options.wrap && USE_NATIVE ? wrapConstructor(sourceProperty) : PROTO && isCallable$1(sourceProperty) ? uncurryThis$1(sourceProperty) : sourceProperty,
1107
+ // add a flag to not completely full polyfills
1108
+ (options.sham || sourceProperty && sourceProperty.sham || targetProperty && targetProperty.sham) && createNonEnumerableProperty(resultProperty, "sham", !0),
1109
+ createNonEnumerableProperty(target, key, resultProperty), PROTO && (hasOwn(path$1, VIRTUAL_PROTOTYPE = TARGET + "Prototype") || createNonEnumerableProperty(path$1, VIRTUAL_PROTOTYPE, {}),
1110
+ // export virtual prototype methods
1111
+ createNonEnumerableProperty(path$1[VIRTUAL_PROTOTYPE], key, sourceProperty),
1112
+ // export real prototype methods
1113
+ options.real && targetPrototype && (FORCED || !targetPrototype[key]) && createNonEnumerableProperty(targetPrototype, key, sourceProperty)));
1114
+ }, ceil = Math.ceil, floor = Math.floor, trunc = Math.trunc || function(x) {
1115
+ var n = +x;
1116
+ return (n > 0 ? floor : ceil)(n);
1117
+ }, toIntegerOrInfinity$2 = function(argument) {
1118
+ var number = +argument;
1119
+ // eslint-disable-next-line no-self-compare -- NaN check
1120
+ return number != number || 0 === number ? 0 : trunc(number);
1121
+ }, toIntegerOrInfinity$1 = toIntegerOrInfinity$2, max = Math.max, min$1 = Math.min, toIntegerOrInfinity = toIntegerOrInfinity$2, min = Math.min, lengthOfArrayLike$2 = function(obj) {
1122
+ return argument = obj.length, (len = toIntegerOrInfinity(argument)) > 0 ? min(len, 9007199254740991) : 0;
1123
+ var argument, len;
1124
+ }, toIndexedObject = toIndexedObject$2, lengthOfArrayLike$1 = lengthOfArrayLike$2, createMethod$1 = function(IS_INCLUDES) {
1125
+ return function($this, el, fromIndex) {
1126
+ var O = toIndexedObject($this), length = lengthOfArrayLike$1(O);
1127
+ if (0 === length) return !IS_INCLUDES && -1;
1128
+ var value, index = function(index, length) {
1129
+ var integer = toIntegerOrInfinity$1(index);
1130
+ return integer < 0 ? max(integer + length, 0) : min$1(integer, length);
1131
+ }(fromIndex, length);
1132
+ // Array#includes uses SameValueZero equality algorithm
1133
+ // eslint-disable-next-line no-self-compare -- NaN check
1134
+ if (IS_INCLUDES && el != el) {
1135
+ for (;length > index; )
1136
+ // eslint-disable-next-line no-self-compare -- NaN check
1137
+ if ((value = O[index++]) != value) return !0;
1138
+ // Array#indexOf ignores holes, Array#includes - not
1139
+ } else for (;length > index; index++) if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
1140
+ return !IS_INCLUDES && -1;
1141
+ };
1142
+ }, $includes = [ createMethod$1(!0), createMethod$1(!1) ][0];
1434
1143
 
1435
- /**
1436
- * Create breakpoints object
1437
- */
1438
- // ============================================================================
1439
- // Main createTheme Function
1440
- // ============================================================================
1441
- /**
1442
- * Create a theme object with computed values
1443
- *
1444
- * @param options - Theme configuration options
1445
- * @returns Complete theme object
1446
- */
1447
- function createThemeObject(...options) {
1448
- // Merge all options
1449
- const mergedOptions = _reduceInstanceProperty(options).call(options, ((acc, option) => deepMerge(acc, option)), {}), palette = {
1450
- primary: createPaletteColor(mergedOptions.palette?.primary || DEFAULT_PALETTE.primary),
1451
- secondary: createPaletteColor(mergedOptions.palette?.secondary || DEFAULT_PALETTE.secondary),
1452
- error: createPaletteColor(mergedOptions.palette?.error || DEFAULT_PALETTE.error),
1453
- warning: createPaletteColor(mergedOptions.palette?.warning || DEFAULT_PALETTE.warning),
1454
- info: createPaletteColor(mergedOptions.palette?.info || DEFAULT_PALETTE.info),
1455
- success: createPaletteColor(mergedOptions.palette?.success || DEFAULT_PALETTE.success),
1456
- // Handle light and dark colors if provided
1457
- ...mergedOptions.palette?.light && {
1458
- light: createPaletteColor(mergedOptions.palette.light)
1459
- },
1460
- ...mergedOptions.palette?.dark && {
1461
- dark: createPaletteColor(mergedOptions.palette.dark)
1462
- },
1463
- background: {
1464
- default: mergedOptions.palette?.background?.default || DEFAULT_PALETTE.background.default,
1465
- subtle: mergedOptions.palette?.background?.subtle || DEFAULT_PALETTE.background.subtle
1466
- },
1467
- text: {
1468
- primary: mergedOptions.palette?.text?.primary || DEFAULT_PALETTE.text.primary,
1469
- secondary: mergedOptions.palette?.text?.secondary || DEFAULT_PALETTE.text.secondary,
1470
- disabled: mergedOptions.palette?.text?.disabled || DEFAULT_PALETTE.text.disabled
1144
+ // `Array.prototype.includes` method
1145
+ // https://tc39.es/ecma262/#sec-array.prototype.includes
1146
+ _export({
1147
+ target: "Array",
1148
+ proto: !0,
1149
+ forced: fails$9((function() {
1150
+ // eslint-disable-next-line es/no-array-prototype-includes -- detection
1151
+ return !Array(1).includes();
1152
+ }))
1153
+ }, {
1154
+ includes: function(el /* , fromIndex = 0 */) {
1155
+ return $includes(this, el, arguments.length > 1 ? arguments[1] : void 0);
1156
+ }
1157
+ });
1158
+
1159
+ var globalThis$2 = globalThis_1, path = path$3, getBuiltInPrototypeMethod$3 = function(CONSTRUCTOR, METHOD) {
1160
+ var Namespace = path[CONSTRUCTOR + "Prototype"], pureMethod = Namespace && Namespace[METHOD];
1161
+ if (pureMethod) return pureMethod;
1162
+ var NativeConstructor = globalThis$2[CONSTRUCTOR], NativePrototype = NativeConstructor && NativeConstructor.prototype;
1163
+ return NativePrototype && NativePrototype[METHOD];
1164
+ }, includes$4 = getBuiltInPrototypeMethod$3("Array", "includes"), isObject = isObject$5, classof$3 = classofRaw$2, MATCH$1 = wellKnownSymbol$5("match"), $TypeError$1 = TypeError, test = {};
1165
+
1166
+ test[wellKnownSymbol$5("toStringTag")] = "z";
1167
+
1168
+ var TO_STRING_TAG_SUPPORT = "[object z]" === String(test), isCallable = isCallable$8, classofRaw = classofRaw$2, TO_STRING_TAG = wellKnownSymbol$5("toStringTag"), $Object = Object, CORRECT_ARGUMENTS = "Arguments" === classofRaw(function() {
1169
+ return arguments;
1170
+ }()), classof$1 = TO_STRING_TAG_SUPPORT ? classofRaw : function(it) {
1171
+ var O, tag, result;
1172
+ return void 0 === it ? "Undefined" : null === it ? "Null" : "string" == typeof (tag = function(it, key) {
1173
+ try {
1174
+ return it[key];
1175
+ } catch (error) {/* empty */}
1176
+ }(O = $Object(it), TO_STRING_TAG)) ? tag : CORRECT_ARGUMENTS ? classofRaw(O) : "Object" === (result = classofRaw(O)) && isCallable(O.callee) ? "Arguments" : result;
1177
+ }, $String = String, MATCH = wellKnownSymbol$5("match"), $$1 = _export, notARegExp = function(it) {
1178
+ if (function(it) {
1179
+ var isRegExp;
1180
+ return isObject(it) && (void 0 !== (isRegExp = it[MATCH$1]) ? !!isRegExp : "RegExp" === classof$3(it));
1181
+ }(it)) throw new $TypeError$1("The method doesn't accept regular expressions");
1182
+ return it;
1183
+ }, requireObjectCoercible = requireObjectCoercible$3, toString = function(argument) {
1184
+ if ("Symbol" === classof$1(argument)) throw new TypeError("Cannot convert a Symbol value to a string");
1185
+ return $String(argument);
1186
+ }, stringIndexOf = functionUncurryThis("".indexOf);
1187
+
1188
+ // `String.prototype.includes` method
1189
+ // https://tc39.es/ecma262/#sec-string.prototype.includes
1190
+ $$1({
1191
+ target: "String",
1192
+ proto: !0,
1193
+ forced: !function(METHOD_NAME) {
1194
+ var regexp = /./;
1195
+ try {
1196
+ "/./"[METHOD_NAME](regexp);
1197
+ } catch (error1) {
1198
+ try {
1199
+ return regexp[MATCH] = !1, "/./"[METHOD_NAME](regexp);
1200
+ } catch (error2) {/* empty */}
1471
1201
  }
1472
- }, typography = deepMerge({
1473
- ...DEFAULT_TYPOGRAPHY
1474
- }, mergedOptions.typography || {}), spacing =
1475
- // ============================================================================
1476
- // Spacing Utilities
1477
- // ============================================================================
1478
- /**
1479
- * Create a spacing function from various input types
1480
- *
1481
- * @param spacingInput - Spacing configuration (number, array, or function), default 4
1482
- * @returns Spacing function
1483
- */
1484
- function(spacingInput = 4) {
1485
- // If it's already a function, return it
1486
- return "function" == typeof spacingInput ? spacingInput :
1487
- // If it's a number, create a function that multiplies by that number
1488
- "number" == typeof spacingInput ? (...values) => 0 === values.length ? "0px" : values.map((value => value * spacingInput + "px")).join(" ") :
1489
- // If it's an array, use it as a scale
1490
- 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(" ");
1202
+ return !1;
1203
+ }("includes")
1204
+ }, {
1205
+ includes: function(searchString /* , position = 0 */) {
1206
+ return !!~stringIndexOf(toString(requireObjectCoercible(this)), toString(notARegExp(searchString)), arguments.length > 1 ? arguments[1] : void 0);
1491
1207
  }
1492
- /**
1493
- * Check if a theme is a JS theme (created with createTheme)
1494
- */ (mergedOptions.spacing), breakpoints = function(breakpointsInput) {
1495
- const values = {
1496
- xs: 0,
1497
- sm: 576,
1498
- md: 768,
1499
- lg: 992,
1500
- xl: 1200,
1501
- xxl: 1440,
1502
- ...breakpointsInput?.values
1503
- }, unit = breakpointsInput?.unit || "px";
1504
- return {
1505
- values: values,
1506
- unit: unit,
1507
- up: key => `@media (min-width:${"number" == typeof key ? key : values[key] ?? 0}${unit})`,
1508
- down: key => `@media (max-width:${("number" == typeof key ? key : values[key] ?? 0) - .05}${unit})`,
1509
- between: (start, end) => {
1510
- const startValue = "number" == typeof start ? start : values[start] ?? 0, endValue = "number" == typeof end ? end : values[end] ?? 0;
1511
- return `@media (min-width:${startValue}${unit}) and (max-width:${endValue - .05}${unit})`;
1512
- }
1513
- };
1514
- }(mergedOptions.breakpoints), shadows = deepMerge({
1515
- ...DEFAULT_SHADOWS
1516
- }, mergedOptions.shadows || {}), transitions = deepMerge({
1517
- ...DEFAULT_TRANSITIONS
1518
- }, mergedOptions.transitions || {}), zIndex = deepMerge({
1519
- ...DEFAULT_ZINDEX
1520
- }, mergedOptions.zIndex || {}), borderRadius = deepMerge({
1521
- ...DEFAULT_BORDER_RADIUS
1522
- }, mergedOptions.borderRadius || {});
1523
- // Create palette
1524
- return {
1525
- // Metadata
1526
- name: mergedOptions.name || "Custom Theme",
1527
- class: mergedOptions.class,
1528
- description: mergedOptions.description,
1529
- author: mergedOptions.author,
1530
- version: mergedOptions.version || "1.0.0",
1531
- tags: mergedOptions.tags,
1532
- supportsDarkMode: mergedOptions.supportsDarkMode,
1533
- status: mergedOptions.status || "experimental",
1534
- a11y: mergedOptions.a11y,
1535
- color: mergedOptions.color || palette.primary.main,
1536
- features: mergedOptions.features,
1537
- dependencies: mergedOptions.dependencies,
1538
- // Theme configuration
1539
- palette: palette,
1540
- typography: typography,
1541
- spacing: spacing,
1542
- breakpoints: breakpoints,
1543
- shadows: shadows,
1544
- transitions: transitions,
1545
- zIndex: zIndex,
1546
- borderRadius: borderRadius,
1547
- custom: mergedOptions.custom || {},
1548
- // Mark as JS theme
1549
- __isJSTheme: !0
1550
- };
1551
- }
1208
+ });
1552
1209
 
1553
- /**
1554
- * Create a new theme registry
1555
- */ function createThemeRegistry() {
1556
- return {};
1557
- }
1210
+ var includes$3 = getBuiltInPrototypeMethod$3("String", "includes"), isPrototypeOf$1 = objectIsPrototypeOf, arrayMethod = includes$4, stringMethod = includes$3, ArrayPrototype$1 = Array.prototype, StringPrototype = String.prototype;
1211
+
1212
+ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
1213
+ var own = it.includes;
1214
+ return it === ArrayPrototype$1 || isPrototypeOf$1(ArrayPrototype$1, it) && own === ArrayPrototype$1.includes ? arrayMethod : "string" == typeof it || it === StringPrototype || isPrototypeOf$1(StringPrototype, it) && own === StringPrototype.includes ? stringMethod : own;
1215
+ }));
1558
1216
 
1559
1217
  /**
1560
- * Register a theme
1561
- * @param registry - Theme registry object
1562
- * @param id - Theme identifier
1563
- * @param metadata - Theme metadata
1564
- */ function registerTheme(registry, id, metadata) {
1565
- registry[id] = metadata;
1566
- }
1567
-
1218
+ * Theme System Constants
1219
+ *
1220
+ * Centralized constants for the theme system to avoid magic numbers and strings.
1221
+ */
1568
1222
  /**
1569
- * Unregister a theme
1570
- * @param registry - Theme registry object
1571
- * @param id - Theme identifier
1572
- */ function unregisterTheme(registry, id) {
1573
- const exists = id in registry;
1574
- return delete registry[id], exists;
1575
- }
1223
+ * Default storage key for theme persistence
1224
+ */ "undefined" != typeof process && process.env;
1576
1225
 
1577
1226
  /**
1578
- * Check if a theme is registered
1579
- * @param registry - Theme registry object
1580
- * @param id - Theme identifier
1581
- */ function hasTheme(registry, id) {
1582
- return id in registry;
1583
- }
1227
+ * Check if code is running in a browser environment
1228
+ */
1229
+ 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
1230
+ , buildThemePath = (themeName, basePath = "/themes", useMinified = !1, cdnPath = null) => {
1231
+ // Validate theme name to prevent path injection
1232
+ 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, {
1233
+ themeName: themeName,
1234
+ pattern: /^[a-z0-9]+(-[a-z0-9]+)*$/
1235
+ });
1236
+ const fileName = `${themeName}${useMinified ? ".min.css" : ".css"}`;
1237
+ return cdnPath ? `${sanitizePath(cdnPath)}/${fileName}` : `${sanitizePath(basePath)}/${fileName.replace(/^\//, "")}`;
1238
+ // Sanitize basePath to prevent path injection
1239
+ }, applyThemeAttributes = (dataAttribute, themeName) => {
1240
+ isServer() || (
1241
+ // Set data attribute on body (with null check)
1242
+ document.body && document.body.setAttribute(dataAttribute, themeName),
1243
+ // Also set on documentElement for broader compatibility
1244
+ document.documentElement.setAttribute(dataAttribute, themeName));
1245
+ }, isValidThemeName = themeName => !(!themeName || "string" != typeof themeName) && /^[a-z0-9]+(-[a-z0-9]+)*$/.test(themeName), createLocalStorageAdapter = () => ({
1246
+ getItem: key => {
1247
+ if (isServer()) return null;
1248
+ try {
1249
+ return localStorage.getItem(key);
1250
+ } catch {
1251
+ return null;
1252
+ }
1253
+ },
1254
+ setItem: (key, value) => {
1255
+ if (!isServer()) try {
1256
+ localStorage.setItem(key, value);
1257
+ } catch {
1258
+ // Silently fail if localStorage is not available
1259
+ }
1260
+ },
1261
+ removeItem: key => {
1262
+ if (!isServer()) try {
1263
+ localStorage.removeItem(key);
1264
+ } catch {
1265
+ // Silently fail
1266
+ }
1267
+ },
1268
+ isAvailable: () => {
1269
+ if (isServer()) return !1;
1270
+ try {
1271
+ const test = "__atomix_storage_test__";
1272
+ return localStorage.setItem(test, test), localStorage.removeItem(test), !0;
1273
+ } catch {
1274
+ return !1;
1275
+ }
1276
+ }
1277
+ }), domUtils = Object.freeze( Object.defineProperty({
1278
+ __proto__: null,
1279
+ applyThemeAttributes: applyThemeAttributes,
1280
+ buildThemePath: buildThemePath,
1281
+ createLocalStorageAdapter: createLocalStorageAdapter,
1282
+ isBrowser: isBrowser,
1283
+ isServer: isServer,
1284
+ isValidThemeName: isValidThemeName,
1285
+ loadThemeCSS: (fullPath, linkId) => isServer() ? Promise.resolve() : new Promise(((resolve, reject) => {
1286
+ if (document.getElementById(linkId)) return void resolve();
1287
+ // Create link element
1288
+ const link = document.createElement("link");
1289
+ link.id = linkId, link.rel = "stylesheet", link.type = "text/css", link.href = fullPath,
1290
+ // Add data attribute for tracking
1291
+ link.setAttribute("data-atomix-theme", "true"),
1292
+ // Handle load success
1293
+ link.onload = () => {
1294
+ resolve();
1295
+ },
1296
+ // Handle load error
1297
+ link.onerror = () => {
1298
+ // Remove failed link element
1299
+ link.remove(), reject(new ThemeError(`Failed to load theme CSS from: ${fullPath}. Please check that the file exists and is accessible.`, ThemeErrorCode.THEME_LOAD_FAILED, {
1300
+ fullPath: fullPath,
1301
+ linkId: linkId
1302
+ }));
1303
+ },
1304
+ // Append to head
1305
+ document.head.appendChild(link);
1306
+ }))
1307
+ }, Symbol.toStringTag, {
1308
+ value: "Module"
1309
+ }));
1584
1310
 
1585
1311
  /**
1586
- * Get theme metadata
1587
- * @param registry - Theme registry object
1588
- * @param id - Theme identifier
1589
- */ function getTheme(registry, id) {
1590
- return registry[id];
1591
- }
1592
-
1312
+ * Check if code is running on the server (SSR)
1313
+ */
1593
1314
  /**
1594
- * Get all registered theme metadata
1595
- * @param registry - Theme registry object
1596
- */ function getAllThemes(registry) {
1597
- return Object.values(registry);
1598
- }
1599
-
1315
+ * Theme Utilities
1316
+ *
1317
+ * Helper utilities for working with themes, including color manipulation,
1318
+ * spacing helpers, and theme value accessors.
1319
+ */
1320
+ // ============================================================================
1321
+ // Color Manipulation Utilities
1322
+ // ============================================================================
1600
1323
  /**
1601
- * Get all registered theme IDs
1602
- * @param registry - Theme registry object
1603
- */ function getThemeIds(registry) {
1604
- return Object.keys(registry);
1324
+ * Convert hex color to RGB object
1325
+ */
1326
+ function hexToRgb(hex) {
1327
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1328
+ return result ? {
1329
+ r: parseInt(result[1], 16),
1330
+ g: parseInt(result[2], 16),
1331
+ b: parseInt(result[3], 16)
1332
+ } : null;
1605
1333
  }
1606
1334
 
1607
1335
  /**
1608
- * Clear all registered themes
1609
- * @param registry - Theme registry object
1610
- */ function clearThemes(registry) {
1611
- Object.keys(registry).forEach((key => delete registry[key]));
1336
+ * Convert RGB to hex color
1337
+ */ function rgbToHex(r, g, b) {
1338
+ const toHex = val => Math.round(Math.max(0, Math.min(255, val))).toString(16).padStart(2, "0");
1339
+ return `#${toHex(r ?? 0)}${toHex(g ?? 0)}${toHex(b ?? 0)}`;
1612
1340
  }
1613
1341
 
1614
1342
  /**
1615
- * Get the number of registered themes
1616
- * @param registry - Theme registry object
1617
- */ function getThemeCount(registry) {
1618
- return Object.keys(registry).length;
1343
+ * Calculate relative luminance of a color
1344
+ * Used for determining contrast ratios
1345
+ */ function getLuminance(color) {
1346
+ const rgb = hexToRgb(color);
1347
+ if (!rgb) return 0;
1348
+ const {r: r, g: g, b: b} = rgb, [rs, gs, bs] = [ r ?? 0, g ?? 0, b ?? 0 ].map((c => {
1349
+ const val = c / 255;
1350
+ return val <= .03928 ? val / 12.92 : Math.pow((val + .055) / 1.055, 2.4);
1351
+ }));
1352
+ return .2126 * (rs ?? 0) + .7152 * (gs ?? 0) + .0722 * (bs ?? 0);
1619
1353
  }
1620
1354
 
1621
1355
  /**
1622
- * CSS Injection Utilities
1623
- *
1624
- * Inject CSS into HTML head via <style> element.
1625
- */
1626
- /**
1627
- * Check if running in browser environment
1628
- */ function isBrowser$1() {
1629
- return "undefined" != typeof document;
1356
+ * Calculate contrast ratio between two colors
1357
+ */ function getContrastRatio(foreground, background) {
1358
+ const lumA = getLuminance(foreground), lumB = getLuminance(background);
1359
+ return (Math.max(lumA, lumB) + .05) / (Math.min(lumA, lumB) + .05);
1630
1360
  }
1631
1361
 
1632
1362
  /**
1633
- * Inject CSS into HTML head via <style> element
1634
- *
1635
- * Creates or updates a style element in the document head.
1636
- * If an element with the same ID exists, it will be updated.
1637
- *
1638
- * @param css - CSS string to inject
1639
- * @param id - Style element ID (default: 'atomix-theme')
1640
- *
1641
- * @example
1642
- * ```typescript
1643
- * const css = ':root { --atomix-color-primary: #7AFFD7; }';
1644
- * injectCSS(css);
1645
- *
1646
- * // With custom ID
1647
- * injectCSS(css, 'my-custom-theme');
1648
- * ```
1649
- */ function injectCSS$1(css, id = "atomix-theme") {
1650
- if (!isBrowser$1()) return void console.warn("injectCSS: Not in browser environment, CSS not injected");
1651
- let styleElement = document.getElementById(id);
1652
- styleElement || (styleElement = document.createElement("style"), styleElement.id = id,
1653
- styleElement.setAttribute("data-atomix-theme", "true"), document.head.appendChild(styleElement)),
1654
- styleElement.textContent = css;
1363
+ * Get appropriate contrast text color (black or white) for a background color
1364
+ */ function getContrastText(background, threshold = 3) {
1365
+ const contrastWithWhite = getContrastRatio("#FFFFFF", background), contrastWithBlack = getContrastRatio("#000000", background);
1366
+ return contrastWithWhite >= threshold ? "#FFFFFF" : contrastWithBlack >= threshold ? "#000000" : contrastWithWhite > contrastWithBlack ? "#FFFFFF" : "#000000";
1655
1367
  }
1656
1368
 
1657
1369
  /**
1658
- * Remove injected CSS from DOM
1659
- *
1660
- * Removes the style element with the given ID from the document head.
1661
- *
1662
- * @param id - Style element ID to remove (default: 'atomix-theme')
1370
+ * Lighten a color by a given amount
1663
1371
  *
1664
- * @example
1665
- * ```typescript
1666
- * removeCSS(); // Removes default 'atomix-theme'
1667
- * removeCSS('my-custom-theme'); // Removes custom ID
1668
- * ```
1669
- */ function removeCSS(id = "atomix-theme") {
1670
- if (!isBrowser$1()) return;
1671
- const styleElement = document.getElementById(id);
1672
- styleElement && styleElement.remove();
1372
+ * @param color - Hex color string
1373
+ * @param amount - Amount to lighten (0-1), default 0.2
1374
+ * @returns Lightened hex color
1375
+ */ function lighten(color, amount = .2) {
1376
+ const rgb = hexToRgb(color);
1377
+ if (!rgb) return color;
1378
+ const {r: r, g: g, b: b} = rgb, lightenValue = val => Math.min(255, Math.round(val + (255 - val) * amount));
1379
+ return rgbToHex(lightenValue(r), lightenValue(g), lightenValue(b));
1673
1380
  }
1674
1381
 
1675
1382
  /**
1676
- * Check if CSS is already injected
1383
+ * Darken a color by a given amount
1677
1384
  *
1678
- * @param id - Style element ID to check (default: 'atomix-theme')
1679
- * @returns True if style element exists
1680
- */ function isCSSInjected(id = "atomix-theme") {
1681
- return !!isBrowser$1() && null !== document.getElementById(id);
1385
+ * @param color - Hex color string
1386
+ * @param amount - Amount to darken (0-1), default 0.2
1387
+ * @returns Darkened hex color
1388
+ */ function darken(color, amount = .2) {
1389
+ const rgb = hexToRgb(color);
1390
+ if (!rgb) return color;
1391
+ const {r: r, g: g, b: b} = rgb, darkenValue = val => Math.max(0, Math.round(val * (1 - amount)));
1392
+ return rgbToHex(darkenValue(r), darkenValue(g), darkenValue(b));
1682
1393
  }
1683
1394
 
1684
1395
  /**
1685
- * CSS File Utilities
1686
- *
1687
- * Save CSS to file system (Node.js only).
1688
- */
1689
- /**
1690
- * Save CSS to file
1691
- *
1692
- * Writes CSS string to a file. Only works in Node.js environment.
1693
- *
1694
- * @param css - CSS string to save
1695
- * @param filePath - Output file path
1696
- * @throws Error if called in browser environment
1396
+ * Add alpha (opacity) to a color
1697
1397
  *
1698
- * @example
1699
- * ```typescript
1700
- * const css = ':root { --atomix-color-primary: #7AFFD7; }';
1701
- * await saveCSSFile(css, './themes/custom.css');
1702
- * ```
1703
- */ "undefined" != typeof process && process.env;
1704
-
1705
- /**
1706
- * Check if code is running in a browser environment
1707
- */
1708
- const isBrowser = () => "undefined" != typeof window && "undefined" != typeof document, isServer = () => !isBrowser(), buildThemePath = (themeName, basePath = "/themes", useMinified = !1, cdnPath = null) => {
1709
- // Validate theme name to prevent path injection
1710
- if (!isValidThemeName(themeName)) throw new Error(`Invalid theme name: "${themeName}". Theme names must be lowercase alphanumeric with hyphens.`);
1711
- const fileName = `${themeName}${useMinified ? ".min.css" : ".css"}`;
1712
- return cdnPath ? `${cdnPath.replace(/[<>"']/g, "")}/${fileName}` : `${basePath.replace(/\/$/, "").replace(/[<>"']/g, "")}/${fileName.replace(/^\//, "")}`;
1713
- // Ensure basePath doesn't end with slash and fileName doesn't start with slash
1714
- // Also sanitize basePath to prevent path injection
1715
- }, isValidThemeName = themeName => !(!themeName || "string" != typeof themeName) && /^[a-z0-9]+(-[a-z0-9]+)*$/.test(themeName);
1398
+ * @param color - Hex color string
1399
+ * @param opacity - Opacity value (0-1)
1400
+ * @returns RGBA color string
1401
+ */ function alpha(color, opacity) {
1402
+ const rgb = hexToRgb(color);
1403
+ if (!rgb) return color;
1404
+ const {r: r, g: g, b: b} = rgb;
1405
+ return `rgba(${r}, ${g}, ${b}, ${Math.max(0, Math.min(1, opacity))})`;
1406
+ }
1716
1407
 
1717
1408
  /**
1718
- * Check if code is running on the server (SSR)
1719
- */
1720
- /**
1721
- * CSS Variable Generator
1722
- *
1723
- * Generates CSS custom properties from theme objects and injects them into the DOM.
1724
- *
1725
- * **Token Naming Alignment:**
1726
- * This generator produces CSS variables that match the SCSS token naming pattern exactly:
1727
- * - Colors: --atomix-primary, --atomix-primary-1 through --atomix-primary-10
1728
- * - Spacing: --atomix-spacing-1, --atomix-spacing-4, etc.
1729
- * - Typography: --atomix-font-size-base, --atomix-font-weight-normal, etc.
1730
- * - Shadows: --atomix-box-shadow, --atomix-box-shadow-sm, etc.
1731
- *
1732
- * All tokens follow the flat structure pattern used in SCSS (not nested like --atomix-palette-primary-main).
1733
- * This ensures compatibility between SCSS themes and JavaScript themes.
1409
+ * Emphasize a color (lighten if dark, darken if light)
1734
1410
  *
1735
- * @see src/styles/03-generic/_generic.root.scss for SCSS token definitions
1736
- */
1737
- /**
1738
- * Convert a nested object to flat CSS variable declarations
1411
+ * @param color - Hex color string
1412
+ * @param coefficient - Amount to emphasize (0-1), default 0.15
1413
+ * @returns Emphasized hex color
1739
1414
  */
1740
- function flattenObject(obj, prefix = "", result = {}) {
1741
- for (const key in obj) {
1742
- if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
1743
- const value = obj[key], newKey = prefix ? `${prefix}-${key}` : key;
1744
- if (value && "object" == typeof value && !Array.isArray(value)) {
1745
- // Skip special objects like functions
1746
- if ("function" == typeof value) continue;
1747
- // Recursively flatten nested objects
1748
- flattenObject(value, newKey, result);
1749
- } else "string" != typeof value && "number" != typeof value || (result[newKey.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()] = String(value));
1750
- }
1751
- return result;
1752
- }
1753
-
1754
1415
  /**
1755
1416
  * Generate a color scale from a base color (1-10 steps)
1756
1417
  * Creates lighter to darker variations
1757
- */ function generateColorScale(baseColor, prefix, colorName) {
1418
+ */
1419
+ function generateColorScale(baseColor, prefix, colorName) {
1758
1420
  const vars = {};
1759
1421
  if (!hexToRgb(baseColor)) return vars;
1760
1422
  // Generate 10-step scale
@@ -1818,7 +1480,16 @@ function generateCSSVariables(theme, options = {}) {
1818
1480
  // Text emphasis: emphasized version of the color for text (--atomix-primary-text-emphasis)
1819
1481
  vars[`${prefix}-${key}-text-emphasis`] = function(color, coefficient = .15) {
1820
1482
  return getLuminance(color) > .5 ? darken(color, coefficient) : lighten(color, coefficient);
1821
- }(color.main, .15),
1483
+ }
1484
+ // ============================================================================
1485
+ // Spacing Utilities
1486
+ // ============================================================================
1487
+ /**
1488
+ * Create a spacing function from various input types
1489
+ *
1490
+ * @param spacingInput - Spacing configuration (number, array, or function), default 4
1491
+ * @returns Spacing function
1492
+ */ (color.main, .15),
1822
1493
  // Background subtle: very light version for backgrounds (--atomix-primary-bg-subtle)
1823
1494
  vars[`${prefix}-${key}-bg-subtle`] = alpha(color.main, .1),
1824
1495
  // Border subtle: light version for borders (--atomix-primary-border-subtle)
@@ -2163,7 +1834,52 @@ function generateCSSVariables(theme, options = {}) {
2163
1834
  return vars[`${prefix}-focus-ring-width`] = "3px", vars[`${prefix}-focus-ring-offset`] = "2px",
2164
1835
  vars[`${prefix}-focus-ring-opacity`] = "0.25", vars;
2165
1836
  }(theme.palette, prefix)), theme.custom && Object.keys(theme.custom).length > 0) {
2166
- const customVars = flattenObject(theme.custom, `${prefix}-custom`);
1837
+ const customVars =
1838
+ /**
1839
+ * CSS Variable Generator
1840
+ *
1841
+ * Generates CSS custom properties from theme objects and injects them into the DOM.
1842
+ *
1843
+ * **Token Naming Alignment:**
1844
+ * This generator produces CSS variables that match the SCSS token naming pattern exactly:
1845
+ * - Colors: --atomix-primary, --atomix-primary-1 through --atomix-primary-10
1846
+ * - Spacing: --atomix-spacing-1, --atomix-spacing-4, etc.
1847
+ * - Typography: --atomix-font-size-base, --atomix-font-weight-normal, etc.
1848
+ * - Shadows: --atomix-box-shadow, --atomix-box-shadow-sm, etc.
1849
+ *
1850
+ * All tokens follow the flat structure pattern used in SCSS (not nested like --atomix-palette-primary-main).
1851
+ * This ensures compatibility between SCSS themes and JavaScript themes.
1852
+ *
1853
+ * @see src/styles/03-generic/_generic.root.scss for SCSS token definitions
1854
+ */
1855
+ /**
1856
+ * Convert a nested object to flat CSS variable declarations
1857
+ * Uses iterative approach for better performance with large objects
1858
+ */
1859
+ function(obj, prefix = "", result = {}) {
1860
+ // Use iterative approach with stack to avoid deep recursion
1861
+ const stack = [ {
1862
+ obj: obj,
1863
+ prefix: prefix
1864
+ } ];
1865
+ for (;stack.length > 0; ) {
1866
+ const {obj: currentObj, prefix: currentPrefix} = stack.pop();
1867
+ for (const key in currentObj) {
1868
+ if (!Object.prototype.hasOwnProperty.call(currentObj, key)) continue;
1869
+ const value = currentObj[key], newKey = currentPrefix ? `${currentPrefix}-${key}` : key;
1870
+ if (value && "object" == typeof value && !Array.isArray(value)) {
1871
+ // Skip special objects like functions
1872
+ if ("function" == typeof value) continue;
1873
+ // Add to stack for iterative processing
1874
+ stack.push({
1875
+ obj: value,
1876
+ prefix: newKey
1877
+ });
1878
+ } else "string" != typeof value && "number" != typeof value || (result[newKey.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()] = String(value));
1879
+ }
1880
+ }
1881
+ return result;
1882
+ }(theme.custom, `${prefix}-custom`);
2167
1883
  Object.assign(variables, customVars);
2168
1884
  }
2169
1885
  // Convert to CSS string
@@ -2234,6 +1950,7 @@ function generateClassName(block, element, modifiers) {
2234
1950
  * Component Theming Utilities
2235
1951
  *
2236
1952
  * Provides consistent patterns for applying theme values to components
1953
+ * using DesignTokens and CSS variables
2237
1954
  */
2238
1955
  /**
2239
1956
  * Get a theme value for a specific component using CSS variables
@@ -2247,33 +1964,28 @@ function generateClassName(block, element, modifiers) {
2247
1964
  }
2248
1965
 
2249
1966
  /**
2250
- * Generate component-specific CSS variables from theme
2251
- */ function generateComponentCSSVars(component, theme, variant, size) {
2252
- const vars = {}, prefixParts = [ "atomix", component ];
2253
- // This is a simplified implementation - in a real system you'd have more
2254
- // sophisticated logic to extract component-specific values from the theme
2255
- variant && prefixParts.push(variant), size && prefixParts.push(size);
1967
+ * Generate component-specific CSS variables from DesignTokens
1968
+ */ function generateComponentCSSVars(component, tokens, variant, size) {
1969
+ const vars = {};
1970
+ if (!tokens) return vars;
1971
+ const prefixParts = [ "atomix", component ];
1972
+ variant && prefixParts.push(variant), size && prefixParts.push(size);
2256
1973
  const prefix = prefixParts.join("-");
2257
- // Add common component properties
2258
- if (theme.palette && (vars[`--${prefix}-color`] = theme.palette.primary?.main || "#7c3aed",
2259
- vars[`--${prefix}-color-hover`] = theme.palette.primary?.dark || "#5b21b6", vars[`--${prefix}-color-active`] = theme.palette.primary?.main || "#7c3aed",
2260
- vars[`--${prefix}-color-disabled`] = theme.palette.text?.disabled || "#9ca3af"),
2261
- theme.typography && (vars[`--${prefix}-font-family`] = theme.typography.fontFamily || "Inter, sans-serif",
2262
- vars[`--${prefix}-font-size`] = theme.typography.fontSize ? `${theme.typography.fontSize}px` : "16px"),
2263
- theme.spacing) {
2264
- const spacing = "function" == typeof theme.spacing ? theme.spacing : val => 8 * val;
2265
- vars[`--${prefix}-spacing-unit`] = `${spacing(1)}px`, vars[`--${prefix}-spacing-sm`] = `${spacing(.5)}px`,
2266
- vars[`--${prefix}-spacing-md`] = `${spacing(1)}px`, vars[`--${prefix}-spacing-lg`] = `${spacing(2)}px`;
2267
- }
2268
- return vars;
1974
+ // Map common DesignTokens to component-specific CSS variables
1975
+ return tokens.primary && (vars[`--${prefix}-color`] = tokens.primary), tokens["primary-9"] && (vars[`--${prefix}-color-hover`] = tokens["primary-9"]),
1976
+ tokens["body-color"] && (vars[`--${prefix}-color-disabled`] = tokens["body-color"]),
1977
+ tokens["body-font-family"] && (vars[`--${prefix}-font-family`] = tokens["body-font-family"]),
1978
+ tokens["body-font-size"] && (vars[`--${prefix}-font-size`] = tokens["body-font-size"]),
1979
+ tokens["spacing-1"] && (vars[`--${prefix}-spacing-sm`] = tokens["spacing-1"]), tokens["spacing-2"] && (vars[`--${prefix}-spacing-md`] = tokens["spacing-2"]),
1980
+ tokens["spacing-4"] && (vars[`--${prefix}-spacing-lg`] = tokens["spacing-4"]), vars;
2269
1981
  }
2270
1982
 
2271
1983
  /**
2272
- * Apply consistent theme to component style object
2273
- */ function applyComponentTheme(component, style = {}, variant, size, theme) {
2274
- // If no theme provided, return original style
2275
- return theme ? {
2276
- ...generateComponentCSSVars(component, theme, variant, size),
1984
+ * Apply consistent theme to component style object using DesignTokens
1985
+ */ function applyComponentTheme(component, style = {}, variant, size, tokens) {
1986
+ // If no tokens provided, return original style
1987
+ return tokens ? {
1988
+ ...generateComponentCSSVars(component, tokens, variant, size),
2277
1989
  ...style
2278
1990
  } : style;
2279
1991
  // Generate component-specific CSS variables
@@ -2281,7 +1993,7 @@ function generateClassName(block, element, modifiers) {
2281
1993
 
2282
1994
  /**
2283
1995
  * Create a hook for consistent component theming
2284
- */ function useComponentTheme(component, variant, size, theme) {
1996
+ */ function useComponentTheme(component, variant, size, tokens) {
2285
1997
  return property => getComponentThemeValue(component, property, variant, size);
2286
1998
  }
2287
1999
 
@@ -2299,23 +2011,29 @@ function generateClassName(block, element, modifiers) {
2299
2011
  */ function loadThemeFromConfigSync(options) {
2300
2012
  // Check if we're in a browser environment
2301
2013
  if ("undefined" != typeof window) throw new Error("loadThemeFromConfigSync: Not available in browser environment. Config loading requires Node.js/SSR environment.");
2302
- // Use dynamic import to load the config loader
2303
- // This allows bundlers to handle external dependencies properly
2304
- let loadAtomixConfig;
2014
+ // Use static import - the function handles browser environment checks internally
2015
+ let config;
2305
2016
  try {
2306
- // eslint-disable-next-line @typescript-eslint/no-var-requires
2307
- const {loadAtomixConfig: loader} = require("../../config/loader");
2308
- loadAtomixConfig = loader;
2017
+ config = loadAtomixConfig({
2018
+ configPath: options?.configPath || "atomix.config.ts",
2019
+ required: !1 !== options?.required
2020
+ });
2309
2021
  } catch (error) {
2310
2022
  if (!1 !== options?.required) throw new Error("Config loader module not available");
2311
2023
  // Return empty tokens if config is not required
2312
2024
  return createTokens({});
2313
2025
  }
2314
- const config = loadAtomixConfig({
2315
- configPath: options?.configPath || "atomix.config.ts",
2316
- required: !1 !== options?.required
2317
- });
2318
- return config?.theme ? isThemeObject$1(config.theme) ? createDesignTokensFromTheme(config.theme) : createTokens(config.theme) : createTokens({});
2026
+ if (!config?.theme) return createTokens({});
2027
+ // Extract tokens from config.theme structure
2028
+ // config.theme can have: { extend?: ThemeTokens, tokens?: ThemeTokens, themes?: ... }
2029
+ // We need to extract the actual DesignTokens (flat structure)
2030
+ const themeConfig = config.theme;
2031
+ // Check if theme is directly a flat object (DesignTokens format)
2032
+ // This handles the case where config.theme might be passed as DesignTokens directly
2033
+ return createTokens(!themeConfig || "object" != typeof themeConfig || "extend" in themeConfig || "tokens" in themeConfig || "themes" in themeConfig ? {} : themeConfig);
2034
+ // If theme has nested structure (extend/tokens/themes), we can't directly use it
2035
+ // Return empty tokens - the theme system will use defaults
2036
+ // TODO: Add proper conversion from ThemeTokens to DesignTokens if needed
2319
2037
  }
2320
2038
 
2321
2039
  /**
@@ -2325,20 +2043,31 @@ function generateClassName(block, element, modifiers) {
2325
2043
  */ async function loadThemeFromConfig(options) {
2326
2044
  // Check if we're in a browser environment
2327
2045
  if ("undefined" != typeof window) throw new Error("loadThemeFromConfig: Not available in browser environment. Config loading requires Node.js/SSR environment.");
2328
- // Dynamic import for config loader
2329
- const {loadAtomixConfig: loadAtomixConfig} = await import("../lib/config/loader"), config = await loadAtomixConfig({
2330
- configPath: options?.configPath || "atomix.config.ts",
2331
- required: !1 !== options?.required
2332
- });
2333
- return config?.theme ? isThemeObject$1(config.theme) ? createDesignTokensFromTheme(config.theme) : createTokens(config.theme) : createTokens({});
2334
- }
2335
-
2336
- /**
2337
- * Check if the provided object is a Theme object
2338
- * @param theme - Object to check
2339
- * @returns True if the object is a Theme object, false otherwise
2340
- */ function isThemeObject$1(theme) {
2341
- return "object" == typeof theme && null !== theme;
2046
+ // Use static import with runtime check
2047
+ // The function will handle browser environment checks internally
2048
+ let config;
2049
+ try {
2050
+ // loadAtomixConfig is synchronous, not async
2051
+ config = loadAtomixConfig({
2052
+ configPath: options?.configPath || "atomix.config.ts",
2053
+ required: !1 !== options?.required
2054
+ });
2055
+ } catch (error) {
2056
+ if (!1 !== options?.required) throw new Error("Config loader module not available");
2057
+ // Return empty tokens if config is not required
2058
+ return createTokens({});
2059
+ }
2060
+ if (!config?.theme) return createTokens({});
2061
+ // Extract tokens from config.theme structure
2062
+ // config.theme can have: { extend?: ThemeTokens, tokens?: ThemeTokens, themes?: ... }
2063
+ // We need to extract the actual DesignTokens (flat structure)
2064
+ const themeConfig = config.theme;
2065
+ // Check if theme is directly a flat object (DesignTokens format)
2066
+ // This handles the case where config.theme might be passed as DesignTokens directly
2067
+ return createTokens(!themeConfig || "object" != typeof themeConfig || "extend" in themeConfig || "tokens" in themeConfig || "themes" in themeConfig ? {} : themeConfig);
2068
+ // If theme has nested structure (extend/tokens/themes), we can't directly use it
2069
+ // Return empty tokens - the theme system will use defaults
2070
+ // TODO: Add proper conversion from ThemeTokens to DesignTokens if needed
2342
2071
  }
2343
2072
 
2344
2073
  /**
@@ -2358,7 +2087,7 @@ ThemeContext.displayName = "ThemeContext";
2358
2087
  * React context provider for theme management with separated concerns.
2359
2088
  * Simplified version focusing on core functionality:
2360
2089
  * - String-based themes (CSS files)
2361
- * - JS Theme objects
2090
+ * - DesignTokens (dynamic themes)
2362
2091
  * - Persistence via localStorage
2363
2092
  *
2364
2093
  * Falls back to 'default' theme if no configuration is found.
@@ -2375,39 +2104,7 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
2375
2104
  onThemeChangeRef.current?.(theme);
2376
2105
  }), []), handleError = useCallback(((error, themeName) => {
2377
2106
  onErrorRef.current?.(error, themeName);
2378
- }), []), storageAdapter = useMemo((() => ({
2379
- getItem: key => {
2380
- if (isServer()) return null;
2381
- try {
2382
- return localStorage.getItem(key);
2383
- } catch {
2384
- return null;
2385
- }
2386
- },
2387
- setItem: (key, value) => {
2388
- if (!isServer()) try {
2389
- localStorage.setItem(key, value);
2390
- } catch {
2391
- // Silently fail if localStorage is not available
2392
- }
2393
- },
2394
- removeItem: key => {
2395
- if (!isServer()) try {
2396
- localStorage.removeItem(key);
2397
- } catch {
2398
- // Silently fail
2399
- }
2400
- },
2401
- isAvailable: () => {
2402
- if (isServer()) return !1;
2403
- try {
2404
- const test = "__atomix_storage_test__";
2405
- return localStorage.setItem(test, test), localStorage.removeItem(test), !0;
2406
- } catch {
2407
- return !1;
2408
- }
2409
- }
2410
- })), []), initialDefaultTheme = useMemo((() => {
2107
+ }), []), storageAdapter = useMemo((() => createLocalStorageAdapter()), []), initialDefaultTheme = useMemo((() => {
2411
2108
  // Check storage first
2412
2109
  if (enablePersistence && storageAdapter.isAvailable()) {
2413
2110
  const stored = storageAdapter.getItem(storageKey);
@@ -2424,72 +2121,121 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
2424
2121
  // For simplicity, we'll treat config tokens as a special theme name
2425
2122
  return "config-theme";
2426
2123
  } catch (error) {
2427
- console.warn("Failed to load theme from config, using default");
2124
+ // Failed to load theme from config, using default
2428
2125
  }
2429
2126
  // Default fallback
2430
2127
  return "default";
2431
- }), [ defaultTheme, enablePersistence, storageKey ]), [currentTheme, setCurrentTheme] = useState((() => initialDefaultTheme)), [activeTheme, setActiveTheme] = useState(null), [isLoading, setIsLoading] = useState(!1), [error, setError] = useState(null), loadedThemesRef = useRef(new Set), themePromisesRef = useRef({});
2128
+ }), [ defaultTheme, enablePersistence, storageKey ]), [currentTheme, setCurrentTheme] = useState((() => "string" == typeof initialDefaultTheme ? initialDefaultTheme : "tokens-theme")), [activeTokens, setActiveTokens] = useState((() =>
2129
+ // If defaultTheme is DesignTokens, store them
2130
+ defaultTheme && "string" != typeof defaultTheme ? createTokens(defaultTheme) : null)), [isLoading, setIsLoading] = useState(!1), [error, setError] = useState(null), loadedThemesRef = useRef(new Set), themePromisesRef = useRef({}), abortControllerRef = useRef(null);
2131
+ // Handle initial DesignTokens defaultTheme
2132
+ useEffect((() => {
2133
+ defaultTheme && "string" != typeof defaultTheme && activeTokens && !isServer() && injectCSS$1(createTheme(defaultTheme), "theme-tokens-theme");
2134
+ }), [ defaultTheme, activeTokens ]), // Run when defaultTheme or activeTokens change
2432
2135
  // Apply initial theme attributes to document element
2433
2136
  useEffect((() => {
2434
- isServer() || ((dataAttribute, themeName) => {
2435
- isServer() || (
2436
- // Set data attribute on body
2437
- document.body.setAttribute(dataAttribute, themeName),
2438
- // Also set on documentElement for broader compatibility
2439
- document.documentElement.setAttribute(dataAttribute, themeName));
2440
- })(String(currentTheme), dataAttribute);
2137
+ isServer() || applyThemeAttributes(String(currentTheme), dataAttribute);
2441
2138
  }), [ currentTheme, dataAttribute ]),
2442
2139
  // Handle theme persistence
2443
2140
  useEffect((() => {
2444
2141
  enablePersistence && storageAdapter.isAvailable() && storageAdapter.setItem(storageKey, String(currentTheme));
2445
- }), [ currentTheme, storageKey, enablePersistence ]);
2142
+ }), [ currentTheme, storageKey, enablePersistence, storageAdapter ]),
2143
+ // Cleanup: Remove completed promises and abort controllers on unmount
2144
+ useEffect((() => () => {
2145
+ // Cancel any in-flight theme loads
2146
+ abortControllerRef.current && (abortControllerRef.current.abort(), abortControllerRef.current = null),
2147
+ Object.entries(themePromisesRef.current).forEach((([key, promise]) => {})),
2148
+ // Clear all on unmount
2149
+ themePromisesRef.current = {};
2150
+ }), []);
2446
2151
  // Function to set theme with proper type handling
2447
2152
  const setTheme = useCallback((async (theme, options) => {
2448
- setIsLoading(!0), setError(null);
2153
+ // Cancel previous theme load if in progress
2154
+ abortControllerRef.current && abortControllerRef.current.abort();
2155
+ // Create new AbortController for this theme load
2156
+ const abortController = new AbortController;
2157
+ abortControllerRef.current = abortController, setIsLoading(!0), setError(null);
2449
2158
  try {
2450
- let themeName, themeObj = null;
2159
+ let themeName;
2160
+ if ("string" != typeof theme) {
2161
+ // Check if aborted before processing
2162
+ if (abortController.signal.aborted) return;
2163
+ // For DesignTokens, create CSS and inject it
2164
+ const {createTheme: createTheme} = await Promise.resolve().then((() => index)), css = createTheme(theme), themeId = "tokens-theme";
2165
+ // Check if aborted after async operation
2166
+ if (abortController.signal.aborted) return;
2167
+ // Remove any previously loaded theme CSS
2168
+ removeCSS(`theme-${currentTheme}`),
2169
+ // Inject new theme CSS
2170
+ injectCSS$1(css, `theme-${themeId}`);
2171
+ // Store tokens for reference
2172
+ const fullTokens = createTokens(theme);
2173
+ // Check if aborted before state update
2174
+ if (abortController.signal.aborted) return;
2175
+ return setActiveTokens(fullTokens), setCurrentTheme(themeId), handleThemeChange(fullTokens),
2176
+ void setIsLoading(!1);
2177
+ }
2451
2178
  // If it's a string theme name, load the associated CSS
2452
- if ("string" == typeof theme ? themeName = theme :
2453
- // If it's a Theme object or DesignTokens, we need to process it
2454
- function(theme) {
2455
- return "object" == typeof theme && null !== theme && "__isJSTheme" in theme && !0 === theme.__isJSTheme;
2456
- }(theme) ? (themeObj = theme,
2457
- // For JS themes, we use a generic name
2458
- themeName = "js-theme", setActiveTheme(themeObj)) :
2459
- // For DesignTokens, we might create a theme from tokens
2460
- themeName = "tokens-theme", "string" == typeof theme && themes[theme]) {
2179
+ if (themeName = theme, "string" == typeof theme && themes[theme]) {
2461
2180
  // Check if theme is already loading
2462
- if (themePromisesRef.current[theme]) return await themePromisesRef.current[theme],
2463
- setCurrentTheme(theme), setActiveTheme(null), void handleThemeChange(theme);
2181
+ if (themePromisesRef.current[theme]) try {
2182
+ // Check if aborted
2183
+ if (await themePromisesRef.current[theme], abortController.signal.aborted) return;
2184
+ return setCurrentTheme(theme), setActiveTokens(null), handleThemeChange(theme),
2185
+ void setIsLoading(!1);
2186
+ } catch {
2187
+ // If previous load failed, continue with new load
2188
+ }
2464
2189
  // Load CSS theme
2465
2190
  const themeLoadPromise = new Promise((async (resolve, reject) => {
2466
2191
  try {
2192
+ // Check if aborted
2193
+ if (abortController.signal.aborted) return void resolve();
2467
2194
  if (!themes[theme]) throw new Error(`Theme metadata not found for theme: ${theme}`);
2468
2195
  {
2469
2196
  // Build CSS path using utility function
2470
2197
  const cssPath = buildThemePath(theme, basePath, useMinified, cdnPath);
2198
+ // Check if aborted
2199
+ if (abortController.signal.aborted) return void resolve();
2200
+ // Load CSS file (using loadThemeCSS from domUtils)
2201
+ const {loadThemeCSS: loadThemeCSS} = await Promise.resolve().then((() => domUtils));
2202
+ // Check if aborted after async operation
2203
+ if (await loadThemeCSS(cssPath, `theme-${theme}`), abortController.signal.aborted) return void resolve();
2471
2204
  // Remove any previously loaded theme CSS
2472
- removeCSS(`theme-${String(currentTheme)}`),
2473
- // Inject new theme CSS
2474
- await injectCSS$1(cssPath, `theme-${theme}`), loadedThemesRef.current.add(theme),
2475
- setCurrentTheme(theme), setActiveTheme(null), handleThemeChange(theme), resolve();
2205
+ removeCSS(`theme-${String(currentTheme)}`), loadedThemesRef.current.add(theme),
2206
+ setCurrentTheme(theme), setActiveTokens(null), handleThemeChange(theme), resolve();
2476
2207
  }
2477
2208
  } catch (err) {
2209
+ // Don't reject if aborted
2210
+ if (abortController.signal.aborted) return void resolve();
2478
2211
  const error = err instanceof Error ? err : new Error(String(err));
2479
2212
  setError(error), handleError(error, String(theme)), reject(error);
2480
2213
  }
2481
2214
  }));
2482
- themePromisesRef.current[theme] = themeLoadPromise, await themeLoadPromise;
2483
- } else themeObj ? (
2484
- // For JS themes, set them directly
2485
- setCurrentTheme(themeName), setActiveTheme(themeObj), handleThemeChange(themeObj)) : (
2486
- // For string theme that isn't in our themes record, just set the name
2487
- setCurrentTheme(themeName), setActiveTheme(null), handleThemeChange(themeName));
2215
+ themePromisesRef.current[theme] = themeLoadPromise;
2216
+ try {
2217
+ await themeLoadPromise;
2218
+ } catch {
2219
+ // Error already handled in promise
2220
+ }
2221
+ // Clean up completed promise after a delay to prevent memory leak
2222
+ setTimeout((() => {
2223
+ themePromisesRef.current[theme] === themeLoadPromise && delete themePromisesRef.current[theme];
2224
+ }), 1e3);
2225
+ } else {
2226
+ // Check if aborted
2227
+ if (abortController.signal.aborted) return;
2228
+ // For string theme that isn't in our themes record, just set the name
2229
+ setCurrentTheme(themeName), setActiveTokens(null), handleThemeChange(themeName);
2230
+ }
2488
2231
  } catch (err) {
2232
+ // Don't set error if aborted
2233
+ if (abortController.signal.aborted) return;
2489
2234
  const error = err instanceof Error ? err : new Error(String(err));
2490
2235
  setError(error), handleError(error, String(theme));
2491
2236
  } finally {
2492
- setIsLoading(!1);
2237
+ // Only update loading state if not aborted
2238
+ abortController.signal.aborted || setIsLoading(!1);
2493
2239
  }
2494
2240
  }), [ themes, currentTheme, handleThemeChange, handleError, basePath, useMinified, cdnPath ]), isThemeLoaded = useCallback((themeName => loadedThemesRef.current.has(themeName)), []), preloadTheme = useCallback((async themeName => {
2495
2241
  if (themes[themeName] && !isThemeLoaded(themeName)) {
@@ -2506,19 +2252,22 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
2506
2252
  setIsLoading(!1);
2507
2253
  }
2508
2254
  }
2509
- }), [ themes, isThemeLoaded, handleError, basePath, useMinified, cdnPath ]), themeManager = useMemo((() => ({})), []), contextValue = useMemo((() => ({
2510
- theme: "string" == typeof currentTheme ? currentTheme : "js-theme",
2511
- activeTheme: activeTheme,
2255
+ }), [ themes, isThemeLoaded, handleError, basePath, useMinified, cdnPath ]), themeManager = useMemo((() => ({})), []), availableThemes = useMemo((() => Object.entries(themes).map((([name, metadata]) => ({
2256
+ ...metadata,
2257
+ name: name
2258
+ })))), [ themes ]), contextValue = useMemo((() => ({
2259
+ theme: currentTheme,
2260
+ activeTokens: activeTokens,
2512
2261
  setTheme: setTheme,
2513
- availableThemes: Object.entries(themes).map((([name, metadata]) => ({
2514
- ...metadata
2515
- }))),
2262
+ availableThemes: availableThemes,
2516
2263
  isLoading: isLoading,
2517
2264
  error: error,
2518
2265
  isThemeLoaded: isThemeLoaded,
2519
2266
  preloadTheme: preloadTheme,
2520
2267
  themeManager: themeManager
2521
- })), [ currentTheme, activeTheme, setTheme, themes, isLoading, error, isThemeLoaded, preloadTheme, themeManager ]);
2268
+ })), [ currentTheme, activeTokens, setTheme, availableThemes,
2269
+ // Use memoized value
2270
+ isLoading, error, isThemeLoaded, preloadTheme, themeManager ]);
2522
2271
  // Check if theme is loaded
2523
2272
  return jsx(ThemeContext.Provider, {
2524
2273
  value: contextValue,
@@ -2556,227 +2305,97 @@ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes:
2556
2305
  if (!context) throw new Error("useTheme must be used within a ThemeProvider");
2557
2306
  return {
2558
2307
  theme: context.theme,
2559
- activeTheme: context.activeTheme,
2308
+ activeTokens: context.activeTokens,
2560
2309
  setTheme: context.setTheme,
2561
2310
  availableThemes: context.availableThemes,
2562
2311
  isLoading: context.isLoading,
2563
- error: context.error,
2564
- isThemeLoaded: context.isThemeLoaded,
2565
- preloadTheme: context.preloadTheme
2566
- };
2567
- }
2568
-
2569
- function useThemeTokens() {
2570
- const {theme: theme, activeTheme: activeTheme} = useTheme(), getToken = useCallback(((tokenName, fallback) => {
2571
- if ("undefined" == typeof window) return fallback || "";
2572
- const cssVarName = `--atomix-${tokenName}`;
2573
- return getComputedStyle(document.documentElement).getPropertyValue(cssVarName).trim() || fallback || "";
2574
- }), []), getThemeValue = useCallback(((path, fallback) => {
2575
- var _context;
2576
- return activeTheme && _reduceInstanceProperty(_context = path.split(".")).call(_context, ((obj, key) => obj?.[key]), activeTheme) || fallback;
2577
- // Navigate through nested theme object using dot notation
2578
- }), [ activeTheme ]);
2579
- // Helper function to get CSS variable value
2580
- // Return unified API for accessing theme values
2581
- return {
2582
- theme: theme,
2583
- activeTheme: activeTheme,
2584
- getToken: getToken,
2585
- getThemeValue: getThemeValue,
2586
- // Commonly used tokens with fallbacks
2587
- colors: {
2588
- primary: getToken("primary", "#3b82f6"),
2589
- secondary: getToken("secondary", "#10b981"),
2590
- error: getToken("error", "#ef4444"),
2591
- success: getToken("success", "#22c55e"),
2592
- warning: getToken("warning", "#eab308"),
2593
- info: getToken("info", "#3b82f6"),
2594
- light: getToken("light", "#f9fafb"),
2595
- dark: getToken("dark", "#111827")
2596
- },
2597
- spacing: {
2598
- 1: getToken("spacing-1", "0.25rem"),
2599
- 2: getToken("spacing-2", "0.5rem"),
2600
- 3: getToken("spacing-3", "0.75rem"),
2601
- 4: getToken("spacing-4", "1rem"),
2602
- 5: getToken("spacing-5", "1.25rem"),
2603
- 6: getToken("spacing-6", "1.5rem"),
2604
- 8: getToken("spacing-8", "2rem"),
2605
- 10: getToken("spacing-10", "2.5rem"),
2606
- 12: getToken("spacing-12", "3rem"),
2607
- 16: getToken("spacing-16", "4rem"),
2608
- 20: getToken("spacing-20", "5rem")
2609
- },
2610
- borderRadius: {
2611
- sm: getToken("border-radius-sm", "0.25rem"),
2612
- md: getToken("border-radius-md", "0.5rem"),
2613
- lg: getToken("border-radius-lg", "0.75rem"),
2614
- xl: getToken("border-radius-xl", "1rem"),
2615
- full: getToken("border-radius-full", "9999px")
2616
- },
2617
- typography: {
2618
- fontFamily: {
2619
- sans: getToken("font-sans-serif", "Inter, system-ui, sans-serif"),
2620
- serif: getToken("font-serif", "Georgia, serif"),
2621
- mono: getToken("font-monospace", "Fira Code, monospace")
2622
- },
2623
- fontSize: {
2624
- xs: getToken("font-size-xs", "0.75rem"),
2625
- sm: getToken("font-size-sm", "0.875rem"),
2626
- md: getToken("font-size-md", "1rem"),
2627
- lg: getToken("font-size-lg", "1.125rem"),
2628
- xl: getToken("font-size-xl", "1.25rem"),
2629
- "2xl": getToken("font-size-2xl", "1.5rem"),
2630
- "3xl": getToken("font-size-3xl", "1.875rem"),
2631
- "4xl": getToken("font-size-4xl", "2.25rem")
2632
- },
2633
- fontWeight: {
2634
- light: getToken("font-weight-light", "300"),
2635
- normal: getToken("font-weight-normal", "400"),
2636
- medium: getToken("font-weight-medium", "500"),
2637
- semibold: getToken("font-weight-semibold", "600"),
2638
- bold: getToken("font-weight-bold", "700")
2639
- }
2640
- },
2641
- shadows: {
2642
- sm: getToken("box-shadow-sm", "0 1px 2px 0 rgba(0, 0, 0, 0.05)"),
2643
- md: getToken("box-shadow-md", "0 4px 6px -1px rgba(0, 0, 0, 0.1)"),
2644
- lg: getToken("box-shadow-lg", "0 10px 15px -3px rgba(0, 0, 0, 0.1)"),
2645
- xl: getToken("box-shadow-xl", "0 20px 25px -5px rgba(0, 0, 0, 0.1)"),
2646
- inset: getToken("box-shadow-inset", "inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)")
2647
- },
2648
- transitions: {
2649
- fast: getToken("transition-fast", "150ms"),
2650
- base: getToken("transition-base", "200ms"),
2651
- slow: getToken("transition-slow", "300ms")
2652
- }
2653
- };
2654
- }
2655
-
2656
- /**
2657
- * Theme System Error Handling
2658
- *
2659
- * Centralized error handling for the Atomix theme system.
2660
- * Provides custom error classes and logging utilities.
2661
- */
2662
- /**
2663
- * Theme error codes
2664
- */ var ThemeErrorCode, LogLevel;
2665
-
2666
- !function(ThemeErrorCode) {
2667
- /** Theme not found in registry */
2668
- ThemeErrorCode.THEME_NOT_FOUND = "THEME_NOT_FOUND",
2669
- /** Theme failed to load */
2670
- ThemeErrorCode.THEME_LOAD_FAILED = "THEME_LOAD_FAILED",
2671
- /** Theme validation failed */
2672
- ThemeErrorCode.THEME_VALIDATION_FAILED = "THEME_VALIDATION_FAILED",
2673
- /** Configuration loading failed */
2674
- ThemeErrorCode.CONFIG_LOAD_FAILED = "CONFIG_LOAD_FAILED",
2675
- /** Configuration validation failed */
2676
- ThemeErrorCode.CONFIG_VALIDATION_FAILED = "CONFIG_VALIDATION_FAILED",
2677
- /** Circular dependency detected */
2678
- ThemeErrorCode.CIRCULAR_DEPENDENCY = "CIRCULAR_DEPENDENCY",
2679
- /** Missing dependency */
2680
- ThemeErrorCode.MISSING_DEPENDENCY = "MISSING_DEPENDENCY",
2681
- /** Storage operation failed */
2682
- ThemeErrorCode.STORAGE_ERROR = "STORAGE_ERROR",
2683
- /** Invalid theme name */
2684
- ThemeErrorCode.INVALID_THEME_NAME = "INVALID_THEME_NAME",
2685
- /** CSS injection failed */
2686
- ThemeErrorCode.CSS_INJECTION_FAILED = "CSS_INJECTION_FAILED",
2687
- /** Unknown error */
2688
- ThemeErrorCode.UNKNOWN_ERROR = "UNKNOWN_ERROR";
2689
- }(ThemeErrorCode || (ThemeErrorCode = {}));
2690
-
2691
- /**
2692
- * Custom error class for theme-related errors
2693
- */
2694
- class ThemeError extends Error {
2695
- constructor(message, code = ThemeErrorCode.UNKNOWN_ERROR, context) {
2696
- super(message), this.name = "ThemeError", this.code = code, this.context = context,
2697
- this.timestamp = Date.now(),
2698
- // Maintains proper stack trace for where our error was thrown (only available on V8)
2699
- Error.captureStackTrace && Error.captureStackTrace(this, ThemeError);
2700
- }
2701
- /**
2702
- * Convert error to JSON for logging
2703
- */ toJSON() {
2704
- return {
2705
- name: this.name,
2706
- message: this.message,
2707
- code: this.code,
2708
- context: this.context,
2709
- timestamp: this.timestamp,
2710
- stack: this.stack
2711
- };
2712
- }
2713
- }
2714
-
2715
- /**
2716
- * Log level
2717
- */ !function(LogLevel) {
2718
- LogLevel[LogLevel.ERROR = 0] = "ERROR", LogLevel[LogLevel.WARN = 1] = "WARN", LogLevel[LogLevel.INFO = 2] = "INFO",
2719
- LogLevel[LogLevel.DEBUG = 3] = "DEBUG";
2720
- }(LogLevel || (LogLevel = {}));
2721
-
2722
- /**
2723
- * Theme Logger
2724
- *
2725
- * Centralized logging for the theme system.
2726
- * Replaces console statements with structured logging.
2727
- */
2728
- class ThemeLogger {
2729
- constructor(config = {}) {
2730
- this.config = {
2731
- level: config.level ?? ("undefined" != typeof process && "production" === process.env?.NODE_ENV ? LogLevel.WARN : LogLevel.INFO),
2732
- enableConsole: config.enableConsole ?? !0,
2733
- onError: config.onError,
2734
- onWarn: config.onWarn,
2735
- onInfo: config.onInfo,
2736
- onDebug: config.onDebug
2737
- };
2738
- }
2739
- /**
2740
- * Log an error
2741
- */ error(message, error, context) {
2742
- if (this.config.level < LogLevel.ERROR) return;
2743
- const errorObj = error instanceof Error ? error : new Error(message), themeError = error instanceof ThemeError ? error : new ThemeError(message, ThemeErrorCode.UNKNOWN_ERROR, context);
2744
- this.config.enableConsole && console.error(`[ThemeError] ${message}`, {
2745
- error: errorObj,
2746
- context: {
2747
- ...context,
2748
- ...themeError.context
2749
- },
2750
- code: themeError.code
2751
- }), this.config.onError?.(themeError, context);
2752
- }
2753
- /**
2754
- * Log a warning
2755
- */ warn(message, context) {
2756
- this.config.level < LogLevel.WARN || (this.config.enableConsole && console.warn(`[ThemeWarning] ${message}`, context || {}),
2757
- this.config.onWarn?.(message, context));
2758
- }
2759
- /**
2760
- * Log an info message
2761
- */ info(message, context) {
2762
- this.config.level < LogLevel.INFO || (this.config.enableConsole && console.info(`[ThemeInfo] ${message}`, context || {}),
2763
- this.config.onInfo?.(message, context));
2764
- }
2765
- /**
2766
- * Log a debug message
2767
- */ debug(message, context) {
2768
- this.config.level < LogLevel.DEBUG || (this.config.enableConsole, this.config.onDebug?.(message, context));
2769
- }
2312
+ error: context.error,
2313
+ isThemeLoaded: context.isThemeLoaded,
2314
+ preloadTheme: context.preloadTheme
2315
+ };
2770
2316
  }
2771
2317
 
2772
- /**
2773
- * Default logger instance
2774
- */ let defaultLogger = null;
2775
-
2776
- /**
2777
- * Get or create default logger
2778
- */ function getLogger() {
2779
- return defaultLogger || (defaultLogger = new ThemeLogger), defaultLogger;
2318
+ function useThemeTokens() {
2319
+ const {theme: theme, activeTokens: activeTokens} = useTheme(), getToken = useCallback(((tokenName, fallback) => {
2320
+ if ("undefined" == typeof window) return fallback || "";
2321
+ const cssVarName = `--atomix-${tokenName}`;
2322
+ return getComputedStyle(document.documentElement).getPropertyValue(cssVarName).trim() || fallback || "";
2323
+ }), []);
2324
+ // Helper function to get CSS variable value
2325
+ // Return unified API for accessing theme values
2326
+ // Note: For SSR or direct token access, use activeTokens directly
2327
+ return {
2328
+ theme: theme,
2329
+ activeTokens: activeTokens,
2330
+ getToken: getToken,
2331
+ // Commonly used tokens with fallbacks
2332
+ colors: {
2333
+ primary: getToken("primary", "#3b82f6"),
2334
+ secondary: getToken("secondary", "#10b981"),
2335
+ error: getToken("error", "#ef4444"),
2336
+ success: getToken("success", "#22c55e"),
2337
+ warning: getToken("warning", "#eab308"),
2338
+ info: getToken("info", "#3b82f6"),
2339
+ light: getToken("light", "#f9fafb"),
2340
+ dark: getToken("dark", "#111827")
2341
+ },
2342
+ spacing: {
2343
+ 1: getToken("spacing-1", "0.25rem"),
2344
+ 2: getToken("spacing-2", "0.5rem"),
2345
+ 3: getToken("spacing-3", "0.75rem"),
2346
+ 4: getToken("spacing-4", "1rem"),
2347
+ 5: getToken("spacing-5", "1.25rem"),
2348
+ 6: getToken("spacing-6", "1.5rem"),
2349
+ 8: getToken("spacing-8", "2rem"),
2350
+ 10: getToken("spacing-10", "2.5rem"),
2351
+ 12: getToken("spacing-12", "3rem"),
2352
+ 16: getToken("spacing-16", "4rem"),
2353
+ 20: getToken("spacing-20", "5rem")
2354
+ },
2355
+ borderRadius: {
2356
+ sm: getToken("border-radius-sm", "0.25rem"),
2357
+ md: getToken("border-radius-md", "0.5rem"),
2358
+ lg: getToken("border-radius-lg", "0.75rem"),
2359
+ xl: getToken("border-radius-xl", "1rem"),
2360
+ full: getToken("border-radius-full", "9999px")
2361
+ },
2362
+ typography: {
2363
+ fontFamily: {
2364
+ sans: getToken("font-sans-serif", "Inter, system-ui, sans-serif"),
2365
+ serif: getToken("font-serif", "Georgia, serif"),
2366
+ mono: getToken("font-monospace", "Fira Code, monospace")
2367
+ },
2368
+ fontSize: {
2369
+ xs: getToken("font-size-xs", "0.75rem"),
2370
+ sm: getToken("font-size-sm", "0.875rem"),
2371
+ md: getToken("font-size-md", "1rem"),
2372
+ lg: getToken("font-size-lg", "1.125rem"),
2373
+ xl: getToken("font-size-xl", "1.25rem"),
2374
+ "2xl": getToken("font-size-2xl", "1.5rem"),
2375
+ "3xl": getToken("font-size-3xl", "1.875rem"),
2376
+ "4xl": getToken("font-size-4xl", "2.25rem")
2377
+ },
2378
+ fontWeight: {
2379
+ light: getToken("font-weight-light", "300"),
2380
+ normal: getToken("font-weight-normal", "400"),
2381
+ medium: getToken("font-weight-medium", "500"),
2382
+ semibold: getToken("font-weight-semibold", "600"),
2383
+ bold: getToken("font-weight-bold", "700")
2384
+ }
2385
+ },
2386
+ shadows: {
2387
+ sm: getToken("box-shadow-sm", "0 1px 2px 0 rgba(0, 0, 0, 0.05)"),
2388
+ md: getToken("box-shadow-md", "0 4px 6px -1px rgba(0, 0, 0, 0.1)"),
2389
+ lg: getToken("box-shadow-lg", "0 10px 15px -3px rgba(0, 0, 0, 0.1)"),
2390
+ xl: getToken("box-shadow-xl", "0 20px 25px -5px rgba(0, 0, 0, 0.1)"),
2391
+ inset: getToken("box-shadow-inset", "inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)")
2392
+ },
2393
+ transitions: {
2394
+ fast: getToken("transition-fast", "150ms"),
2395
+ base: getToken("transition-base", "200ms"),
2396
+ slow: getToken("transition-slow", "300ms")
2397
+ }
2398
+ };
2780
2399
  }
2781
2400
 
2782
2401
  /**
@@ -2940,29 +2559,13 @@ class ThemeLogger {
2940
2559
  this.styleId = "atomix-theme-applicator", this.root = root;
2941
2560
  }
2942
2561
  /**
2943
- * Apply a complete theme configuration
2562
+ * Apply a complete theme configuration using DesignTokens
2944
2563
  *
2945
- * Uses the unified theme system to convert Theme to DesignTokens and inject CSS.
2564
+ * Uses the unified theme system to generate and inject CSS.
2946
2565
  * Automatically respects atomix.config.ts when using DesignTokens.
2947
- */ applyTheme(theme) {
2566
+ */ applyTheme(tokens) {
2948
2567
  // Clear previously applied variables
2949
2568
  this.clearAppliedVars(),
2950
- // Check if it's DesignTokens
2951
- this.isDesignTokens(theme) ?
2952
- // Direct DesignTokens - use unified theme system (with config support)
2953
- this.applyDesignTokens(theme) : injectCSS$1(createTheme(theme, {
2954
- selector: ":root",
2955
- prefix: "atomix"
2956
- }), this.styleId),
2957
- // Apply component overrides (only for Theme objects)
2958
- !this.isDesignTokens(theme) && theme.components && this.applyComponentOverrides(theme.components);
2959
- }
2960
- /**
2961
- * Apply DesignTokens using unified theme system
2962
- *
2963
- * Uses createTheme() which automatically loads from atomix.config.ts
2964
- * if no tokens are provided, ensuring config is always respected.
2965
- */ applyDesignTokens(tokens) {
2966
2569
  // Inject CSS into DOM
2967
2570
  injectCSS$1(createTheme(tokens, {
2968
2571
  selector: ":root",
@@ -2970,51 +2573,13 @@ class ThemeLogger {
2970
2573
  }), this.styleId);
2971
2574
  }
2972
2575
  /**
2973
- * Check if object is DesignTokens
2974
- */ isDesignTokens(obj) {
2975
- // DesignTokens is a flat object with string keys, no nested structures
2976
- return null !== obj && "object" == typeof obj && !("palette" in obj) && !("typography" in obj) && !("__isJSTheme" in obj);
2977
- }
2978
- /**
2979
- * Apply global CSS variables (for component overrides)
2576
+ * Apply global CSS variables
2980
2577
  */ applyGlobalCSSVars(vars) {
2981
2578
  Object.entries(vars).forEach((([key, value]) => {
2982
2579
  this.root.style.setProperty(key, String(value));
2983
2580
  }));
2984
2581
  }
2985
2582
  /**
2986
- * Apply component-level overrides
2987
- */ applyComponentOverrides(overrides) {
2988
- Object.entries(overrides).forEach((([componentName, override]) => {
2989
- override && this.applyComponentOverride(componentName, override);
2990
- }));
2991
- }
2992
- /**
2993
- * Apply override for a specific component
2994
- */ applyComponentOverride(componentName, override) {
2995
- const vars = {}, componentKey = componentName.toLowerCase();
2996
- // Apply component-level CSS variables
2997
- override.cssVars && Object.entries(override.cssVars).forEach((([key, value]) => {
2998
- // If key doesn't start with --, add component prefix
2999
- const varKey = key.startsWith("--") ? key : `--atomix-${componentKey}-${key}`;
3000
- vars[varKey] = value;
3001
- })),
3002
- // Apply part-specific CSS variables
3003
- override.parts && Object.entries(override.parts).forEach((([partName, partOverride]) => {
3004
- partOverride.cssVars && Object.entries(partOverride.cssVars).forEach((([key, value]) => {
3005
- const varKey = key.startsWith("--") ? key : `--atomix-${componentKey}-${partName}-${key}`;
3006
- vars[varKey] = value;
3007
- }));
3008
- })),
3009
- // Apply variant-specific CSS variables
3010
- override.variants && Object.entries(override.variants).forEach((([variantName, variantOverride]) => {
3011
- variantOverride.cssVars && Object.entries(variantOverride.cssVars).forEach((([key, value]) => {
3012
- const varKey = key.startsWith("--") ? key : `--atomix-${componentKey}-${variantName}-${key}`;
3013
- vars[varKey] = value;
3014
- }));
3015
- })), this.applyGlobalCSSVars(vars);
3016
- }
3017
- /**
3018
2583
  * Clear all applied CSS variables
3019
2584
  */ clearAppliedVars() {
3020
2585
  removeCSS(this.styleId);
@@ -3043,8 +2608,8 @@ class ThemeLogger {
3043
2608
 
3044
2609
  /**
3045
2610
  * Apply theme using global applicator
3046
- */ function applyTheme(theme) {
3047
- getThemeApplicator().applyTheme(theme);
2611
+ */ function applyTheme(tokens) {
2612
+ getThemeApplicator().applyTheme(tokens);
3048
2613
  }
3049
2614
 
3050
2615
  const VIEWPORT_PRESETS = {
@@ -4532,10 +4097,374 @@ class ThemeValidator {
4532
4097
  };
4533
4098
 
4534
4099
  /**
4535
- * Theme Comparator Component
4100
+ * Theme Comparator Component
4101
+ *
4102
+ * Compares two themes and highlights differences
4103
+ */ var aCallable = aCallable$3, toObject = toObject$2, IndexedObject = indexedObject, lengthOfArrayLike = lengthOfArrayLike$2, $TypeError = TypeError, REDUCE_EMPTY = "Reduce of empty array with no initial value", createMethod = function(IS_RIGHT) {
4104
+ return function(that, callbackfn, argumentsLength, memo) {
4105
+ var O = toObject(that), self = IndexedObject(O), length = lengthOfArrayLike(O);
4106
+ if (aCallable(callbackfn), 0 === length && argumentsLength < 2) throw new $TypeError(REDUCE_EMPTY);
4107
+ var index = IS_RIGHT ? length - 1 : 0, i = IS_RIGHT ? -1 : 1;
4108
+ if (argumentsLength < 2) for (;;) {
4109
+ if (index in self) {
4110
+ memo = self[index], index += i;
4111
+ break;
4112
+ }
4113
+ if (index += i, IS_RIGHT ? index < 0 : length <= index) throw new $TypeError(REDUCE_EMPTY);
4114
+ }
4115
+ for (;IS_RIGHT ? index >= 0 : length > index; index += i) index in self && (memo = callbackfn(memo, self[index], index, O));
4116
+ return memo;
4117
+ };
4118
+ }, arrayReduce = {
4119
+ // `Array.prototype.reduce` method
4120
+ // https://tc39.es/ecma262/#sec-array.prototype.reduce
4121
+ left: createMethod(!1),
4122
+ // `Array.prototype.reduceRight` method
4123
+ // https://tc39.es/ecma262/#sec-array.prototype.reduceright
4124
+ right: createMethod(!0)
4125
+ }, fails = fails$9, globalThis$1 = globalThis_1, userAgent = environmentUserAgent, classof = classofRaw$2, userAgentStartsWith = function(string) {
4126
+ return userAgent.slice(0, string.length) === string;
4127
+ }, environment = userAgentStartsWith("Bun/") ? "BUN" : userAgentStartsWith("Cloudflare-Workers") ? "CLOUDFLARE" : userAgentStartsWith("Deno/") ? "DENO" : userAgentStartsWith("Node.js/") ? "NODE" : globalThis$1.Bun && "string" == typeof Bun.version ? "BUN" : globalThis$1.Deno && "object" == typeof Deno.version ? "DENO" : "process" === classof(globalThis$1.process) ? "NODE" : globalThis$1.window && globalThis$1.document ? "BROWSER" : "REST", $reduce = arrayReduce.left;
4128
+
4129
+ // `Array.prototype.reduce` method
4130
+ // https://tc39.es/ecma262/#sec-array.prototype.reduce
4131
+ _export({
4132
+ target: "Array",
4133
+ proto: !0,
4134
+ forced: !("NODE" === environment) && environmentV8Version > 79 && environmentV8Version < 83 || !function(METHOD_NAME, argument) {
4135
+ var method = [][METHOD_NAME];
4136
+ return !!method && fails((function() {
4137
+ // eslint-disable-next-line no-useless-call -- required for testing
4138
+ method.call(null, argument || function() {
4139
+ return 1;
4140
+ }, 1);
4141
+ }));
4142
+ }("reduce")
4143
+ }, {
4144
+ reduce: function(callbackfn /* , initialValue */) {
4145
+ var length = arguments.length;
4146
+ return $reduce(this, callbackfn, length, length > 1 ? arguments[1] : void 0);
4147
+ }
4148
+ });
4149
+
4150
+ var reduce$3 = getBuiltInPrototypeMethod$3("Array", "reduce"), isPrototypeOf = objectIsPrototypeOf, method = reduce$3, ArrayPrototype = Array.prototype;
4151
+
4152
+ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
4153
+ var own = it.reduce;
4154
+ return it === ArrayPrototype || isPrototypeOf(ArrayPrototype, it) && own === ArrayPrototype.reduce ? method : own;
4155
+ })), DEFAULT_PALETTE = {
4156
+ primary: {
4157
+ main: "#7c3aed",
4158
+ // Primary-6
4159
+ light: "#d0b2f5",
4160
+ // Primary-3
4161
+ dark: "#3c1583",
4162
+ // Primary-9
4163
+ contrastText: "#ffffff"
4164
+ },
4165
+ secondary: {
4166
+ main: "#f3f4f6",
4167
+ // Gray-2
4168
+ light: "#ffffff",
4169
+ // Gray-1
4170
+ dark: "#e5e7eb",
4171
+ // Gray-3
4172
+ contrastText: "#1f2937"
4173
+ },
4174
+ error: {
4175
+ main: "#ef4444",
4176
+ // Red-6
4177
+ light: "#fca5a5",
4178
+ // Red-4
4179
+ dark: "#991b1b",
4180
+ // Red-9
4181
+ contrastText: "#ffffff"
4182
+ },
4183
+ warning: {
4184
+ main: "#eab308",
4185
+ // Yellow-6
4186
+ light: "#fde047",
4187
+ // Yellow-4
4188
+ dark: "#854d0e",
4189
+ // Yellow-9
4190
+ contrastText: "#000000"
4191
+ },
4192
+ info: {
4193
+ main: "#3b82f6",
4194
+ // Blue-6
4195
+ light: "#93c5fd",
4196
+ // Blue-4
4197
+ dark: "#1e40af",
4198
+ // Blue-9
4199
+ contrastText: "#ffffff"
4200
+ },
4201
+ success: {
4202
+ main: "#22c55e",
4203
+ // Green-6
4204
+ light: "#86efac",
4205
+ // Green-4
4206
+ dark: "#166534",
4207
+ // Green-9
4208
+ contrastText: "#ffffff"
4209
+ },
4210
+ background: {
4211
+ default: "#ffffff",
4212
+ // Primary-bg
4213
+ paper: "#f3f4f6",
4214
+ // Secondary-bg
4215
+ subtle: "#d1d5db"
4216
+ },
4217
+ text: {
4218
+ primary: "#111827",
4219
+ // Gray-10
4220
+ secondary: "#374151",
4221
+ // Gray-8
4222
+ disabled: "#9ca3af"
4223
+ }
4224
+ }, DEFAULT_TYPOGRAPHY = {
4225
+ fontFamily: '"Roboto", "Helvetica Neue", "Helvetica", "Arial", sans-serif',
4226
+ fontSize: 16,
4227
+ // 1rem
4228
+ fontWeightLight: 300,
4229
+ fontWeightRegular: 400,
4230
+ fontWeightMedium: 500,
4231
+ fontWeightSemiBold: 600,
4232
+ fontWeightBold: 700,
4233
+ fontWeightHeavy: 800,
4234
+ fontWeightBlack: 900,
4235
+ h1: {
4236
+ fontSize: "2.5rem",
4237
+ // 40px
4238
+ fontWeight: 700,
4239
+ lineHeight: 1.3,
4240
+ letterSpacing: "-1px"
4241
+ },
4242
+ h2: {
4243
+ fontSize: "2rem",
4244
+ // 32px
4245
+ fontWeight: 700,
4246
+ lineHeight: 1.3,
4247
+ letterSpacing: "-1px"
4248
+ },
4249
+ h3: {
4250
+ fontSize: "1.5rem",
4251
+ // 24px
4252
+ fontWeight: 700,
4253
+ lineHeight: 1.3,
4254
+ letterSpacing: "-1px"
4255
+ },
4256
+ h4: {
4257
+ fontSize: "1.25rem",
4258
+ // 20px
4259
+ fontWeight: 700,
4260
+ lineHeight: 1.3,
4261
+ letterSpacing: "-0.5px"
4262
+ },
4263
+ h5: {
4264
+ fontSize: "1.125rem",
4265
+ // 18px
4266
+ fontWeight: 700,
4267
+ lineHeight: 1.3,
4268
+ letterSpacing: "-0.5px"
4269
+ },
4270
+ h6: {
4271
+ fontSize: "1rem",
4272
+ // 16px
4273
+ fontWeight: 700,
4274
+ lineHeight: 1.3,
4275
+ letterSpacing: "-0.5px"
4276
+ },
4277
+ body1: {
4278
+ fontSize: "1rem",
4279
+ // 16px
4280
+ fontWeight: 400,
4281
+ lineHeight: 1.2
4282
+ },
4283
+ body2: {
4284
+ fontSize: "0.875rem",
4285
+ // 14px
4286
+ fontWeight: 400,
4287
+ lineHeight: 1.2
4288
+ }
4289
+ }, DEFAULT_SHADOWS = {
4290
+ xs: "0px 1px 2px 0px rgba(45, 54, 67, 0.04), 0px 2px 4px 0px rgba(45, 54, 67, 0.08)",
4291
+ sm: "0 2px 4px rgba(0, 0, 0, 0.075)",
4292
+ md: "0 4px 8px rgba(0, 0, 0, 0.1)",
4293
+ lg: "0 16px 48px rgba(0, 0, 0, 0.175)",
4294
+ xl: "0px 16px 64px -8px rgba(45, 54, 67, 0.14)",
4295
+ inset: "inset 0 1px 2px rgba(0, 0, 0, 0.075)"
4296
+ }, DEFAULT_TRANSITIONS = {
4297
+ duration: {
4298
+ shortest: 150,
4299
+ shorter: 200,
4300
+ short: 250,
4301
+ standard: 300,
4302
+ complex: 375,
4303
+ enteringScreen: 225,
4304
+ leavingScreen: 195
4305
+ },
4306
+ easing: {
4307
+ easeInOut: "cubic-bezier(0.4, 0, 0.2, 1)",
4308
+ easeOut: "cubic-bezier(0.0, 0, 0.2, 1)",
4309
+ easeIn: "cubic-bezier(0.4, 0, 1, 1)",
4310
+ sharp: "cubic-bezier(0.4, 0, 0.6, 1)"
4311
+ }
4312
+ }, DEFAULT_ZINDEX = {
4313
+ mobileStepper: 1e3,
4314
+ speedDial: 1050,
4315
+ appBar: 1020,
4316
+ drawer: 1070,
4317
+ modal: 1040,
4318
+ snackbar: 1080,
4319
+ tooltip: 1060
4320
+ }, DEFAULT_BORDER_RADIUS = {
4321
+ base: "0.5rem",
4322
+ // 8px (spacing-2)
4323
+ sm: "0.25rem",
4324
+ // 4px (spacing-1)
4325
+ md: "0.25rem",
4326
+ // 4px (spacing-1)
4327
+ lg: "0.625rem",
4328
+ // 10px (spacing-2.5)
4329
+ xl: "0.75rem",
4330
+ // 12px (spacing-3)
4331
+ xxl: "1rem",
4332
+ // 16px (spacing-4)
4333
+ "3xl": "1.5rem",
4334
+ // 24px (spacing-6)
4335
+ "4xl": "2rem",
4336
+ // 32px (spacing-8)
4337
+ pill: "50rem"
4338
+ };
4339
+
4340
+ // ============================================================================
4341
+ // Default Theme Values
4342
+ // ============================================================================
4343
+ // ============================================================================
4344
+ // Helper Functions
4345
+ // ============================================================================
4346
+ /**
4347
+ * Create a complete palette color from partial configuration
4348
+ */
4349
+ function createPaletteColor(color) {
4350
+ return "string" == typeof color ? {
4351
+ main: color,
4352
+ light: lighten(color),
4353
+ dark: darken(color),
4354
+ contrastText: getContrastText(color)
4355
+ } : {
4356
+ main: color.main || "#000000",
4357
+ light: color.light || lighten(color.main || "#000000"),
4358
+ dark: color.dark || darken(color.main || "#000000"),
4359
+ contrastText: color.contrastText || getContrastText(color.main || "#000000")
4360
+ };
4361
+ }
4362
+
4363
+ /**
4364
+ * Create breakpoints object
4365
+ */
4366
+ // ============================================================================
4367
+ // Main createTheme Function
4368
+ // ============================================================================
4369
+ /**
4370
+ * Create a theme object with computed values
4536
4371
  *
4537
- * Compares two themes and highlights differences
4372
+ * @param options - Theme configuration options
4373
+ * @returns Complete theme object
4538
4374
  */
4375
+ function createThemeObject(...options) {
4376
+ // Merge all options
4377
+ const mergedOptions = _reduceInstanceProperty(options).call(options, ((acc, option) => deepMerge(acc, option)), {}), palette = {
4378
+ primary: createPaletteColor(mergedOptions.palette?.primary || DEFAULT_PALETTE.primary),
4379
+ secondary: createPaletteColor(mergedOptions.palette?.secondary || DEFAULT_PALETTE.secondary),
4380
+ error: createPaletteColor(mergedOptions.palette?.error || DEFAULT_PALETTE.error),
4381
+ warning: createPaletteColor(mergedOptions.palette?.warning || DEFAULT_PALETTE.warning),
4382
+ info: createPaletteColor(mergedOptions.palette?.info || DEFAULT_PALETTE.info),
4383
+ success: createPaletteColor(mergedOptions.palette?.success || DEFAULT_PALETTE.success),
4384
+ // Handle light and dark colors if provided
4385
+ ...mergedOptions.palette?.light && {
4386
+ light: createPaletteColor(mergedOptions.palette.light)
4387
+ },
4388
+ ...mergedOptions.palette?.dark && {
4389
+ dark: createPaletteColor(mergedOptions.palette.dark)
4390
+ },
4391
+ background: {
4392
+ default: mergedOptions.palette?.background?.default || DEFAULT_PALETTE.background.default,
4393
+ subtle: mergedOptions.palette?.background?.subtle || DEFAULT_PALETTE.background.subtle
4394
+ },
4395
+ text: {
4396
+ primary: mergedOptions.palette?.text?.primary || DEFAULT_PALETTE.text.primary,
4397
+ secondary: mergedOptions.palette?.text?.secondary || DEFAULT_PALETTE.text.secondary,
4398
+ disabled: mergedOptions.palette?.text?.disabled || DEFAULT_PALETTE.text.disabled
4399
+ }
4400
+ }, typography = deepMerge({
4401
+ ...DEFAULT_TYPOGRAPHY
4402
+ }, mergedOptions.typography || {}), spacing = function(spacingInput = 4) {
4403
+ // If it's already a function, return it
4404
+ return "function" == typeof spacingInput ? spacingInput :
4405
+ // If it's a number, create a function that multiplies by that number
4406
+ "number" == typeof spacingInput ? (...values) => 0 === values.length ? "0px" : values.map((value => value * spacingInput + "px")).join(" ") :
4407
+ // If it's an array, use it as a scale
4408
+ 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(" ");
4409
+ }(mergedOptions.spacing), breakpoints = function(breakpointsInput) {
4410
+ const values = {
4411
+ xs: 0,
4412
+ sm: 576,
4413
+ md: 768,
4414
+ lg: 992,
4415
+ xl: 1200,
4416
+ xxl: 1440,
4417
+ ...breakpointsInput?.values
4418
+ }, unit = breakpointsInput?.unit || "px";
4419
+ return {
4420
+ values: values,
4421
+ unit: unit,
4422
+ up: key => `@media (min-width:${"number" == typeof key ? key : values[key] ?? 0}${unit})`,
4423
+ down: key => `@media (max-width:${("number" == typeof key ? key : values[key] ?? 0) - .05}${unit})`,
4424
+ between: (start, end) => {
4425
+ const startValue = "number" == typeof start ? start : values[start] ?? 0, endValue = "number" == typeof end ? end : values[end] ?? 0;
4426
+ return `@media (min-width:${startValue}${unit}) and (max-width:${endValue - .05}${unit})`;
4427
+ }
4428
+ };
4429
+ }(mergedOptions.breakpoints), shadows = deepMerge({
4430
+ ...DEFAULT_SHADOWS
4431
+ }, mergedOptions.shadows || {}), transitions = deepMerge({
4432
+ ...DEFAULT_TRANSITIONS
4433
+ }, mergedOptions.transitions || {}), zIndex = deepMerge({
4434
+ ...DEFAULT_ZINDEX
4435
+ }, mergedOptions.zIndex || {}), borderRadius = deepMerge({
4436
+ ...DEFAULT_BORDER_RADIUS
4437
+ }, mergedOptions.borderRadius || {});
4438
+ // Create palette
4439
+ return {
4440
+ // Metadata
4441
+ name: mergedOptions.name || "Custom Theme",
4442
+ class: mergedOptions.class,
4443
+ description: mergedOptions.description,
4444
+ author: mergedOptions.author,
4445
+ version: mergedOptions.version || "1.0.0",
4446
+ tags: mergedOptions.tags,
4447
+ supportsDarkMode: mergedOptions.supportsDarkMode,
4448
+ status: mergedOptions.status || "experimental",
4449
+ a11y: mergedOptions.a11y,
4450
+ color: mergedOptions.color || palette.primary.main,
4451
+ features: mergedOptions.features,
4452
+ dependencies: mergedOptions.dependencies,
4453
+ // Theme configuration
4454
+ palette: palette,
4455
+ typography: typography,
4456
+ spacing: spacing,
4457
+ breakpoints: breakpoints,
4458
+ shadows: shadows,
4459
+ transitions: transitions,
4460
+ zIndex: zIndex,
4461
+ borderRadius: borderRadius,
4462
+ custom: mergedOptions.custom || {},
4463
+ // Mark as JS theme
4464
+ __isJSTheme: !0
4465
+ };
4466
+ }
4467
+
4539
4468
  /**
4540
4469
  * useHistory Hook
4541
4470
  *
@@ -4553,8 +4482,7 @@ class ThemeValidator {
4553
4482
  * maxHistorySize: 50
4554
4483
  * });
4555
4484
  * ```
4556
- */
4557
- function useHistory(options = {}) {
4485
+ */ function useHistory(options = {}) {
4558
4486
  const {maxHistorySize: maxHistorySize = 50, initialState: initialState} = options, [state, setStateInternal] = useState(initialState), historyRef = useRef([ initialState ]), currentIndexRef = useRef(0), [canUndo, setCanUndo] = useState(!1), [canRedo, setCanRedo] = useState(!1), updateHistoryState = useCallback((() => {
4559
4487
  setCanUndo(currentIndexRef.current > 0), setCanRedo(currentIndexRef.current < historyRef.current.length - 1);
4560
4488
  }), []), setState = useCallback((newState => {
@@ -4995,6 +4923,23 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
4995
4923
  });
4996
4924
  };
4997
4925
 
4926
+ /**
4927
+ * Theme Adapter
4928
+ *
4929
+ * Converts between Theme objects and DesignTokens.
4930
+ */
4931
+ /**
4932
+ * Convert DesignTokens to Theme-compatible CSS variables
4933
+ *
4934
+ * @param tokens - DesignTokens object
4935
+ * @returns CSS variables object compatible with Theme.cssVars
4936
+ */ function designTokensToCSSVars(tokens) {
4937
+ const cssVars = {};
4938
+ return Object.entries(tokens).forEach((([key, value]) => {
4939
+ void 0 !== value && (cssVars[`--atomix-${key}`] = String(value));
4940
+ })), cssVars;
4941
+ }
4942
+
4998
4943
  /**
4999
4944
  * Map SCSS tokens to CSS custom properties
5000
4945
  *
@@ -5015,11 +4960,14 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
5015
4960
  /**
5016
4961
  * Apply CSS variables to an element
5017
4962
  *
5018
- * @param element - Target element (defaults to document.documentElement)
5019
4963
  * @param vars - CSS variables to apply
5020
- */ function applyCSSVariables(vars, element = document.documentElement) {
4964
+ * @param element - Target element (defaults to document.documentElement)
4965
+ */ function applyCSSVariables(vars, element) {
4966
+ if ("undefined" == typeof window) return;
4967
+ // SSR safety
4968
+ const target = element || document.documentElement;
5021
4969
  Object.entries(vars).forEach((([key, value]) => {
5022
- element.style.setProperty(key, String(value));
4970
+ target.style.setProperty(key, String(value));
5023
4971
  }));
5024
4972
  }
5025
4973
 
@@ -5028,9 +4976,12 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
5028
4976
  *
5029
4977
  * @param varNames - Variable names to remove
5030
4978
  * @param element - Target element (defaults to document.documentElement)
5031
- */ function removeCSSVariables(varNames, element = document.documentElement) {
4979
+ */ function removeCSSVariables(varNames, element) {
4980
+ if ("undefined" == typeof window) return;
4981
+ // SSR safety
4982
+ const target = element || document.documentElement;
5032
4983
  varNames.forEach((varName => {
5033
- element.style.removeProperty(varName);
4984
+ target.style.removeProperty(varName);
5034
4985
  }));
5035
4986
  }
5036
4987
 
@@ -5040,8 +4991,11 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
5040
4991
  * @param varName - Variable name to get
5041
4992
  * @param element - Target element (defaults to document.documentElement)
5042
4993
  * @returns Variable value or null if not found
5043
- */ function getCSSVariable(varName, element = document.documentElement) {
5044
- return getComputedStyle(element).getPropertyValue(varName).trim() || null;
4994
+ */ function getCSSVariable(varName, element) {
4995
+ if ("undefined" == typeof window) return null;
4996
+ // SSR safety
4997
+ const target = element || document.documentElement;
4998
+ return getComputedStyle(target).getPropertyValue(varName).trim() || null;
5045
4999
  }
5046
5000
 
5047
5001
  /**
@@ -5085,28 +5039,8 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
5085
5039
  /**
5086
5040
  * Theme Helper Functions
5087
5041
  *
5088
- * Utility functions for working with themes and DesignTokens
5042
+ * Utility functions for working with DesignTokens
5089
5043
  */
5090
- /**
5091
- * Get DesignTokens from current theme
5092
- *
5093
- * Converts a Theme object to DesignTokens. Useful when you need to
5094
- * work with DesignTokens but have a Theme object.
5095
- *
5096
- * @param theme - Theme object to convert
5097
- * @returns DesignTokens object
5098
- *
5099
- * @example
5100
- * ```typescript
5101
- * // If you have a Theme object, convert it to DesignTokens
5102
- * const tokens = getDesignTokensFromTheme(theme);
5103
- * // Now you can use tokens with unified theme system
5104
- * const css = createTheme(tokens);
5105
- * ```
5106
- */ function getDesignTokensFromTheme(theme) {
5107
- return theme ? createDesignTokensFromTheme(theme) : null;
5108
- }
5109
-
5110
5044
  /**
5111
5045
  * Check if a value is DesignTokens
5112
5046
  *
@@ -5126,17 +5060,6 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
5126
5060
  // Check if keys look like DesignTokens (kebab-case, no nesting)
5127
5061
  }
5128
5062
 
5129
- /**
5130
- * Check if a value is a Theme object
5131
- *
5132
- * Type guard to check if an object is a Theme.
5133
- *
5134
- * @param value - Value to check
5135
- * @returns True if value is Theme
5136
- */ function isThemeObject(value) {
5137
- return !(!value || "object" != typeof value) && ("__isJSTheme" in value || "palette" in value && "typography" in value);
5138
- }
5139
-
5140
5063
  /**
5141
5064
  * RTL (Right-to-Left) Support Utilities
5142
5065
  *
@@ -5325,13 +5248,13 @@ class RTLManager {
5325
5248
  /**
5326
5249
  * Theme System Exports
5327
5250
  *
5328
- * Unified theme system - handles both DesignTokens and Theme objects.
5251
+ * Simplified theme system using DesignTokens only.
5329
5252
  *
5330
5253
  * @example
5331
5254
  * ```typescript
5332
5255
  * import { createTheme, injectTheme } from '@shohojdhara/atomix/theme';
5333
5256
  *
5334
- * // Using DesignTokens (recommended - flat structure)
5257
+ * // Using DesignTokens
5335
5258
  * const css = createTheme({ 'primary': '#7AFFD7', 'spacing-4': '1rem' });
5336
5259
  * injectTheme(css);
5337
5260
  *
@@ -5344,7 +5267,7 @@ class RTLManager {
5344
5267
  // ============================================================================
5345
5268
  // Core Theme Functions
5346
5269
  // ============================================================================
5347
- // Unified createTheme (handles both DesignTokens and Theme objects)
5270
+ // Create theme CSS from DesignTokens
5348
5271
  /**
5349
5272
  * Inject theme CSS into DOM
5350
5273
  */ function injectTheme(css, id = "atomix-theme") {
@@ -5370,16 +5293,8 @@ class RTLManager {
5370
5293
  }),
5371
5294
  // Write file
5372
5295
  await fs.writeFile(filePath, css, "utf8");
5373
- }
5374
- /**
5375
- * Theme System Constants
5376
- *
5377
- * Centralized constants for the theme system to avoid magic numbers and strings.
5378
- */
5379
- /**
5380
- * Default storage key for theme persistence
5381
- */ (css, filePath);
5296
+ }(css, filePath);
5382
5297
  }
5383
5298
 
5384
- export { RTLManager, ThemeApplicator, ThemeComparator, ThemeContext, ThemeErrorBoundary, ThemeInspector, ThemeLiveEditor, ThemePreview, ThemeProvider, ThemeValidator, applyCSSVariables, applyComponentTheme, applyTheme, camelToKebab, clearThemes, createDesignTokensFromTheme, createTheme, createThemeObject, createThemeRegistry, createTokens, cssVarsToStyle, deepMerge, defaultTokens, designTokensToCSSVars, designTokensToTheme, extendTheme, extractComponentName, generateCSSVariableName, generateCSSVariables$1 as generateCSSVariables, generateCSSVariablesForSelector, generateClassName, generateComponentCSSVars, getAllThemes, getCSSVariable, getComponentThemeValue, getDesignTokensFromTheme, getTheme, getThemeApplicator, getThemeCount, getThemeIds, hasTheme, injectCSS$1 as injectCSS, injectTheme, isCSSInjected, isDesignTokens, isThemeObject, isValidCSSVariableName, loadThemeFromConfig, loadThemeFromConfigSync, mapSCSSTokensToCSSVars, mergeCSSVars, mergeTheme, normalizeThemeTokens, registerTheme, removeCSS, removeCSSVariables, removeTheme, saveTheme, themePropertyToCSSVar, themeToDesignTokens, unregisterTheme, useComponentTheme, useHistory, useTheme, useThemeTokens };
5299
+ 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, loadThemeFromConfig, loadThemeFromConfigSync, mapSCSSTokensToCSSVars, mergeCSSVars, mergeTheme, normalizeThemeTokens, registerTheme, removeCSS, removeCSSVariables, removeTheme, saveTheme, themePropertyToCSSVar, unregisterTheme, useComponentTheme, useHistory, useTheme, useThemeTokens };
5385
5300
  //# sourceMappingURL=theme.js.map