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