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