@shohojdhara/atomix 0.3.6 → 0.3.8
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.
- package/README.md +3 -3
- package/dist/atomix.css +77 -0
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +77 -0
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.js +50 -142
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +2 -2
- package/dist/core.js +179 -274
- package/dist/core.js.map +1 -1
- package/dist/forms.js +50 -142
- package/dist/forms.js.map +1 -1
- package/dist/heavy.js +179 -274
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +1255 -1226
- package/dist/index.esm.js +2806 -2958
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +3113 -3269
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/theme.d.ts +313 -667
- package/dist/theme.js +1818 -2589
- package/dist/theme.js.map +1 -1
- package/package.json +1 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +128 -356
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +1 -1
- package/src/components/Button/Button.tsx +85 -167
- package/src/components/DataTable/DataTable.stories.tsx +238 -0
- package/src/components/DataTable/DataTable.test.tsx +450 -0
- package/src/components/DataTable/DataTable.tsx +384 -61
- package/src/components/DatePicker/DatePicker.tsx +29 -38
- package/src/components/Upload/Upload.tsx +539 -40
- package/src/lib/composables/useAtomixGlass.ts +7 -7
- package/src/lib/composables/useDataTable.ts +355 -15
- package/src/lib/composables/useDatePicker.ts +19 -0
- package/src/lib/config/loader.ts +2 -3
- package/src/lib/constants/components.ts +17 -0
- package/src/lib/hooks/usePerformanceMonitor.ts +1 -1
- package/src/lib/theme/adapters/cssVariableMapper.ts +29 -14
- package/src/lib/theme/adapters/index.ts +1 -4
- package/src/lib/theme/config/configLoader.ts +82 -223
- package/src/lib/theme/config/loader.ts +15 -21
- package/src/lib/theme/constants/constants.ts +1 -1
- package/src/lib/theme/core/ThemeRegistry.ts +75 -279
- package/src/lib/theme/core/composeTheme.ts +30 -88
- package/src/lib/theme/core/createTheme.ts +88 -51
- package/src/lib/theme/core/createThemeObject.ts +2 -2
- package/src/lib/theme/core/index.ts +15 -2
- package/src/lib/theme/errors/errors.ts +1 -1
- package/src/lib/theme/generators/generateCSSNested.ts +131 -0
- package/src/lib/theme/generators/generateCSSVariables.ts +24 -16
- package/src/lib/theme/generators/index.ts +6 -0
- package/src/lib/theme/index.ts +45 -27
- package/src/lib/theme/runtime/ThemeApplicator.ts +6 -109
- package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +1 -1
- package/src/lib/theme/runtime/ThemeProvider.tsx +393 -544
- package/src/lib/theme/runtime/index.ts +1 -0
- package/src/lib/theme/runtime/useTheme.ts +1 -1
- package/src/lib/theme/runtime/useThemeTokens.ts +122 -0
- package/src/lib/theme/test/testTheme.ts +2 -1
- package/src/lib/theme/types.ts +14 -14
- package/src/lib/theme/utils/componentTheming.ts +140 -0
- package/src/lib/theme/utils/domUtils.ts +57 -15
- package/src/lib/theme/utils/injectCSS.ts +0 -1
- package/src/lib/theme/utils/naming.ts +100 -0
- package/src/lib/theme/utils/themeHelpers.ts +1 -39
- package/src/lib/theme/utils/themeUtils.ts +1 -170
- package/src/lib/types/components.ts +145 -0
- package/src/lib/utils/componentUtils.ts +1 -1
- package/src/lib/utils/dataTableExport.ts +143 -0
- package/src/lib/utils/memoryMonitor.ts +3 -3
- package/src/lib/utils/themeNaming.ts +135 -0
- package/src/styles/06-components/_components.data-table.scss +95 -0
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";
|
|
@@ -319,6 +321,14 @@ import { createContext, useRef, useEffect, useCallback, useMemo, useState, useCo
|
|
|
319
321
|
};
|
|
320
322
|
}
|
|
321
323
|
|
|
324
|
+
const tokens = Object.freeze( Object.defineProperty({
|
|
325
|
+
__proto__: null,
|
|
326
|
+
createTokens: createTokens,
|
|
327
|
+
defaultTokens: defaultTokens
|
|
328
|
+
}, Symbol.toStringTag, {
|
|
329
|
+
value: "Module"
|
|
330
|
+
}));
|
|
331
|
+
|
|
322
332
|
/**
|
|
323
333
|
* CSS Variable Generator
|
|
324
334
|
*
|
|
@@ -375,1521 +385,842 @@ import { createContext, useRef, useEffect, useCallback, useMemo, useState, useCo
|
|
|
375
385
|
});
|
|
376
386
|
}
|
|
377
387
|
|
|
378
|
-
|
|
388
|
+
/**
|
|
389
|
+
* Theme System Error Handling
|
|
390
|
+
*
|
|
391
|
+
* Centralized error handling for the Atomix theme system.
|
|
392
|
+
* Provides custom error classes and logging utilities.
|
|
393
|
+
*/
|
|
394
|
+
/**
|
|
395
|
+
* Theme error codes
|
|
396
|
+
*/ var ThemeErrorCode, LogLevel;
|
|
379
397
|
|
|
380
|
-
function
|
|
381
|
-
|
|
382
|
-
|
|
398
|
+
!function(ThemeErrorCode) {
|
|
399
|
+
/** Theme not found in registry */
|
|
400
|
+
ThemeErrorCode.THEME_NOT_FOUND = "THEME_NOT_FOUND",
|
|
401
|
+
/** Theme failed to load */
|
|
402
|
+
ThemeErrorCode.THEME_LOAD_FAILED = "THEME_LOAD_FAILED",
|
|
403
|
+
/** Theme validation failed */
|
|
404
|
+
ThemeErrorCode.THEME_VALIDATION_FAILED = "THEME_VALIDATION_FAILED",
|
|
405
|
+
/** Configuration loading failed */
|
|
406
|
+
ThemeErrorCode.CONFIG_LOAD_FAILED = "CONFIG_LOAD_FAILED",
|
|
407
|
+
/** Configuration validation failed */
|
|
408
|
+
ThemeErrorCode.CONFIG_VALIDATION_FAILED = "CONFIG_VALIDATION_FAILED",
|
|
409
|
+
/** Circular dependency detected */
|
|
410
|
+
ThemeErrorCode.CIRCULAR_DEPENDENCY = "CIRCULAR_DEPENDENCY",
|
|
411
|
+
/** Missing dependency */
|
|
412
|
+
ThemeErrorCode.MISSING_DEPENDENCY = "MISSING_DEPENDENCY",
|
|
413
|
+
/** Storage operation failed */
|
|
414
|
+
ThemeErrorCode.STORAGE_ERROR = "STORAGE_ERROR",
|
|
415
|
+
/** Invalid theme name */
|
|
416
|
+
ThemeErrorCode.INVALID_THEME_NAME = "INVALID_THEME_NAME",
|
|
417
|
+
/** CSS injection failed */
|
|
418
|
+
ThemeErrorCode.CSS_INJECTION_FAILED = "CSS_INJECTION_FAILED",
|
|
419
|
+
/** Unknown error */
|
|
420
|
+
ThemeErrorCode.UNKNOWN_ERROR = "UNKNOWN_ERROR";
|
|
421
|
+
}(ThemeErrorCode || (ThemeErrorCode = {}));
|
|
383
422
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
423
|
+
/**
|
|
424
|
+
* Custom error class for theme-related errors
|
|
425
|
+
*/
|
|
426
|
+
class ThemeError extends Error {
|
|
427
|
+
constructor(message, code = ThemeErrorCode.UNKNOWN_ERROR, context) {
|
|
428
|
+
super(message), this.name = "ThemeError", this.code = code, this.context = context,
|
|
429
|
+
this.timestamp = Date.now(),
|
|
430
|
+
// Maintains proper stack trace for where our error was thrown (only available on V8)
|
|
431
|
+
Error.captureStackTrace && Error.captureStackTrace(this, ThemeError);
|
|
389
432
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
}
|
|
402
|
-
|
|
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;
|
|
433
|
+
/**
|
|
434
|
+
* Convert error to JSON for logging
|
|
435
|
+
*/ toJSON() {
|
|
436
|
+
return {
|
|
437
|
+
name: this.name,
|
|
438
|
+
message: this.message,
|
|
439
|
+
code: this.code,
|
|
440
|
+
context: this.context,
|
|
441
|
+
timestamp: this.timestamp,
|
|
442
|
+
stack: this.stack
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
}
|
|
467
446
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
!version && userAgent$1 && (!(match = userAgent$1.match(/Edge\/(\d+)/)) || match[1] >= 74) && (match = userAgent$1.match(/Chrome\/(\d+)/)) && (version = +match[1]);
|
|
447
|
+
/**
|
|
448
|
+
* Log level
|
|
449
|
+
*/ !function(LogLevel) {
|
|
450
|
+
LogLevel[LogLevel.ERROR = 0] = "ERROR", LogLevel[LogLevel.WARN = 1] = "WARN", LogLevel[LogLevel.INFO = 2] = "INFO",
|
|
451
|
+
LogLevel[LogLevel.DEBUG = 3] = "DEBUG";
|
|
452
|
+
}(LogLevel || (LogLevel = {}));
|
|
475
453
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
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;
|
|
454
|
+
/**
|
|
455
|
+
* Theme Logger
|
|
456
|
+
*
|
|
457
|
+
* Centralized logging for the theme system.
|
|
458
|
+
* Replaces console statements with structured logging.
|
|
459
|
+
*/
|
|
460
|
+
class ThemeLogger {
|
|
461
|
+
constructor(config = {}) {
|
|
462
|
+
this.config = {
|
|
463
|
+
level: config.level ?? ("undefined" != typeof process && "production" === process.env?.NODE_ENV ? LogLevel.WARN : LogLevel.INFO),
|
|
464
|
+
enableConsole: config.enableConsole ?? !0,
|
|
465
|
+
onError: config.onError,
|
|
466
|
+
onWarn: config.onWarn,
|
|
467
|
+
onInfo: config.onInfo,
|
|
468
|
+
onDebug: config.onDebug
|
|
469
|
+
};
|
|
512
470
|
}
|
|
513
|
-
|
|
514
|
-
|
|
471
|
+
/**
|
|
472
|
+
* Log an error
|
|
473
|
+
*/ error(message, error, context) {
|
|
474
|
+
if (this.config.level < LogLevel.ERROR) return;
|
|
475
|
+
const errorObj = error instanceof Error ? error : new Error(message), themeError = error instanceof ThemeError ? error : new ThemeError(message, ThemeErrorCode.UNKNOWN_ERROR, context);
|
|
476
|
+
this.config.enableConsole && console.error(`[ThemeError] ${message}`, {
|
|
477
|
+
error: errorObj,
|
|
478
|
+
context: {
|
|
479
|
+
...context,
|
|
480
|
+
...themeError.context
|
|
481
|
+
},
|
|
482
|
+
code: themeError.code
|
|
483
|
+
}), this.config.onError?.(themeError, context);
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Log a warning
|
|
487
|
+
*/ warn(message, context) {
|
|
488
|
+
this.config.level < LogLevel.WARN || (this.config.enableConsole && console.warn(`[ThemeWarning] ${message}`, context || {}),
|
|
489
|
+
this.config.onWarn?.(message, context));
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Log an info message
|
|
493
|
+
*/ info(message, context) {
|
|
494
|
+
this.config.level < LogLevel.INFO || (this.config.enableConsole && console.info(`[ThemeInfo] ${message}`, context || {}),
|
|
495
|
+
this.config.onInfo?.(message, context));
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Log a debug message
|
|
499
|
+
*/ debug(message, context) {
|
|
500
|
+
this.config.level < LogLevel.DEBUG || (this.config.enableConsole, this.config.onDebug?.(message, context));
|
|
501
|
+
}
|
|
502
|
+
}
|
|
515
503
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
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
|
-
});
|
|
504
|
+
/**
|
|
505
|
+
* Default logger instance
|
|
506
|
+
*/ let defaultLogger = null;
|
|
523
507
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
return
|
|
528
|
-
}
|
|
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;
|
|
508
|
+
/**
|
|
509
|
+
* Get or create default logger
|
|
510
|
+
*/ function getLogger() {
|
|
511
|
+
return defaultLogger || (defaultLogger = new ThemeLogger), defaultLogger;
|
|
512
|
+
}
|
|
585
513
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
514
|
+
/**
|
|
515
|
+
* Core Theme Functions
|
|
516
|
+
*
|
|
517
|
+
* Simplified theme system using DesignTokens only.
|
|
518
|
+
* Config-first approach: loads from atomix.config.ts when no input is provided.
|
|
519
|
+
*/
|
|
520
|
+
/**
|
|
521
|
+
* Create theme CSS from DesignTokens
|
|
522
|
+
*
|
|
523
|
+
* **Config-First Approach**: If no input is provided, loads from `atomix.config.ts`.
|
|
524
|
+
*
|
|
525
|
+
* @param input - DesignTokens (partial) or undefined (loads from config)
|
|
526
|
+
* @param options - CSS generation options (prefix is automatically read from config if not provided)
|
|
527
|
+
* @returns CSS string with custom properties
|
|
528
|
+
* @throws Error if config loading fails when no input is provided
|
|
529
|
+
*
|
|
530
|
+
* @example
|
|
531
|
+
* ```typescript
|
|
532
|
+
* // Loads from atomix.config.ts
|
|
533
|
+
* const css = createTheme();
|
|
534
|
+
*
|
|
535
|
+
* // Using DesignTokens
|
|
536
|
+
* const css = createTheme({
|
|
537
|
+
* 'primary': '#7c3aed',
|
|
538
|
+
* 'spacing-4': '1rem',
|
|
539
|
+
* });
|
|
540
|
+
*
|
|
541
|
+
* // With custom options
|
|
542
|
+
* const css = createTheme(undefined, { prefix: 'myapp', selector: ':root' });
|
|
543
|
+
* ```
|
|
544
|
+
*/ function createTheme(input, options) {
|
|
545
|
+
// Validate options if provided
|
|
546
|
+
if (options?.prefix) {
|
|
547
|
+
const prefixPattern = /^[a-z][a-z0-9-]*$/;
|
|
548
|
+
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, {
|
|
549
|
+
prefix: options.prefix,
|
|
550
|
+
pattern: prefixPattern.toString()
|
|
595
551
|
});
|
|
596
552
|
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
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);
|
|
626
|
-
}
|
|
627
|
-
return new NativeConstructor(a, b, c);
|
|
628
|
-
}
|
|
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);
|
|
553
|
+
// Validate selector if provided
|
|
554
|
+
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, {
|
|
555
|
+
selector: options.selector
|
|
556
|
+
});
|
|
557
|
+
// Determine tokens based on input
|
|
558
|
+
let tokens;
|
|
559
|
+
if (input) {
|
|
560
|
+
// Validate input tokens structure
|
|
561
|
+
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, {
|
|
562
|
+
inputType: typeof input
|
|
563
|
+
});
|
|
564
|
+
// Use DesignTokens directly
|
|
565
|
+
tokens = input;
|
|
691
566
|
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
test[wellKnownSymbol$5("toStringTag")] = "z";
|
|
702
|
-
|
|
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 = /./;
|
|
567
|
+
// Merge with defaults and generate CSS
|
|
568
|
+
else {
|
|
569
|
+
// Check if we're in a browser environment
|
|
570
|
+
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, {
|
|
571
|
+
environment: "browser"
|
|
572
|
+
});
|
|
573
|
+
// Load from config when no input provided
|
|
574
|
+
let loadThemeFromConfigSync, loadAtomixConfig;
|
|
730
575
|
try {
|
|
731
|
-
"
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
576
|
+
const configLoaderModule = require("../config/configLoader"), loaderModule = require("../../config/loader");
|
|
577
|
+
// Get prefix from config if needed
|
|
578
|
+
if (loadThemeFromConfigSync = configLoaderModule.loadThemeFromConfigSync, loadAtomixConfig = loaderModule.loadAtomixConfig,
|
|
579
|
+
tokens = loadThemeFromConfigSync(), !options?.prefix) try {
|
|
580
|
+
const config = loadAtomixConfig({
|
|
581
|
+
configPath: "atomix.config.ts",
|
|
582
|
+
required: !1
|
|
583
|
+
});
|
|
584
|
+
options = {
|
|
585
|
+
...options,
|
|
586
|
+
prefix: config?.prefix || "atomix"
|
|
587
|
+
};
|
|
588
|
+
} catch (error) {
|
|
589
|
+
// If config loading fails, use default prefix
|
|
590
|
+
options = {
|
|
591
|
+
...options,
|
|
592
|
+
prefix: "atomix"
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
} catch (error) {
|
|
596
|
+
throw new ThemeError("No input provided and config loading is not available in this environment. Please provide tokens explicitly.", ThemeErrorCode.CONFIG_LOAD_FAILED, {
|
|
597
|
+
error: error instanceof Error ? error.message : String(error)
|
|
598
|
+
});
|
|
736
599
|
}
|
|
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
600
|
}
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
}));
|
|
601
|
+
const allTokens = createTokens(tokens), prefix = options?.prefix ?? "atomix";
|
|
602
|
+
// Get prefix from options or use default
|
|
603
|
+
return generateCSSVariables$1(allTokens, {
|
|
604
|
+
...options,
|
|
605
|
+
prefix: prefix
|
|
606
|
+
});
|
|
607
|
+
}
|
|
751
608
|
|
|
752
609
|
/**
|
|
753
|
-
* Theme Utilities
|
|
610
|
+
* Theme Composition Utilities
|
|
754
611
|
*
|
|
755
|
-
*
|
|
756
|
-
* spacing helpers, and theme value accessors.
|
|
612
|
+
* Simplified utilities for composing and merging DesignTokens.
|
|
757
613
|
*/
|
|
758
614
|
// ============================================================================
|
|
759
|
-
//
|
|
615
|
+
// Deep Merge Utility
|
|
760
616
|
// ============================================================================
|
|
761
617
|
/**
|
|
762
|
-
*
|
|
763
|
-
*/ function
|
|
764
|
-
|
|
765
|
-
return result ? {
|
|
766
|
-
r: parseInt(result[1], 16),
|
|
767
|
-
g: parseInt(result[2], 16),
|
|
768
|
-
b: parseInt(result[3], 16)
|
|
769
|
-
} : null;
|
|
618
|
+
* Check if value is an object
|
|
619
|
+
*/ function isObject$6(item) {
|
|
620
|
+
return item && "object" == typeof item && !Array.isArray(item) && "function" != typeof item;
|
|
770
621
|
}
|
|
771
622
|
|
|
772
623
|
/**
|
|
773
|
-
*
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
624
|
+
* Deep merge multiple objects
|
|
625
|
+
* Later objects override earlier ones
|
|
626
|
+
*/ function deepMerge(...objects) {
|
|
627
|
+
if (0 === objects.length) return {};
|
|
628
|
+
if (1 === objects.length) return objects[0];
|
|
629
|
+
const [target, ...sources] = objects, result = {
|
|
630
|
+
...target
|
|
631
|
+
};
|
|
632
|
+
for (const source of sources) if (source) for (const key in source) {
|
|
633
|
+
if (!Object.prototype.hasOwnProperty.call(source, key)) continue;
|
|
634
|
+
const targetValue = result[key], sourceValue = source[key];
|
|
635
|
+
isObject$6(targetValue) && isObject$6(sourceValue) ?
|
|
636
|
+
// Recursively merge objects
|
|
637
|
+
result[key] = deepMerge(targetValue, sourceValue) :
|
|
638
|
+
// Override with source value
|
|
639
|
+
result[key] = sourceValue;
|
|
640
|
+
}
|
|
641
|
+
return result;
|
|
777
642
|
}
|
|
778
643
|
|
|
779
644
|
/**
|
|
780
|
-
*
|
|
781
|
-
*
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
645
|
+
* Merge multiple DesignTokens objects into a single DesignTokens object
|
|
646
|
+
*
|
|
647
|
+
* @param tokens - DesignTokens objects to merge
|
|
648
|
+
* @returns Merged DesignTokens object
|
|
649
|
+
*
|
|
650
|
+
* @example
|
|
651
|
+
* ```typescript
|
|
652
|
+
* const baseTokens = { 'primary': '#000', 'spacing-4': '1rem' };
|
|
653
|
+
* const customTokens = { 'secondary': '#fff', 'spacing-4': '1.5rem' };
|
|
654
|
+
* const merged = mergeTheme(baseTokens, customTokens);
|
|
655
|
+
* // Returns: { 'primary': '#000', 'secondary': '#fff', 'spacing-4': '1.5rem' }
|
|
656
|
+
* ```
|
|
657
|
+
*/ function mergeTheme(...tokens) {
|
|
658
|
+
return deepMerge({}, ...tokens);
|
|
790
659
|
}
|
|
791
660
|
|
|
792
661
|
/**
|
|
793
|
-
*
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
662
|
+
* Extend DesignTokens with additional tokens
|
|
663
|
+
*
|
|
664
|
+
* @param baseTokens - Base DesignTokens to extend
|
|
665
|
+
* @param extension - Additional DesignTokens to merge
|
|
666
|
+
* @returns Extended DesignTokens object
|
|
667
|
+
*
|
|
668
|
+
* @example
|
|
669
|
+
* ```typescript
|
|
670
|
+
* const base = { 'primary': '#000' };
|
|
671
|
+
* const extended = extendTheme(base, { 'secondary': '#fff' });
|
|
672
|
+
* // Returns: { 'primary': '#000', 'secondary': '#fff' }
|
|
673
|
+
* ```
|
|
674
|
+
*/ function extendTheme(baseTokens, extension) {
|
|
675
|
+
return mergeTheme(baseTokens, extension);
|
|
797
676
|
}
|
|
798
677
|
|
|
799
678
|
/**
|
|
800
|
-
*
|
|
801
|
-
*/ function
|
|
802
|
-
|
|
803
|
-
return contrastWithWhite >= threshold ? "#FFFFFF" : contrastWithBlack >= threshold ? "#000000" : contrastWithWhite > contrastWithBlack ? "#FFFFFF" : "#000000";
|
|
679
|
+
* Create a new theme registry
|
|
680
|
+
*/ function createThemeRegistry() {
|
|
681
|
+
return {};
|
|
804
682
|
}
|
|
805
683
|
|
|
806
684
|
/**
|
|
807
|
-
*
|
|
808
|
-
*
|
|
809
|
-
* @param
|
|
810
|
-
* @param
|
|
811
|
-
|
|
812
|
-
|
|
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));
|
|
685
|
+
* Register a theme
|
|
686
|
+
* @param registry - Theme registry object
|
|
687
|
+
* @param id - Theme identifier
|
|
688
|
+
* @param metadata - Theme metadata
|
|
689
|
+
*/ function registerTheme(registry, id, metadata) {
|
|
690
|
+
registry[id] = metadata;
|
|
817
691
|
}
|
|
818
692
|
|
|
819
693
|
/**
|
|
820
|
-
*
|
|
821
|
-
*
|
|
822
|
-
* @param
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
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));
|
|
694
|
+
* Unregister a theme
|
|
695
|
+
* @param registry - Theme registry object
|
|
696
|
+
* @param id - Theme identifier
|
|
697
|
+
*/ function unregisterTheme(registry, id) {
|
|
698
|
+
const exists = id in registry;
|
|
699
|
+
return delete registry[id], exists;
|
|
830
700
|
}
|
|
831
701
|
|
|
832
702
|
/**
|
|
833
|
-
*
|
|
834
|
-
*
|
|
835
|
-
* @param
|
|
836
|
-
|
|
837
|
-
|
|
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))})`;
|
|
703
|
+
* Check if a theme is registered
|
|
704
|
+
* @param registry - Theme registry object
|
|
705
|
+
* @param id - Theme identifier
|
|
706
|
+
*/ function hasTheme(registry, id) {
|
|
707
|
+
return id in registry;
|
|
843
708
|
}
|
|
844
709
|
|
|
845
710
|
/**
|
|
846
|
-
*
|
|
847
|
-
*
|
|
848
|
-
* @param
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
*/
|
|
852
|
-
/**
|
|
853
|
-
* Check if a theme is a JS theme (created with createTheme)
|
|
854
|
-
*/
|
|
855
|
-
function isJSTheme(theme) {
|
|
856
|
-
return theme && "object" == typeof theme && !0 === theme.__isJSTheme;
|
|
711
|
+
* Get theme metadata
|
|
712
|
+
* @param registry - Theme registry object
|
|
713
|
+
* @param id - Theme identifier
|
|
714
|
+
*/ function getTheme(registry, id) {
|
|
715
|
+
return registry[id];
|
|
857
716
|
}
|
|
858
717
|
|
|
859
718
|
/**
|
|
860
|
-
*
|
|
861
|
-
*
|
|
862
|
-
|
|
863
|
-
|
|
719
|
+
* Get all registered theme metadata
|
|
720
|
+
* @param registry - Theme registry object
|
|
721
|
+
*/ function getAllThemes(registry) {
|
|
722
|
+
return Object.values(registry);
|
|
723
|
+
}
|
|
724
|
+
|
|
864
725
|
/**
|
|
865
|
-
*
|
|
866
|
-
*
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
* @param theme - Theme object to convert
|
|
870
|
-
* @returns Partial DesignTokens object
|
|
871
|
-
*
|
|
872
|
-
* @example
|
|
873
|
-
* ```typescript
|
|
874
|
-
* const theme = createTheme({ palette: { primary: { main: '#7c3aed' } } });
|
|
875
|
-
* const tokens = themeToDesignTokens(theme);
|
|
876
|
-
* // Returns: { 'primary': '#7c3aed', ... }
|
|
877
|
-
* ```
|
|
878
|
-
*/ function themeToDesignTokens(theme) {
|
|
879
|
-
const tokens = {};
|
|
880
|
-
// Convert palette colors
|
|
881
|
-
if (theme.palette) {
|
|
882
|
-
// Primary colors
|
|
883
|
-
if (theme.palette.primary && (tokens.primary = theme.palette.primary.main, theme.palette.primary.light && (tokens["primary-3"] = theme.palette.primary.light),
|
|
884
|
-
theme.palette.primary.dark && (tokens["primary-9"] = theme.palette.primary.dark),
|
|
885
|
-
theme.palette.primary.main)) {
|
|
886
|
-
const rgb = hexToRgb(theme.palette.primary.main);
|
|
887
|
-
rgb && (tokens["primary-rgb"] = `${rgb.r}, ${rgb.g}, ${rgb.b}`);
|
|
888
|
-
}
|
|
889
|
-
// Secondary colors
|
|
890
|
-
if (theme.palette.secondary) {
|
|
891
|
-
tokens.secondary = theme.palette.secondary.main, theme.palette.secondary.light && (tokens["gray-1"] = theme.palette.secondary.light),
|
|
892
|
-
theme.palette.secondary.dark && (tokens["gray-3"] = theme.palette.secondary.dark);
|
|
893
|
-
const rgb = hexToRgb(theme.palette.secondary.main);
|
|
894
|
-
rgb && (tokens["secondary-rgb"] = `${rgb.r}, ${rgb.g}, ${rgb.b}`);
|
|
895
|
-
}
|
|
896
|
-
// Error colors
|
|
897
|
-
if (theme.palette.error) {
|
|
898
|
-
tokens.error = theme.palette.error.main, tokens["red-6"] = theme.palette.error.main,
|
|
899
|
-
theme.palette.error.light && (tokens["red-4"] = theme.palette.error.light), theme.palette.error.dark && (tokens["red-9"] = theme.palette.error.dark);
|
|
900
|
-
const rgb = hexToRgb(theme.palette.error.main);
|
|
901
|
-
rgb && (tokens["error-rgb"] = `${rgb.r}, ${rgb.g}, ${rgb.b}`);
|
|
902
|
-
}
|
|
903
|
-
// Success colors
|
|
904
|
-
if (theme.palette.success) {
|
|
905
|
-
tokens.success = theme.palette.success.main, tokens["green-6"] = theme.palette.success.main,
|
|
906
|
-
theme.palette.success.light && (tokens["green-4"] = theme.palette.success.light),
|
|
907
|
-
theme.palette.success.dark && (tokens["green-9"] = theme.palette.success.dark);
|
|
908
|
-
const rgb = hexToRgb(theme.palette.success.main);
|
|
909
|
-
rgb && (tokens["success-rgb"] = `${rgb.r}, ${rgb.g}, ${rgb.b}`);
|
|
910
|
-
}
|
|
911
|
-
// Warning colors
|
|
912
|
-
if (theme.palette.warning) {
|
|
913
|
-
tokens.warning = theme.palette.warning.main, tokens["yellow-6"] = theme.palette.warning.main,
|
|
914
|
-
theme.palette.warning.light && (tokens["yellow-4"] = theme.palette.warning.light),
|
|
915
|
-
theme.palette.warning.dark && (tokens["yellow-9"] = theme.palette.warning.dark);
|
|
916
|
-
const rgb = hexToRgb(theme.palette.warning.main);
|
|
917
|
-
rgb && (tokens["warning-rgb"] = `${rgb.r}, ${rgb.g}, ${rgb.b}`);
|
|
918
|
-
}
|
|
919
|
-
// Info colors
|
|
920
|
-
if (theme.palette.info) {
|
|
921
|
-
tokens.info = theme.palette.info.main, tokens["blue-6"] = theme.palette.info.main,
|
|
922
|
-
theme.palette.info.light && (tokens["blue-4"] = theme.palette.info.light), theme.palette.info.dark && (tokens["blue-9"] = theme.palette.info.dark);
|
|
923
|
-
const rgb = hexToRgb(theme.palette.info.main);
|
|
924
|
-
rgb && (tokens["info-rgb"] = `${rgb.r}, ${rgb.g}, ${rgb.b}`);
|
|
925
|
-
}
|
|
926
|
-
// Background colors
|
|
927
|
-
theme.palette.background && (tokens["body-bg"] = theme.palette.background.default,
|
|
928
|
-
tokens["primary-bg-subtle"] = theme.palette.background.default, tokens["secondary-bg-subtle"] = theme.palette.background.paper,
|
|
929
|
-
tokens["tertiary-bg-subtle"] = theme.palette.background.subtle),
|
|
930
|
-
// Text colors
|
|
931
|
-
theme.palette.text && (tokens["body-color"] = theme.palette.text.primary, tokens["heading-color"] = theme.palette.text.primary,
|
|
932
|
-
tokens["primary-text-emphasis"] = theme.palette.text.primary, tokens["secondary-text-emphasis"] = theme.palette.text.secondary,
|
|
933
|
-
tokens["disabled-text-emphasis"] = theme.palette.text.disabled);
|
|
934
|
-
}
|
|
935
|
-
// Convert typography
|
|
936
|
-
// Convert spacing (if available as object)
|
|
937
|
-
if (theme.typography && (tokens["body-font-family"] = theme.typography.fontFamily,
|
|
938
|
-
tokens["font-sans-serif"] = theme.typography.fontFamily, tokens["body-font-size"] = `${theme.typography.fontSize}px`,
|
|
939
|
-
tokens["body-font-weight"] = String(theme.typography.fontWeightRegular),
|
|
940
|
-
// Font weights
|
|
941
|
-
tokens["font-weight-light"] = String(theme.typography.fontWeightLight), tokens["font-weight-normal"] = String(theme.typography.fontWeightRegular),
|
|
942
|
-
tokens["font-weight-medium"] = String(theme.typography.fontWeightMedium), tokens["font-weight-semibold"] = String(theme.typography.fontWeightSemiBold),
|
|
943
|
-
tokens["font-weight-bold"] = String(theme.typography.fontWeightBold),
|
|
944
|
-
// Line heights
|
|
945
|
-
theme.typography.h1?.lineHeight && (tokens["line-height-base"] = String(theme.typography.h1.lineHeight))),
|
|
946
|
-
theme.spacing && "object" == typeof theme.spacing && !("__isSpacingFunction" in theme.spacing)) {
|
|
947
|
-
const spacing = theme.spacing;
|
|
948
|
-
Object.entries(spacing).forEach((([key, value]) => {
|
|
949
|
-
tokens[`spacing-${key}`] = String(value);
|
|
950
|
-
}));
|
|
951
|
-
}
|
|
952
|
-
// Convert border radius
|
|
953
|
-
return theme.borderRadius && Object.entries(theme.borderRadius).forEach((([key, value]) => {
|
|
954
|
-
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);
|
|
955
|
-
})),
|
|
956
|
-
// Convert shadows
|
|
957
|
-
theme.shadows && Object.entries(theme.shadows).forEach((([key, value]) => {
|
|
958
|
-
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);
|
|
959
|
-
})),
|
|
960
|
-
// Convert z-index
|
|
961
|
-
theme.zIndex && Object.entries(theme.zIndex).forEach((([key, value]) => {
|
|
962
|
-
tokens[`z-${key}`] = String(value);
|
|
963
|
-
})),
|
|
964
|
-
// Convert transitions
|
|
965
|
-
theme.transitions && (theme.transitions.duration && Object.entries(theme.transitions.duration).forEach((([key, value]) => {
|
|
966
|
-
tokens[`transition-duration-${key}`] = String(value);
|
|
967
|
-
})), theme.transitions.easing && Object.entries(theme.transitions.easing).forEach((([key, value]) => {
|
|
968
|
-
tokens[`easing-${key}`] = String(value);
|
|
969
|
-
}))),
|
|
970
|
-
// Convert breakpoints
|
|
971
|
-
theme.breakpoints?.values && Object.entries(theme.breakpoints.values).forEach((([key, value]) => {
|
|
972
|
-
tokens[`breakpoint-${key}`] = String(value);
|
|
973
|
-
})),
|
|
974
|
-
// Merge any existing cssVars from theme
|
|
975
|
-
theme.cssVars && Object.entries(theme.cssVars).forEach((([key, value]) => {
|
|
976
|
-
// Remove --atomix- prefix if present
|
|
977
|
-
const cleanKey = key.replace(/^--atomix-/, "").replace(/^--/, "");
|
|
978
|
-
tokens[cleanKey] = String(value);
|
|
979
|
-
})), tokens;
|
|
726
|
+
* Get all registered theme IDs
|
|
727
|
+
* @param registry - Theme registry object
|
|
728
|
+
*/ function getThemeIds(registry) {
|
|
729
|
+
return Object.keys(registry);
|
|
980
730
|
}
|
|
981
731
|
|
|
982
732
|
/**
|
|
983
|
-
*
|
|
984
|
-
*
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
*/ function designTokensToCSSVars(tokens) {
|
|
988
|
-
const cssVars = {};
|
|
989
|
-
return Object.entries(tokens).forEach((([key, value]) => {
|
|
990
|
-
void 0 !== value && (cssVars[`--atomix-${key}`] = String(value));
|
|
991
|
-
})), cssVars;
|
|
733
|
+
* Clear all registered themes
|
|
734
|
+
* @param registry - Theme registry object
|
|
735
|
+
*/ function clearThemes(registry) {
|
|
736
|
+
Object.keys(registry).forEach((key => delete registry[key]));
|
|
992
737
|
}
|
|
993
738
|
|
|
994
739
|
/**
|
|
995
|
-
*
|
|
996
|
-
*
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
* @param theme - Theme object to convert
|
|
1000
|
-
* @returns Complete DesignTokens object
|
|
1001
|
-
*/ function createDesignTokensFromTheme(theme) {
|
|
1002
|
-
return createTokens(themeToDesignTokens(theme));
|
|
740
|
+
* Get the number of registered themes
|
|
741
|
+
* @param registry - Theme registry object
|
|
742
|
+
*/ function getThemeCount(registry) {
|
|
743
|
+
return Object.keys(registry).length;
|
|
1003
744
|
}
|
|
1004
745
|
|
|
1005
746
|
/**
|
|
1006
|
-
*
|
|
747
|
+
* Core Theme Engine
|
|
1007
748
|
*
|
|
1008
|
-
*
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
749
|
+
* Core theme creation, composition, and registry functionality
|
|
750
|
+
*/ const index = Object.freeze( Object.defineProperty({
|
|
751
|
+
__proto__: null,
|
|
752
|
+
clearThemes: clearThemes,
|
|
753
|
+
createTheme: createTheme,
|
|
754
|
+
createThemeRegistry: createThemeRegistry,
|
|
755
|
+
deepMerge: deepMerge,
|
|
756
|
+
extendTheme: extendTheme,
|
|
757
|
+
getAllThemes: getAllThemes,
|
|
758
|
+
getTheme: getTheme,
|
|
759
|
+
getThemeCount: getThemeCount,
|
|
760
|
+
getThemeIds: getThemeIds,
|
|
761
|
+
hasTheme: hasTheme,
|
|
762
|
+
mergeTheme: mergeTheme,
|
|
763
|
+
registerTheme: registerTheme,
|
|
764
|
+
unregisterTheme: unregisterTheme
|
|
765
|
+
}, Symbol.toStringTag, {
|
|
766
|
+
value: "Module"
|
|
767
|
+
}));
|
|
1017
768
|
|
|
1018
769
|
/**
|
|
1019
|
-
*
|
|
770
|
+
* CSS Injection Utilities
|
|
1020
771
|
*
|
|
1021
|
-
*
|
|
772
|
+
* Inject CSS into HTML head via <style> element.
|
|
1022
773
|
*/
|
|
1023
774
|
/**
|
|
1024
|
-
*
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
* Maps config structure to actual DesignTokens key names.
|
|
1028
|
-
*/ function flattenConfigTokens(tokens, prefix = "atomix") {
|
|
1029
|
-
const flat = {};
|
|
1030
|
-
// Colors
|
|
1031
|
-
return tokens.colors && Object.entries(tokens.colors).forEach((([key, value]) => {
|
|
1032
|
-
var _context;
|
|
1033
|
-
// Simple color: 'primary': '#7AFFD7'
|
|
1034
|
-
// Map directly to DesignTokens keys (e.g., 'primary', 'secondary', 'error')
|
|
1035
|
-
// Only map if it's a valid semantic color key
|
|
1036
|
-
if ("string" == typeof value) _includesInstanceProperty(_context = [ "primary", "secondary", "success", "info", "warning", "error", "light", "dark" ]).call(_context, key) && (flat[key] = value); else if (value && "object" == typeof value)
|
|
1037
|
-
// Color scale or palette
|
|
1038
|
-
if ("main" in value) {
|
|
1039
|
-
var _context2;
|
|
1040
|
-
// PaletteColorOptions: { main: '#7AFFD7', light?: '#...', dark?: '#...' }
|
|
1041
|
-
const palette = value, baseKey = key;
|
|
1042
|
-
// Map main to base color (e.g., primary, secondary, error)
|
|
1043
|
-
_includesInstanceProperty(_context2 = [ "primary", "secondary", "success", "info", "warning", "error", "light", "dark" ]).call(_context2, key) && (flat[baseKey] = palette.main,
|
|
1044
|
-
// Map light/dark to appropriate scale values
|
|
1045
|
-
// light typically maps to step 3, dark to step 9
|
|
1046
|
-
palette.light && (flat[`${key}-3`] = palette.light), palette.dark && (flat[`${key}-9`] = palette.dark));
|
|
1047
|
-
} else
|
|
1048
|
-
// Color scale: { 1: '#fff', 2: '#eee', ..., 6: '#main', ... }
|
|
1049
|
-
// Or full scale: { 1: '#...', 2: '#...', ..., 10: '#...' }
|
|
1050
|
-
Object.entries(value).forEach((([scaleKey, scaleValue]) => {
|
|
1051
|
-
if ("string" == typeof scaleValue)
|
|
1052
|
-
// Map scale keys to DesignTokens format
|
|
1053
|
-
if ("main" === scaleKey || "6" === scaleKey) {
|
|
1054
|
-
var _context3, _context4;
|
|
1055
|
-
// Main color maps to base key (e.g., 'primary')
|
|
1056
|
-
_includesInstanceProperty(_context3 = [ "primary", "secondary", "success", "info", "warning", "error", "light", "dark" ]).call(_context3, key) && (flat[key] = scaleValue),
|
|
1057
|
-
// Also map to step 6 if it's a scale color
|
|
1058
|
-
_includesInstanceProperty(_context4 = [ "primary", "red", "green", "blue", "yellow", "gray" ]).call(_context4, key) && (flat[`${key}-6`] = scaleValue);
|
|
1059
|
-
} else {
|
|
1060
|
-
// Map scale numbers (1-10) to DesignTokens format
|
|
1061
|
-
const scaleNum = parseInt(scaleKey, 10);
|
|
1062
|
-
!isNaN(scaleNum) && scaleNum >= 1 && scaleNum <= 10 && (flat[`${key}-${scaleKey}`] = scaleValue);
|
|
1063
|
-
}
|
|
1064
|
-
}));
|
|
1065
|
-
})),
|
|
1066
|
-
// Spacing
|
|
1067
|
-
tokens.spacing && Object.entries(tokens.spacing).forEach((([key, value]) => {
|
|
1068
|
-
flat[`spacing-${key}`] = String(value);
|
|
1069
|
-
})),
|
|
1070
|
-
// Border Radius
|
|
1071
|
-
tokens.borderRadius && Object.entries(tokens.borderRadius).forEach((([key, value]) => {
|
|
1072
|
-
// Map to DesignTokens format
|
|
1073
|
-
"sm" === key || "base" === key || "" === key ? flat["border-radius-sm"] = String(value) : "md" === key || "default" === key ? flat["border-radius"] = String(value) : "lg" === key ? flat["border-radius-lg"] = String(value) : flat[`border-radius-${key}`] = String(value);
|
|
1074
|
-
})),
|
|
1075
|
-
// Typography
|
|
1076
|
-
tokens.typography && (
|
|
1077
|
-
// Font Families
|
|
1078
|
-
tokens.typography.fontFamilies && Object.entries(tokens.typography.fontFamilies).forEach((([key, value]) => {
|
|
1079
|
-
// Map to DesignTokens format
|
|
1080
|
-
"sans" === key || "base" === key ? (flat["font-sans-serif"] = String(value), flat["body-font-family"] = String(value)) : "mono" === key ? flat["font-monospace"] = String(value) : flat[`font-family-${key}`] = String(value);
|
|
1081
|
-
})),
|
|
1082
|
-
// Font Sizes
|
|
1083
|
-
tokens.typography.fontSizes && Object.entries(tokens.typography.fontSizes).forEach((([key, value]) => {
|
|
1084
|
-
flat[`font-size-${key}`] = String(value);
|
|
1085
|
-
})),
|
|
1086
|
-
// Font Weights
|
|
1087
|
-
tokens.typography.fontWeights && Object.entries(tokens.typography.fontWeights).forEach((([key, value]) => {
|
|
1088
|
-
flat[`font-weight-${key}`] = String(value);
|
|
1089
|
-
})),
|
|
1090
|
-
// Line Heights
|
|
1091
|
-
tokens.typography.lineHeights && Object.entries(tokens.typography.lineHeights).forEach((([key, value]) => {
|
|
1092
|
-
"base" === key || "default" === key ? flat["line-height-base"] = String(value) : flat[`line-height-${key}`] = String(value);
|
|
1093
|
-
}))),
|
|
1094
|
-
// Shadows
|
|
1095
|
-
tokens.shadows && Object.entries(tokens.shadows).forEach((([key, value]) => {
|
|
1096
|
-
flat[`shadow-${key}`] = String(value);
|
|
1097
|
-
})),
|
|
1098
|
-
// Z-Index
|
|
1099
|
-
tokens.zIndex && Object.entries(tokens.zIndex).forEach((([key, value]) => {
|
|
1100
|
-
flat[`z-index-${key}`] = String(value);
|
|
1101
|
-
})),
|
|
1102
|
-
// Transitions
|
|
1103
|
-
tokens.transitions && tokens.transitions.durations && Object.entries(tokens.transitions.durations).forEach((([key, value]) => {
|
|
1104
|
-
flat[`transition-${key}`] = String(value);
|
|
1105
|
-
})), flat;
|
|
775
|
+
* Check if running in browser environment
|
|
776
|
+
*/ function isBrowser$1() {
|
|
777
|
+
return "undefined" != typeof document;
|
|
1106
778
|
}
|
|
1107
779
|
|
|
1108
780
|
/**
|
|
1109
|
-
*
|
|
781
|
+
* Inject CSS into HTML head via <style> element
|
|
1110
782
|
*
|
|
1111
|
-
*
|
|
1112
|
-
*
|
|
783
|
+
* Creates or updates a style element in the document head.
|
|
784
|
+
* If an element with the same ID exists, it will be updated.
|
|
1113
785
|
*
|
|
1114
|
-
* @param
|
|
1115
|
-
* @
|
|
1116
|
-
* @throws Error if config file is not found or cannot be loaded
|
|
786
|
+
* @param css - CSS string to inject
|
|
787
|
+
* @param id - Style element ID (default: 'atomix-theme')
|
|
1117
788
|
*
|
|
1118
789
|
* @example
|
|
1119
790
|
* ```typescript
|
|
1120
|
-
* const
|
|
1121
|
-
*
|
|
1122
|
-
*
|
|
791
|
+
* const css = ':root { --atomix-color-primary: #7AFFD7; }';
|
|
792
|
+
* injectCSS(css);
|
|
793
|
+
*
|
|
794
|
+
* // With custom ID
|
|
795
|
+
* injectCSS(css, 'my-custom-theme');
|
|
1123
796
|
* ```
|
|
1124
|
-
*/
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
required: !0
|
|
1131
|
-
});
|
|
1132
|
-
if (!config || !config.theme) throw new Error(`Config file ${configPath} does not contain theme configuration.`);
|
|
1133
|
-
// Extract tokens from config
|
|
1134
|
-
const tokens = config.theme.tokens || config.theme.extend || {};
|
|
1135
|
-
if (0 === Object.keys(tokens).length) throw new Error(`Config file ${configPath} has empty theme configuration.`);
|
|
1136
|
-
// Convert nested structure to flat tokens
|
|
1137
|
-
return flattenConfigTokens(tokens, config.prefix || "atomix");
|
|
797
|
+
*/ function injectCSS$1(css, id = "atomix-theme") {
|
|
798
|
+
if (!isBrowser$1()) return;
|
|
799
|
+
let styleElement = document.getElementById(id);
|
|
800
|
+
styleElement || (styleElement = document.createElement("style"), styleElement.id = id,
|
|
801
|
+
styleElement.setAttribute("data-atomix-theme", "true"), document.head.appendChild(styleElement)),
|
|
802
|
+
styleElement.textContent = css;
|
|
1138
803
|
}
|
|
1139
804
|
|
|
1140
805
|
/**
|
|
1141
|
-
*
|
|
806
|
+
* Remove injected CSS from DOM
|
|
807
|
+
*
|
|
808
|
+
* Removes the style element with the given ID from the document head.
|
|
1142
809
|
*
|
|
1143
|
-
*
|
|
1144
|
-
* Only works in Node.js environment.
|
|
1145
|
-
* Config file is required - throws error if not found.
|
|
810
|
+
* @param id - Style element ID to remove (default: 'atomix-theme')
|
|
1146
811
|
*
|
|
1147
|
-
* @
|
|
1148
|
-
*
|
|
1149
|
-
*
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
required: !0
|
|
1157
|
-
});
|
|
1158
|
-
if (!config || !config.theme) throw new Error(`Config file ${configPath} does not contain theme configuration.`);
|
|
1159
|
-
// Extract tokens from config
|
|
1160
|
-
const tokens = config.theme.tokens || config.theme.extend || {};
|
|
1161
|
-
if (0 === Object.keys(tokens).length) throw new Error(`Config file ${configPath} has empty theme configuration.`);
|
|
1162
|
-
// Convert nested structure to flat tokens
|
|
1163
|
-
return flattenConfigTokens(tokens, config.prefix || "atomix");
|
|
812
|
+
* @example
|
|
813
|
+
* ```typescript
|
|
814
|
+
* removeCSS(); // Removes default 'atomix-theme'
|
|
815
|
+
* removeCSS('my-custom-theme'); // Removes custom ID
|
|
816
|
+
* ```
|
|
817
|
+
*/ function removeCSS(id = "atomix-theme") {
|
|
818
|
+
if (!isBrowser$1()) return;
|
|
819
|
+
const styleElement = document.getElementById(id);
|
|
820
|
+
styleElement && styleElement.remove();
|
|
1164
821
|
}
|
|
1165
822
|
|
|
1166
823
|
/**
|
|
1167
|
-
*
|
|
824
|
+
* Check if CSS is already injected
|
|
1168
825
|
*
|
|
1169
|
-
*
|
|
1170
|
-
*
|
|
1171
|
-
|
|
826
|
+
* @param id - Style element ID to check (default: 'atomix-theme')
|
|
827
|
+
* @returns True if style element exists
|
|
828
|
+
*/ function isCSSInjected(id = "atomix-theme") {
|
|
829
|
+
return !!isBrowser$1() && null !== document.getElementById(id);
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* CSS File Utilities
|
|
834
|
+
*
|
|
835
|
+
* Save CSS to file system (Node.js only).
|
|
1172
836
|
*/
|
|
1173
837
|
/**
|
|
1174
|
-
*
|
|
838
|
+
* Save CSS to file
|
|
1175
839
|
*
|
|
1176
|
-
*
|
|
1177
|
-
* Config file is required for automatic loading.
|
|
840
|
+
* Writes CSS string to a file. Only works in Node.js environment.
|
|
1178
841
|
*
|
|
1179
|
-
* @param
|
|
1180
|
-
* @param
|
|
1181
|
-
* @
|
|
1182
|
-
* @throws Error if config loading fails when no input is provided
|
|
842
|
+
* @param css - CSS string to save
|
|
843
|
+
* @param filePath - Output file path
|
|
844
|
+
* @throws Error if called in browser environment
|
|
1183
845
|
*
|
|
1184
846
|
* @example
|
|
1185
847
|
* ```typescript
|
|
1186
|
-
*
|
|
1187
|
-
*
|
|
1188
|
-
*
|
|
1189
|
-
* // Using DesignTokens
|
|
1190
|
-
* const css = createTheme({
|
|
1191
|
-
* 'primary': '#7c3aed',
|
|
1192
|
-
* 'spacing-4': '1rem',
|
|
1193
|
-
* });
|
|
1194
|
-
*
|
|
1195
|
-
* // Using Theme object
|
|
1196
|
-
* const theme = createThemeObject({ palette: { primary: { main: '#7c3aed' } } });
|
|
1197
|
-
* const css = createTheme(theme);
|
|
1198
|
-
*
|
|
1199
|
-
* // With custom options
|
|
1200
|
-
* const css = createTheme(undefined, { prefix: 'myapp', selector: ':root' });
|
|
848
|
+
* const css = ':root { --atomix-color-primary: #7AFFD7; }';
|
|
849
|
+
* await saveCSSFile(css, './themes/custom.css');
|
|
1201
850
|
* ```
|
|
1202
|
-
*/
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
// Convert Theme to DesignTokens
|
|
1207
|
-
tokens = !0 === input.__isJSTheme || input.palette && input.typography ? themeToDesignTokens(input) : input; else {
|
|
1208
|
-
const configTokens = loadThemeFromConfigSync();
|
|
1209
|
-
// Get prefix from config
|
|
1210
|
-
try {
|
|
1211
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
1212
|
-
const {loadAtomixConfig: loadAtomixConfig} = require("../../config/loader"), config = loadAtomixConfig({
|
|
1213
|
-
configPath: "atomix.config.ts",
|
|
1214
|
-
required: !0
|
|
1215
|
-
});
|
|
1216
|
-
configPrefix = config?.prefix;
|
|
1217
|
-
} catch (error) {
|
|
1218
|
-
// Prefix loading failed, but tokens were loaded, so continue
|
|
1219
|
-
}
|
|
1220
|
-
tokens = configTokens;
|
|
1221
|
-
}
|
|
1222
|
-
// Merge with defaults and generate CSS
|
|
1223
|
-
return generateCSSVariables$1(createTokens(tokens), {
|
|
1224
|
-
...options,
|
|
1225
|
-
prefix: options?.prefix ?? configPrefix ?? "atomix"
|
|
1226
|
-
});
|
|
851
|
+
*/ var commonjsGlobal = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {};
|
|
852
|
+
|
|
853
|
+
function getDefaultExportFromCjs(x) {
|
|
854
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x.default : x;
|
|
1227
855
|
}
|
|
1228
856
|
|
|
1229
|
-
var
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
if (argumentsLength < 2) for (;;) {
|
|
1235
|
-
if (index in self) {
|
|
1236
|
-
memo = self[index], index += i;
|
|
1237
|
-
break;
|
|
1238
|
-
}
|
|
1239
|
-
if (index += i, IS_RIGHT ? index < 0 : length <= index) throw new $TypeError(REDUCE_EMPTY);
|
|
1240
|
-
}
|
|
1241
|
-
for (;IS_RIGHT ? index >= 0 : length > index; index += i) index in self && (memo = callbackfn(memo, self[index], index, O));
|
|
1242
|
-
return memo;
|
|
1243
|
-
};
|
|
1244
|
-
}, arrayReduce = {
|
|
1245
|
-
// `Array.prototype.reduce` method
|
|
1246
|
-
// https://tc39.es/ecma262/#sec-array.prototype.reduce
|
|
1247
|
-
left: createMethod(!1),
|
|
1248
|
-
// `Array.prototype.reduceRight` method
|
|
1249
|
-
// https://tc39.es/ecma262/#sec-array.prototype.reduceright
|
|
1250
|
-
right: createMethod(!0)
|
|
1251
|
-
}, fails = fails$9, globalThis$1 = globalThis_1, userAgent = environmentUserAgent, classof = classofRaw$2, userAgentStartsWith = function(string) {
|
|
1252
|
-
return userAgent.slice(0, string.length) === string;
|
|
1253
|
-
}, 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;
|
|
1254
|
-
|
|
1255
|
-
// `Array.prototype.reduce` method
|
|
1256
|
-
// https://tc39.es/ecma262/#sec-array.prototype.reduce
|
|
1257
|
-
_export({
|
|
1258
|
-
target: "Array",
|
|
1259
|
-
proto: !0,
|
|
1260
|
-
forced: !("NODE" === environment) && environmentV8Version > 79 && environmentV8Version < 83 || !function(METHOD_NAME, argument) {
|
|
1261
|
-
var method = [][METHOD_NAME];
|
|
1262
|
-
return !!method && fails((function() {
|
|
1263
|
-
// eslint-disable-next-line no-useless-call -- required for testing
|
|
1264
|
-
method.call(null, argument || function() {
|
|
1265
|
-
return 1;
|
|
1266
|
-
}, 1);
|
|
1267
|
-
}));
|
|
1268
|
-
}("reduce")
|
|
1269
|
-
}, {
|
|
1270
|
-
reduce: function(callbackfn /* , initialValue */) {
|
|
1271
|
-
var length = arguments.length;
|
|
1272
|
-
return $reduce(this, callbackfn, length, length > 1 ? arguments[1] : void 0);
|
|
857
|
+
var fails$9 = function(exec) {
|
|
858
|
+
try {
|
|
859
|
+
return !!exec();
|
|
860
|
+
} catch (error) {
|
|
861
|
+
return !0;
|
|
1273
862
|
}
|
|
1274
|
-
})
|
|
863
|
+
}, functionBindNative = !fails$9((function() {
|
|
864
|
+
// eslint-disable-next-line es/no-function-prototype-bind -- safe
|
|
865
|
+
var test = function() {/* empty */}.bind();
|
|
866
|
+
// eslint-disable-next-line no-prototype-builtins -- safe
|
|
867
|
+
return "function" != typeof test || test.hasOwnProperty("prototype");
|
|
868
|
+
})), 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) {
|
|
869
|
+
return function() {
|
|
870
|
+
return call$5.apply(fn, arguments);
|
|
871
|
+
};
|
|
872
|
+
}, objectIsPrototypeOf = functionUncurryThis({}.isPrototypeOf), check = function(it) {
|
|
873
|
+
return it && it.Math === Math && it;
|
|
874
|
+
}, globalThis_1 =
|
|
875
|
+
// eslint-disable-next-line es/no-global-this -- safe
|
|
876
|
+
check("object" == typeof globalThis && globalThis) || check("object" == typeof window && window) ||
|
|
877
|
+
// eslint-disable-next-line no-restricted-globals -- safe
|
|
878
|
+
check("object" == typeof self && self) || check("object" == typeof commonjsGlobal && commonjsGlobal) || check("object" == typeof commonjsGlobal && commonjsGlobal) ||
|
|
879
|
+
// eslint-disable-next-line no-new-func -- fallback
|
|
880
|
+
function() {
|
|
881
|
+
return this;
|
|
882
|
+
}() || 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() {
|
|
883
|
+
return call$4.apply(apply$1, arguments);
|
|
884
|
+
}), uncurryThis$7 = functionUncurryThis, toString$3 = uncurryThis$7({}.toString), stringSlice = uncurryThis$7("".slice), classofRaw$2 = function(it) {
|
|
885
|
+
return stringSlice(toString$3(it), 8, -1);
|
|
886
|
+
}, classofRaw$1 = classofRaw$2, uncurryThis$6 = functionUncurryThis, functionUncurryThisClause = function(fn) {
|
|
887
|
+
// Nashorn bug:
|
|
888
|
+
// https://github.com/zloirock/core-js/issues/1128
|
|
889
|
+
// https://github.com/zloirock/core-js/issues/1130
|
|
890
|
+
if ("Function" === classofRaw$1(fn)) return uncurryThis$6(fn);
|
|
891
|
+
}, documentAll = "object" == typeof document && document.all, isCallable$8 = void 0 === documentAll && void 0 !== documentAll ? function(argument) {
|
|
892
|
+
return "function" == typeof argument || argument === documentAll;
|
|
893
|
+
} : function(argument) {
|
|
894
|
+
return "function" == typeof argument;
|
|
895
|
+
}, objectGetOwnPropertyDescriptor = {}, descriptors = !fails$9((function() {
|
|
896
|
+
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
897
|
+
return 7 !== Object.defineProperty({}, 1, {
|
|
898
|
+
get: function() {
|
|
899
|
+
return 7;
|
|
900
|
+
}
|
|
901
|
+
})[1];
|
|
902
|
+
})), NATIVE_BIND$1 = functionBindNative, call$3 = Function.prototype.call, functionCall = NATIVE_BIND$1 ? call$3.bind(call$3) : function() {
|
|
903
|
+
return call$3.apply(call$3, arguments);
|
|
904
|
+
}, objectPropertyIsEnumerable = {}, $propertyIsEnumerable = {}.propertyIsEnumerable, getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor, NASHORN_BUG = getOwnPropertyDescriptor$1 && !$propertyIsEnumerable.call({
|
|
905
|
+
1: 2
|
|
906
|
+
}, 1);
|
|
1275
907
|
|
|
1276
|
-
|
|
908
|
+
// `Object.prototype.propertyIsEnumerable` method implementation
|
|
909
|
+
// https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
|
|
910
|
+
objectPropertyIsEnumerable.f = NASHORN_BUG ? function(V) {
|
|
911
|
+
var descriptor = getOwnPropertyDescriptor$1(this, V);
|
|
912
|
+
return !!descriptor && descriptor.enumerable;
|
|
913
|
+
} : $propertyIsEnumerable;
|
|
1277
914
|
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
915
|
+
var match, version, createPropertyDescriptor$2 = function(bitmap, value) {
|
|
916
|
+
return {
|
|
917
|
+
enumerable: !(1 & bitmap),
|
|
918
|
+
configurable: !(2 & bitmap),
|
|
919
|
+
writable: !(4 & bitmap),
|
|
920
|
+
value: value
|
|
921
|
+
};
|
|
922
|
+
}, fails$6 = fails$9, classof$4 = classofRaw$2, $Object$3 = Object, split = functionUncurryThis("".split), indexedObject = fails$6((function() {
|
|
923
|
+
// throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
|
|
924
|
+
// eslint-disable-next-line no-prototype-builtins -- safe
|
|
925
|
+
return !$Object$3("z").propertyIsEnumerable(0);
|
|
926
|
+
})) ? function(it) {
|
|
927
|
+
return "String" === classof$4(it) ? split(it, "") : $Object$3(it);
|
|
928
|
+
} : $Object$3, isNullOrUndefined$2 = function(it) {
|
|
929
|
+
return null == it;
|
|
930
|
+
}, isNullOrUndefined$1 = isNullOrUndefined$2, $TypeError$7 = TypeError, requireObjectCoercible$3 = function(it) {
|
|
931
|
+
if (isNullOrUndefined$1(it)) throw new $TypeError$7("Can't call method on " + it);
|
|
932
|
+
return it;
|
|
933
|
+
}, IndexedObject$1 = indexedObject, requireObjectCoercible$2 = requireObjectCoercible$3, toIndexedObject$2 = function(it) {
|
|
934
|
+
return IndexedObject$1(requireObjectCoercible$2(it));
|
|
935
|
+
}, isCallable$7 = isCallable$8, isObject$5 = function(it) {
|
|
936
|
+
return "object" == typeof it ? null !== it : isCallable$7(it);
|
|
937
|
+
}, path$3 = {}, path$2 = path$3, globalThis$b = globalThis_1, isCallable$6 = isCallable$8, aFunction = function(variable) {
|
|
938
|
+
return isCallable$6(variable) ? variable : void 0;
|
|
939
|
+
}, 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;
|
|
1282
940
|
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
//
|
|
1289
|
-
|
|
1290
|
-
// ============================================================================
|
|
1291
|
-
/**
|
|
1292
|
-
* Check if value is an object
|
|
1293
|
-
*/ function isObject(item) {
|
|
1294
|
-
return item && "object" == typeof item && !Array.isArray(item) && "function" != typeof item;
|
|
1295
|
-
}
|
|
941
|
+
v8 && (
|
|
942
|
+
// in old Chrome, versions of V8 isn't V8 = Chrome / 10
|
|
943
|
+
// but their correct versions are not interesting for us
|
|
944
|
+
version = (match = v8.split("."))[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1])),
|
|
945
|
+
// BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
|
|
946
|
+
// so check `userAgent` even if `.v8` exists, but 0
|
|
947
|
+
!version && userAgent$1 && (!(match = userAgent$1.match(/Edge\/(\d+)/)) || match[1] >= 74) && (match = userAgent$1.match(/Chrome\/(\d+)/)) && (version = +match[1]);
|
|
1296
948
|
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
949
|
+
var environmentV8Version = version, V8_VERSION = environmentV8Version, fails$5 = fails$9, $String$3 = globalThis_1.String, symbolConstructorDetection = !!Object.getOwnPropertySymbols && !fails$5((function() {
|
|
950
|
+
var symbol = Symbol("symbol detection");
|
|
951
|
+
// Chrome 38 Symbol has incorrect toString conversion
|
|
952
|
+
// `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
|
|
953
|
+
// nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will,
|
|
954
|
+
// of course, fail.
|
|
955
|
+
return !$String$3(symbol) || !(Object(symbol) instanceof Symbol) ||
|
|
956
|
+
// Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
|
|
957
|
+
!Symbol.sham && V8_VERSION && V8_VERSION < 41;
|
|
958
|
+
})), useSymbolAsUid = symbolConstructorDetection && !Symbol.sham && "symbol" == typeof Symbol.iterator, isCallable$5 = isCallable$8, isPrototypeOf$2 = objectIsPrototypeOf, $Object$2 = Object, isSymbol$2 = useSymbolAsUid ? function(it) {
|
|
959
|
+
return "symbol" == typeof it;
|
|
960
|
+
} : function(it) {
|
|
961
|
+
var $Symbol = function(namespace, method) {
|
|
962
|
+
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];
|
|
963
|
+
}("Symbol");
|
|
964
|
+
return isCallable$5($Symbol) && isPrototypeOf$2($Symbol.prototype, $Object$2(it));
|
|
965
|
+
}, $String$2 = String, isCallable$4 = isCallable$8, $TypeError$6 = TypeError, aCallable$3 = function(argument) {
|
|
966
|
+
if (isCallable$4(argument)) return argument;
|
|
967
|
+
throw new $TypeError$6(function(argument) {
|
|
968
|
+
try {
|
|
969
|
+
return $String$2(argument);
|
|
970
|
+
} catch (error) {
|
|
971
|
+
return "Object";
|
|
972
|
+
}
|
|
973
|
+
}(argument) + " is not a function");
|
|
974
|
+
}, aCallable$2 = aCallable$3, isNullOrUndefined = isNullOrUndefined$2, call$2 = functionCall, isCallable$3 = isCallable$8, isObject$4 = isObject$5, $TypeError$5 = TypeError, sharedStore = {
|
|
975
|
+
exports: {}
|
|
976
|
+
}, globalThis$7 = globalThis_1, defineProperty = Object.defineProperty, globalThis$6 = globalThis_1, store$1 = sharedStore.exports = globalThis$6["__core-js_shared__"] || function(key, value) {
|
|
977
|
+
try {
|
|
978
|
+
defineProperty(globalThis$7, key, {
|
|
979
|
+
value: value,
|
|
980
|
+
configurable: !0,
|
|
981
|
+
writable: !0
|
|
982
|
+
});
|
|
983
|
+
} catch (error) {
|
|
984
|
+
globalThis$7[key] = value;
|
|
1314
985
|
}
|
|
1315
|
-
return
|
|
1316
|
-
}
|
|
986
|
+
return value;
|
|
987
|
+
}("__core-js_shared__", {});
|
|
1317
988
|
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
* @returns Merged theme options
|
|
1326
|
-
*
|
|
1327
|
-
* @example
|
|
1328
|
-
* ```typescript
|
|
1329
|
-
* const baseTheme = { palette: { primary: { main: '#000' } } };
|
|
1330
|
-
* const customTheme = { palette: { secondary: { main: '#fff' } } };
|
|
1331
|
-
* const merged = mergeTheme(baseTheme, customTheme);
|
|
1332
|
-
* ```
|
|
1333
|
-
*/ function mergeTheme(...themes) {
|
|
1334
|
-
return deepMerge({}, ...themes);
|
|
1335
|
-
}
|
|
989
|
+
/* eslint-disable es/no-symbol -- required for testing */ (store$1.versions || (store$1.versions = [])).push({
|
|
990
|
+
version: "3.43.0",
|
|
991
|
+
mode: "pure",
|
|
992
|
+
copyright: "© 2014-2025 Denis Pushkarev (zloirock.ru)",
|
|
993
|
+
license: "https://github.com/zloirock/core-js/blob/v3.43.0/LICENSE",
|
|
994
|
+
source: "https://github.com/zloirock/core-js"
|
|
995
|
+
});
|
|
1336
996
|
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
primary: theme.palette.primary,
|
|
1374
|
-
secondary: theme.palette.secondary,
|
|
1375
|
-
error: theme.palette.error,
|
|
1376
|
-
warning: theme.palette.warning,
|
|
1377
|
-
info: theme.palette.info,
|
|
1378
|
-
success: theme.palette.success,
|
|
1379
|
-
background: theme.palette.background,
|
|
1380
|
-
text: theme.palette.text
|
|
1381
|
-
},
|
|
1382
|
-
typography: {
|
|
1383
|
-
fontFamily: theme.typography.fontFamily,
|
|
1384
|
-
fontSize: theme.typography.fontSize,
|
|
1385
|
-
fontWeightLight: theme.typography.fontWeightLight,
|
|
1386
|
-
fontWeightRegular: theme.typography.fontWeightRegular,
|
|
1387
|
-
fontWeightMedium: theme.typography.fontWeightMedium,
|
|
1388
|
-
fontWeightSemiBold: theme.typography.fontWeightSemiBold,
|
|
1389
|
-
fontWeightBold: theme.typography.fontWeightBold,
|
|
1390
|
-
h1: theme.typography.h1,
|
|
1391
|
-
h2: theme.typography.h2,
|
|
1392
|
-
h3: theme.typography.h3,
|
|
1393
|
-
h4: theme.typography.h4,
|
|
1394
|
-
h5: theme.typography.h5,
|
|
1395
|
-
h6: theme.typography.h6,
|
|
1396
|
-
body1: theme.typography.body1,
|
|
1397
|
-
body2: theme.typography.body2
|
|
1398
|
-
},
|
|
1399
|
-
shadows: theme.shadows,
|
|
1400
|
-
transitions: theme.transitions,
|
|
1401
|
-
zIndex: theme.zIndex,
|
|
1402
|
-
custom: theme.custom
|
|
1403
|
-
} : baseTheme, extension));
|
|
1404
|
-
}
|
|
997
|
+
var key, value, store = sharedStore.exports, requireObjectCoercible$1 = requireObjectCoercible$3, $Object$1 = Object, toObject$2 = function(argument) {
|
|
998
|
+
return $Object$1(requireObjectCoercible$1(argument));
|
|
999
|
+
}, toObject$1 = toObject$2, hasOwnProperty = functionUncurryThis({}.hasOwnProperty), hasOwnProperty_1 = Object.hasOwn || function(it, key) {
|
|
1000
|
+
return hasOwnProperty(toObject$1(it), key);
|
|
1001
|
+
}, 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) {
|
|
1002
|
+
return "Symbol(" + (void 0 === key ? "" : key) + ")_" + toString$2(++id + postfix, 36);
|
|
1003
|
+
}, wellKnownSymbol$5 = function(name) {
|
|
1004
|
+
return hasOwn$2(WellKnownSymbolsStore, name) || (WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn$2(Symbol$1, name) ? Symbol$1[name] : createWellKnownSymbol("Symbol." + name)),
|
|
1005
|
+
WellKnownSymbolsStore[name];
|
|
1006
|
+
}, call$1 = functionCall, isObject$3 = isObject$5, isSymbol$1 = isSymbol$2, $TypeError$4 = TypeError, TO_PRIMITIVE = wellKnownSymbol$5("toPrimitive"), toPrimitive = function(input, pref) {
|
|
1007
|
+
if (!isObject$3(input) || isSymbol$1(input)) return input;
|
|
1008
|
+
var result, func, exoticToPrim = (func = input[TO_PRIMITIVE], isNullOrUndefined(func) ? void 0 : aCallable$2(func));
|
|
1009
|
+
if (exoticToPrim) {
|
|
1010
|
+
if (void 0 === pref && (pref = "default"), result = call$1(exoticToPrim, input, pref),
|
|
1011
|
+
!isObject$3(result) || isSymbol$1(result)) return result;
|
|
1012
|
+
throw new $TypeError$4("Can't convert object to primitive value");
|
|
1013
|
+
}
|
|
1014
|
+
return void 0 === pref && (pref = "number"), function(input, pref) {
|
|
1015
|
+
var fn, val;
|
|
1016
|
+
if ("string" === pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
|
|
1017
|
+
if (isCallable$3(fn = input.valueOf) && !isObject$4(val = call$2(fn, input))) return val;
|
|
1018
|
+
if ("string" !== pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
|
|
1019
|
+
throw new $TypeError$5("Can't convert object to primitive value");
|
|
1020
|
+
}(input, pref);
|
|
1021
|
+
}, isSymbol = isSymbol$2, toPropertyKey$2 = function(argument) {
|
|
1022
|
+
var key = toPrimitive(argument, "string");
|
|
1023
|
+
return isSymbol(key) ? key : key + "";
|
|
1024
|
+
}, isObject$2 = isObject$5, document$1 = globalThis_1.document, EXISTS = isObject$2(document$1) && isObject$2(document$1.createElement), ie8DomDefine = !descriptors && !fails$9((function() {
|
|
1025
|
+
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
1026
|
+
return 7 !== Object.defineProperty((it = "div", EXISTS ? document$1.createElement(it) : {}), "a", {
|
|
1027
|
+
get: function() {
|
|
1028
|
+
return 7;
|
|
1029
|
+
}
|
|
1030
|
+
}).a;
|
|
1031
|
+
var it;
|
|
1032
|
+
})), 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;
|
|
1405
1033
|
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
// Primary-9
|
|
1414
|
-
contrastText: "#ffffff"
|
|
1415
|
-
},
|
|
1416
|
-
secondary: {
|
|
1417
|
-
main: "#f3f4f6",
|
|
1418
|
-
// Gray-2
|
|
1419
|
-
light: "#ffffff",
|
|
1420
|
-
// Gray-1
|
|
1421
|
-
dark: "#e5e7eb",
|
|
1422
|
-
// Gray-3
|
|
1423
|
-
contrastText: "#1f2937"
|
|
1424
|
-
},
|
|
1425
|
-
error: {
|
|
1426
|
-
main: "#ef4444",
|
|
1427
|
-
// Red-6
|
|
1428
|
-
light: "#fca5a5",
|
|
1429
|
-
// Red-4
|
|
1430
|
-
dark: "#991b1b",
|
|
1431
|
-
// Red-9
|
|
1432
|
-
contrastText: "#ffffff"
|
|
1433
|
-
},
|
|
1434
|
-
warning: {
|
|
1435
|
-
main: "#eab308",
|
|
1436
|
-
// Yellow-6
|
|
1437
|
-
light: "#fde047",
|
|
1438
|
-
// Yellow-4
|
|
1439
|
-
dark: "#854d0e",
|
|
1440
|
-
// Yellow-9
|
|
1441
|
-
contrastText: "#000000"
|
|
1442
|
-
},
|
|
1443
|
-
info: {
|
|
1444
|
-
main: "#3b82f6",
|
|
1445
|
-
// Blue-6
|
|
1446
|
-
light: "#93c5fd",
|
|
1447
|
-
// Blue-4
|
|
1448
|
-
dark: "#1e40af",
|
|
1449
|
-
// Blue-9
|
|
1450
|
-
contrastText: "#ffffff"
|
|
1451
|
-
},
|
|
1452
|
-
success: {
|
|
1453
|
-
main: "#22c55e",
|
|
1454
|
-
// Green-6
|
|
1455
|
-
light: "#86efac",
|
|
1456
|
-
// Green-4
|
|
1457
|
-
dark: "#166534",
|
|
1458
|
-
// Green-9
|
|
1459
|
-
contrastText: "#ffffff"
|
|
1460
|
-
},
|
|
1461
|
-
background: {
|
|
1462
|
-
default: "#ffffff",
|
|
1463
|
-
// Primary-bg
|
|
1464
|
-
paper: "#f3f4f6",
|
|
1465
|
-
// Secondary-bg
|
|
1466
|
-
subtle: "#d1d5db"
|
|
1467
|
-
},
|
|
1468
|
-
text: {
|
|
1469
|
-
primary: "#111827",
|
|
1470
|
-
// Gray-10
|
|
1471
|
-
secondary: "#374151",
|
|
1472
|
-
// Gray-8
|
|
1473
|
-
disabled: "#9ca3af"
|
|
1474
|
-
}
|
|
1475
|
-
}, DEFAULT_TYPOGRAPHY = {
|
|
1476
|
-
fontFamily: '"Roboto", "Helvetica Neue", "Helvetica", "Arial", sans-serif',
|
|
1477
|
-
fontSize: 16,
|
|
1478
|
-
// 1rem
|
|
1479
|
-
fontWeightLight: 300,
|
|
1480
|
-
fontWeightRegular: 400,
|
|
1481
|
-
fontWeightMedium: 500,
|
|
1482
|
-
fontWeightSemiBold: 600,
|
|
1483
|
-
fontWeightBold: 700,
|
|
1484
|
-
fontWeightHeavy: 800,
|
|
1485
|
-
fontWeightBlack: 900,
|
|
1486
|
-
h1: {
|
|
1487
|
-
fontSize: "2.5rem",
|
|
1488
|
-
// 40px
|
|
1489
|
-
fontWeight: 700,
|
|
1490
|
-
lineHeight: 1.3,
|
|
1491
|
-
letterSpacing: "-1px"
|
|
1492
|
-
},
|
|
1493
|
-
h2: {
|
|
1494
|
-
fontSize: "2rem",
|
|
1495
|
-
// 32px
|
|
1496
|
-
fontWeight: 700,
|
|
1497
|
-
lineHeight: 1.3,
|
|
1498
|
-
letterSpacing: "-1px"
|
|
1499
|
-
},
|
|
1500
|
-
h3: {
|
|
1501
|
-
fontSize: "1.5rem",
|
|
1502
|
-
// 24px
|
|
1503
|
-
fontWeight: 700,
|
|
1504
|
-
lineHeight: 1.3,
|
|
1505
|
-
letterSpacing: "-1px"
|
|
1506
|
-
},
|
|
1507
|
-
h4: {
|
|
1508
|
-
fontSize: "1.25rem",
|
|
1509
|
-
// 20px
|
|
1510
|
-
fontWeight: 700,
|
|
1511
|
-
lineHeight: 1.3,
|
|
1512
|
-
letterSpacing: "-0.5px"
|
|
1513
|
-
},
|
|
1514
|
-
h5: {
|
|
1515
|
-
fontSize: "1.125rem",
|
|
1516
|
-
// 18px
|
|
1517
|
-
fontWeight: 700,
|
|
1518
|
-
lineHeight: 1.3,
|
|
1519
|
-
letterSpacing: "-0.5px"
|
|
1520
|
-
},
|
|
1521
|
-
h6: {
|
|
1522
|
-
fontSize: "1rem",
|
|
1523
|
-
// 16px
|
|
1524
|
-
fontWeight: 700,
|
|
1525
|
-
lineHeight: 1.3,
|
|
1526
|
-
letterSpacing: "-0.5px"
|
|
1527
|
-
},
|
|
1528
|
-
body1: {
|
|
1529
|
-
fontSize: "1rem",
|
|
1530
|
-
// 16px
|
|
1531
|
-
fontWeight: 400,
|
|
1532
|
-
lineHeight: 1.2
|
|
1533
|
-
},
|
|
1534
|
-
body2: {
|
|
1535
|
-
fontSize: "0.875rem",
|
|
1536
|
-
// 14px
|
|
1537
|
-
fontWeight: 400,
|
|
1538
|
-
lineHeight: 1.2
|
|
1539
|
-
}
|
|
1540
|
-
}, DEFAULT_SHADOWS = {
|
|
1541
|
-
xs: "0px 1px 2px 0px rgba(45, 54, 67, 0.04), 0px 2px 4px 0px rgba(45, 54, 67, 0.08)",
|
|
1542
|
-
sm: "0 2px 4px rgba(0, 0, 0, 0.075)",
|
|
1543
|
-
md: "0 4px 8px rgba(0, 0, 0, 0.1)",
|
|
1544
|
-
lg: "0 16px 48px rgba(0, 0, 0, 0.175)",
|
|
1545
|
-
xl: "0px 16px 64px -8px rgba(45, 54, 67, 0.14)",
|
|
1546
|
-
inset: "inset 0 1px 2px rgba(0, 0, 0, 0.075)"
|
|
1547
|
-
}, DEFAULT_TRANSITIONS = {
|
|
1548
|
-
duration: {
|
|
1549
|
-
shortest: 150,
|
|
1550
|
-
shorter: 200,
|
|
1551
|
-
short: 250,
|
|
1552
|
-
standard: 300,
|
|
1553
|
-
complex: 375,
|
|
1554
|
-
enteringScreen: 225,
|
|
1555
|
-
leavingScreen: 195
|
|
1556
|
-
},
|
|
1557
|
-
easing: {
|
|
1558
|
-
easeInOut: "cubic-bezier(0.4, 0, 0.2, 1)",
|
|
1559
|
-
easeOut: "cubic-bezier(0.0, 0, 0.2, 1)",
|
|
1560
|
-
easeIn: "cubic-bezier(0.4, 0, 1, 1)",
|
|
1561
|
-
sharp: "cubic-bezier(0.4, 0, 0.6, 1)"
|
|
1562
|
-
}
|
|
1563
|
-
}, DEFAULT_ZINDEX = {
|
|
1564
|
-
mobileStepper: 1e3,
|
|
1565
|
-
speedDial: 1050,
|
|
1566
|
-
appBar: 1020,
|
|
1567
|
-
drawer: 1070,
|
|
1568
|
-
modal: 1040,
|
|
1569
|
-
snackbar: 1080,
|
|
1570
|
-
tooltip: 1060
|
|
1571
|
-
}, DEFAULT_BORDER_RADIUS = {
|
|
1572
|
-
base: "0.5rem",
|
|
1573
|
-
// 8px (spacing-2)
|
|
1574
|
-
sm: "0.25rem",
|
|
1575
|
-
// 4px (spacing-1)
|
|
1576
|
-
md: "0.25rem",
|
|
1577
|
-
// 4px (spacing-1)
|
|
1578
|
-
lg: "0.625rem",
|
|
1579
|
-
// 10px (spacing-2.5)
|
|
1580
|
-
xl: "0.75rem",
|
|
1581
|
-
// 12px (spacing-3)
|
|
1582
|
-
xxl: "1rem",
|
|
1583
|
-
// 16px (spacing-4)
|
|
1584
|
-
"3xl": "1.5rem",
|
|
1585
|
-
// 24px (spacing-6)
|
|
1586
|
-
"4xl": "2rem",
|
|
1587
|
-
// 32px (spacing-8)
|
|
1588
|
-
pill: "50rem"
|
|
1034
|
+
// `Object.getOwnPropertyDescriptor` method
|
|
1035
|
+
// https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
|
|
1036
|
+
objectGetOwnPropertyDescriptor.f = DESCRIPTORS$3 ? $getOwnPropertyDescriptor$1 : function(O, P) {
|
|
1037
|
+
if (O = toIndexedObject$1(O), P = toPropertyKey$1(P), IE8_DOM_DEFINE$1) try {
|
|
1038
|
+
return $getOwnPropertyDescriptor$1(O, P);
|
|
1039
|
+
} catch (error) {/* empty */}
|
|
1040
|
+
if (hasOwn$1(O, P)) return createPropertyDescriptor$1(!call(propertyIsEnumerableModule.f, O, P), O[P]);
|
|
1589
1041
|
};
|
|
1590
1042
|
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
return
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
dark: color.dark || darken(color.main || "#000000"),
|
|
1607
|
-
contrastText: color.contrastText || getContrastText(color.main || "#000000")
|
|
1608
|
-
};
|
|
1609
|
-
}
|
|
1043
|
+
var fails$3 = fails$9, isCallable$2 = isCallable$8, replacement = /#|\.prototype\./, isForced$1 = function(feature, detection) {
|
|
1044
|
+
var value = data[normalize(feature)];
|
|
1045
|
+
return value === POLYFILL || value !== NATIVE && (isCallable$2(detection) ? fails$3(detection) : !!detection);
|
|
1046
|
+
}, normalize = isForced$1.normalize = function(string) {
|
|
1047
|
+
return String(string).replace(replacement, ".").toLowerCase();
|
|
1048
|
+
}, 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() {
|
|
1049
|
+
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
1050
|
+
return 42 !== Object.defineProperty((function() {/* empty */}), "prototype", {
|
|
1051
|
+
value: 42,
|
|
1052
|
+
writable: !1
|
|
1053
|
+
}).prototype;
|
|
1054
|
+
})), 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) {
|
|
1055
|
+
if (isObject$1(argument)) return argument;
|
|
1056
|
+
throw new $TypeError$3($String$1(argument) + " is not an object");
|
|
1057
|
+
}, toPropertyKey = toPropertyKey$2, $TypeError$2 = TypeError, $defineProperty = Object.defineProperty, $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
1610
1058
|
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
function
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
info: createPaletteColor(mergedOptions.palette?.info || DEFAULT_PALETTE.info),
|
|
1631
|
-
success: createPaletteColor(mergedOptions.palette?.success || DEFAULT_PALETTE.success),
|
|
1632
|
-
// Handle light and dark colors if provided
|
|
1633
|
-
...mergedOptions.palette?.light && {
|
|
1634
|
-
light: createPaletteColor(mergedOptions.palette.light)
|
|
1635
|
-
},
|
|
1636
|
-
...mergedOptions.palette?.dark && {
|
|
1637
|
-
dark: createPaletteColor(mergedOptions.palette.dark)
|
|
1638
|
-
},
|
|
1639
|
-
background: {
|
|
1640
|
-
default: mergedOptions.palette?.background?.default || DEFAULT_PALETTE.background.default,
|
|
1641
|
-
subtle: mergedOptions.palette?.background?.subtle || DEFAULT_PALETTE.background.subtle
|
|
1642
|
-
},
|
|
1643
|
-
text: {
|
|
1644
|
-
primary: mergedOptions.palette?.text?.primary || DEFAULT_PALETTE.text.primary,
|
|
1645
|
-
secondary: mergedOptions.palette?.text?.secondary || DEFAULT_PALETTE.text.secondary,
|
|
1646
|
-
disabled: mergedOptions.palette?.text?.disabled || DEFAULT_PALETTE.text.disabled
|
|
1647
|
-
}
|
|
1648
|
-
}, typography = deepMerge({
|
|
1649
|
-
...DEFAULT_TYPOGRAPHY
|
|
1650
|
-
}, mergedOptions.typography || {}), spacing =
|
|
1651
|
-
// ============================================================================
|
|
1652
|
-
// Spacing Utilities
|
|
1653
|
-
// ============================================================================
|
|
1654
|
-
/**
|
|
1655
|
-
* Create a spacing function from various input types
|
|
1656
|
-
*
|
|
1657
|
-
* @param spacingInput - Spacing configuration (number, array, or function), default 4
|
|
1658
|
-
* @returns Spacing function
|
|
1659
|
-
*/
|
|
1660
|
-
function(spacingInput = 4) {
|
|
1661
|
-
// If it's already a function, return it
|
|
1662
|
-
return "function" == typeof spacingInput ? spacingInput :
|
|
1663
|
-
// If it's a number, create a function that multiplies by that number
|
|
1664
|
-
"number" == typeof spacingInput ? (...values) => 0 === values.length ? "0px" : values.map((value => value * spacingInput + "px")).join(" ") :
|
|
1665
|
-
// If it's an array, use it as a scale
|
|
1666
|
-
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(" ");
|
|
1667
|
-
}(mergedOptions.spacing), breakpoints = function(breakpointsInput) {
|
|
1668
|
-
const values = {
|
|
1669
|
-
xs: 0,
|
|
1670
|
-
sm: 576,
|
|
1671
|
-
md: 768,
|
|
1672
|
-
lg: 992,
|
|
1673
|
-
xl: 1200,
|
|
1674
|
-
xxl: 1440,
|
|
1675
|
-
...breakpointsInput?.values
|
|
1676
|
-
}, unit = breakpointsInput?.unit || "px";
|
|
1677
|
-
return {
|
|
1678
|
-
values: values,
|
|
1679
|
-
unit: unit,
|
|
1680
|
-
up: key => `@media (min-width:${"number" == typeof key ? key : values[key] ?? 0}${unit})`,
|
|
1681
|
-
down: key => `@media (max-width:${("number" == typeof key ? key : values[key] ?? 0) - .05}${unit})`,
|
|
1682
|
-
between: (start, end) => {
|
|
1683
|
-
const startValue = "number" == typeof start ? start : values[start] ?? 0, endValue = "number" == typeof end ? end : values[end] ?? 0;
|
|
1684
|
-
return `@media (min-width:${startValue}${unit}) and (max-width:${endValue - .05}${unit})`;
|
|
1685
|
-
}
|
|
1686
|
-
};
|
|
1687
|
-
}(mergedOptions.breakpoints), shadows = deepMerge({
|
|
1688
|
-
...DEFAULT_SHADOWS
|
|
1689
|
-
}, mergedOptions.shadows || {}), transitions = deepMerge({
|
|
1690
|
-
...DEFAULT_TRANSITIONS
|
|
1691
|
-
}, mergedOptions.transitions || {}), zIndex = deepMerge({
|
|
1692
|
-
...DEFAULT_ZINDEX
|
|
1693
|
-
}, mergedOptions.zIndex || {}), borderRadius = deepMerge({
|
|
1694
|
-
...DEFAULT_BORDER_RADIUS
|
|
1695
|
-
}, mergedOptions.borderRadius || {});
|
|
1696
|
-
// Create palette
|
|
1697
|
-
return {
|
|
1698
|
-
// Metadata
|
|
1699
|
-
name: mergedOptions.name || "Custom Theme",
|
|
1700
|
-
class: mergedOptions.class,
|
|
1701
|
-
description: mergedOptions.description,
|
|
1702
|
-
author: mergedOptions.author,
|
|
1703
|
-
version: mergedOptions.version || "1.0.0",
|
|
1704
|
-
tags: mergedOptions.tags,
|
|
1705
|
-
supportsDarkMode: mergedOptions.supportsDarkMode,
|
|
1706
|
-
status: mergedOptions.status || "experimental",
|
|
1707
|
-
a11y: mergedOptions.a11y,
|
|
1708
|
-
color: mergedOptions.color || palette.primary.main,
|
|
1709
|
-
features: mergedOptions.features,
|
|
1710
|
-
dependencies: mergedOptions.dependencies,
|
|
1711
|
-
// Theme configuration
|
|
1712
|
-
palette: palette,
|
|
1713
|
-
typography: typography,
|
|
1714
|
-
spacing: spacing,
|
|
1715
|
-
breakpoints: breakpoints,
|
|
1716
|
-
shadows: shadows,
|
|
1717
|
-
transitions: transitions,
|
|
1718
|
-
zIndex: zIndex,
|
|
1719
|
-
borderRadius: borderRadius,
|
|
1720
|
-
custom: mergedOptions.custom || {},
|
|
1721
|
-
// Mark as JS theme
|
|
1722
|
-
__isJSTheme: !0
|
|
1723
|
-
};
|
|
1724
|
-
}
|
|
1059
|
+
// `Object.defineProperty` method
|
|
1060
|
+
// https://tc39.es/ecma262/#sec-object.defineproperty
|
|
1061
|
+
objectDefineProperty.f = DESCRIPTORS$1 ? V8_PROTOTYPE_DEFINE_BUG ? function(O, P, Attributes) {
|
|
1062
|
+
if (anObject(O), P = toPropertyKey(P), anObject(Attributes), "function" == typeof O && "prototype" === P && "value" in Attributes && "writable" in Attributes && !Attributes.writable) {
|
|
1063
|
+
var current = $getOwnPropertyDescriptor(O, P);
|
|
1064
|
+
current && current.writable && (O[P] = Attributes.value, Attributes = {
|
|
1065
|
+
configurable: "configurable" in Attributes ? Attributes.configurable : current.configurable,
|
|
1066
|
+
enumerable: "enumerable" in Attributes ? Attributes.enumerable : current.enumerable,
|
|
1067
|
+
writable: !1
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
return $defineProperty(O, P, Attributes);
|
|
1071
|
+
} : $defineProperty : function(O, P, Attributes) {
|
|
1072
|
+
if (anObject(O), P = toPropertyKey(P), anObject(Attributes), IE8_DOM_DEFINE) try {
|
|
1073
|
+
return $defineProperty(O, P, Attributes);
|
|
1074
|
+
} catch (error) {/* empty */}
|
|
1075
|
+
if ("get" in Attributes || "set" in Attributes) throw new $TypeError$2("Accessors not supported");
|
|
1076
|
+
return "value" in Attributes && (O[P] = Attributes.value), O;
|
|
1077
|
+
};
|
|
1725
1078
|
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
*
|
|
1734
|
-
* @param config - Configuration to validate
|
|
1735
|
-
* @returns Validation result with errors and warnings
|
|
1736
|
-
*/
|
|
1737
|
-
/**
|
|
1738
|
-
* Validate CSS theme
|
|
1739
|
-
*/
|
|
1740
|
-
function validateCSSTheme(themeId, theme) {
|
|
1741
|
-
const errors = [];
|
|
1742
|
-
// CSS themes don't require createTheme function
|
|
1743
|
-
// But can have optional cssPath
|
|
1744
|
-
return {
|
|
1745
|
-
valid: 0 === errors.length,
|
|
1746
|
-
errors: errors,
|
|
1747
|
-
warnings: []
|
|
1079
|
+
var definePropertyModule = objectDefineProperty, createPropertyDescriptor = createPropertyDescriptor$2, createNonEnumerableProperty$1 = descriptors ? function(object, key, value) {
|
|
1080
|
+
return definePropertyModule.f(object, key, createPropertyDescriptor(1, value));
|
|
1081
|
+
} : function(object, key, value) {
|
|
1082
|
+
return object[key] = value, object;
|
|
1083
|
+
}, 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) {
|
|
1084
|
+
return aCallable$1(fn), void 0 === that ? fn : NATIVE_BIND ? bind$1(fn, that) : function() {
|
|
1085
|
+
return fn.apply(that, arguments);
|
|
1748
1086
|
};
|
|
1749
|
-
}
|
|
1087
|
+
}, createNonEnumerableProperty = createNonEnumerableProperty$1, hasOwn = hasOwnProperty_1, wrapConstructor = function(NativeConstructor) {
|
|
1088
|
+
var Wrapper = function(a, b, c) {
|
|
1089
|
+
if (this instanceof Wrapper) {
|
|
1090
|
+
switch (arguments.length) {
|
|
1091
|
+
case 0:
|
|
1092
|
+
return new NativeConstructor;
|
|
1750
1093
|
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
warnings: []
|
|
1094
|
+
case 1:
|
|
1095
|
+
return new NativeConstructor(a);
|
|
1096
|
+
|
|
1097
|
+
case 2:
|
|
1098
|
+
return new NativeConstructor(a, b);
|
|
1099
|
+
}
|
|
1100
|
+
return new NativeConstructor(a, b, c);
|
|
1101
|
+
}
|
|
1102
|
+
return apply(NativeConstructor, this, arguments);
|
|
1761
1103
|
};
|
|
1762
|
-
|
|
1104
|
+
return Wrapper.prototype = NativeConstructor.prototype, Wrapper;
|
|
1105
|
+
}, _export = function(options, source) {
|
|
1106
|
+
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;
|
|
1107
|
+
for (key in source)
|
|
1108
|
+
// contains in native
|
|
1109
|
+
USE_NATIVE = !(FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? "." : "#") + key, options.forced)) && nativeSource && hasOwn(nativeSource, key),
|
|
1110
|
+
targetProperty = target[key], USE_NATIVE && (nativeProperty = options.dontCallGetSet ? (descriptor = getOwnPropertyDescriptor(nativeSource, key)) && descriptor.value : nativeSource[key]),
|
|
1111
|
+
// export native or implementation
|
|
1112
|
+
sourceProperty = USE_NATIVE && nativeProperty ? nativeProperty : source[key], (FORCED || PROTO || typeof targetProperty != typeof sourceProperty) && (
|
|
1113
|
+
// bind methods to global for calling from export context
|
|
1114
|
+
resultProperty = options.bind && USE_NATIVE ? bind(sourceProperty, globalThis$3) : options.wrap && USE_NATIVE ? wrapConstructor(sourceProperty) : PROTO && isCallable$1(sourceProperty) ? uncurryThis$1(sourceProperty) : sourceProperty,
|
|
1115
|
+
// add a flag to not completely full polyfills
|
|
1116
|
+
(options.sham || sourceProperty && sourceProperty.sham || targetProperty && targetProperty.sham) && createNonEnumerableProperty(resultProperty, "sham", !0),
|
|
1117
|
+
createNonEnumerableProperty(target, key, resultProperty), PROTO && (hasOwn(path$1, VIRTUAL_PROTOTYPE = TARGET + "Prototype") || createNonEnumerableProperty(path$1, VIRTUAL_PROTOTYPE, {}),
|
|
1118
|
+
// export virtual prototype methods
|
|
1119
|
+
createNonEnumerableProperty(path$1[VIRTUAL_PROTOTYPE], key, sourceProperty),
|
|
1120
|
+
// export real prototype methods
|
|
1121
|
+
options.real && targetPrototype && (FORCED || !targetPrototype[key]) && createNonEnumerableProperty(targetPrototype, key, sourceProperty)));
|
|
1122
|
+
}, ceil = Math.ceil, floor = Math.floor, trunc = Math.trunc || function(x) {
|
|
1123
|
+
var n = +x;
|
|
1124
|
+
return (n > 0 ? floor : ceil)(n);
|
|
1125
|
+
}, toIntegerOrInfinity$2 = function(argument) {
|
|
1126
|
+
var number = +argument;
|
|
1127
|
+
// eslint-disable-next-line no-self-compare -- NaN check
|
|
1128
|
+
return number != number || 0 === number ? 0 : trunc(number);
|
|
1129
|
+
}, toIntegerOrInfinity$1 = toIntegerOrInfinity$2, max = Math.max, min$1 = Math.min, toIntegerOrInfinity = toIntegerOrInfinity$2, min = Math.min, lengthOfArrayLike$2 = function(obj) {
|
|
1130
|
+
return argument = obj.length, (len = toIntegerOrInfinity(argument)) > 0 ? min(len, 9007199254740991) : 0;
|
|
1131
|
+
var argument, len;
|
|
1132
|
+
}, toIndexedObject = toIndexedObject$2, lengthOfArrayLike$1 = lengthOfArrayLike$2, createMethod$1 = function(IS_INCLUDES) {
|
|
1133
|
+
return function($this, el, fromIndex) {
|
|
1134
|
+
var O = toIndexedObject($this), length = lengthOfArrayLike$1(O);
|
|
1135
|
+
if (0 === length) return !IS_INCLUDES && -1;
|
|
1136
|
+
var value, index = function(index, length) {
|
|
1137
|
+
var integer = toIntegerOrInfinity$1(index);
|
|
1138
|
+
return integer < 0 ? max(integer + length, 0) : min$1(integer, length);
|
|
1139
|
+
}(fromIndex, length);
|
|
1140
|
+
// Array#includes uses SameValueZero equality algorithm
|
|
1141
|
+
// eslint-disable-next-line no-self-compare -- NaN check
|
|
1142
|
+
if (IS_INCLUDES && el != el) {
|
|
1143
|
+
for (;length > index; )
|
|
1144
|
+
// eslint-disable-next-line no-self-compare -- NaN check
|
|
1145
|
+
if ((value = O[index++]) != value) return !0;
|
|
1146
|
+
// Array#indexOf ignores holes, Array#includes - not
|
|
1147
|
+
} else for (;length > index; index++) if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
|
|
1148
|
+
return !IS_INCLUDES && -1;
|
|
1149
|
+
};
|
|
1150
|
+
}, $includes = [ createMethod$1(!0), createMethod$1(!1) ][0];
|
|
1763
1151
|
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1152
|
+
// `Array.prototype.includes` method
|
|
1153
|
+
// https://tc39.es/ecma262/#sec-array.prototype.includes
|
|
1154
|
+
_export({
|
|
1155
|
+
target: "Array",
|
|
1156
|
+
proto: !0,
|
|
1157
|
+
forced: fails$9((function() {
|
|
1158
|
+
// eslint-disable-next-line es/no-array-prototype-includes -- detection
|
|
1159
|
+
return !Array(1).includes();
|
|
1160
|
+
}))
|
|
1161
|
+
}, {
|
|
1162
|
+
includes: function(el /* , fromIndex = 0 */) {
|
|
1163
|
+
return $includes(this, el, arguments.length > 1 ? arguments[1] : void 0);
|
|
1164
|
+
}
|
|
1165
|
+
});
|
|
1777
1166
|
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
ThemeErrorCode.THEME_VALIDATION_FAILED = "THEME_VALIDATION_FAILED",
|
|
1785
|
-
/** Configuration loading failed */
|
|
1786
|
-
ThemeErrorCode.CONFIG_LOAD_FAILED = "CONFIG_LOAD_FAILED",
|
|
1787
|
-
/** Configuration validation failed */
|
|
1788
|
-
ThemeErrorCode.CONFIG_VALIDATION_FAILED = "CONFIG_VALIDATION_FAILED",
|
|
1789
|
-
/** Circular dependency detected */
|
|
1790
|
-
ThemeErrorCode.CIRCULAR_DEPENDENCY = "CIRCULAR_DEPENDENCY",
|
|
1791
|
-
/** Missing dependency */
|
|
1792
|
-
ThemeErrorCode.MISSING_DEPENDENCY = "MISSING_DEPENDENCY",
|
|
1793
|
-
/** Storage operation failed */
|
|
1794
|
-
ThemeErrorCode.STORAGE_ERROR = "STORAGE_ERROR",
|
|
1795
|
-
/** Invalid theme name */
|
|
1796
|
-
ThemeErrorCode.INVALID_THEME_NAME = "INVALID_THEME_NAME",
|
|
1797
|
-
/** CSS injection failed */
|
|
1798
|
-
ThemeErrorCode.CSS_INJECTION_FAILED = "CSS_INJECTION_FAILED",
|
|
1799
|
-
/** Unknown error */
|
|
1800
|
-
ThemeErrorCode.UNKNOWN_ERROR = "UNKNOWN_ERROR";
|
|
1801
|
-
}(ThemeErrorCode || (ThemeErrorCode = {}));
|
|
1167
|
+
var globalThis$2 = globalThis_1, path = path$3, getBuiltInPrototypeMethod$3 = function(CONSTRUCTOR, METHOD) {
|
|
1168
|
+
var Namespace = path[CONSTRUCTOR + "Prototype"], pureMethod = Namespace && Namespace[METHOD];
|
|
1169
|
+
if (pureMethod) return pureMethod;
|
|
1170
|
+
var NativeConstructor = globalThis$2[CONSTRUCTOR], NativePrototype = NativeConstructor && NativeConstructor.prototype;
|
|
1171
|
+
return NativePrototype && NativePrototype[METHOD];
|
|
1172
|
+
}, includes$4 = getBuiltInPrototypeMethod$3("Array", "includes"), isObject = isObject$5, classof$3 = classofRaw$2, MATCH$1 = wellKnownSymbol$5("match"), $TypeError$1 = TypeError, test = {};
|
|
1802
1173
|
|
|
1803
|
-
|
|
1804
|
-
* Custom error class for theme-related errors
|
|
1805
|
-
*/
|
|
1806
|
-
class ThemeError extends Error {
|
|
1807
|
-
constructor(message, code = ThemeErrorCode.UNKNOWN_ERROR, context) {
|
|
1808
|
-
super(message), this.name = "ThemeError", this.code = code, this.context = context,
|
|
1809
|
-
this.timestamp = Date.now(),
|
|
1810
|
-
// Maintains proper stack trace for where our error was thrown (only available on V8)
|
|
1811
|
-
Error.captureStackTrace && Error.captureStackTrace(this, ThemeError);
|
|
1812
|
-
}
|
|
1813
|
-
/**
|
|
1814
|
-
* Convert error to JSON for logging
|
|
1815
|
-
*/ toJSON() {
|
|
1816
|
-
return {
|
|
1817
|
-
name: this.name,
|
|
1818
|
-
message: this.message,
|
|
1819
|
-
code: this.code,
|
|
1820
|
-
context: this.context,
|
|
1821
|
-
timestamp: this.timestamp,
|
|
1822
|
-
stack: this.stack
|
|
1823
|
-
};
|
|
1824
|
-
}
|
|
1825
|
-
}
|
|
1174
|
+
test[wellKnownSymbol$5("toStringTag")] = "z";
|
|
1826
1175
|
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1176
|
+
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() {
|
|
1177
|
+
return arguments;
|
|
1178
|
+
}()), classof$1 = TO_STRING_TAG_SUPPORT ? classofRaw : function(it) {
|
|
1179
|
+
var O, tag, result;
|
|
1180
|
+
return void 0 === it ? "Undefined" : null === it ? "Null" : "string" == typeof (tag = function(it, key) {
|
|
1181
|
+
try {
|
|
1182
|
+
return it[key];
|
|
1183
|
+
} catch (error) {/* empty */}
|
|
1184
|
+
}(O = $Object(it), TO_STRING_TAG)) ? tag : CORRECT_ARGUMENTS ? classofRaw(O) : "Object" === (result = classofRaw(O)) && isCallable(O.callee) ? "Arguments" : result;
|
|
1185
|
+
}, $String = String, MATCH = wellKnownSymbol$5("match"), $$1 = _export, notARegExp = function(it) {
|
|
1186
|
+
if (function(it) {
|
|
1187
|
+
var isRegExp;
|
|
1188
|
+
return isObject(it) && (void 0 !== (isRegExp = it[MATCH$1]) ? !!isRegExp : "RegExp" === classof$3(it));
|
|
1189
|
+
}(it)) throw new $TypeError$1("The method doesn't accept regular expressions");
|
|
1190
|
+
return it;
|
|
1191
|
+
}, requireObjectCoercible = requireObjectCoercible$3, toString = function(argument) {
|
|
1192
|
+
if ("Symbol" === classof$1(argument)) throw new TypeError("Cannot convert a Symbol value to a string");
|
|
1193
|
+
return $String(argument);
|
|
1194
|
+
}, stringIndexOf = functionUncurryThis("".indexOf);
|
|
1833
1195
|
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
*/ error(message, error, context) {
|
|
1854
|
-
if (this.config.level < LogLevel.ERROR) return;
|
|
1855
|
-
const errorObj = error instanceof Error ? error : new Error(message), themeError = error instanceof ThemeError ? error : new ThemeError(message, ThemeErrorCode.UNKNOWN_ERROR, context);
|
|
1856
|
-
this.config.enableConsole && console.error(`[ThemeError] ${message}`, {
|
|
1857
|
-
error: errorObj,
|
|
1858
|
-
context: {
|
|
1859
|
-
...context,
|
|
1860
|
-
...themeError.context
|
|
1861
|
-
},
|
|
1862
|
-
code: themeError.code
|
|
1863
|
-
}), this.config.onError?.(themeError, context);
|
|
1864
|
-
}
|
|
1865
|
-
/**
|
|
1866
|
-
* Log a warning
|
|
1867
|
-
*/ warn(message, context) {
|
|
1868
|
-
this.config.level < LogLevel.WARN || (this.config.enableConsole && console.warn(`[ThemeWarning] ${message}`, context || {}),
|
|
1869
|
-
this.config.onWarn?.(message, context));
|
|
1870
|
-
}
|
|
1871
|
-
/**
|
|
1872
|
-
* Log an info message
|
|
1873
|
-
*/ info(message, context) {
|
|
1874
|
-
this.config.level < LogLevel.INFO || (this.config.enableConsole && console.info(`[ThemeInfo] ${message}`, context || {}),
|
|
1875
|
-
this.config.onInfo?.(message, context));
|
|
1876
|
-
}
|
|
1877
|
-
/**
|
|
1878
|
-
* Log a debug message
|
|
1879
|
-
*/ debug(message, context) {
|
|
1880
|
-
this.config.level < LogLevel.DEBUG || (this.config.enableConsole, this.config.onDebug?.(message, context));
|
|
1196
|
+
// `String.prototype.includes` method
|
|
1197
|
+
// https://tc39.es/ecma262/#sec-string.prototype.includes
|
|
1198
|
+
$$1({
|
|
1199
|
+
target: "String",
|
|
1200
|
+
proto: !0,
|
|
1201
|
+
forced: !function(METHOD_NAME) {
|
|
1202
|
+
var regexp = /./;
|
|
1203
|
+
try {
|
|
1204
|
+
"/./"[METHOD_NAME](regexp);
|
|
1205
|
+
} catch (error1) {
|
|
1206
|
+
try {
|
|
1207
|
+
return regexp[MATCH] = !1, "/./"[METHOD_NAME](regexp);
|
|
1208
|
+
} catch (error2) {/* empty */}
|
|
1209
|
+
}
|
|
1210
|
+
return !1;
|
|
1211
|
+
}("includes")
|
|
1212
|
+
}, {
|
|
1213
|
+
includes: function(searchString /* , position = 0 */) {
|
|
1214
|
+
return !!~stringIndexOf(toString(requireObjectCoercible(this)), toString(notARegExp(searchString)), arguments.length > 1 ? arguments[1] : void 0);
|
|
1881
1215
|
}
|
|
1882
|
-
}
|
|
1216
|
+
});
|
|
1883
1217
|
|
|
1884
|
-
|
|
1885
|
-
* Default logger instance
|
|
1886
|
-
*/ let defaultLogger = null;
|
|
1218
|
+
var includes$3 = getBuiltInPrototypeMethod$3("String", "includes"), isPrototypeOf$1 = objectIsPrototypeOf, arrayMethod = includes$4, stringMethod = includes$3, ArrayPrototype$1 = Array.prototype, StringPrototype = String.prototype;
|
|
1887
1219
|
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
}
|
|
1220
|
+
const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
1221
|
+
var own = it.includes;
|
|
1222
|
+
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;
|
|
1223
|
+
}));
|
|
1893
1224
|
|
|
1894
1225
|
/**
|
|
1895
1226
|
* Theme System Constants
|
|
@@ -1898,712 +1229,202 @@ class ThemeLogger {
|
|
|
1898
1229
|
*/
|
|
1899
1230
|
/**
|
|
1900
1231
|
* Default storage key for theme persistence
|
|
1901
|
-
*/
|
|
1902
|
-
|
|
1903
|
-
/**
|
|
1904
|
-
* Default data attribute name for theme
|
|
1905
|
-
*/ process.env.NODE_ENV;
|
|
1232
|
+
*/ "undefined" != typeof process && process.env;
|
|
1906
1233
|
|
|
1907
1234
|
/**
|
|
1908
|
-
*
|
|
1235
|
+
* Check if code is running in a browser environment
|
|
1909
1236
|
*/
|
|
1910
|
-
const
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
}
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1237
|
+
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
|
|
1238
|
+
, buildThemePath = (themeName, basePath = "/themes", useMinified = !1, cdnPath = null) => {
|
|
1239
|
+
// Validate theme name to prevent path injection
|
|
1240
|
+
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, {
|
|
1241
|
+
themeName: themeName,
|
|
1242
|
+
pattern: /^[a-z0-9]+(-[a-z0-9]+)*$/
|
|
1243
|
+
});
|
|
1244
|
+
const fileName = `${themeName}${useMinified ? ".min.css" : ".css"}`;
|
|
1245
|
+
return cdnPath ? `${sanitizePath(cdnPath)}/${fileName}` : `${sanitizePath(basePath)}/${fileName.replace(/^\//, "")}`;
|
|
1246
|
+
// Sanitize basePath to prevent path injection
|
|
1247
|
+
}, applyThemeAttributes = (dataAttribute, themeName) => {
|
|
1248
|
+
isServer() || (
|
|
1249
|
+
// Set data attribute on body (with null check)
|
|
1250
|
+
document.body && document.body.setAttribute(dataAttribute, themeName),
|
|
1251
|
+
// Also set on documentElement for broader compatibility
|
|
1252
|
+
document.documentElement.setAttribute(dataAttribute, themeName));
|
|
1253
|
+
}, isValidThemeName = themeName => !(!themeName || "string" != typeof themeName) && /^[a-z0-9]+(-[a-z0-9]+)*$/.test(themeName), createLocalStorageAdapter = () => ({
|
|
1254
|
+
getItem: key => {
|
|
1255
|
+
if (isServer()) return null;
|
|
1256
|
+
try {
|
|
1257
|
+
return localStorage.getItem(key);
|
|
1258
|
+
} catch {
|
|
1259
|
+
return null;
|
|
1260
|
+
}
|
|
1261
|
+
},
|
|
1262
|
+
setItem: (key, value) => {
|
|
1263
|
+
if (!isServer()) try {
|
|
1264
|
+
localStorage.setItem(key, value);
|
|
1265
|
+
} catch {
|
|
1266
|
+
// Silently fail if localStorage is not available
|
|
1267
|
+
}
|
|
1268
|
+
},
|
|
1269
|
+
removeItem: key => {
|
|
1270
|
+
if (!isServer()) try {
|
|
1271
|
+
localStorage.removeItem(key);
|
|
1272
|
+
} catch {
|
|
1273
|
+
// Silently fail
|
|
1274
|
+
}
|
|
1275
|
+
},
|
|
1276
|
+
isAvailable: () => {
|
|
1277
|
+
if (isServer()) return !1;
|
|
1278
|
+
try {
|
|
1279
|
+
const test = "__atomix_storage_test__";
|
|
1280
|
+
return localStorage.setItem(test, test), localStorage.removeItem(test), !0;
|
|
1281
|
+
} catch {
|
|
1282
|
+
return !1;
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
}), domUtils = Object.freeze( Object.defineProperty({
|
|
1286
|
+
__proto__: null,
|
|
1287
|
+
applyThemeAttributes: applyThemeAttributes,
|
|
1288
|
+
buildThemePath: buildThemePath,
|
|
1289
|
+
createLocalStorageAdapter: createLocalStorageAdapter,
|
|
1290
|
+
isBrowser: isBrowser,
|
|
1291
|
+
isServer: isServer,
|
|
1292
|
+
isValidThemeName: isValidThemeName,
|
|
1293
|
+
loadThemeCSS: (fullPath, linkId) => isServer() ? Promise.resolve() : new Promise(((resolve, reject) => {
|
|
1294
|
+
if (document.getElementById(linkId)) return void resolve();
|
|
1295
|
+
// Create link element
|
|
1296
|
+
const link = document.createElement("link");
|
|
1297
|
+
link.id = linkId, link.rel = "stylesheet", link.type = "text/css", link.href = fullPath,
|
|
1298
|
+
// Add data attribute for tracking
|
|
1299
|
+
link.setAttribute("data-atomix-theme", "true"),
|
|
1300
|
+
// Handle load success
|
|
1301
|
+
link.onload = () => {
|
|
1302
|
+
resolve();
|
|
1303
|
+
},
|
|
1304
|
+
// Handle load error
|
|
1305
|
+
link.onerror = () => {
|
|
1306
|
+
// Remove failed link element
|
|
1307
|
+
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, {
|
|
1308
|
+
fullPath: fullPath,
|
|
1309
|
+
linkId: linkId
|
|
1310
|
+
}));
|
|
1311
|
+
},
|
|
1312
|
+
// Append to head
|
|
1313
|
+
document.head.appendChild(link);
|
|
1314
|
+
}))
|
|
1315
|
+
}, Symbol.toStringTag, {
|
|
1316
|
+
value: "Module"
|
|
1317
|
+
}));
|
|
1920
1318
|
|
|
1921
1319
|
/**
|
|
1922
|
-
*
|
|
1320
|
+
* Check if code is running on the server (SSR)
|
|
1923
1321
|
*/
|
|
1924
1322
|
/**
|
|
1925
|
-
* Theme
|
|
1323
|
+
* Theme Utilities
|
|
1926
1324
|
*
|
|
1927
|
-
*
|
|
1325
|
+
* Helper utilities for working with themes, including color manipulation,
|
|
1326
|
+
* spacing helpers, and theme value accessors.
|
|
1928
1327
|
*/
|
|
1328
|
+
// ============================================================================
|
|
1329
|
+
// Color Manipulation Utilities
|
|
1330
|
+
// ============================================================================
|
|
1929
1331
|
/**
|
|
1930
|
-
*
|
|
1332
|
+
* Convert hex color to RGB object
|
|
1931
1333
|
*/
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1334
|
+
function hexToRgb(hex) {
|
|
1335
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
1336
|
+
return result ? {
|
|
1337
|
+
r: parseInt(result[1], 16),
|
|
1338
|
+
g: parseInt(result[2], 16),
|
|
1339
|
+
b: parseInt(result[3], 16)
|
|
1340
|
+
} : null;
|
|
1341
|
+
}
|
|
1937
1342
|
|
|
1938
1343
|
/**
|
|
1939
|
-
*
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
*
|
|
1944
|
-
* @example
|
|
1945
|
-
* ```typescript
|
|
1946
|
-
* import { loadThemeConfig } from '@shohojdhara/atomix/theme/config';
|
|
1947
|
-
* const config = loadThemeConfig();
|
|
1948
|
-
* ```
|
|
1949
|
-
*/
|
|
1950
|
-
/**
|
|
1951
|
-
* Theme Registry
|
|
1952
|
-
*
|
|
1953
|
-
* Manages theme registration, discovery, and dependency resolution
|
|
1954
|
-
*/
|
|
1955
|
-
class ThemeRegistry {
|
|
1956
|
-
constructor() {
|
|
1957
|
-
this.entries = new Map, this.config = null, this.initialized = !1;
|
|
1958
|
-
}
|
|
1959
|
-
/**
|
|
1960
|
-
* Initialize registry from config
|
|
1961
|
-
*/ async initialize(config) {
|
|
1962
|
-
if (!this.initialized) {
|
|
1963
|
-
// Load config if not provided
|
|
1964
|
-
if (config) this.config = config; else try {
|
|
1965
|
-
this.config = function(options = {}) {
|
|
1966
|
-
const {configPath: configPath = DEFAULT_ATOMIX_CONFIG_PATH, validate: validate = !0, env: env = ("undefined" != typeof process && process.env && "production" === process.env.NODE_ENV ? "production" : "development")} = options;
|
|
1967
|
-
// Return cached config if available
|
|
1968
|
-
if (cachedConfig) return cachedConfig;
|
|
1969
|
-
// Try to load config dynamically
|
|
1970
|
-
let config;
|
|
1971
|
-
try {
|
|
1972
|
-
// In browser/Vite environment, we can't load config dynamically
|
|
1973
|
-
if ("undefined" != typeof window) throw new Error("Theme config loading not supported in browser environment");
|
|
1974
|
-
// In ESM environments, require might be undefined.
|
|
1975
|
-
let nodeRequire, configModule;
|
|
1976
|
-
try {
|
|
1977
|
-
nodeRequire = require;
|
|
1978
|
-
} catch {
|
|
1979
|
-
// require is not defined
|
|
1980
|
-
}
|
|
1981
|
-
if (!nodeRequire) throw new Error("Theme config loading not supported in this environment (require is undefined)");
|
|
1982
|
-
// Try require (Node.js/CommonJS)
|
|
1983
|
-
try {
|
|
1984
|
-
// Try relative path first
|
|
1985
|
-
try {
|
|
1986
|
-
configModule = nodeRequire("../../../../atomix.config");
|
|
1987
|
-
} catch {
|
|
1988
|
-
// If relative path fails, try to resolve from process.cwd()
|
|
1989
|
-
const path = nodeRequire("path"), fs = nodeRequire("fs");
|
|
1990
|
-
let configFilePath = path.resolve(process.cwd(), configPath);
|
|
1991
|
-
// If atomix.config.ts not found at the root, use the default path
|
|
1992
|
-
if (fs.existsSync(configFilePath) || configPath !== DEFAULT_ATOMIX_CONFIG_PATH || (configFilePath = path.resolve(process.cwd(), DEFAULT_ATOMIX_CONFIG_PATH)),
|
|
1993
|
-
!fs.existsSync(configFilePath)) throw new Error(`Config file not found: ${configFilePath}`);
|
|
1994
|
-
{
|
|
1995
|
-
const resolvedPath = nodeRequire.resolve(configFilePath);
|
|
1996
|
-
nodeRequire.cache && nodeRequire.cache[resolvedPath] && delete nodeRequire.cache[resolvedPath],
|
|
1997
|
-
configModule = nodeRequire(configFilePath);
|
|
1998
|
-
}
|
|
1999
|
-
}
|
|
2000
|
-
} catch (requireError) {
|
|
2001
|
-
const errorMessage = requireError instanceof Error ? requireError.message : String(requireError);
|
|
2002
|
-
throw new ThemeError(`Cannot load config: ${errorMessage}`, ThemeErrorCode.CONFIG_LOAD_FAILED, {
|
|
2003
|
-
configPath: configPath,
|
|
2004
|
-
error: errorMessage
|
|
2005
|
-
});
|
|
2006
|
-
}
|
|
2007
|
-
const rawConfig = configModule.default || configModule, finalConfig =
|
|
2008
|
-
/**
|
|
2009
|
-
* Apply environment-specific overrides to configuration
|
|
2010
|
-
*
|
|
2011
|
-
* @param config - Base configuration
|
|
2012
|
-
* @param env - Environment name
|
|
2013
|
-
* @returns Configuration with environment overrides applied
|
|
2014
|
-
*/
|
|
2015
|
-
function(config, env) {
|
|
2016
|
-
const overridden = {
|
|
2017
|
-
...config
|
|
2018
|
-
};
|
|
2019
|
-
// Production overrides
|
|
2020
|
-
return "production" === env && overridden.runtime && (overridden.runtime = {
|
|
2021
|
-
...overridden.runtime,
|
|
2022
|
-
useMinified: !0,
|
|
2023
|
-
lazy: !0
|
|
2024
|
-
}),
|
|
2025
|
-
// Development overrides
|
|
2026
|
-
"development" === env && (overridden.runtime && (overridden.runtime = {
|
|
2027
|
-
...overridden.runtime,
|
|
2028
|
-
useMinified: !1,
|
|
2029
|
-
lazy: !1
|
|
2030
|
-
}), overridden.build && (overridden.build = {
|
|
2031
|
-
...overridden.build,
|
|
2032
|
-
sass: {
|
|
2033
|
-
...overridden.build.sass,
|
|
2034
|
-
sourceMap: !0
|
|
2035
|
-
}
|
|
2036
|
-
})),
|
|
2037
|
-
// Test overrides
|
|
2038
|
-
"test" === env && overridden.runtime && (overridden.runtime = {
|
|
2039
|
-
...overridden.runtime,
|
|
2040
|
-
enablePersistence: !1,
|
|
2041
|
-
preload: []
|
|
2042
|
-
}), overridden;
|
|
2043
|
-
}({
|
|
2044
|
-
themes: rawConfig.theme?.themes || {},
|
|
2045
|
-
build: rawConfig.build || {},
|
|
2046
|
-
runtime: rawConfig.runtime || {},
|
|
2047
|
-
integration: rawConfig.integration || {},
|
|
2048
|
-
dependencies: rawConfig.dependencies || {},
|
|
2049
|
-
validated: !1,
|
|
2050
|
-
// Will be set after validation
|
|
2051
|
-
// Store tokens for generator
|
|
2052
|
-
__tokens: rawConfig.theme?.tokens,
|
|
2053
|
-
__extend: rawConfig.theme?.extend
|
|
2054
|
-
}, env);
|
|
2055
|
-
// Process the AtomixConfig structure
|
|
2056
|
-
// Validate if requested
|
|
2057
|
-
let validationResult = null;
|
|
2058
|
-
validate && (validationResult = function(config) {
|
|
2059
|
-
const errors = [], warnings = [];
|
|
2060
|
-
// Validate top-level structure
|
|
2061
|
-
if (!config || "object" != typeof config) return errors.push("Configuration must be an object"),
|
|
2062
|
-
{
|
|
2063
|
-
valid: !1,
|
|
2064
|
-
errors: errors,
|
|
2065
|
-
warnings: warnings
|
|
2066
|
-
};
|
|
2067
|
-
// Validate themes
|
|
2068
|
-
if (config.themes && "object" == typeof config.themes) {
|
|
2069
|
-
const themeErrors =
|
|
2070
|
-
/**
|
|
2071
|
-
* Validate themes object
|
|
2072
|
-
*/
|
|
2073
|
-
function(themes) {
|
|
2074
|
-
const errors = [], warnings = [];
|
|
2075
|
-
0 === Object.keys(themes).length && warnings.push("No themes defined in configuration");
|
|
2076
|
-
for (const [themeId, theme] of Object.entries(themes))
|
|
2077
|
-
// Validate theme ID
|
|
2078
|
-
if (themeId && "string" == typeof themeId)
|
|
2079
|
-
// Validate theme object
|
|
2080
|
-
if (theme && "object" == typeof theme)
|
|
2081
|
-
// Validate theme type
|
|
2082
|
-
if (!theme.type || "css" !== theme.type && "js" !== theme.type) errors.push(`Theme "${themeId}" must have type "css" or "js"`); else {
|
|
2083
|
-
// Validate CSS theme
|
|
2084
|
-
if (
|
|
2085
|
-
// Validate required fields
|
|
2086
|
-
theme.name && "string" == typeof theme.name || errors.push(`Theme "${themeId}" must have a "name" string`),
|
|
2087
|
-
"css" === theme.type) {
|
|
2088
|
-
const cssErrors = validateCSSTheme();
|
|
2089
|
-
errors.push(...cssErrors.errors), warnings.push(...cssErrors.warnings);
|
|
2090
|
-
}
|
|
2091
|
-
// Validate JS theme
|
|
2092
|
-
if ("js" === theme.type) {
|
|
2093
|
-
const jsErrors = validateJSTheme(themeId, theme);
|
|
2094
|
-
errors.push(...jsErrors.errors), warnings.push(...jsErrors.warnings);
|
|
2095
|
-
}
|
|
2096
|
-
// Validate accessibility (only critical checks)
|
|
2097
|
-
theme.a11y?.contrastTarget && ("number" != typeof theme.a11y.contrastTarget || theme.a11y.contrastTarget < 1 || theme.a11y.contrastTarget > 21) && warnings.push(`Theme "${themeId}" has invalid contrast target: ${theme.a11y.contrastTarget}`);
|
|
2098
|
-
} else errors.push(`Theme "${themeId}" must be an object`); else errors.push(`Invalid theme ID: ${themeId}`);
|
|
2099
|
-
return {
|
|
2100
|
-
valid: 0 === errors.length,
|
|
2101
|
-
errors: errors,
|
|
2102
|
-
warnings: warnings
|
|
2103
|
-
};
|
|
2104
|
-
}(config.themes);
|
|
2105
|
-
errors.push(...themeErrors.errors), warnings.push(...themeErrors.warnings);
|
|
2106
|
-
}
|
|
2107
|
-
// Validate build config (only if provided)
|
|
2108
|
-
else errors.push('Configuration must have a "themes" object');
|
|
2109
|
-
if (config.build) {
|
|
2110
|
-
const buildErrors = function(build) {
|
|
2111
|
-
const errors = [];
|
|
2112
|
-
// Only validate structure if provided
|
|
2113
|
-
return build.output && "object" != typeof build.output && errors.push("Build output must be an object"),
|
|
2114
|
-
build.sass && "object" != typeof build.sass && errors.push("Build sass config must be an object"),
|
|
2115
|
-
{
|
|
2116
|
-
valid: 0 === errors.length,
|
|
2117
|
-
errors: errors,
|
|
2118
|
-
warnings: []
|
|
2119
|
-
};
|
|
2120
|
-
}
|
|
2121
|
-
/**
|
|
2122
|
-
* Validate runtime configuration
|
|
2123
|
-
*/ (config.build);
|
|
2124
|
-
errors.push(...buildErrors.errors), warnings.push(...buildErrors.warnings);
|
|
2125
|
-
}
|
|
2126
|
-
// Validate runtime config (only if provided)
|
|
2127
|
-
if (config.runtime) {
|
|
2128
|
-
const runtimeErrors = function(runtime) {
|
|
2129
|
-
const errors = [];
|
|
2130
|
-
return runtime.basePath && "string" != typeof runtime.basePath && errors.push("Runtime basePath must be a string"),
|
|
2131
|
-
runtime.defaultTheme && "string" != typeof runtime.defaultTheme && errors.push("Runtime defaultTheme must be a string"),
|
|
2132
|
-
runtime.preload && !Array.isArray(runtime.preload) && errors.push("Runtime preload must be an array"),
|
|
2133
|
-
runtime.storageKey && "string" != typeof runtime.storageKey && errors.push("Runtime storageKey must be a string"),
|
|
2134
|
-
{
|
|
2135
|
-
valid: 0 === errors.length,
|
|
2136
|
-
errors: errors,
|
|
2137
|
-
warnings: []
|
|
2138
|
-
};
|
|
2139
|
-
}
|
|
2140
|
-
/**
|
|
2141
|
-
* Validate integration configuration
|
|
2142
|
-
*/ (config.runtime);
|
|
2143
|
-
errors.push(...runtimeErrors.errors), warnings.push(...runtimeErrors.warnings);
|
|
2144
|
-
}
|
|
2145
|
-
// Validate integration config (only if provided)
|
|
2146
|
-
if (config.integration) {
|
|
2147
|
-
const integrationErrors = function(integration) {
|
|
2148
|
-
const errors = [];
|
|
2149
|
-
// Only validate structure if provided
|
|
2150
|
-
return integration.classNames && "object" != typeof integration.classNames && errors.push("Integration classNames must be an object"),
|
|
2151
|
-
{
|
|
2152
|
-
valid: 0 === errors.length,
|
|
2153
|
-
errors: errors,
|
|
2154
|
-
warnings: []
|
|
2155
|
-
};
|
|
2156
|
-
}
|
|
2157
|
-
/**
|
|
2158
|
-
* Validate dependencies
|
|
2159
|
-
*/ (config.integration);
|
|
2160
|
-
errors.push(...integrationErrors.errors), warnings.push(...integrationErrors.warnings);
|
|
2161
|
-
}
|
|
2162
|
-
// Validate dependencies
|
|
2163
|
-
if (config.dependencies) {
|
|
2164
|
-
const depErrors = function(dependencies, themes) {
|
|
2165
|
-
const errors = [], warnings = [];
|
|
2166
|
-
for (const [themeId, deps] of Object.entries(dependencies))
|
|
2167
|
-
// Check if theme exists
|
|
2168
|
-
if (themes[themeId])
|
|
2169
|
-
// Validate dependencies array
|
|
2170
|
-
if (Array.isArray(deps))
|
|
2171
|
-
// Check if all dependencies exist
|
|
2172
|
-
for (const dep of deps) themes[dep] || errors.push(`Theme "${themeId}" depends on non-existent theme: ${dep}`); else errors.push(`Dependencies for "${themeId}" must be an array`); else warnings.push(`Dependencies defined for non-existent theme: ${themeId}`);
|
|
2173
|
-
return {
|
|
2174
|
-
valid: 0 === errors.length,
|
|
2175
|
-
errors: errors,
|
|
2176
|
-
warnings: warnings
|
|
2177
|
-
};
|
|
2178
|
-
}(config.dependencies, config.themes || {});
|
|
2179
|
-
errors.push(...depErrors.errors), warnings.push(...depErrors.warnings);
|
|
2180
|
-
}
|
|
2181
|
-
return {
|
|
2182
|
-
valid: 0 === errors.length,
|
|
2183
|
-
errors: errors,
|
|
2184
|
-
warnings: warnings
|
|
2185
|
-
};
|
|
2186
|
-
}(finalConfig)), config = {
|
|
2187
|
-
...finalConfig,
|
|
2188
|
-
validated: validate,
|
|
2189
|
-
errors: validationResult?.errors,
|
|
2190
|
-
warnings: validationResult?.warnings
|
|
2191
|
-
};
|
|
2192
|
-
} catch (error) {
|
|
2193
|
-
// Fallback: return default config structure
|
|
2194
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2195
|
-
logger.warn(`Failed to load theme config from ${configPath}`, {
|
|
2196
|
-
configPath: configPath,
|
|
2197
|
-
error: errorMessage
|
|
2198
|
-
}), config = {
|
|
2199
|
-
themes: {},
|
|
2200
|
-
build: {
|
|
2201
|
-
output: {
|
|
2202
|
-
directory: "themes",
|
|
2203
|
-
formats: {
|
|
2204
|
-
expanded: ".css",
|
|
2205
|
-
compressed: ".min.css"
|
|
2206
|
-
}
|
|
2207
|
-
},
|
|
2208
|
-
sass: {
|
|
2209
|
-
...DEFAULT_SASS_CONFIG,
|
|
2210
|
-
loadPaths: [ ...DEFAULT_SASS_CONFIG.loadPaths ]
|
|
2211
|
-
}
|
|
2212
|
-
},
|
|
2213
|
-
runtime: {
|
|
2214
|
-
basePath: "/themes",
|
|
2215
|
-
cdnPath: null,
|
|
2216
|
-
preload: [],
|
|
2217
|
-
lazy: !0,
|
|
2218
|
-
defaultTheme: "",
|
|
2219
|
-
// No default - use built-in styles (empty string instead of undefined)
|
|
2220
|
-
storageKey: "atomix-theme",
|
|
2221
|
-
dataAttribute: "data-theme",
|
|
2222
|
-
enablePersistence: !0,
|
|
2223
|
-
useMinified: "production" === env
|
|
2224
|
-
},
|
|
2225
|
-
integration: {
|
|
2226
|
-
cssVariables: DEFAULT_INTEGRATION_CSS_VARIABLES,
|
|
2227
|
-
classNames: DEFAULT_INTEGRATION_CLASS_NAMES
|
|
2228
|
-
},
|
|
2229
|
-
dependencies: {},
|
|
2230
|
-
validated: !1,
|
|
2231
|
-
errors: [ `Failed to load config: ${error instanceof Error ? error.message : String(error)}` ],
|
|
2232
|
-
warnings: [],
|
|
2233
|
-
__tokens: {},
|
|
2234
|
-
__extend: {}
|
|
2235
|
-
};
|
|
2236
|
-
}
|
|
2237
|
-
// Cache the loaded config
|
|
2238
|
-
return cachedConfig = config, config;
|
|
2239
|
-
}();
|
|
2240
|
-
} catch (error) {
|
|
2241
|
-
// In browser environments, config loading will fail
|
|
2242
|
-
// Use empty config as fallback
|
|
2243
|
-
this.config = {
|
|
2244
|
-
themes: {},
|
|
2245
|
-
build: {
|
|
2246
|
-
output: {
|
|
2247
|
-
directory: "themes",
|
|
2248
|
-
formats: {
|
|
2249
|
-
expanded: ".css",
|
|
2250
|
-
compressed: ".min.css"
|
|
2251
|
-
}
|
|
2252
|
-
},
|
|
2253
|
-
sass: {
|
|
2254
|
-
style: "expanded",
|
|
2255
|
-
sourceMap: !0,
|
|
2256
|
-
loadPaths: [ "src" ]
|
|
2257
|
-
}
|
|
2258
|
-
},
|
|
2259
|
-
runtime: {
|
|
2260
|
-
basePath: "",
|
|
2261
|
-
defaultTheme: void 0
|
|
2262
|
-
},
|
|
2263
|
-
integration: {
|
|
2264
|
-
cssVariables: {
|
|
2265
|
-
colorMode: "--color-mode"
|
|
2266
|
-
},
|
|
2267
|
-
classNames: {
|
|
2268
|
-
theme: "data-theme",
|
|
2269
|
-
colorMode: "data-color-mode"
|
|
2270
|
-
}
|
|
2271
|
-
},
|
|
2272
|
-
dependencies: {},
|
|
2273
|
-
validated: !1,
|
|
2274
|
-
errors: [],
|
|
2275
|
-
warnings: [],
|
|
2276
|
-
__tokens: {},
|
|
2277
|
-
__extend: {}
|
|
2278
|
-
};
|
|
2279
|
-
}
|
|
2280
|
-
// Register all themes from config
|
|
2281
|
-
for (const [themeId, definition] of Object.entries(this.config.themes)) this.register(themeId, definition);
|
|
2282
|
-
// Resolve dependencies
|
|
2283
|
-
this.resolveDependencies(), this.initialized = !0;
|
|
2284
|
-
}
|
|
2285
|
-
}
|
|
2286
|
-
/**
|
|
2287
|
-
* Register a theme
|
|
2288
|
-
*/ register(themeId, definition) {
|
|
2289
|
-
// Get dependencies from config or definition
|
|
2290
|
-
const entry = {
|
|
2291
|
-
id: themeId,
|
|
2292
|
-
definition: definition,
|
|
2293
|
-
loaded: !1,
|
|
2294
|
-
dependencies: [ ...this.config?.dependencies?.[themeId] || definition.dependencies || [] ],
|
|
2295
|
-
dependents: []
|
|
2296
|
-
};
|
|
2297
|
-
this.entries.set(themeId, entry);
|
|
2298
|
-
}
|
|
2299
|
-
/**
|
|
2300
|
-
* Get theme entry
|
|
2301
|
-
*/ get(themeId) {
|
|
2302
|
-
return this.entries.get(themeId);
|
|
2303
|
-
}
|
|
2304
|
-
/**
|
|
2305
|
-
* Check if theme exists
|
|
2306
|
-
*/ has(themeId) {
|
|
2307
|
-
return this.entries.has(themeId);
|
|
2308
|
-
}
|
|
2309
|
-
/**
|
|
2310
|
-
* Get all theme IDs
|
|
2311
|
-
*/ getAllIds() {
|
|
2312
|
-
return Array.from(this.entries.keys());
|
|
2313
|
-
}
|
|
2314
|
-
/**
|
|
2315
|
-
* Get all theme metadata
|
|
2316
|
-
*/ getAllMetadata() {
|
|
2317
|
-
return Array.from(this.entries.values()).map((entry => ({
|
|
2318
|
-
id: entry.id,
|
|
2319
|
-
name: entry.definition.name,
|
|
2320
|
-
type: entry.definition.type,
|
|
2321
|
-
class: entry.definition.class,
|
|
2322
|
-
description: entry.definition.description,
|
|
2323
|
-
author: entry.definition.author,
|
|
2324
|
-
version: entry.definition.version,
|
|
2325
|
-
tags: entry.definition.tags,
|
|
2326
|
-
supportsDarkMode: entry.definition.supportsDarkMode,
|
|
2327
|
-
status: entry.definition.status,
|
|
2328
|
-
a11y: entry.definition.a11y,
|
|
2329
|
-
color: entry.definition.color,
|
|
2330
|
-
features: entry.definition.features,
|
|
2331
|
-
dependencies: entry.dependencies
|
|
2332
|
-
})));
|
|
2333
|
-
}
|
|
2334
|
-
/**
|
|
2335
|
-
* Get theme definition
|
|
2336
|
-
*/ getDefinition(themeId) {
|
|
2337
|
-
return this.entries.get(themeId)?.definition;
|
|
2338
|
-
}
|
|
2339
|
-
/**
|
|
2340
|
-
* Check if a theme is loaded
|
|
2341
|
-
*/ isThemeLoaded(themeId) {
|
|
2342
|
-
const entry = this.entries.get(themeId);
|
|
2343
|
-
return !!entry && entry.loaded;
|
|
2344
|
-
}
|
|
2345
|
-
/**
|
|
2346
|
-
* Mark a theme as loaded
|
|
2347
|
-
*/ markLoaded(themeId, theme) {
|
|
2348
|
-
const entry = this.entries.get(themeId);
|
|
2349
|
-
entry && (entry.loaded = !0, theme && (entry.theme = theme));
|
|
2350
|
-
}
|
|
2351
|
-
/**
|
|
2352
|
-
* Get theme object (for JS themes)
|
|
2353
|
-
*/ getTheme(themeId) {
|
|
2354
|
-
const entry = this.entries.get(themeId);
|
|
2355
|
-
return entry?.loaded ? entry.theme : void 0;
|
|
2356
|
-
}
|
|
2357
|
-
/**
|
|
2358
|
-
* Get dependencies for a theme
|
|
2359
|
-
*/ getDependencies(themeId) {
|
|
2360
|
-
return this.entries.get(themeId)?.dependencies || [];
|
|
2361
|
-
}
|
|
2362
|
-
/**
|
|
2363
|
-
* Get dependents for a theme (themes that depend on this one)
|
|
2364
|
-
*/ getDependents(themeId) {
|
|
2365
|
-
return this.entries.get(themeId)?.dependents || [];
|
|
2366
|
-
}
|
|
2367
|
-
/**
|
|
2368
|
-
* Resolve all dependencies in correct order
|
|
2369
|
-
*/ resolveDependencyOrder(themeId) {
|
|
2370
|
-
const resolved = [], visited = new Set, visiting = new Set, visit = id => {
|
|
2371
|
-
if (visiting.has(id)) throw new Error(`Circular dependency detected involving theme: ${id}`);
|
|
2372
|
-
if (visited.has(id)) return;
|
|
2373
|
-
visiting.add(id);
|
|
2374
|
-
const entry = this.entries.get(id);
|
|
2375
|
-
if (entry) for (const dep of entry.dependencies) {
|
|
2376
|
-
if (!this.has(dep)) throw new Error(`Theme "${id}" depends on non-existent theme: ${dep}`);
|
|
2377
|
-
visit(dep);
|
|
2378
|
-
}
|
|
2379
|
-
visiting.delete(id), visited.add(id), resolved.push(id);
|
|
2380
|
-
};
|
|
2381
|
-
return visit(themeId), resolved;
|
|
2382
|
-
}
|
|
2383
|
-
/**
|
|
2384
|
-
* Resolve dependencies and build dependency graph
|
|
2385
|
-
*/ resolveDependencies() {
|
|
2386
|
-
// Build dependents map
|
|
2387
|
-
for (const entry of this.entries.values()) for (const dep of entry.dependencies) {
|
|
2388
|
-
const depEntry = this.entries.get(dep);
|
|
2389
|
-
var _context;
|
|
2390
|
-
depEntry && (_includesInstanceProperty(_context = depEntry.dependents).call(_context, entry.id) || depEntry.dependents.push(entry.id));
|
|
2391
|
-
}
|
|
2392
|
-
}
|
|
2393
|
-
/**
|
|
2394
|
-
* Validate all themes
|
|
2395
|
-
*/ validate() {
|
|
2396
|
-
const errors = [];
|
|
2397
|
-
// Check for circular dependencies
|
|
2398
|
-
for (const themeId of this.entries.keys()) try {
|
|
2399
|
-
this.resolveDependencyOrder(themeId);
|
|
2400
|
-
} catch (error) {
|
|
2401
|
-
errors.push(error instanceof Error ? error.message : String(error));
|
|
2402
|
-
}
|
|
2403
|
-
// Check for missing dependencies
|
|
2404
|
-
for (const [themeId, entry] of this.entries.entries()) for (const dep of entry.dependencies) this.has(dep) || errors.push(`Theme "${themeId}" depends on non-existent theme: ${dep}`);
|
|
2405
|
-
return {
|
|
2406
|
-
valid: 0 === errors.length,
|
|
2407
|
-
errors: errors
|
|
2408
|
-
};
|
|
2409
|
-
}
|
|
2410
|
-
/**
|
|
2411
|
-
* Clear registry
|
|
2412
|
-
*/ clear() {
|
|
2413
|
-
this.entries.clear(), this.config = null, this.initialized = !1;
|
|
2414
|
-
}
|
|
1344
|
+
* Convert RGB to hex color
|
|
1345
|
+
*/ function rgbToHex(r, g, b) {
|
|
1346
|
+
const toHex = val => Math.round(Math.max(0, Math.min(255, val))).toString(16).padStart(2, "0");
|
|
1347
|
+
return `#${toHex(r ?? 0)}${toHex(g ?? 0)}${toHex(b ?? 0)}`;
|
|
2415
1348
|
}
|
|
2416
1349
|
|
|
2417
1350
|
/**
|
|
2418
|
-
*
|
|
2419
|
-
*
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
1351
|
+
* Calculate relative luminance of a color
|
|
1352
|
+
* Used for determining contrast ratios
|
|
1353
|
+
*/ function getLuminance(color) {
|
|
1354
|
+
const rgb = hexToRgb(color);
|
|
1355
|
+
if (!rgb) return 0;
|
|
1356
|
+
const {r: r, g: g, b: b} = rgb, [rs, gs, bs] = [ r ?? 0, g ?? 0, b ?? 0 ].map((c => {
|
|
1357
|
+
const val = c / 255;
|
|
1358
|
+
return val <= .03928 ? val / 12.92 : Math.pow((val + .055) / 1.055, 2.4);
|
|
1359
|
+
}));
|
|
1360
|
+
return .2126 * (rs ?? 0) + .7152 * (gs ?? 0) + .0722 * (bs ?? 0);
|
|
2426
1361
|
}
|
|
2427
1362
|
|
|
2428
1363
|
/**
|
|
2429
|
-
*
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
*
|
|
2434
|
-
* @param css - CSS string to inject
|
|
2435
|
-
* @param id - Style element ID (default: 'atomix-theme')
|
|
2436
|
-
*
|
|
2437
|
-
* @example
|
|
2438
|
-
* ```typescript
|
|
2439
|
-
* const css = ':root { --atomix-color-primary: #7AFFD7; }';
|
|
2440
|
-
* injectCSS(css);
|
|
2441
|
-
*
|
|
2442
|
-
* // With custom ID
|
|
2443
|
-
* injectCSS(css, 'my-custom-theme');
|
|
2444
|
-
* ```
|
|
2445
|
-
*/ function injectCSS$1(css, id = "atomix-theme") {
|
|
2446
|
-
if (!isBrowser$1()) return void console.warn("injectCSS: Not in browser environment, CSS not injected");
|
|
2447
|
-
let styleElement = document.getElementById(id);
|
|
2448
|
-
styleElement || (styleElement = document.createElement("style"), styleElement.id = id,
|
|
2449
|
-
styleElement.setAttribute("data-atomix-theme", "true"), document.head.appendChild(styleElement)),
|
|
2450
|
-
styleElement.textContent = css;
|
|
1364
|
+
* Calculate contrast ratio between two colors
|
|
1365
|
+
*/ function getContrastRatio(foreground, background) {
|
|
1366
|
+
const lumA = getLuminance(foreground), lumB = getLuminance(background);
|
|
1367
|
+
return (Math.max(lumA, lumB) + .05) / (Math.min(lumA, lumB) + .05);
|
|
2451
1368
|
}
|
|
2452
1369
|
|
|
2453
1370
|
/**
|
|
2454
|
-
*
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
* @param id - Style element ID to remove (default: 'atomix-theme')
|
|
2459
|
-
*
|
|
2460
|
-
* @example
|
|
2461
|
-
* ```typescript
|
|
2462
|
-
* removeCSS(); // Removes default 'atomix-theme'
|
|
2463
|
-
* removeCSS('my-custom-theme'); // Removes custom ID
|
|
2464
|
-
* ```
|
|
2465
|
-
*/ function removeCSS(id = "atomix-theme") {
|
|
2466
|
-
if (!isBrowser$1()) return;
|
|
2467
|
-
const styleElement = document.getElementById(id);
|
|
2468
|
-
styleElement && styleElement.remove();
|
|
1371
|
+
* Get appropriate contrast text color (black or white) for a background color
|
|
1372
|
+
*/ function getContrastText(background, threshold = 3) {
|
|
1373
|
+
const contrastWithWhite = getContrastRatio("#FFFFFF", background), contrastWithBlack = getContrastRatio("#000000", background);
|
|
1374
|
+
return contrastWithWhite >= threshold ? "#FFFFFF" : contrastWithBlack >= threshold ? "#000000" : contrastWithWhite > contrastWithBlack ? "#FFFFFF" : "#000000";
|
|
2469
1375
|
}
|
|
2470
1376
|
|
|
2471
1377
|
/**
|
|
2472
|
-
*
|
|
1378
|
+
* Lighten a color by a given amount
|
|
2473
1379
|
*
|
|
2474
|
-
* @param
|
|
2475
|
-
* @
|
|
2476
|
-
|
|
2477
|
-
|
|
1380
|
+
* @param color - Hex color string
|
|
1381
|
+
* @param amount - Amount to lighten (0-1), default 0.2
|
|
1382
|
+
* @returns Lightened hex color
|
|
1383
|
+
*/ function lighten(color, amount = .2) {
|
|
1384
|
+
const rgb = hexToRgb(color);
|
|
1385
|
+
if (!rgb) return color;
|
|
1386
|
+
const {r: r, g: g, b: b} = rgb, lightenValue = val => Math.min(255, Math.round(val + (255 - val) * amount));
|
|
1387
|
+
return rgbToHex(lightenValue(r), lightenValue(g), lightenValue(b));
|
|
2478
1388
|
}
|
|
2479
1389
|
|
|
2480
1390
|
/**
|
|
2481
|
-
*
|
|
2482
|
-
*
|
|
2483
|
-
* Save CSS to file system (Node.js only).
|
|
2484
|
-
*/
|
|
2485
|
-
/**
|
|
2486
|
-
* Save CSS to file
|
|
2487
|
-
*
|
|
2488
|
-
* Writes CSS string to a file. Only works in Node.js environment.
|
|
2489
|
-
*
|
|
2490
|
-
* @param css - CSS string to save
|
|
2491
|
-
* @param filePath - Output file path
|
|
2492
|
-
* @throws Error if called in browser environment
|
|
1391
|
+
* Darken a color by a given amount
|
|
2493
1392
|
*
|
|
2494
|
-
* @
|
|
2495
|
-
*
|
|
2496
|
-
*
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
// Dynamic import to avoid bundling Node.js modules in browser builds
|
|
2503
|
-
const fs = await import("fs/promises"), dir = (await import("path")).dirname(filePath);
|
|
2504
|
-
await fs.mkdir(dir, {
|
|
2505
|
-
recursive: !0
|
|
2506
|
-
}),
|
|
2507
|
-
// Write file
|
|
2508
|
-
await fs.writeFile(filePath, css, "utf8");
|
|
1393
|
+
* @param color - Hex color string
|
|
1394
|
+
* @param amount - Amount to darken (0-1), default 0.2
|
|
1395
|
+
* @returns Darkened hex color
|
|
1396
|
+
*/ function darken(color, amount = .2) {
|
|
1397
|
+
const rgb = hexToRgb(color);
|
|
1398
|
+
if (!rgb) return color;
|
|
1399
|
+
const {r: r, g: g, b: b} = rgb, darkenValue = val => Math.max(0, Math.round(val * (1 - amount)));
|
|
1400
|
+
return rgbToHex(darkenValue(r), darkenValue(g), darkenValue(b));
|
|
2509
1401
|
}
|
|
2510
1402
|
|
|
2511
1403
|
/**
|
|
2512
|
-
*
|
|
2513
|
-
*
|
|
2514
|
-
* Synchronous version of saveCSSFile. Only works in Node.js environment.
|
|
1404
|
+
* Add alpha (opacity) to a color
|
|
2515
1405
|
*
|
|
2516
|
-
* @param
|
|
2517
|
-
* @param
|
|
2518
|
-
* @
|
|
2519
|
-
*/ function
|
|
2520
|
-
|
|
2521
|
-
if (
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
const fs = require("fs"), dir = require("path").dirname(filePath);
|
|
2525
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
2526
|
-
fs.existsSync(dir) || fs.mkdirSync(dir, {
|
|
2527
|
-
recursive: !0
|
|
2528
|
-
}),
|
|
2529
|
-
// Write file
|
|
2530
|
-
fs.writeFileSync(filePath, css, "utf8");
|
|
1406
|
+
* @param color - Hex color string
|
|
1407
|
+
* @param opacity - Opacity value (0-1)
|
|
1408
|
+
* @returns RGBA color string
|
|
1409
|
+
*/ function alpha(color, opacity) {
|
|
1410
|
+
const rgb = hexToRgb(color);
|
|
1411
|
+
if (!rgb) return color;
|
|
1412
|
+
const {r: r, g: g, b: b} = rgb;
|
|
1413
|
+
return `rgba(${r}, ${g}, ${b}, ${Math.max(0, Math.min(1, opacity))})`;
|
|
2531
1414
|
}
|
|
2532
1415
|
|
|
2533
1416
|
/**
|
|
2534
|
-
*
|
|
2535
|
-
*/ const isBrowser = () => "undefined" != typeof window && "undefined" != typeof document, isServer = () => !isBrowser(), getThemeLinkId = themeName => `atomix-theme-${themeName}`, buildThemePath = (themeName, basePath = "/themes", useMinified = !1, cdnPath = null) => {
|
|
2536
|
-
// Validate theme name to prevent path injection
|
|
2537
|
-
if (!isValidThemeName(themeName)) throw new Error(`Invalid theme name: "${themeName}". Theme names must be lowercase alphanumeric with hyphens.`);
|
|
2538
|
-
const fileName = `${themeName}${useMinified ? ".min.css" : ".css"}`;
|
|
2539
|
-
return cdnPath ? `${cdnPath.replace(/[<>"']/g, "")}/${fileName}` : `${basePath.replace(/\/$/, "").replace(/[<>"']/g, "")}/${fileName.replace(/^\//, "")}`;
|
|
2540
|
-
// Ensure basePath doesn't end with slash and fileName doesn't start with slash
|
|
2541
|
-
// Also sanitize basePath to prevent path injection
|
|
2542
|
-
}, loadThemeCSS = (fullPath, linkId) => isServer() ? Promise.resolve() : new Promise(((resolve, reject) => {
|
|
2543
|
-
if (document.getElementById(linkId)) return void resolve();
|
|
2544
|
-
// Create link element
|
|
2545
|
-
const link = document.createElement("link");
|
|
2546
|
-
link.id = linkId, link.rel = "stylesheet", link.type = "text/css", link.href = fullPath,
|
|
2547
|
-
// Add data attribute for tracking
|
|
2548
|
-
link.setAttribute("data-atomix-theme", "true"),
|
|
2549
|
-
// Handle load success
|
|
2550
|
-
link.onload = () => {
|
|
2551
|
-
resolve();
|
|
2552
|
-
},
|
|
2553
|
-
// Handle load error
|
|
2554
|
-
link.onerror = () => {
|
|
2555
|
-
// Remove failed link element
|
|
2556
|
-
link.remove(), reject(new Error(`Failed to load theme CSS: ${fullPath}`));
|
|
2557
|
-
},
|
|
2558
|
-
// Append to head
|
|
2559
|
-
document.head.appendChild(link);
|
|
2560
|
-
})), isThemeLoaded = themeName => {
|
|
2561
|
-
if (isServer()) return !1;
|
|
2562
|
-
const linkId = getThemeLinkId(themeName);
|
|
2563
|
-
return null !== document.getElementById(linkId);
|
|
2564
|
-
}, isValidThemeName = themeName => !(!themeName || "string" != typeof themeName) && /^[a-z0-9]+(-[a-z0-9]+)*$/.test(themeName);
|
|
2565
|
-
|
|
2566
|
-
/**
|
|
2567
|
-
* Check if code is running on the server (SSR)
|
|
2568
|
-
*/
|
|
2569
|
-
/**
|
|
2570
|
-
* CSS Variable Generator
|
|
2571
|
-
*
|
|
2572
|
-
* Generates CSS custom properties from theme objects and injects them into the DOM.
|
|
2573
|
-
*
|
|
2574
|
-
* **Token Naming Alignment:**
|
|
2575
|
-
* This generator produces CSS variables that match the SCSS token naming pattern exactly:
|
|
2576
|
-
* - Colors: --atomix-primary, --atomix-primary-1 through --atomix-primary-10
|
|
2577
|
-
* - Spacing: --atomix-spacing-1, --atomix-spacing-4, etc.
|
|
2578
|
-
* - Typography: --atomix-font-size-base, --atomix-font-weight-normal, etc.
|
|
2579
|
-
* - Shadows: --atomix-box-shadow, --atomix-box-shadow-sm, etc.
|
|
2580
|
-
*
|
|
2581
|
-
* All tokens follow the flat structure pattern used in SCSS (not nested like --atomix-palette-primary-main).
|
|
2582
|
-
* This ensures compatibility between SCSS themes and JavaScript themes.
|
|
1417
|
+
* Emphasize a color (lighten if dark, darken if light)
|
|
2583
1418
|
*
|
|
2584
|
-
* @
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
* Convert a nested object to flat CSS variable declarations
|
|
1419
|
+
* @param color - Hex color string
|
|
1420
|
+
* @param coefficient - Amount to emphasize (0-1), default 0.15
|
|
1421
|
+
* @returns Emphasized hex color
|
|
2588
1422
|
*/
|
|
2589
|
-
function flattenObject(obj, prefix = "", result = {}) {
|
|
2590
|
-
for (const key in obj) {
|
|
2591
|
-
if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
|
|
2592
|
-
const value = obj[key], newKey = prefix ? `${prefix}-${key}` : key;
|
|
2593
|
-
if (value && "object" == typeof value && !Array.isArray(value)) {
|
|
2594
|
-
// Skip special objects like functions
|
|
2595
|
-
if ("function" == typeof value) continue;
|
|
2596
|
-
// Recursively flatten nested objects
|
|
2597
|
-
flattenObject(value, newKey, result);
|
|
2598
|
-
} else "string" != typeof value && "number" != typeof value || (result[newKey.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()] = String(value));
|
|
2599
|
-
}
|
|
2600
|
-
return result;
|
|
2601
|
-
}
|
|
2602
|
-
|
|
2603
1423
|
/**
|
|
2604
1424
|
* Generate a color scale from a base color (1-10 steps)
|
|
2605
1425
|
* Creates lighter to darker variations
|
|
2606
|
-
*/
|
|
1426
|
+
*/
|
|
1427
|
+
function generateColorScale(baseColor, prefix, colorName) {
|
|
2607
1428
|
const vars = {};
|
|
2608
1429
|
if (!hexToRgb(baseColor)) return vars;
|
|
2609
1430
|
// Generate 10-step scale
|
|
@@ -2667,7 +1488,16 @@ function generateCSSVariables(theme, options = {}) {
|
|
|
2667
1488
|
// Text emphasis: emphasized version of the color for text (--atomix-primary-text-emphasis)
|
|
2668
1489
|
vars[`${prefix}-${key}-text-emphasis`] = function(color, coefficient = .15) {
|
|
2669
1490
|
return getLuminance(color) > .5 ? darken(color, coefficient) : lighten(color, coefficient);
|
|
2670
|
-
}
|
|
1491
|
+
}
|
|
1492
|
+
// ============================================================================
|
|
1493
|
+
// Spacing Utilities
|
|
1494
|
+
// ============================================================================
|
|
1495
|
+
/**
|
|
1496
|
+
* Create a spacing function from various input types
|
|
1497
|
+
*
|
|
1498
|
+
* @param spacingInput - Spacing configuration (number, array, or function), default 4
|
|
1499
|
+
* @returns Spacing function
|
|
1500
|
+
*/ (color.main, .15),
|
|
2671
1501
|
// Background subtle: very light version for backgrounds (--atomix-primary-bg-subtle)
|
|
2672
1502
|
vars[`${prefix}-${key}-bg-subtle`] = alpha(color.main, .1),
|
|
2673
1503
|
// Border subtle: light version for borders (--atomix-primary-border-subtle)
|
|
@@ -3012,7 +1842,52 @@ function generateCSSVariables(theme, options = {}) {
|
|
|
3012
1842
|
return vars[`${prefix}-focus-ring-width`] = "3px", vars[`${prefix}-focus-ring-offset`] = "2px",
|
|
3013
1843
|
vars[`${prefix}-focus-ring-opacity`] = "0.25", vars;
|
|
3014
1844
|
}(theme.palette, prefix)), theme.custom && Object.keys(theme.custom).length > 0) {
|
|
3015
|
-
const customVars =
|
|
1845
|
+
const customVars =
|
|
1846
|
+
/**
|
|
1847
|
+
* CSS Variable Generator
|
|
1848
|
+
*
|
|
1849
|
+
* Generates CSS custom properties from theme objects and injects them into the DOM.
|
|
1850
|
+
*
|
|
1851
|
+
* **Token Naming Alignment:**
|
|
1852
|
+
* This generator produces CSS variables that match the SCSS token naming pattern exactly:
|
|
1853
|
+
* - Colors: --atomix-primary, --atomix-primary-1 through --atomix-primary-10
|
|
1854
|
+
* - Spacing: --atomix-spacing-1, --atomix-spacing-4, etc.
|
|
1855
|
+
* - Typography: --atomix-font-size-base, --atomix-font-weight-normal, etc.
|
|
1856
|
+
* - Shadows: --atomix-box-shadow, --atomix-box-shadow-sm, etc.
|
|
1857
|
+
*
|
|
1858
|
+
* All tokens follow the flat structure pattern used in SCSS (not nested like --atomix-palette-primary-main).
|
|
1859
|
+
* This ensures compatibility between SCSS themes and JavaScript themes.
|
|
1860
|
+
*
|
|
1861
|
+
* @see src/styles/03-generic/_generic.root.scss for SCSS token definitions
|
|
1862
|
+
*/
|
|
1863
|
+
/**
|
|
1864
|
+
* Convert a nested object to flat CSS variable declarations
|
|
1865
|
+
* Uses iterative approach for better performance with large objects
|
|
1866
|
+
*/
|
|
1867
|
+
function(obj, prefix = "", result = {}) {
|
|
1868
|
+
// Use iterative approach with stack to avoid deep recursion
|
|
1869
|
+
const stack = [ {
|
|
1870
|
+
obj: obj,
|
|
1871
|
+
prefix: prefix
|
|
1872
|
+
} ];
|
|
1873
|
+
for (;stack.length > 0; ) {
|
|
1874
|
+
const {obj: currentObj, prefix: currentPrefix} = stack.pop();
|
|
1875
|
+
for (const key in currentObj) {
|
|
1876
|
+
if (!Object.prototype.hasOwnProperty.call(currentObj, key)) continue;
|
|
1877
|
+
const value = currentObj[key], newKey = currentPrefix ? `${currentPrefix}-${key}` : key;
|
|
1878
|
+
if (value && "object" == typeof value && !Array.isArray(value)) {
|
|
1879
|
+
// Skip special objects like functions
|
|
1880
|
+
if ("function" == typeof value) continue;
|
|
1881
|
+
// Add to stack for iterative processing
|
|
1882
|
+
stack.push({
|
|
1883
|
+
obj: value,
|
|
1884
|
+
prefix: newKey
|
|
1885
|
+
});
|
|
1886
|
+
} else "string" != typeof value && "number" != typeof value || (result[newKey.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()] = String(value));
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
return result;
|
|
1890
|
+
}(theme.custom, `${prefix}-custom`);
|
|
3016
1891
|
Object.assign(variables, customVars);
|
|
3017
1892
|
}
|
|
3018
1893
|
// Convert to CSS string
|
|
@@ -3033,243 +1908,211 @@ function generateCSSVariables(theme, options = {}) {
|
|
|
3033
1908
|
styleElement.textContent = css;
|
|
3034
1909
|
}
|
|
3035
1910
|
/**
|
|
3036
|
-
*
|
|
1911
|
+
* Naming Utilities
|
|
3037
1912
|
*
|
|
3038
|
-
*
|
|
1913
|
+
* Provides consistent naming conventions across the theme system
|
|
3039
1914
|
*/
|
|
3040
1915
|
/**
|
|
3041
|
-
*
|
|
1916
|
+
* Generate consistent CSS class names following BEM methodology
|
|
3042
1917
|
*/ (css, styleId), css;
|
|
3043
1918
|
}
|
|
3044
1919
|
|
|
3045
|
-
|
|
1920
|
+
function generateClassName(block, element, modifiers) {
|
|
1921
|
+
let className = block;
|
|
1922
|
+
return element && (className += `__${element}`), modifiers && Object.entries(modifiers).forEach((([key, value]) => {
|
|
1923
|
+
value && (className += `--${key}`, "string" == typeof value && value !== key && (className += `-${value}`));
|
|
1924
|
+
})), className;
|
|
1925
|
+
}
|
|
3046
1926
|
|
|
3047
|
-
|
|
1927
|
+
/**
|
|
1928
|
+
* Generate consistent CSS variable names
|
|
1929
|
+
*/ function generateCSSVariableName(property, options = {}) {
|
|
1930
|
+
const {prefix: prefix = "atomix", component: component, variant: variant, state: state} = options, parts = [ prefix ];
|
|
1931
|
+
return component && parts.push(component), variant && parts.push(variant), state && parts.push(state),
|
|
1932
|
+
parts.push(property), `--${parts.join("-")}`;
|
|
1933
|
+
}
|
|
3048
1934
|
|
|
3049
1935
|
/**
|
|
3050
|
-
*
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
1936
|
+
* Normalize theme tokens to consistent naming convention
|
|
1937
|
+
*/ function normalizeThemeTokens(tokens) {
|
|
1938
|
+
const normalized = {};
|
|
1939
|
+
for (const [key, value] of Object.entries(tokens))
|
|
1940
|
+
// Recursively normalize nested objects
|
|
1941
|
+
normalized[key] = "object" == typeof value && null !== value ? normalizeThemeTokens(value) : value;
|
|
1942
|
+
return normalized;
|
|
1943
|
+
}
|
|
1944
|
+
|
|
3057
1945
|
/**
|
|
3058
|
-
*
|
|
1946
|
+
* Convert camelCase to kebab-case for CSS custom properties
|
|
1947
|
+
*/ function camelToKebab(str) {
|
|
1948
|
+
return str.replace(/[A-Z]/g, (match => `-${match.toLowerCase()}`));
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
/**
|
|
1952
|
+
* Convert theme property to CSS variable name
|
|
1953
|
+
*/ function themePropertyToCSSVar(propertyPath, prefix = "atomix") {
|
|
1954
|
+
return `--${prefix}-${propertyPath.split(".").map((part => camelToKebab(part))).join("-")}`;
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
/**
|
|
1958
|
+
* Component Theming Utilities
|
|
3059
1959
|
*
|
|
3060
|
-
*
|
|
1960
|
+
* Provides consistent patterns for applying theme values to components
|
|
1961
|
+
* using DesignTokens and CSS variables
|
|
3061
1962
|
*/
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
*/ applyTheme(theme) {
|
|
3072
|
-
// Clear previously applied variables
|
|
3073
|
-
this.clearAppliedVars(),
|
|
3074
|
-
// Check if it's DesignTokens
|
|
3075
|
-
this.isDesignTokens(theme) ?
|
|
3076
|
-
// Direct DesignTokens - use unified theme system (with config support)
|
|
3077
|
-
this.applyDesignTokens(theme) : injectCSS$1(createTheme(theme, {
|
|
3078
|
-
selector: ":root",
|
|
3079
|
-
prefix: "atomix"
|
|
3080
|
-
}), this.styleId),
|
|
3081
|
-
// Apply component overrides (only for Theme objects)
|
|
3082
|
-
!this.isDesignTokens(theme) && theme.components && this.applyComponentOverrides(theme.components);
|
|
3083
|
-
}
|
|
3084
|
-
/**
|
|
3085
|
-
* Apply DesignTokens using unified theme system
|
|
3086
|
-
*
|
|
3087
|
-
* Uses createTheme() which automatically loads from atomix.config.ts
|
|
3088
|
-
* if no tokens are provided, ensuring config is always respected.
|
|
3089
|
-
*/ applyDesignTokens(tokens) {
|
|
3090
|
-
// Inject CSS into DOM
|
|
3091
|
-
injectCSS$1(createTheme(tokens, {
|
|
3092
|
-
selector: ":root",
|
|
3093
|
-
prefix: "atomix"
|
|
3094
|
-
}), this.styleId);
|
|
3095
|
-
}
|
|
3096
|
-
/**
|
|
3097
|
-
* Check if object is DesignTokens
|
|
3098
|
-
*/ isDesignTokens(obj) {
|
|
3099
|
-
// DesignTokens is a flat object with string keys, no nested structures
|
|
3100
|
-
return null !== obj && "object" == typeof obj && !("palette" in obj) && !("typography" in obj) && !("__isJSTheme" in obj);
|
|
3101
|
-
}
|
|
3102
|
-
/**
|
|
3103
|
-
* Apply global CSS variables (for component overrides)
|
|
3104
|
-
*/ applyGlobalCSSVars(vars) {
|
|
3105
|
-
Object.entries(vars).forEach((([key, value]) => {
|
|
3106
|
-
this.root.style.setProperty(key, String(value));
|
|
3107
|
-
}));
|
|
3108
|
-
}
|
|
3109
|
-
/**
|
|
3110
|
-
* Apply component-level overrides
|
|
3111
|
-
*/ applyComponentOverrides(overrides) {
|
|
3112
|
-
Object.entries(overrides).forEach((([componentName, override]) => {
|
|
3113
|
-
override && this.applyComponentOverride(componentName, override);
|
|
3114
|
-
}));
|
|
3115
|
-
}
|
|
3116
|
-
/**
|
|
3117
|
-
* Apply override for a specific component
|
|
3118
|
-
*/ applyComponentOverride(componentName, override) {
|
|
3119
|
-
const vars = {}, componentKey = componentName.toLowerCase();
|
|
3120
|
-
// Apply component-level CSS variables
|
|
3121
|
-
override.cssVars && Object.entries(override.cssVars).forEach((([key, value]) => {
|
|
3122
|
-
// If key doesn't start with --, add component prefix
|
|
3123
|
-
const varKey = key.startsWith("--") ? key : `--atomix-${componentKey}-${key}`;
|
|
3124
|
-
vars[varKey] = value;
|
|
3125
|
-
})),
|
|
3126
|
-
// Apply part-specific CSS variables
|
|
3127
|
-
override.parts && Object.entries(override.parts).forEach((([partName, partOverride]) => {
|
|
3128
|
-
partOverride.cssVars && Object.entries(partOverride.cssVars).forEach((([key, value]) => {
|
|
3129
|
-
const varKey = key.startsWith("--") ? key : `--atomix-${componentKey}-${partName}-${key}`;
|
|
3130
|
-
vars[varKey] = value;
|
|
3131
|
-
}));
|
|
3132
|
-
})),
|
|
3133
|
-
// Apply variant-specific CSS variables
|
|
3134
|
-
override.variants && Object.entries(override.variants).forEach((([variantName, variantOverride]) => {
|
|
3135
|
-
variantOverride.cssVars && Object.entries(variantOverride.cssVars).forEach((([key, value]) => {
|
|
3136
|
-
const varKey = key.startsWith("--") ? key : `--atomix-${componentKey}-${variantName}-${key}`;
|
|
3137
|
-
vars[varKey] = value;
|
|
3138
|
-
}));
|
|
3139
|
-
})), this.applyGlobalCSSVars(vars);
|
|
3140
|
-
}
|
|
3141
|
-
/**
|
|
3142
|
-
* Clear all applied CSS variables
|
|
3143
|
-
*/ clearAppliedVars() {
|
|
3144
|
-
removeCSS(this.styleId);
|
|
3145
|
-
}
|
|
3146
|
-
/**
|
|
3147
|
-
* Remove theme application
|
|
3148
|
-
*/ removeTheme() {
|
|
3149
|
-
this.clearAppliedVars(), removeCSS(this.styleId);
|
|
3150
|
-
}
|
|
3151
|
-
/**
|
|
3152
|
-
* Update specific CSS variables without clearing all
|
|
3153
|
-
*/ updateCSSVars(vars) {
|
|
3154
|
-
this.applyGlobalCSSVars(vars);
|
|
3155
|
-
}
|
|
1963
|
+
/**
|
|
1964
|
+
* Get a theme value for a specific component using CSS variables
|
|
1965
|
+
* This ensures all components access theme values consistently
|
|
1966
|
+
*/ function getComponentThemeValue(component, property, variant, size) {
|
|
1967
|
+
// Build CSS variable name following consistent pattern
|
|
1968
|
+
const parts = [ "atomix", component ];
|
|
1969
|
+
// Return CSS variable reference with fallback
|
|
1970
|
+
return variant && parts.push(variant), size && parts.push(size), parts.push(property),
|
|
1971
|
+
`var(--${parts.join("-")}, var(--atomix-${property}, initial))`;
|
|
3156
1972
|
}
|
|
3157
1973
|
|
|
3158
1974
|
/**
|
|
3159
|
-
*
|
|
3160
|
-
*/
|
|
1975
|
+
* Generate component-specific CSS variables from DesignTokens
|
|
1976
|
+
*/ function generateComponentCSSVars(component, tokens, variant, size) {
|
|
1977
|
+
const vars = {};
|
|
1978
|
+
if (!tokens) return vars;
|
|
1979
|
+
const prefixParts = [ "atomix", component ];
|
|
1980
|
+
variant && prefixParts.push(variant), size && prefixParts.push(size);
|
|
1981
|
+
const prefix = prefixParts.join("-");
|
|
1982
|
+
// Map common DesignTokens to component-specific CSS variables
|
|
1983
|
+
return tokens.primary && (vars[`--${prefix}-color`] = tokens.primary), tokens["primary-9"] && (vars[`--${prefix}-color-hover`] = tokens["primary-9"]),
|
|
1984
|
+
tokens["body-color"] && (vars[`--${prefix}-color-disabled`] = tokens["body-color"]),
|
|
1985
|
+
tokens["body-font-family"] && (vars[`--${prefix}-font-family`] = tokens["body-font-family"]),
|
|
1986
|
+
tokens["body-font-size"] && (vars[`--${prefix}-font-size`] = tokens["body-font-size"]),
|
|
1987
|
+
tokens["spacing-1"] && (vars[`--${prefix}-spacing-sm`] = tokens["spacing-1"]), tokens["spacing-2"] && (vars[`--${prefix}-spacing-md`] = tokens["spacing-2"]),
|
|
1988
|
+
tokens["spacing-4"] && (vars[`--${prefix}-spacing-lg`] = tokens["spacing-4"]), vars;
|
|
1989
|
+
}
|
|
3161
1990
|
|
|
3162
1991
|
/**
|
|
3163
|
-
*
|
|
3164
|
-
*/ function
|
|
3165
|
-
|
|
1992
|
+
* Apply consistent theme to component style object using DesignTokens
|
|
1993
|
+
*/ function applyComponentTheme(component, style = {}, variant, size, tokens) {
|
|
1994
|
+
// If no tokens provided, return original style
|
|
1995
|
+
return tokens ? {
|
|
1996
|
+
...generateComponentCSSVars(component, tokens, variant, size),
|
|
1997
|
+
...style
|
|
1998
|
+
} : style;
|
|
1999
|
+
// Generate component-specific CSS variables
|
|
3166
2000
|
}
|
|
3167
2001
|
|
|
3168
2002
|
/**
|
|
3169
|
-
*
|
|
3170
|
-
*/ function
|
|
3171
|
-
|
|
2003
|
+
* Create a hook for consistent component theming
|
|
2004
|
+
*/ function useComponentTheme(component, variant, size, tokens) {
|
|
2005
|
+
return property => getComponentThemeValue(component, property, variant, size);
|
|
3172
2006
|
}
|
|
3173
2007
|
|
|
3174
2008
|
/**
|
|
3175
|
-
*
|
|
3176
|
-
*
|
|
3177
|
-
* Provides theme context to child components and manages theme state.
|
|
2009
|
+
* Theme Configuration Loader
|
|
3178
2010
|
*
|
|
3179
|
-
*
|
|
3180
|
-
*
|
|
2011
|
+
* Provides functions to load theme configurations from atomix.config.ts
|
|
2012
|
+
* Includes both sync and async versions, with automatic fallbacks
|
|
2013
|
+
*/
|
|
2014
|
+
/**
|
|
2015
|
+
* Load theme from config file (synchronous, Node.js only)
|
|
2016
|
+
* @param configPath - Path to config file (default: atomix.config.ts)
|
|
2017
|
+
* @returns DesignTokens from theme configuration
|
|
2018
|
+
* @throws Error if config loading is not available in browser environment
|
|
2019
|
+
*/ function loadThemeFromConfigSync(options) {
|
|
2020
|
+
// Check if we're in a browser environment
|
|
2021
|
+
if ("undefined" != typeof window) throw new Error("loadThemeFromConfigSync: Not available in browser environment. Config loading requires Node.js/SSR environment.");
|
|
2022
|
+
// Use static import - the function handles browser environment checks internally
|
|
2023
|
+
let config;
|
|
2024
|
+
try {
|
|
2025
|
+
config = loadAtomixConfig({
|
|
2026
|
+
configPath: options?.configPath || "atomix.config.ts",
|
|
2027
|
+
required: !1 !== options?.required
|
|
2028
|
+
});
|
|
2029
|
+
} catch (error) {
|
|
2030
|
+
if (!1 !== options?.required) throw new Error("Config loader module not available");
|
|
2031
|
+
// Return empty tokens if config is not required
|
|
2032
|
+
return createTokens({});
|
|
2033
|
+
}
|
|
2034
|
+
if (!config?.theme) return createTokens({});
|
|
2035
|
+
// Extract tokens from config.theme structure
|
|
2036
|
+
// config.theme can have: { extend?: ThemeTokens, tokens?: ThemeTokens, themes?: ... }
|
|
2037
|
+
// We need to extract the actual DesignTokens (flat structure)
|
|
2038
|
+
const themeConfig = config.theme;
|
|
2039
|
+
// Check if theme is directly a flat object (DesignTokens format)
|
|
2040
|
+
// This handles the case where config.theme might be passed as DesignTokens directly
|
|
2041
|
+
return createTokens(!themeConfig || "object" != typeof themeConfig || "extend" in themeConfig || "tokens" in themeConfig || "themes" in themeConfig ? {} : themeConfig);
|
|
2042
|
+
// If theme has nested structure (extend/tokens/themes), we can't directly use it
|
|
2043
|
+
// Return empty tokens - the theme system will use defaults
|
|
2044
|
+
// TODO: Add proper conversion from ThemeTokens to DesignTokens if needed
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
/**
|
|
2048
|
+
* Load theme from config file (asynchronous)
|
|
2049
|
+
* @param configPath - Path to config file (default: atomix.config.ts)
|
|
2050
|
+
* @returns Promise resolving to DesignTokens from theme configuration
|
|
2051
|
+
*/ async function loadThemeFromConfig(options) {
|
|
2052
|
+
// Check if we're in a browser environment
|
|
2053
|
+
if ("undefined" != typeof window) throw new Error("loadThemeFromConfig: Not available in browser environment. Config loading requires Node.js/SSR environment.");
|
|
2054
|
+
// Use static import with runtime check
|
|
2055
|
+
// The function will handle browser environment checks internally
|
|
2056
|
+
let config;
|
|
2057
|
+
try {
|
|
2058
|
+
// loadAtomixConfig is synchronous, not async
|
|
2059
|
+
config = loadAtomixConfig({
|
|
2060
|
+
configPath: options?.configPath || "atomix.config.ts",
|
|
2061
|
+
required: !1 !== options?.required
|
|
2062
|
+
});
|
|
2063
|
+
} catch (error) {
|
|
2064
|
+
if (!1 !== options?.required) throw new Error("Config loader module not available");
|
|
2065
|
+
// Return empty tokens if config is not required
|
|
2066
|
+
return createTokens({});
|
|
2067
|
+
}
|
|
2068
|
+
if (!config?.theme) return createTokens({});
|
|
2069
|
+
// Extract tokens from config.theme structure
|
|
2070
|
+
// config.theme can have: { extend?: ThemeTokens, tokens?: ThemeTokens, themes?: ... }
|
|
2071
|
+
// We need to extract the actual DesignTokens (flat structure)
|
|
2072
|
+
const themeConfig = config.theme;
|
|
2073
|
+
// Check if theme is directly a flat object (DesignTokens format)
|
|
2074
|
+
// This handles the case where config.theme might be passed as DesignTokens directly
|
|
2075
|
+
return createTokens(!themeConfig || "object" != typeof themeConfig || "extend" in themeConfig || "tokens" in themeConfig || "themes" in themeConfig ? {} : themeConfig);
|
|
2076
|
+
// If theme has nested structure (extend/tokens/themes), we can't directly use it
|
|
2077
|
+
// Return empty tokens - the theme system will use defaults
|
|
2078
|
+
// TODO: Add proper conversion from ThemeTokens to DesignTokens if needed
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
/**
|
|
2082
|
+
* Theme Context
|
|
3181
2083
|
*
|
|
3182
|
-
*
|
|
3183
|
-
|
|
3184
|
-
|
|
2084
|
+
* React context for theme management
|
|
2085
|
+
*/
|
|
2086
|
+
/**
|
|
2087
|
+
* Theme context with default values
|
|
2088
|
+
*/ const ThemeContext = createContext(null);
|
|
2089
|
+
|
|
2090
|
+
ThemeContext.displayName = "ThemeContext";
|
|
2091
|
+
|
|
2092
|
+
/**
|
|
2093
|
+
* Theme Provider
|
|
3185
2094
|
*
|
|
3186
|
-
*
|
|
3187
|
-
*
|
|
3188
|
-
*
|
|
3189
|
-
*
|
|
3190
|
-
*
|
|
3191
|
-
* </ThemeProvider>
|
|
3192
|
-
* );
|
|
3193
|
-
* }
|
|
2095
|
+
* React context provider for theme management with separated concerns.
|
|
2096
|
+
* Simplified version focusing on core functionality:
|
|
2097
|
+
* - String-based themes (CSS files)
|
|
2098
|
+
* - DesignTokens (dynamic themes)
|
|
2099
|
+
* - Persistence via localStorage
|
|
3194
2100
|
*
|
|
3195
|
-
*
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
* <ThemeProvider defaultTheme="dark">
|
|
3199
|
-
* <YourApp />
|
|
3200
|
-
* </ThemeProvider>
|
|
3201
|
-
* );
|
|
3202
|
-
* }
|
|
3203
|
-
* ```
|
|
3204
|
-
*/ const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes: themes = {}, basePath: basePath = "/themes", cdnPath: cdnPath = null, preload: preload = [], lazy: lazy = !0, storageKey: storageKey = "atomix-theme", dataAttribute: dataAttribute = "data-theme", enablePersistence: enablePersistence = !0, useMinified: useMinified = !1, onThemeChange: onThemeChange, onError: onError}) => {
|
|
2101
|
+
* Falls back to 'default' theme if no configuration is found.
|
|
2102
|
+
*/
|
|
2103
|
+
const ThemeProvider = ({children: children, defaultTheme: defaultTheme, themes: themes = {}, basePath: basePath = "/themes", cdnPath: cdnPath = null, useMinified: useMinified = !1, storageKey: storageKey = "atomix-theme", dataAttribute: dataAttribute = "data-theme", enablePersistence: enablePersistence = !0, onThemeChange: onThemeChange, onError: onError}) => {
|
|
3205
2104
|
// Store callbacks in refs to avoid recreating when they change
|
|
3206
2105
|
const onThemeChangeRef = useRef(onThemeChange), onErrorRef = useRef(onError);
|
|
3207
|
-
// Update
|
|
2106
|
+
// Update ref when callback changes
|
|
3208
2107
|
useEffect((() => {
|
|
3209
2108
|
onThemeChangeRef.current = onThemeChange, onErrorRef.current = onError;
|
|
3210
2109
|
}), [ onThemeChange, onError ]);
|
|
3211
|
-
// Create stable wrapper functions that read from
|
|
2110
|
+
// Create stable wrapper functions that read from ref
|
|
3212
2111
|
const handleThemeChange = useCallback((theme => {
|
|
3213
2112
|
onThemeChangeRef.current?.(theme);
|
|
3214
2113
|
}), []), handleError = useCallback(((error, themeName) => {
|
|
3215
2114
|
onErrorRef.current?.(error, themeName);
|
|
3216
|
-
}), []),
|
|
3217
|
-
// Only update if themes object actually changed (shallow comparison)
|
|
3218
|
-
const currentKeys = Object.keys(themes), prevKeys = Object.keys(themesRef.current);
|
|
3219
|
-
return currentKeys.length !== prevKeys.length || currentKeys.some((key => themes[key] !== themesRef.current[key])) ? (themesRef.current = themes,
|
|
3220
|
-
themes) : themesRef.current;
|
|
3221
|
-
}), [ themes ]), logger = useMemo((() => getLogger()), []), registry = useMemo((() => {
|
|
3222
|
-
const reg = new ThemeRegistry;
|
|
3223
|
-
// Register themes from props
|
|
3224
|
-
if (themesStable && Object.keys(themesStable).length > 0) for (const [themeId, metadata] of Object.entries(themesStable)) reg.has(themeId) || reg.register(themeId, {
|
|
3225
|
-
type: "css",
|
|
3226
|
-
name: metadata.name,
|
|
3227
|
-
class: metadata.class || themeId,
|
|
3228
|
-
description: metadata.description,
|
|
3229
|
-
author: metadata.author,
|
|
3230
|
-
version: metadata.version,
|
|
3231
|
-
tags: metadata.tags,
|
|
3232
|
-
supportsDarkMode: metadata.supportsDarkMode,
|
|
3233
|
-
status: metadata.status,
|
|
3234
|
-
a11y: metadata.a11y,
|
|
3235
|
-
color: metadata.color,
|
|
3236
|
-
features: metadata.features,
|
|
3237
|
-
dependencies: metadata.dependencies
|
|
3238
|
-
});
|
|
3239
|
-
return reg;
|
|
3240
|
-
}), [ themesStable ]), storageAdapter = useMemo((() => ({
|
|
3241
|
-
getItem: key => {
|
|
3242
|
-
if (isServer()) return null;
|
|
3243
|
-
try {
|
|
3244
|
-
return localStorage.getItem(key);
|
|
3245
|
-
} catch {
|
|
3246
|
-
return null;
|
|
3247
|
-
}
|
|
3248
|
-
},
|
|
3249
|
-
setItem: (key, value) => {
|
|
3250
|
-
if (!isServer()) try {
|
|
3251
|
-
localStorage.setItem(key, value);
|
|
3252
|
-
} catch {
|
|
3253
|
-
// Silently fail if localStorage is not available
|
|
3254
|
-
}
|
|
3255
|
-
},
|
|
3256
|
-
removeItem: key => {
|
|
3257
|
-
if (!isServer()) try {
|
|
3258
|
-
localStorage.removeItem(key);
|
|
3259
|
-
} catch {
|
|
3260
|
-
// Silently fail
|
|
3261
|
-
}
|
|
3262
|
-
},
|
|
3263
|
-
isAvailable: () => {
|
|
3264
|
-
if (isServer()) return !1;
|
|
3265
|
-
try {
|
|
3266
|
-
const test = "__atomix_storage_test__";
|
|
3267
|
-
return localStorage.setItem(test, test), localStorage.removeItem(test), !0;
|
|
3268
|
-
} catch {
|
|
3269
|
-
return !1;
|
|
3270
|
-
}
|
|
3271
|
-
}
|
|
3272
|
-
})), []), themeApplicator = useMemo((() => isServer() ? null : new ThemeApplicator), []), initialDefaultTheme = useMemo((() => {
|
|
2115
|
+
}), []), storageAdapter = useMemo((() => createLocalStorageAdapter()), []), initialDefaultTheme = useMemo((() => {
|
|
3273
2116
|
// Check storage first
|
|
3274
2117
|
if (enablePersistence && storageAdapter.isAvailable()) {
|
|
3275
2118
|
const stored = storageAdapter.getItem(storageKey);
|
|
@@ -3277,193 +2120,169 @@ class ThemeApplicator {
|
|
|
3277
2120
|
}
|
|
3278
2121
|
// If defaultTheme is provided, use it
|
|
3279
2122
|
if (null != defaultTheme) return defaultTheme;
|
|
3280
|
-
//
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
version: meta.version,
|
|
3291
|
-
tags: meta.tags,
|
|
3292
|
-
supportsDarkMode: meta.supportsDarkMode,
|
|
3293
|
-
status: meta.status,
|
|
3294
|
-
a11y: meta.a11y,
|
|
3295
|
-
color: meta.color,
|
|
3296
|
-
features: meta.features,
|
|
3297
|
-
dependencies: meta.dependencies
|
|
3298
|
-
}))))), [isLoading, setIsLoading] = useState(!1), [error, setError] = useState(null), loadedThemesRef = useRef(new Set), previousThemeRef = useRef(null);
|
|
3299
|
-
// Get default theme (with automatic config loading)
|
|
3300
|
-
useCallback((() => {
|
|
3301
|
-
// Check storage first
|
|
3302
|
-
if (enablePersistence && storageAdapter.isAvailable()) {
|
|
3303
|
-
const stored = storageAdapter.getItem(storageKey);
|
|
3304
|
-
if (stored) return stored;
|
|
2123
|
+
// Try to load from atomix.config.ts as fallback, but only in Node.js/SSR environments
|
|
2124
|
+
if ("undefined" == typeof window) try {
|
|
2125
|
+
// Dynamically import the config loader to avoid bundling issues in browser
|
|
2126
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
2127
|
+
const {loadThemeFromConfigSync: loadThemeFromConfigSync} = require("../config/configLoader"), configTokens = loadThemeFromConfigSync();
|
|
2128
|
+
if (configTokens && Object.keys(configTokens).length > 0)
|
|
2129
|
+
// For simplicity, we'll treat config tokens as a special theme name
|
|
2130
|
+
return "config-theme";
|
|
2131
|
+
} catch (error) {
|
|
2132
|
+
// Failed to load theme from config, using default
|
|
3305
2133
|
}
|
|
3306
|
-
//
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
//
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
}), [
|
|
3316
|
-
//
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
}), [
|
|
3328
|
-
|
|
3329
|
-
|
|
2134
|
+
// Default fallback
|
|
2135
|
+
return "default";
|
|
2136
|
+
}), [ defaultTheme, enablePersistence, storageKey ]), [currentTheme, setCurrentTheme] = useState((() => "string" == typeof initialDefaultTheme ? initialDefaultTheme : "tokens-theme")), [activeTokens, setActiveTokens] = useState((() => {
|
|
2137
|
+
// If defaultTheme is DesignTokens, store them
|
|
2138
|
+
if (defaultTheme && "string" != typeof defaultTheme) {
|
|
2139
|
+
const {createTokens: createTokens} = require("../tokens/tokens");
|
|
2140
|
+
return createTokens(defaultTheme);
|
|
2141
|
+
}
|
|
2142
|
+
return null;
|
|
2143
|
+
})), [isLoading, setIsLoading] = useState(!1), [error, setError] = useState(null), loadedThemesRef = useRef(new Set), themePromisesRef = useRef({}), abortControllerRef = useRef(null);
|
|
2144
|
+
// Handle initial DesignTokens defaultTheme
|
|
2145
|
+
useEffect((() => {
|
|
2146
|
+
defaultTheme && "string" != typeof defaultTheme && activeTokens && !isServer() && injectCSS$1(createTheme(defaultTheme), "theme-tokens-theme");
|
|
2147
|
+
}), [ defaultTheme, activeTokens ]), // Run when defaultTheme or activeTokens change
|
|
2148
|
+
// Apply initial theme attributes to document element
|
|
2149
|
+
useEffect((() => {
|
|
2150
|
+
isServer() || applyThemeAttributes(String(currentTheme), dataAttribute);
|
|
2151
|
+
}), [ currentTheme, dataAttribute ]),
|
|
2152
|
+
// Handle theme persistence
|
|
2153
|
+
useEffect((() => {
|
|
2154
|
+
enablePersistence && storageAdapter.isAvailable() && storageAdapter.setItem(storageKey, String(currentTheme));
|
|
2155
|
+
}), [ currentTheme, storageKey, enablePersistence, storageAdapter ]),
|
|
2156
|
+
// Cleanup: Remove completed promises and abort controllers on unmount
|
|
2157
|
+
useEffect((() => () => {
|
|
2158
|
+
// Cancel any in-flight theme loads
|
|
2159
|
+
abortControllerRef.current && (abortControllerRef.current.abort(), abortControllerRef.current = null),
|
|
2160
|
+
Object.entries(themePromisesRef.current).forEach((([key, promise]) => {})),
|
|
2161
|
+
// Clear all on unmount
|
|
2162
|
+
themePromisesRef.current = {};
|
|
2163
|
+
}), []);
|
|
2164
|
+
// Function to set theme with proper type handling
|
|
2165
|
+
const setTheme = useCallback((async (theme, options) => {
|
|
2166
|
+
// Cancel previous theme load if in progress
|
|
2167
|
+
abortControllerRef.current && abortControllerRef.current.abort();
|
|
2168
|
+
// Create new AbortController for this theme load
|
|
2169
|
+
const abortController = new AbortController;
|
|
2170
|
+
abortControllerRef.current = abortController, setIsLoading(!0), setError(null);
|
|
3330
2171
|
try {
|
|
3331
|
-
|
|
2172
|
+
let themeName;
|
|
3332
2173
|
if ("string" != typeof theme) {
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
}
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
2174
|
+
// Check if aborted before processing
|
|
2175
|
+
if (abortController.signal.aborted) return;
|
|
2176
|
+
// For DesignTokens, create CSS and inject it
|
|
2177
|
+
const {createTheme: createTheme} = await Promise.resolve().then((() => index)), css = createTheme(theme), themeId = "tokens-theme";
|
|
2178
|
+
// Check if aborted after async operation
|
|
2179
|
+
if (abortController.signal.aborted) return;
|
|
2180
|
+
// Remove any previously loaded theme CSS
|
|
2181
|
+
removeCSS(`theme-${currentTheme}`),
|
|
2182
|
+
// Inject new theme CSS
|
|
2183
|
+
injectCSS$1(css, `theme-${themeId}`);
|
|
2184
|
+
// Store tokens for reference
|
|
2185
|
+
const {createTokens: createTokens} = await Promise.resolve().then((() => tokens)), fullTokens = createTokens(theme);
|
|
2186
|
+
// Check if aborted before state update
|
|
2187
|
+
if (abortController.signal.aborted) return;
|
|
2188
|
+
return setActiveTokens(fullTokens), setCurrentTheme(themeId), handleThemeChange(fullTokens),
|
|
2189
|
+
void setIsLoading(!1);
|
|
2190
|
+
}
|
|
2191
|
+
// If it's a string theme name, load the associated CSS
|
|
2192
|
+
if (themeName = theme, "string" == typeof theme && themes[theme]) {
|
|
2193
|
+
// Check if theme is already loading
|
|
2194
|
+
if (themePromisesRef.current[theme]) try {
|
|
2195
|
+
// Check if aborted
|
|
2196
|
+
if (await themePromisesRef.current[theme], abortController.signal.aborted) return;
|
|
2197
|
+
return setCurrentTheme(theme), setActiveTokens(null), handleThemeChange(theme),
|
|
3351
2198
|
void setIsLoading(!1);
|
|
2199
|
+
} catch {
|
|
2200
|
+
// If previous load failed, continue with new load
|
|
3352
2201
|
}
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
2202
|
+
// Load CSS theme
|
|
2203
|
+
const themeLoadPromise = new Promise((async (resolve, reject) => {
|
|
2204
|
+
try {
|
|
2205
|
+
// Check if aborted
|
|
2206
|
+
if (abortController.signal.aborted) return void resolve();
|
|
2207
|
+
if (!themes[theme]) throw new Error(`Theme metadata not found for theme: ${theme}`);
|
|
2208
|
+
{
|
|
2209
|
+
// Build CSS path using utility function
|
|
2210
|
+
const cssPath = buildThemePath(theme, basePath, useMinified, cdnPath);
|
|
2211
|
+
// Check if aborted
|
|
2212
|
+
if (abortController.signal.aborted) return void resolve();
|
|
2213
|
+
// Load CSS file (using loadThemeCSS from domUtils)
|
|
2214
|
+
const {loadThemeCSS: loadThemeCSS} = await Promise.resolve().then((() => domUtils));
|
|
2215
|
+
// Check if aborted after async operation
|
|
2216
|
+
if (await loadThemeCSS(cssPath, `theme-${theme}`), abortController.signal.aborted) return void resolve();
|
|
2217
|
+
// Remove any previously loaded theme CSS
|
|
2218
|
+
removeCSS(`theme-${String(currentTheme)}`), loadedThemesRef.current.add(theme),
|
|
2219
|
+
setCurrentTheme(theme), setActiveTokens(null), handleThemeChange(theme), resolve();
|
|
2220
|
+
}
|
|
2221
|
+
} catch (err) {
|
|
2222
|
+
// Don't reject if aborted
|
|
2223
|
+
if (abortController.signal.aborted) return void resolve();
|
|
2224
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
2225
|
+
setError(error), handleError(error, String(theme)), reject(error);
|
|
2226
|
+
}
|
|
2227
|
+
}));
|
|
2228
|
+
themePromisesRef.current[theme] = themeLoadPromise;
|
|
2229
|
+
try {
|
|
2230
|
+
await themeLoadPromise;
|
|
2231
|
+
} catch {
|
|
2232
|
+
// Error already handled in promise
|
|
3356
2233
|
}
|
|
2234
|
+
// Clean up completed promise after a delay to prevent memory leak
|
|
2235
|
+
setTimeout((() => {
|
|
2236
|
+
themePromisesRef.current[theme] === themeLoadPromise && delete themePromisesRef.current[theme];
|
|
2237
|
+
}), 1e3);
|
|
2238
|
+
} else {
|
|
2239
|
+
// Check if aborted
|
|
2240
|
+
if (abortController.signal.aborted) return;
|
|
2241
|
+
// For string theme that isn't in our themes record, just set the name
|
|
2242
|
+
setCurrentTheme(themeName), setActiveTokens(null), handleThemeChange(themeName);
|
|
3357
2243
|
}
|
|
3358
|
-
// Check if theme exists
|
|
3359
|
-
if (!registry.has(theme)) {
|
|
3360
|
-
const error = new Error(`Theme "${theme}" not found in registry`);
|
|
3361
|
-
if (handleError(error, theme), setError(error), fallbackOnError && currentTheme) return void setIsLoading(!1);
|
|
3362
|
-
throw setIsLoading(!1), error;
|
|
3363
|
-
}
|
|
3364
|
-
// Load theme CSS if needed
|
|
3365
|
-
const themePath = customPath || buildThemePath(theme, basePath, useMinified, cdnPath || void 0), linkId = getThemeLinkId(theme);
|
|
3366
|
-
// Remove previous theme if requested
|
|
3367
|
-
removePrevious && previousThemeRef.current && previousThemeRef.current !== theme && (themeNameOrLinkId => {
|
|
3368
|
-
if (isServer()) return;
|
|
3369
|
-
// Try as link ID first, then as theme name
|
|
3370
|
-
let link = document.getElementById(themeNameOrLinkId);
|
|
3371
|
-
if (!link) {
|
|
3372
|
-
const linkId = getThemeLinkId(themeNameOrLinkId);
|
|
3373
|
-
link = document.getElementById(linkId);
|
|
3374
|
-
}
|
|
3375
|
-
link && link.remove();
|
|
3376
|
-
})(previousThemeRef.current),
|
|
3377
|
-
// Load CSS if not already loaded
|
|
3378
|
-
isThemeLoaded(theme) || (await loadThemeCSS(themePath, linkId), loadedThemesRef.current.add(theme)),
|
|
3379
|
-
// Apply theme attributes
|
|
3380
|
-
((dataAttribute, themeName) => {
|
|
3381
|
-
isServer() || (
|
|
3382
|
-
// Set data attribute on body
|
|
3383
|
-
document.body.setAttribute(dataAttribute, themeName),
|
|
3384
|
-
// Also set on documentElement for broader compatibility
|
|
3385
|
-
document.documentElement.setAttribute(dataAttribute, themeName));
|
|
3386
|
-
})(dataAttribute, theme),
|
|
3387
|
-
// Update state
|
|
3388
|
-
previousThemeRef.current = currentTheme, setCurrentTheme(theme), setActiveTheme(null),
|
|
3389
|
-
previousThemeRef.current, Date.now(), handleThemeChange(theme),
|
|
3390
|
-
// Persist to storage
|
|
3391
|
-
enablePersistence && storageAdapter.isAvailable() && storageAdapter.setItem(storageKey, theme),
|
|
3392
|
-
setIsLoading(!1);
|
|
3393
2244
|
} catch (err) {
|
|
2245
|
+
// Don't set error if aborted
|
|
2246
|
+
if (abortController.signal.aborted) return;
|
|
3394
2247
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
if (!isServer() && !isThemeLoaded(themeName)) {
|
|
3400
|
-
setIsLoading(!0);
|
|
3401
|
-
try {
|
|
3402
|
-
if (!registry.has(themeName)) throw new Error(`Theme "${themeName}" not found in registry`);
|
|
3403
|
-
const themePath = buildThemePath(themeName, basePath, useMinified, cdnPath || void 0), linkId = getThemeLinkId(themeName);
|
|
3404
|
-
await loadThemeCSS(themePath, linkId), loadedThemesRef.current.add(themeName);
|
|
3405
|
-
} catch (err) {
|
|
3406
|
-
const error = err instanceof Error ? err : new Error(String(err));
|
|
3407
|
-
handleError(error, themeName), setError(error);
|
|
3408
|
-
} finally {
|
|
3409
|
-
setIsLoading(!1);
|
|
3410
|
-
}
|
|
2248
|
+
setError(error), handleError(error, String(theme));
|
|
2249
|
+
} finally {
|
|
2250
|
+
// Only update loading state if not aborted
|
|
2251
|
+
abortController.signal.aborted || setIsLoading(!1);
|
|
3411
2252
|
}
|
|
3412
|
-
}), [
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
null === defaultThemeValue || "object" != typeof defaultThemeValue || "palette" in defaultThemeValue || "typography" in defaultThemeValue || "__isJSTheme" in defaultThemeValue || "string" == typeof defaultThemeValue ?
|
|
3421
|
-
// Handle string or Theme object
|
|
3422
|
-
await setTheme(defaultThemeValue, {
|
|
3423
|
-
removePrevious: !1,
|
|
3424
|
-
fallbackOnError: !0
|
|
3425
|
-
}) : (
|
|
3426
|
-
// Apply config tokens directly
|
|
3427
|
-
await applyJSTheme(defaultThemeValue, !1),
|
|
3428
|
-
// Update state and emit events
|
|
3429
|
-
setCurrentTheme("config-theme"), setActiveTheme(null), Date.now(), handleThemeChange("config-theme"),
|
|
3430
|
-
// Persist to storage
|
|
3431
|
-
enablePersistence && storageAdapter.isAvailable() && storageAdapter.setItem(storageKey, "config-theme"));
|
|
3432
|
-
} catch (err) {
|
|
3433
|
-
const error = err instanceof Error ? err : new Error(String(err));
|
|
3434
|
-
throw logger.error("Failed to load theme from config", error, {
|
|
3435
|
-
theme: defaultThemeValue
|
|
3436
|
-
}), handleError(error, "config-theme"), setError(error), error;
|
|
3437
|
-
}
|
|
3438
|
-
})();
|
|
3439
|
-
}
|
|
3440
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3441
|
-
), []), // Only run once on mount - initialDefaultTheme is stable
|
|
3442
|
-
// Preload themes
|
|
3443
|
-
useEffect((() => {
|
|
3444
|
-
!isServer() && preload && 0 !== preload.length && (async () => {
|
|
3445
|
-
for (const themeName of preload) if (!isThemeLoaded(themeName)) try {
|
|
3446
|
-
await preloadTheme(themeName);
|
|
2253
|
+
}), [ themes, currentTheme, handleThemeChange, handleError, basePath, useMinified, cdnPath ]), isThemeLoaded = useCallback((themeName => loadedThemesRef.current.has(themeName)), []), preloadTheme = useCallback((async themeName => {
|
|
2254
|
+
if (themes[themeName] && !isThemeLoaded(themeName)) {
|
|
2255
|
+
setIsLoading(!0);
|
|
2256
|
+
try {
|
|
2257
|
+
// Build CSS path using utility function
|
|
2258
|
+
const cssPath = buildThemePath(themeName, basePath, useMinified, cdnPath);
|
|
2259
|
+
// Preload CSS by fetching it
|
|
2260
|
+
await fetch(cssPath), loadedThemesRef.current.add(themeName);
|
|
3447
2261
|
} catch (err) {
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
2262
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
2263
|
+
setError(error), handleError(error, themeName);
|
|
2264
|
+
} finally {
|
|
2265
|
+
setIsLoading(!1);
|
|
3452
2266
|
}
|
|
3453
|
-
}
|
|
3454
|
-
}), [
|
|
3455
|
-
|
|
3456
|
-
|
|
2267
|
+
}
|
|
2268
|
+
}), [ themes, isThemeLoaded, handleError, basePath, useMinified, cdnPath ]), themeManager = useMemo((() => ({})), []), availableThemes = useMemo((() => Object.entries(themes).map((([name, metadata]) => ({
|
|
2269
|
+
...metadata,
|
|
2270
|
+
name: name
|
|
2271
|
+
})))), [ themes ]), contextValue = useMemo((() => ({
|
|
3457
2272
|
theme: currentTheme,
|
|
3458
|
-
|
|
2273
|
+
activeTokens: activeTokens,
|
|
3459
2274
|
setTheme: setTheme,
|
|
3460
2275
|
availableThemes: availableThemes,
|
|
3461
2276
|
isLoading: isLoading,
|
|
3462
2277
|
error: error,
|
|
3463
|
-
isThemeLoaded: isThemeLoaded
|
|
3464
|
-
preloadTheme: preloadTheme
|
|
3465
|
-
|
|
3466
|
-
|
|
2278
|
+
isThemeLoaded: isThemeLoaded,
|
|
2279
|
+
preloadTheme: preloadTheme,
|
|
2280
|
+
themeManager: themeManager
|
|
2281
|
+
})), [ currentTheme, activeTokens, setTheme, availableThemes,
|
|
2282
|
+
// Use memoized value
|
|
2283
|
+
isLoading, error, isThemeLoaded, preloadTheme, themeManager ]);
|
|
2284
|
+
// Check if theme is loaded
|
|
2285
|
+
return jsx(ThemeContext.Provider, {
|
|
3467
2286
|
value: contextValue,
|
|
3468
2287
|
children: children
|
|
3469
2288
|
});
|
|
@@ -3499,7 +2318,7 @@ class ThemeApplicator {
|
|
|
3499
2318
|
if (!context) throw new Error("useTheme must be used within a ThemeProvider");
|
|
3500
2319
|
return {
|
|
3501
2320
|
theme: context.theme,
|
|
3502
|
-
|
|
2321
|
+
activeTokens: context.activeTokens,
|
|
3503
2322
|
setTheme: context.setTheme,
|
|
3504
2323
|
availableThemes: context.availableThemes,
|
|
3505
2324
|
isLoading: context.isLoading,
|
|
@@ -3509,6 +2328,89 @@ class ThemeApplicator {
|
|
|
3509
2328
|
};
|
|
3510
2329
|
}
|
|
3511
2330
|
|
|
2331
|
+
function useThemeTokens() {
|
|
2332
|
+
const {theme: theme, activeTokens: activeTokens} = useTheme(), getToken = useCallback(((tokenName, fallback) => {
|
|
2333
|
+
if ("undefined" == typeof window) return fallback || "";
|
|
2334
|
+
const cssVarName = `--atomix-${tokenName}`;
|
|
2335
|
+
return getComputedStyle(document.documentElement).getPropertyValue(cssVarName).trim() || fallback || "";
|
|
2336
|
+
}), []);
|
|
2337
|
+
// Helper function to get CSS variable value
|
|
2338
|
+
// Return unified API for accessing theme values
|
|
2339
|
+
// Note: For SSR or direct token access, use activeTokens directly
|
|
2340
|
+
return {
|
|
2341
|
+
theme: theme,
|
|
2342
|
+
activeTokens: activeTokens,
|
|
2343
|
+
getToken: getToken,
|
|
2344
|
+
// Commonly used tokens with fallbacks
|
|
2345
|
+
colors: {
|
|
2346
|
+
primary: getToken("primary", "#3b82f6"),
|
|
2347
|
+
secondary: getToken("secondary", "#10b981"),
|
|
2348
|
+
error: getToken("error", "#ef4444"),
|
|
2349
|
+
success: getToken("success", "#22c55e"),
|
|
2350
|
+
warning: getToken("warning", "#eab308"),
|
|
2351
|
+
info: getToken("info", "#3b82f6"),
|
|
2352
|
+
light: getToken("light", "#f9fafb"),
|
|
2353
|
+
dark: getToken("dark", "#111827")
|
|
2354
|
+
},
|
|
2355
|
+
spacing: {
|
|
2356
|
+
1: getToken("spacing-1", "0.25rem"),
|
|
2357
|
+
2: getToken("spacing-2", "0.5rem"),
|
|
2358
|
+
3: getToken("spacing-3", "0.75rem"),
|
|
2359
|
+
4: getToken("spacing-4", "1rem"),
|
|
2360
|
+
5: getToken("spacing-5", "1.25rem"),
|
|
2361
|
+
6: getToken("spacing-6", "1.5rem"),
|
|
2362
|
+
8: getToken("spacing-8", "2rem"),
|
|
2363
|
+
10: getToken("spacing-10", "2.5rem"),
|
|
2364
|
+
12: getToken("spacing-12", "3rem"),
|
|
2365
|
+
16: getToken("spacing-16", "4rem"),
|
|
2366
|
+
20: getToken("spacing-20", "5rem")
|
|
2367
|
+
},
|
|
2368
|
+
borderRadius: {
|
|
2369
|
+
sm: getToken("border-radius-sm", "0.25rem"),
|
|
2370
|
+
md: getToken("border-radius-md", "0.5rem"),
|
|
2371
|
+
lg: getToken("border-radius-lg", "0.75rem"),
|
|
2372
|
+
xl: getToken("border-radius-xl", "1rem"),
|
|
2373
|
+
full: getToken("border-radius-full", "9999px")
|
|
2374
|
+
},
|
|
2375
|
+
typography: {
|
|
2376
|
+
fontFamily: {
|
|
2377
|
+
sans: getToken("font-sans-serif", "Inter, system-ui, sans-serif"),
|
|
2378
|
+
serif: getToken("font-serif", "Georgia, serif"),
|
|
2379
|
+
mono: getToken("font-monospace", "Fira Code, monospace")
|
|
2380
|
+
},
|
|
2381
|
+
fontSize: {
|
|
2382
|
+
xs: getToken("font-size-xs", "0.75rem"),
|
|
2383
|
+
sm: getToken("font-size-sm", "0.875rem"),
|
|
2384
|
+
md: getToken("font-size-md", "1rem"),
|
|
2385
|
+
lg: getToken("font-size-lg", "1.125rem"),
|
|
2386
|
+
xl: getToken("font-size-xl", "1.25rem"),
|
|
2387
|
+
"2xl": getToken("font-size-2xl", "1.5rem"),
|
|
2388
|
+
"3xl": getToken("font-size-3xl", "1.875rem"),
|
|
2389
|
+
"4xl": getToken("font-size-4xl", "2.25rem")
|
|
2390
|
+
},
|
|
2391
|
+
fontWeight: {
|
|
2392
|
+
light: getToken("font-weight-light", "300"),
|
|
2393
|
+
normal: getToken("font-weight-normal", "400"),
|
|
2394
|
+
medium: getToken("font-weight-medium", "500"),
|
|
2395
|
+
semibold: getToken("font-weight-semibold", "600"),
|
|
2396
|
+
bold: getToken("font-weight-bold", "700")
|
|
2397
|
+
}
|
|
2398
|
+
},
|
|
2399
|
+
shadows: {
|
|
2400
|
+
sm: getToken("box-shadow-sm", "0 1px 2px 0 rgba(0, 0, 0, 0.05)"),
|
|
2401
|
+
md: getToken("box-shadow-md", "0 4px 6px -1px rgba(0, 0, 0, 0.1)"),
|
|
2402
|
+
lg: getToken("box-shadow-lg", "0 10px 15px -3px rgba(0, 0, 0, 0.1)"),
|
|
2403
|
+
xl: getToken("box-shadow-xl", "0 20px 25px -5px rgba(0, 0, 0, 0.1)"),
|
|
2404
|
+
inset: getToken("box-shadow-inset", "inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)")
|
|
2405
|
+
},
|
|
2406
|
+
transitions: {
|
|
2407
|
+
fast: getToken("transition-fast", "150ms"),
|
|
2408
|
+
base: getToken("transition-base", "200ms"),
|
|
2409
|
+
slow: getToken("transition-slow", "300ms")
|
|
2410
|
+
}
|
|
2411
|
+
};
|
|
2412
|
+
}
|
|
2413
|
+
|
|
3512
2414
|
/**
|
|
3513
2415
|
* Default fallback UI
|
|
3514
2416
|
*/ const DefaultFallback = ({error: error, errorInfo: errorInfo}) => {
|
|
@@ -3557,7 +2459,7 @@ class ThemeApplicator {
|
|
|
3557
2459
|
},
|
|
3558
2460
|
children: JSON.stringify(context, null, 2)
|
|
3559
2461
|
}) ]
|
|
3560
|
-
}), "development" === process.env
|
|
2462
|
+
}), ("undefined" == typeof process || "development" === process.env?.NODE_ENV) && errorInfo && jsxs("details", {
|
|
3561
2463
|
style: {
|
|
3562
2464
|
marginTop: "1rem"
|
|
3563
2465
|
},
|
|
@@ -3653,6 +2555,76 @@ class ThemeApplicator {
|
|
|
3653
2555
|
}
|
|
3654
2556
|
}
|
|
3655
2557
|
|
|
2558
|
+
/**
|
|
2559
|
+
* Theme Applicator
|
|
2560
|
+
*
|
|
2561
|
+
* Applies theme configurations to the DOM, including CSS variables,
|
|
2562
|
+
* component overrides, typography, spacing, and color palettes.
|
|
2563
|
+
*
|
|
2564
|
+
* Uses the unified theme system for CSS generation and injection.
|
|
2565
|
+
*/
|
|
2566
|
+
/**
|
|
2567
|
+
* Theme applicator class for runtime theme application
|
|
2568
|
+
*
|
|
2569
|
+
* Uses the unified theme system for efficient CSS variable generation and injection.
|
|
2570
|
+
*/ class ThemeApplicator {
|
|
2571
|
+
constructor(root = document.documentElement) {
|
|
2572
|
+
this.styleId = "atomix-theme-applicator", this.root = root;
|
|
2573
|
+
}
|
|
2574
|
+
/**
|
|
2575
|
+
* Apply a complete theme configuration using DesignTokens
|
|
2576
|
+
*
|
|
2577
|
+
* Uses the unified theme system to generate and inject CSS.
|
|
2578
|
+
* Automatically respects atomix.config.ts when using DesignTokens.
|
|
2579
|
+
*/ applyTheme(tokens) {
|
|
2580
|
+
// Clear previously applied variables
|
|
2581
|
+
this.clearAppliedVars(),
|
|
2582
|
+
// Inject CSS into DOM
|
|
2583
|
+
injectCSS$1(createTheme(tokens, {
|
|
2584
|
+
selector: ":root",
|
|
2585
|
+
prefix: "atomix"
|
|
2586
|
+
}), this.styleId);
|
|
2587
|
+
}
|
|
2588
|
+
/**
|
|
2589
|
+
* Apply global CSS variables
|
|
2590
|
+
*/ applyGlobalCSSVars(vars) {
|
|
2591
|
+
Object.entries(vars).forEach((([key, value]) => {
|
|
2592
|
+
this.root.style.setProperty(key, String(value));
|
|
2593
|
+
}));
|
|
2594
|
+
}
|
|
2595
|
+
/**
|
|
2596
|
+
* Clear all applied CSS variables
|
|
2597
|
+
*/ clearAppliedVars() {
|
|
2598
|
+
removeCSS(this.styleId);
|
|
2599
|
+
}
|
|
2600
|
+
/**
|
|
2601
|
+
* Remove theme application
|
|
2602
|
+
*/ removeTheme() {
|
|
2603
|
+
this.clearAppliedVars(), removeCSS(this.styleId);
|
|
2604
|
+
}
|
|
2605
|
+
/**
|
|
2606
|
+
* Update specific CSS variables without clearing all
|
|
2607
|
+
*/ updateCSSVars(vars) {
|
|
2608
|
+
this.applyGlobalCSSVars(vars);
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
|
|
2612
|
+
/**
|
|
2613
|
+
* Global theme applicator instance
|
|
2614
|
+
*/ let globalApplicator = null;
|
|
2615
|
+
|
|
2616
|
+
/**
|
|
2617
|
+
* Get or create global theme applicator
|
|
2618
|
+
*/ function getThemeApplicator() {
|
|
2619
|
+
return globalApplicator || (globalApplicator = new ThemeApplicator), globalApplicator;
|
|
2620
|
+
}
|
|
2621
|
+
|
|
2622
|
+
/**
|
|
2623
|
+
* Apply theme using global applicator
|
|
2624
|
+
*/ function applyTheme(tokens) {
|
|
2625
|
+
getThemeApplicator().applyTheme(tokens);
|
|
2626
|
+
}
|
|
2627
|
+
|
|
3656
2628
|
const VIEWPORT_PRESETS = {
|
|
3657
2629
|
mobile: {
|
|
3658
2630
|
width: 375,
|
|
@@ -5138,10 +4110,374 @@ class ThemeValidator {
|
|
|
5138
4110
|
};
|
|
5139
4111
|
|
|
5140
4112
|
/**
|
|
5141
|
-
* Theme Comparator Component
|
|
4113
|
+
* Theme Comparator Component
|
|
4114
|
+
*
|
|
4115
|
+
* Compares two themes and highlights differences
|
|
4116
|
+
*/ 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) {
|
|
4117
|
+
return function(that, callbackfn, argumentsLength, memo) {
|
|
4118
|
+
var O = toObject(that), self = IndexedObject(O), length = lengthOfArrayLike(O);
|
|
4119
|
+
if (aCallable(callbackfn), 0 === length && argumentsLength < 2) throw new $TypeError(REDUCE_EMPTY);
|
|
4120
|
+
var index = IS_RIGHT ? length - 1 : 0, i = IS_RIGHT ? -1 : 1;
|
|
4121
|
+
if (argumentsLength < 2) for (;;) {
|
|
4122
|
+
if (index in self) {
|
|
4123
|
+
memo = self[index], index += i;
|
|
4124
|
+
break;
|
|
4125
|
+
}
|
|
4126
|
+
if (index += i, IS_RIGHT ? index < 0 : length <= index) throw new $TypeError(REDUCE_EMPTY);
|
|
4127
|
+
}
|
|
4128
|
+
for (;IS_RIGHT ? index >= 0 : length > index; index += i) index in self && (memo = callbackfn(memo, self[index], index, O));
|
|
4129
|
+
return memo;
|
|
4130
|
+
};
|
|
4131
|
+
}, arrayReduce = {
|
|
4132
|
+
// `Array.prototype.reduce` method
|
|
4133
|
+
// https://tc39.es/ecma262/#sec-array.prototype.reduce
|
|
4134
|
+
left: createMethod(!1),
|
|
4135
|
+
// `Array.prototype.reduceRight` method
|
|
4136
|
+
// https://tc39.es/ecma262/#sec-array.prototype.reduceright
|
|
4137
|
+
right: createMethod(!0)
|
|
4138
|
+
}, fails = fails$9, globalThis$1 = globalThis_1, userAgent = environmentUserAgent, classof = classofRaw$2, userAgentStartsWith = function(string) {
|
|
4139
|
+
return userAgent.slice(0, string.length) === string;
|
|
4140
|
+
}, 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;
|
|
4141
|
+
|
|
4142
|
+
// `Array.prototype.reduce` method
|
|
4143
|
+
// https://tc39.es/ecma262/#sec-array.prototype.reduce
|
|
4144
|
+
_export({
|
|
4145
|
+
target: "Array",
|
|
4146
|
+
proto: !0,
|
|
4147
|
+
forced: !("NODE" === environment) && environmentV8Version > 79 && environmentV8Version < 83 || !function(METHOD_NAME, argument) {
|
|
4148
|
+
var method = [][METHOD_NAME];
|
|
4149
|
+
return !!method && fails((function() {
|
|
4150
|
+
// eslint-disable-next-line no-useless-call -- required for testing
|
|
4151
|
+
method.call(null, argument || function() {
|
|
4152
|
+
return 1;
|
|
4153
|
+
}, 1);
|
|
4154
|
+
}));
|
|
4155
|
+
}("reduce")
|
|
4156
|
+
}, {
|
|
4157
|
+
reduce: function(callbackfn /* , initialValue */) {
|
|
4158
|
+
var length = arguments.length;
|
|
4159
|
+
return $reduce(this, callbackfn, length, length > 1 ? arguments[1] : void 0);
|
|
4160
|
+
}
|
|
4161
|
+
});
|
|
4162
|
+
|
|
4163
|
+
var reduce$3 = getBuiltInPrototypeMethod$3("Array", "reduce"), isPrototypeOf = objectIsPrototypeOf, method = reduce$3, ArrayPrototype = Array.prototype;
|
|
4164
|
+
|
|
4165
|
+
const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
4166
|
+
var own = it.reduce;
|
|
4167
|
+
return it === ArrayPrototype || isPrototypeOf(ArrayPrototype, it) && own === ArrayPrototype.reduce ? method : own;
|
|
4168
|
+
})), DEFAULT_PALETTE = {
|
|
4169
|
+
primary: {
|
|
4170
|
+
main: "#7c3aed",
|
|
4171
|
+
// Primary-6
|
|
4172
|
+
light: "#d0b2f5",
|
|
4173
|
+
// Primary-3
|
|
4174
|
+
dark: "#3c1583",
|
|
4175
|
+
// Primary-9
|
|
4176
|
+
contrastText: "#ffffff"
|
|
4177
|
+
},
|
|
4178
|
+
secondary: {
|
|
4179
|
+
main: "#f3f4f6",
|
|
4180
|
+
// Gray-2
|
|
4181
|
+
light: "#ffffff",
|
|
4182
|
+
// Gray-1
|
|
4183
|
+
dark: "#e5e7eb",
|
|
4184
|
+
// Gray-3
|
|
4185
|
+
contrastText: "#1f2937"
|
|
4186
|
+
},
|
|
4187
|
+
error: {
|
|
4188
|
+
main: "#ef4444",
|
|
4189
|
+
// Red-6
|
|
4190
|
+
light: "#fca5a5",
|
|
4191
|
+
// Red-4
|
|
4192
|
+
dark: "#991b1b",
|
|
4193
|
+
// Red-9
|
|
4194
|
+
contrastText: "#ffffff"
|
|
4195
|
+
},
|
|
4196
|
+
warning: {
|
|
4197
|
+
main: "#eab308",
|
|
4198
|
+
// Yellow-6
|
|
4199
|
+
light: "#fde047",
|
|
4200
|
+
// Yellow-4
|
|
4201
|
+
dark: "#854d0e",
|
|
4202
|
+
// Yellow-9
|
|
4203
|
+
contrastText: "#000000"
|
|
4204
|
+
},
|
|
4205
|
+
info: {
|
|
4206
|
+
main: "#3b82f6",
|
|
4207
|
+
// Blue-6
|
|
4208
|
+
light: "#93c5fd",
|
|
4209
|
+
// Blue-4
|
|
4210
|
+
dark: "#1e40af",
|
|
4211
|
+
// Blue-9
|
|
4212
|
+
contrastText: "#ffffff"
|
|
4213
|
+
},
|
|
4214
|
+
success: {
|
|
4215
|
+
main: "#22c55e",
|
|
4216
|
+
// Green-6
|
|
4217
|
+
light: "#86efac",
|
|
4218
|
+
// Green-4
|
|
4219
|
+
dark: "#166534",
|
|
4220
|
+
// Green-9
|
|
4221
|
+
contrastText: "#ffffff"
|
|
4222
|
+
},
|
|
4223
|
+
background: {
|
|
4224
|
+
default: "#ffffff",
|
|
4225
|
+
// Primary-bg
|
|
4226
|
+
paper: "#f3f4f6",
|
|
4227
|
+
// Secondary-bg
|
|
4228
|
+
subtle: "#d1d5db"
|
|
4229
|
+
},
|
|
4230
|
+
text: {
|
|
4231
|
+
primary: "#111827",
|
|
4232
|
+
// Gray-10
|
|
4233
|
+
secondary: "#374151",
|
|
4234
|
+
// Gray-8
|
|
4235
|
+
disabled: "#9ca3af"
|
|
4236
|
+
}
|
|
4237
|
+
}, DEFAULT_TYPOGRAPHY = {
|
|
4238
|
+
fontFamily: '"Roboto", "Helvetica Neue", "Helvetica", "Arial", sans-serif',
|
|
4239
|
+
fontSize: 16,
|
|
4240
|
+
// 1rem
|
|
4241
|
+
fontWeightLight: 300,
|
|
4242
|
+
fontWeightRegular: 400,
|
|
4243
|
+
fontWeightMedium: 500,
|
|
4244
|
+
fontWeightSemiBold: 600,
|
|
4245
|
+
fontWeightBold: 700,
|
|
4246
|
+
fontWeightHeavy: 800,
|
|
4247
|
+
fontWeightBlack: 900,
|
|
4248
|
+
h1: {
|
|
4249
|
+
fontSize: "2.5rem",
|
|
4250
|
+
// 40px
|
|
4251
|
+
fontWeight: 700,
|
|
4252
|
+
lineHeight: 1.3,
|
|
4253
|
+
letterSpacing: "-1px"
|
|
4254
|
+
},
|
|
4255
|
+
h2: {
|
|
4256
|
+
fontSize: "2rem",
|
|
4257
|
+
// 32px
|
|
4258
|
+
fontWeight: 700,
|
|
4259
|
+
lineHeight: 1.3,
|
|
4260
|
+
letterSpacing: "-1px"
|
|
4261
|
+
},
|
|
4262
|
+
h3: {
|
|
4263
|
+
fontSize: "1.5rem",
|
|
4264
|
+
// 24px
|
|
4265
|
+
fontWeight: 700,
|
|
4266
|
+
lineHeight: 1.3,
|
|
4267
|
+
letterSpacing: "-1px"
|
|
4268
|
+
},
|
|
4269
|
+
h4: {
|
|
4270
|
+
fontSize: "1.25rem",
|
|
4271
|
+
// 20px
|
|
4272
|
+
fontWeight: 700,
|
|
4273
|
+
lineHeight: 1.3,
|
|
4274
|
+
letterSpacing: "-0.5px"
|
|
4275
|
+
},
|
|
4276
|
+
h5: {
|
|
4277
|
+
fontSize: "1.125rem",
|
|
4278
|
+
// 18px
|
|
4279
|
+
fontWeight: 700,
|
|
4280
|
+
lineHeight: 1.3,
|
|
4281
|
+
letterSpacing: "-0.5px"
|
|
4282
|
+
},
|
|
4283
|
+
h6: {
|
|
4284
|
+
fontSize: "1rem",
|
|
4285
|
+
// 16px
|
|
4286
|
+
fontWeight: 700,
|
|
4287
|
+
lineHeight: 1.3,
|
|
4288
|
+
letterSpacing: "-0.5px"
|
|
4289
|
+
},
|
|
4290
|
+
body1: {
|
|
4291
|
+
fontSize: "1rem",
|
|
4292
|
+
// 16px
|
|
4293
|
+
fontWeight: 400,
|
|
4294
|
+
lineHeight: 1.2
|
|
4295
|
+
},
|
|
4296
|
+
body2: {
|
|
4297
|
+
fontSize: "0.875rem",
|
|
4298
|
+
// 14px
|
|
4299
|
+
fontWeight: 400,
|
|
4300
|
+
lineHeight: 1.2
|
|
4301
|
+
}
|
|
4302
|
+
}, DEFAULT_SHADOWS = {
|
|
4303
|
+
xs: "0px 1px 2px 0px rgba(45, 54, 67, 0.04), 0px 2px 4px 0px rgba(45, 54, 67, 0.08)",
|
|
4304
|
+
sm: "0 2px 4px rgba(0, 0, 0, 0.075)",
|
|
4305
|
+
md: "0 4px 8px rgba(0, 0, 0, 0.1)",
|
|
4306
|
+
lg: "0 16px 48px rgba(0, 0, 0, 0.175)",
|
|
4307
|
+
xl: "0px 16px 64px -8px rgba(45, 54, 67, 0.14)",
|
|
4308
|
+
inset: "inset 0 1px 2px rgba(0, 0, 0, 0.075)"
|
|
4309
|
+
}, DEFAULT_TRANSITIONS = {
|
|
4310
|
+
duration: {
|
|
4311
|
+
shortest: 150,
|
|
4312
|
+
shorter: 200,
|
|
4313
|
+
short: 250,
|
|
4314
|
+
standard: 300,
|
|
4315
|
+
complex: 375,
|
|
4316
|
+
enteringScreen: 225,
|
|
4317
|
+
leavingScreen: 195
|
|
4318
|
+
},
|
|
4319
|
+
easing: {
|
|
4320
|
+
easeInOut: "cubic-bezier(0.4, 0, 0.2, 1)",
|
|
4321
|
+
easeOut: "cubic-bezier(0.0, 0, 0.2, 1)",
|
|
4322
|
+
easeIn: "cubic-bezier(0.4, 0, 1, 1)",
|
|
4323
|
+
sharp: "cubic-bezier(0.4, 0, 0.6, 1)"
|
|
4324
|
+
}
|
|
4325
|
+
}, DEFAULT_ZINDEX = {
|
|
4326
|
+
mobileStepper: 1e3,
|
|
4327
|
+
speedDial: 1050,
|
|
4328
|
+
appBar: 1020,
|
|
4329
|
+
drawer: 1070,
|
|
4330
|
+
modal: 1040,
|
|
4331
|
+
snackbar: 1080,
|
|
4332
|
+
tooltip: 1060
|
|
4333
|
+
}, DEFAULT_BORDER_RADIUS = {
|
|
4334
|
+
base: "0.5rem",
|
|
4335
|
+
// 8px (spacing-2)
|
|
4336
|
+
sm: "0.25rem",
|
|
4337
|
+
// 4px (spacing-1)
|
|
4338
|
+
md: "0.25rem",
|
|
4339
|
+
// 4px (spacing-1)
|
|
4340
|
+
lg: "0.625rem",
|
|
4341
|
+
// 10px (spacing-2.5)
|
|
4342
|
+
xl: "0.75rem",
|
|
4343
|
+
// 12px (spacing-3)
|
|
4344
|
+
xxl: "1rem",
|
|
4345
|
+
// 16px (spacing-4)
|
|
4346
|
+
"3xl": "1.5rem",
|
|
4347
|
+
// 24px (spacing-6)
|
|
4348
|
+
"4xl": "2rem",
|
|
4349
|
+
// 32px (spacing-8)
|
|
4350
|
+
pill: "50rem"
|
|
4351
|
+
};
|
|
4352
|
+
|
|
4353
|
+
// ============================================================================
|
|
4354
|
+
// Default Theme Values
|
|
4355
|
+
// ============================================================================
|
|
4356
|
+
// ============================================================================
|
|
4357
|
+
// Helper Functions
|
|
4358
|
+
// ============================================================================
|
|
4359
|
+
/**
|
|
4360
|
+
* Create a complete palette color from partial configuration
|
|
4361
|
+
*/
|
|
4362
|
+
function createPaletteColor(color) {
|
|
4363
|
+
return "string" == typeof color ? {
|
|
4364
|
+
main: color,
|
|
4365
|
+
light: lighten(color),
|
|
4366
|
+
dark: darken(color),
|
|
4367
|
+
contrastText: getContrastText(color)
|
|
4368
|
+
} : {
|
|
4369
|
+
main: color.main || "#000000",
|
|
4370
|
+
light: color.light || lighten(color.main || "#000000"),
|
|
4371
|
+
dark: color.dark || darken(color.main || "#000000"),
|
|
4372
|
+
contrastText: color.contrastText || getContrastText(color.main || "#000000")
|
|
4373
|
+
};
|
|
4374
|
+
}
|
|
4375
|
+
|
|
4376
|
+
/**
|
|
4377
|
+
* Create breakpoints object
|
|
4378
|
+
*/
|
|
4379
|
+
// ============================================================================
|
|
4380
|
+
// Main createTheme Function
|
|
4381
|
+
// ============================================================================
|
|
4382
|
+
/**
|
|
4383
|
+
* Create a theme object with computed values
|
|
5142
4384
|
*
|
|
5143
|
-
*
|
|
4385
|
+
* @param options - Theme configuration options
|
|
4386
|
+
* @returns Complete theme object
|
|
5144
4387
|
*/
|
|
4388
|
+
function createThemeObject(...options) {
|
|
4389
|
+
// Merge all options
|
|
4390
|
+
const mergedOptions = _reduceInstanceProperty(options).call(options, ((acc, option) => deepMerge(acc, option)), {}), palette = {
|
|
4391
|
+
primary: createPaletteColor(mergedOptions.palette?.primary || DEFAULT_PALETTE.primary),
|
|
4392
|
+
secondary: createPaletteColor(mergedOptions.palette?.secondary || DEFAULT_PALETTE.secondary),
|
|
4393
|
+
error: createPaletteColor(mergedOptions.palette?.error || DEFAULT_PALETTE.error),
|
|
4394
|
+
warning: createPaletteColor(mergedOptions.palette?.warning || DEFAULT_PALETTE.warning),
|
|
4395
|
+
info: createPaletteColor(mergedOptions.palette?.info || DEFAULT_PALETTE.info),
|
|
4396
|
+
success: createPaletteColor(mergedOptions.palette?.success || DEFAULT_PALETTE.success),
|
|
4397
|
+
// Handle light and dark colors if provided
|
|
4398
|
+
...mergedOptions.palette?.light && {
|
|
4399
|
+
light: createPaletteColor(mergedOptions.palette.light)
|
|
4400
|
+
},
|
|
4401
|
+
...mergedOptions.palette?.dark && {
|
|
4402
|
+
dark: createPaletteColor(mergedOptions.palette.dark)
|
|
4403
|
+
},
|
|
4404
|
+
background: {
|
|
4405
|
+
default: mergedOptions.palette?.background?.default || DEFAULT_PALETTE.background.default,
|
|
4406
|
+
subtle: mergedOptions.palette?.background?.subtle || DEFAULT_PALETTE.background.subtle
|
|
4407
|
+
},
|
|
4408
|
+
text: {
|
|
4409
|
+
primary: mergedOptions.palette?.text?.primary || DEFAULT_PALETTE.text.primary,
|
|
4410
|
+
secondary: mergedOptions.palette?.text?.secondary || DEFAULT_PALETTE.text.secondary,
|
|
4411
|
+
disabled: mergedOptions.palette?.text?.disabled || DEFAULT_PALETTE.text.disabled
|
|
4412
|
+
}
|
|
4413
|
+
}, typography = deepMerge({
|
|
4414
|
+
...DEFAULT_TYPOGRAPHY
|
|
4415
|
+
}, mergedOptions.typography || {}), spacing = function(spacingInput = 4) {
|
|
4416
|
+
// If it's already a function, return it
|
|
4417
|
+
return "function" == typeof spacingInput ? spacingInput :
|
|
4418
|
+
// If it's a number, create a function that multiplies by that number
|
|
4419
|
+
"number" == typeof spacingInput ? (...values) => 0 === values.length ? "0px" : values.map((value => value * spacingInput + "px")).join(" ") :
|
|
4420
|
+
// If it's an array, use it as a scale
|
|
4421
|
+
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(" ");
|
|
4422
|
+
}(mergedOptions.spacing), breakpoints = function(breakpointsInput) {
|
|
4423
|
+
const values = {
|
|
4424
|
+
xs: 0,
|
|
4425
|
+
sm: 576,
|
|
4426
|
+
md: 768,
|
|
4427
|
+
lg: 992,
|
|
4428
|
+
xl: 1200,
|
|
4429
|
+
xxl: 1440,
|
|
4430
|
+
...breakpointsInput?.values
|
|
4431
|
+
}, unit = breakpointsInput?.unit || "px";
|
|
4432
|
+
return {
|
|
4433
|
+
values: values,
|
|
4434
|
+
unit: unit,
|
|
4435
|
+
up: key => `@media (min-width:${"number" == typeof key ? key : values[key] ?? 0}${unit})`,
|
|
4436
|
+
down: key => `@media (max-width:${("number" == typeof key ? key : values[key] ?? 0) - .05}${unit})`,
|
|
4437
|
+
between: (start, end) => {
|
|
4438
|
+
const startValue = "number" == typeof start ? start : values[start] ?? 0, endValue = "number" == typeof end ? end : values[end] ?? 0;
|
|
4439
|
+
return `@media (min-width:${startValue}${unit}) and (max-width:${endValue - .05}${unit})`;
|
|
4440
|
+
}
|
|
4441
|
+
};
|
|
4442
|
+
}(mergedOptions.breakpoints), shadows = deepMerge({
|
|
4443
|
+
...DEFAULT_SHADOWS
|
|
4444
|
+
}, mergedOptions.shadows || {}), transitions = deepMerge({
|
|
4445
|
+
...DEFAULT_TRANSITIONS
|
|
4446
|
+
}, mergedOptions.transitions || {}), zIndex = deepMerge({
|
|
4447
|
+
...DEFAULT_ZINDEX
|
|
4448
|
+
}, mergedOptions.zIndex || {}), borderRadius = deepMerge({
|
|
4449
|
+
...DEFAULT_BORDER_RADIUS
|
|
4450
|
+
}, mergedOptions.borderRadius || {});
|
|
4451
|
+
// Create palette
|
|
4452
|
+
return {
|
|
4453
|
+
// Metadata
|
|
4454
|
+
name: mergedOptions.name || "Custom Theme",
|
|
4455
|
+
class: mergedOptions.class,
|
|
4456
|
+
description: mergedOptions.description,
|
|
4457
|
+
author: mergedOptions.author,
|
|
4458
|
+
version: mergedOptions.version || "1.0.0",
|
|
4459
|
+
tags: mergedOptions.tags,
|
|
4460
|
+
supportsDarkMode: mergedOptions.supportsDarkMode,
|
|
4461
|
+
status: mergedOptions.status || "experimental",
|
|
4462
|
+
a11y: mergedOptions.a11y,
|
|
4463
|
+
color: mergedOptions.color || palette.primary.main,
|
|
4464
|
+
features: mergedOptions.features,
|
|
4465
|
+
dependencies: mergedOptions.dependencies,
|
|
4466
|
+
// Theme configuration
|
|
4467
|
+
palette: palette,
|
|
4468
|
+
typography: typography,
|
|
4469
|
+
spacing: spacing,
|
|
4470
|
+
breakpoints: breakpoints,
|
|
4471
|
+
shadows: shadows,
|
|
4472
|
+
transitions: transitions,
|
|
4473
|
+
zIndex: zIndex,
|
|
4474
|
+
borderRadius: borderRadius,
|
|
4475
|
+
custom: mergedOptions.custom || {},
|
|
4476
|
+
// Mark as JS theme
|
|
4477
|
+
__isJSTheme: !0
|
|
4478
|
+
};
|
|
4479
|
+
}
|
|
4480
|
+
|
|
5145
4481
|
/**
|
|
5146
4482
|
* useHistory Hook
|
|
5147
4483
|
*
|
|
@@ -5159,8 +4495,7 @@ class ThemeValidator {
|
|
|
5159
4495
|
* maxHistorySize: 50
|
|
5160
4496
|
* });
|
|
5161
4497
|
* ```
|
|
5162
|
-
*/
|
|
5163
|
-
function useHistory(options = {}) {
|
|
4498
|
+
*/ function useHistory(options = {}) {
|
|
5164
4499
|
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((() => {
|
|
5165
4500
|
setCanUndo(currentIndexRef.current > 0), setCanRedo(currentIndexRef.current < historyRef.current.length - 1);
|
|
5166
4501
|
}), []), setState = useCallback((newState => {
|
|
@@ -5602,59 +4937,20 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
|
|
|
5602
4937
|
};
|
|
5603
4938
|
|
|
5604
4939
|
/**
|
|
5605
|
-
*
|
|
4940
|
+
* Theme Adapter
|
|
5606
4941
|
*
|
|
5607
|
-
*
|
|
5608
|
-
* and component configurations.
|
|
4942
|
+
* Converts between Theme objects and DesignTokens.
|
|
5609
4943
|
*/
|
|
5610
4944
|
/**
|
|
5611
|
-
*
|
|
5612
|
-
*
|
|
5613
|
-
* @example
|
|
5614
|
-
* generateCSSVariableName('button', 'bg', { prefix: 'atomix' })
|
|
5615
|
-
* // Returns: '--atomix-button-bg'
|
|
5616
|
-
*/ function generateCSSVariableName(component, property, options = {}) {
|
|
5617
|
-
const {prefix: prefix = "atomix", separator: separator = "-", includeComponent: includeComponent = !0} = options, parts = [ prefix ];
|
|
5618
|
-
return includeComponent && parts.push(component), parts.push(property), `--${parts.join(separator)}`;
|
|
5619
|
-
}
|
|
5620
|
-
|
|
5621
|
-
/**
|
|
5622
|
-
* Generate CSS variables object from configuration
|
|
4945
|
+
* Convert DesignTokens to Theme-compatible CSS variables
|
|
5623
4946
|
*
|
|
5624
|
-
* @
|
|
5625
|
-
*
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
const vars = {}, {component: component, properties: properties, parts: parts, states: states, variants: variants} = config;
|
|
5632
|
-
// Base properties
|
|
5633
|
-
return Object.entries(properties).forEach((([key, value]) => {
|
|
5634
|
-
const varName = generateCSSVariableName(component, key, options);
|
|
5635
|
-
vars[varName] = String(value);
|
|
5636
|
-
})),
|
|
5637
|
-
// Part properties
|
|
5638
|
-
parts && Object.entries(parts).forEach((([partName, partProps]) => {
|
|
5639
|
-
Object.entries(partProps).forEach((([key, value]) => {
|
|
5640
|
-
const varName = generateCSSVariableName(component, `${partName}-${key}`, options);
|
|
5641
|
-
vars[varName] = String(value);
|
|
5642
|
-
}));
|
|
5643
|
-
})),
|
|
5644
|
-
// State properties
|
|
5645
|
-
states && Object.entries(states).forEach((([stateName, stateProps]) => {
|
|
5646
|
-
Object.entries(stateProps).forEach((([key, value]) => {
|
|
5647
|
-
const varName = generateCSSVariableName(component, `${stateName}-${key}`, options);
|
|
5648
|
-
vars[varName] = String(value);
|
|
5649
|
-
}));
|
|
5650
|
-
})),
|
|
5651
|
-
// Variant properties
|
|
5652
|
-
variants && Object.entries(variants).forEach((([variantName, variantProps]) => {
|
|
5653
|
-
Object.entries(variantProps).forEach((([key, value]) => {
|
|
5654
|
-
const varName = generateCSSVariableName(component, `${variantName}-${key}`, options);
|
|
5655
|
-
vars[varName] = String(value);
|
|
5656
|
-
}));
|
|
5657
|
-
})), vars;
|
|
4947
|
+
* @param tokens - DesignTokens object
|
|
4948
|
+
* @returns CSS variables object compatible with Theme.cssVars
|
|
4949
|
+
*/ function designTokensToCSSVars(tokens) {
|
|
4950
|
+
const cssVars = {};
|
|
4951
|
+
return Object.entries(tokens).forEach((([key, value]) => {
|
|
4952
|
+
void 0 !== value && (cssVars[`--atomix-${key}`] = String(value));
|
|
4953
|
+
})), cssVars;
|
|
5658
4954
|
}
|
|
5659
4955
|
|
|
5660
4956
|
/**
|
|
@@ -5677,11 +4973,14 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
|
|
|
5677
4973
|
/**
|
|
5678
4974
|
* Apply CSS variables to an element
|
|
5679
4975
|
*
|
|
5680
|
-
* @param element - Target element (defaults to document.documentElement)
|
|
5681
4976
|
* @param vars - CSS variables to apply
|
|
5682
|
-
|
|
4977
|
+
* @param element - Target element (defaults to document.documentElement)
|
|
4978
|
+
*/ function applyCSSVariables(vars, element) {
|
|
4979
|
+
if ("undefined" == typeof window) return;
|
|
4980
|
+
// SSR safety
|
|
4981
|
+
const target = element || document.documentElement;
|
|
5683
4982
|
Object.entries(vars).forEach((([key, value]) => {
|
|
5684
|
-
|
|
4983
|
+
target.style.setProperty(key, String(value));
|
|
5685
4984
|
}));
|
|
5686
4985
|
}
|
|
5687
4986
|
|
|
@@ -5690,9 +4989,12 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
|
|
|
5690
4989
|
*
|
|
5691
4990
|
* @param varNames - Variable names to remove
|
|
5692
4991
|
* @param element - Target element (defaults to document.documentElement)
|
|
5693
|
-
*/ function removeCSSVariables(varNames, element
|
|
4992
|
+
*/ function removeCSSVariables(varNames, element) {
|
|
4993
|
+
if ("undefined" == typeof window) return;
|
|
4994
|
+
// SSR safety
|
|
4995
|
+
const target = element || document.documentElement;
|
|
5694
4996
|
varNames.forEach((varName => {
|
|
5695
|
-
|
|
4997
|
+
target.style.removeProperty(varName);
|
|
5696
4998
|
}));
|
|
5697
4999
|
}
|
|
5698
5000
|
|
|
@@ -5702,8 +5004,11 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
|
|
|
5702
5004
|
* @param varName - Variable name to get
|
|
5703
5005
|
* @param element - Target element (defaults to document.documentElement)
|
|
5704
5006
|
* @returns Variable value or null if not found
|
|
5705
|
-
*/ function getCSSVariable(varName, element
|
|
5706
|
-
|
|
5007
|
+
*/ function getCSSVariable(varName, element) {
|
|
5008
|
+
if ("undefined" == typeof window) return null;
|
|
5009
|
+
// SSR safety
|
|
5010
|
+
const target = element || document.documentElement;
|
|
5011
|
+
return getComputedStyle(target).getPropertyValue(varName).trim() || null;
|
|
5707
5012
|
}
|
|
5708
5013
|
|
|
5709
5014
|
/**
|
|
@@ -5747,28 +5052,8 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
|
|
|
5747
5052
|
/**
|
|
5748
5053
|
* Theme Helper Functions
|
|
5749
5054
|
*
|
|
5750
|
-
* Utility functions for working with
|
|
5055
|
+
* Utility functions for working with DesignTokens
|
|
5751
5056
|
*/
|
|
5752
|
-
/**
|
|
5753
|
-
* Get DesignTokens from current theme
|
|
5754
|
-
*
|
|
5755
|
-
* Converts a Theme object to DesignTokens. Useful when you need to
|
|
5756
|
-
* work with DesignTokens but have a Theme object.
|
|
5757
|
-
*
|
|
5758
|
-
* @param theme - Theme object to convert
|
|
5759
|
-
* @returns DesignTokens object
|
|
5760
|
-
*
|
|
5761
|
-
* @example
|
|
5762
|
-
* ```typescript
|
|
5763
|
-
* // If you have a Theme object, convert it to DesignTokens
|
|
5764
|
-
* const tokens = getDesignTokensFromTheme(theme);
|
|
5765
|
-
* // Now you can use tokens with unified theme system
|
|
5766
|
-
* const css = createTheme(tokens);
|
|
5767
|
-
* ```
|
|
5768
|
-
*/ function getDesignTokensFromTheme(theme) {
|
|
5769
|
-
return theme ? createDesignTokensFromTheme(theme) : null;
|
|
5770
|
-
}
|
|
5771
|
-
|
|
5772
5057
|
/**
|
|
5773
5058
|
* Check if a value is DesignTokens
|
|
5774
5059
|
*
|
|
@@ -5788,17 +5073,6 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
|
|
|
5788
5073
|
// Check if keys look like DesignTokens (kebab-case, no nesting)
|
|
5789
5074
|
}
|
|
5790
5075
|
|
|
5791
|
-
/**
|
|
5792
|
-
* Check if a value is a Theme object
|
|
5793
|
-
*
|
|
5794
|
-
* Type guard to check if an object is a Theme.
|
|
5795
|
-
*
|
|
5796
|
-
* @param value - Value to check
|
|
5797
|
-
* @returns True if value is Theme
|
|
5798
|
-
*/ function isThemeObject(value) {
|
|
5799
|
-
return !(!value || "object" != typeof value) && ("__isJSTheme" in value || "palette" in value && "typography" in value);
|
|
5800
|
-
}
|
|
5801
|
-
|
|
5802
5076
|
/**
|
|
5803
5077
|
* RTL (Right-to-Left) Support Utilities
|
|
5804
5078
|
*
|
|
@@ -5987,13 +5261,13 @@ class RTLManager {
|
|
|
5987
5261
|
/**
|
|
5988
5262
|
* Theme System Exports
|
|
5989
5263
|
*
|
|
5990
|
-
*
|
|
5264
|
+
* Simplified theme system using DesignTokens only.
|
|
5991
5265
|
*
|
|
5992
5266
|
* @example
|
|
5993
5267
|
* ```typescript
|
|
5994
5268
|
* import { createTheme, injectTheme } from '@shohojdhara/atomix/theme';
|
|
5995
5269
|
*
|
|
5996
|
-
* // Using DesignTokens
|
|
5270
|
+
* // Using DesignTokens
|
|
5997
5271
|
* const css = createTheme({ 'primary': '#7AFFD7', 'spacing-4': '1rem' });
|
|
5998
5272
|
* injectTheme(css);
|
|
5999
5273
|
*
|
|
@@ -6006,7 +5280,7 @@ class RTLManager {
|
|
|
6006
5280
|
// ============================================================================
|
|
6007
5281
|
// Core Theme Functions
|
|
6008
5282
|
// ============================================================================
|
|
6009
|
-
//
|
|
5283
|
+
// Create theme CSS from DesignTokens
|
|
6010
5284
|
/**
|
|
6011
5285
|
* Inject theme CSS into DOM
|
|
6012
5286
|
*/ function injectTheme(css, id = "atomix-theme") {
|
|
@@ -6022,63 +5296,18 @@ class RTLManager {
|
|
|
6022
5296
|
/**
|
|
6023
5297
|
* Save theme to CSS file
|
|
6024
5298
|
*/ async function saveTheme(css, filePath) {
|
|
6025
|
-
await
|
|
5299
|
+
await async function(css, filePath) {
|
|
5300
|
+
// Check if in browser environment
|
|
5301
|
+
if ("undefined" != typeof window) throw new Error("saveCSSFile can only be used in Node.js environment. Use injectCSS() for browser environments.");
|
|
5302
|
+
// Dynamic import to avoid bundling Node.js modules in browser builds
|
|
5303
|
+
const fs = await import("fs/promises"), dir = (await import("path")).dirname(filePath);
|
|
5304
|
+
await fs.mkdir(dir, {
|
|
5305
|
+
recursive: !0
|
|
5306
|
+
}),
|
|
5307
|
+
// Write file
|
|
5308
|
+
await fs.writeFile(filePath, css, "utf8");
|
|
5309
|
+
}(css, filePath);
|
|
6026
5310
|
}
|
|
6027
5311
|
|
|
6028
|
-
|
|
6029
|
-
* Atomix Config Loader
|
|
6030
|
-
*
|
|
6031
|
-
* Helper functions to load atomix.config.ts from external projects.
|
|
6032
|
-
* Similar to how Tailwind loads tailwind.config.js
|
|
6033
|
-
*/
|
|
6034
|
-
/**
|
|
6035
|
-
* Load Atomix configuration from project root
|
|
6036
|
-
*
|
|
6037
|
-
* Attempts to load atomix.config.ts from the current working directory.
|
|
6038
|
-
* Falls back to default config if file doesn't exist.
|
|
6039
|
-
*
|
|
6040
|
-
* @param options - Loader options
|
|
6041
|
-
* @returns Loaded configuration or default
|
|
6042
|
-
*
|
|
6043
|
-
* @example
|
|
6044
|
-
* ```typescript
|
|
6045
|
-
* import { loadAtomixConfig } from '@shohojdhara/atomix/config';
|
|
6046
|
-
* import { createTheme } from '@shohojdhara/atomix/theme';
|
|
6047
|
-
*
|
|
6048
|
-
* const config = loadAtomixConfig();
|
|
6049
|
-
* const theme = createTheme(config.theme?.tokens || {});
|
|
6050
|
-
* ```
|
|
6051
|
-
*/ const loader = Object.freeze( Object.defineProperty({
|
|
6052
|
-
__proto__: null,
|
|
6053
|
-
loadAtomixConfig: function(options = {}) {
|
|
6054
|
-
const {configPath: configPath = "atomix.config.ts", required: required = !1} = options, defaultConfig = {
|
|
6055
|
-
prefix: "atomix",
|
|
6056
|
-
theme: {
|
|
6057
|
-
extend: {}
|
|
6058
|
-
}
|
|
6059
|
-
};
|
|
6060
|
-
// Default config
|
|
6061
|
-
// In browser environments, config loading is not supported
|
|
6062
|
-
if ("undefined" != typeof window) {
|
|
6063
|
-
if (required) throw new Error("Config loading not supported in browser environment");
|
|
6064
|
-
return defaultConfig;
|
|
6065
|
-
}
|
|
6066
|
-
// Try to load config file
|
|
6067
|
-
try {
|
|
6068
|
-
// Use dynamic import for ESM compatibility
|
|
6069
|
-
const configModule = require(configPath), config = configModule.default || configModule;
|
|
6070
|
-
// Validate it's an AtomixConfig
|
|
6071
|
-
if (config && "object" == typeof config) return config;
|
|
6072
|
-
throw new Error("Invalid config format");
|
|
6073
|
-
} catch (error) {
|
|
6074
|
-
if (required) throw new Error(`Failed to load config from ${configPath}: ${error.message}`);
|
|
6075
|
-
// Return default config if not required
|
|
6076
|
-
return defaultConfig;
|
|
6077
|
-
}
|
|
6078
|
-
}
|
|
6079
|
-
}, Symbol.toStringTag, {
|
|
6080
|
-
value: "Module"
|
|
6081
|
-
}));
|
|
6082
|
-
|
|
6083
|
-
export { RTLManager, ThemeApplicator, ThemeComparator, ThemeContext, ThemeErrorBoundary, ThemeInspector, ThemeLiveEditor, ThemePreview, ThemeProvider, ThemeRegistry, ThemeValidator, applyCSSVariables, applyTheme, createDesignTokensFromTheme, createTheme, createThemeObject, createTokens, cssVarsToStyle, deepMerge, defaultTokens, designTokensToCSSVars, designTokensToTheme, extendTheme, extractComponentName, generateCSSVariableName, generateCSSVariables$1 as generateCSSVariables, generateCSSVariablesForSelector, generateComponentCSSVars, getCSSVariable, getDesignTokensFromTheme, getThemeApplicator, injectCSS$1 as injectCSS, injectTheme, isCSSInjected, isDesignTokens, isThemeObject, isValidCSSVariableName, loadThemeFromConfig, loadThemeFromConfigSync, mapSCSSTokensToCSSVars, mergeCSSVars, mergeTheme, removeCSS, removeCSSVariables, removeTheme, saveCSSFile, saveCSSFileSync, saveTheme, themeToDesignTokens, useHistory, useTheme };
|
|
5312
|
+
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 };
|
|
6084
5313
|
//# sourceMappingURL=theme.js.map
|