@shohojdhara/atomix 0.5.1 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/atomix.config.ts +45 -33
- package/build-tools/webpack-loader.js +5 -4
- package/dist/atomix.css +138 -17
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/build-tools/webpack-loader.js +5 -4
- package/dist/charts.d.ts +23 -23
- package/dist/charts.js +40 -37
- package/dist/charts.js.map +1 -1
- package/dist/config.d.ts +699 -0
- package/dist/config.js +17 -0
- package/dist/config.js.map +1 -0
- package/dist/core.d.ts +2 -2
- package/dist/core.js +111 -50
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +3 -6
- package/dist/forms.js +2 -2
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +1 -1
- package/dist/heavy.js +173 -111
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +1881 -790
- package/dist/index.esm.js +2713 -816
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +2693 -780
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/layout.js +59 -60
- package/dist/layout.js.map +1 -1
- package/dist/theme.d.ts +1390 -276
- package/dist/theme.js +2133 -625
- package/dist/theme.js.map +1 -1
- package/package.json +14 -9
- package/scripts/atomix-cli.js +15 -1
- package/scripts/cli/__tests__/complexity-utils.test.js +24 -0
- package/scripts/cli/__tests__/detector.test.js +50 -0
- package/scripts/cli/__tests__/template-engine.test.js +23 -0
- package/scripts/cli/__tests__/test-setup.js +3 -0
- package/scripts/cli/commands/doctor.js +15 -3
- package/scripts/cli/commands/generate.js +113 -51
- package/scripts/cli/internal/ai-engine.js +30 -10
- package/scripts/cli/internal/complexity-utils.js +60 -0
- package/scripts/cli/internal/component-validator.js +49 -16
- package/scripts/cli/internal/config-loader.js +30 -20
- package/scripts/cli/internal/generator.js +89 -36
- package/scripts/cli/internal/hook-generator.js +5 -2
- package/scripts/cli/internal/itcss-generator.js +16 -12
- package/scripts/cli/templates/next-templates.js +81 -30
- package/scripts/cli/templates/storybook-templates.js +12 -2
- package/scripts/cli/utils/detector.js +45 -7
- package/scripts/cli/utils/diagnostics.js +78 -0
- package/scripts/cli/utils/telemetry.js +13 -0
- package/src/components/Accordion/Accordion.stories.tsx +4 -0
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +1 -1
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +219 -0
- package/src/components/AtomixGlass/glass-utils.ts +1 -1
- package/src/components/Button/Button.tsx +114 -57
- package/src/components/Callout/Callout.tsx +4 -4
- package/src/components/Chart/ChartRenderer.tsx +1 -1
- package/src/components/Chart/DonutChart.tsx +11 -8
- package/src/components/EdgePanel/EdgePanel.tsx +119 -115
- package/src/components/Form/Select.tsx +4 -4
- package/src/components/List/List.tsx +4 -4
- package/src/components/Navigation/SideMenu/SideMenu.tsx +6 -6
- package/src/components/PhotoViewer/PhotoViewerImage.tsx +1 -1
- package/src/components/ProductReview/ProductReview.tsx +4 -2
- package/src/components/Rating/Rating.tsx +4 -2
- package/src/components/SectionIntro/SectionIntro.tsx +4 -2
- package/src/components/Steps/Steps.tsx +1 -1
- package/src/components/Tabs/Tabs.tsx +5 -5
- package/src/components/Testimonial/Testimonial.tsx +4 -2
- package/src/components/VideoPlayer/VideoPlayer.tsx +4 -2
- package/src/layouts/CssGrid/CssGrid.stories.tsx +464 -0
- package/src/layouts/CssGrid/CssGrid.tsx +215 -0
- package/src/layouts/CssGrid/index.ts +8 -0
- package/src/layouts/CssGrid/scripts/CssGrid.js +284 -0
- package/src/layouts/CssGrid/scripts/index.js +43 -0
- package/src/layouts/Grid/scripts/Container.js +139 -0
- package/src/layouts/Grid/scripts/Grid.js +184 -0
- package/src/layouts/Grid/scripts/GridCol.js +273 -0
- package/src/layouts/Grid/scripts/Row.js +154 -0
- package/src/layouts/Grid/scripts/index.js +48 -0
- package/src/layouts/MasonryGrid/MasonryGrid.tsx +71 -59
- package/src/lib/composables/atomix-glass/useGlassSize.ts +1 -1
- package/src/lib/composables/useAccordion.ts +5 -5
- package/src/lib/composables/useAtomixGlass.ts +3 -3
- package/src/lib/composables/useBarChart.ts +2 -2
- package/src/lib/composables/useChart.ts +3 -2
- package/src/lib/composables/useChartToolbar.ts +48 -66
- package/src/lib/composables/useDataTable.ts +1 -1
- package/src/lib/composables/useDatePicker.ts +2 -2
- package/src/lib/composables/useEdgePanel.ts +45 -54
- package/src/lib/composables/useHeroBackgroundSlider.ts +5 -5
- package/src/lib/composables/usePhotoViewer.ts +2 -3
- package/src/lib/composables/usePieChart.ts +1 -1
- package/src/lib/composables/usePopover.ts +151 -139
- package/src/lib/composables/useSideMenu.ts +28 -41
- package/src/lib/composables/useSlider.ts +2 -6
- package/src/lib/composables/useTooltip.ts +2 -2
- package/src/lib/config/index.ts +38 -323
- package/src/lib/config/loader.ts +419 -0
- package/src/lib/config/public-api.ts +43 -0
- package/src/lib/config/types.ts +389 -0
- package/src/lib/config/validator.ts +305 -0
- package/src/lib/theme/adapters/index.ts +1 -1
- package/src/lib/theme/adapters/themeAdapter.ts +358 -229
- package/src/lib/theme/components/ThemeToggle.tsx +276 -0
- package/src/lib/theme/config/configLoader.ts +351 -0
- package/src/lib/theme/config/loader.ts +221 -0
- package/src/lib/theme/core/createTheme.ts +126 -50
- package/src/lib/theme/core/createThemeObject.ts +7 -4
- package/src/lib/theme/devtools/Comparator.tsx +1 -1
- package/src/lib/theme/devtools/Inspector.tsx +1 -1
- package/src/lib/theme/devtools/LiveEditor.tsx +1 -1
- package/src/lib/theme/hooks/useThemeSwitcher.ts +164 -0
- package/src/lib/theme/index.ts +322 -38
- package/src/lib/theme/runtime/ThemeProvider.tsx +45 -11
- 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/_index.scss +1 -0
- package/src/styles/01-settings/_settings.atomix-glass.scss +174 -0
- package/src/styles/01-settings/_settings.masonry-grid.scss +42 -6
- package/src/styles/02-tools/_tools.glass.scss +6 -0
- package/src/styles/05-objects/_objects.masonry-grid.scss +162 -24
- package/src/styles/06-components/_components.atomix-glass.scss +4 -4
- package/src/lib/composables/useBreadcrumb.ts +0 -81
- package/src/lib/composables/useChartInteractions.ts +0 -123
- package/src/lib/composables/useChartPerformance.ts +0 -347
- package/src/lib/composables/useDropdown.ts +0 -338
- package/src/lib/composables/useModal.ts +0 -110
- package/src/lib/hooks/usePerformanceMonitor.ts +0 -148
- package/src/lib/utils/displacement-generator.ts +0 -92
- package/src/lib/utils/memoryMonitor.ts +0 -191
- package/src/styles/01-settings/_settings.testtypecheck.scss +0 -53
- package/src/styles/01-settings/_settings.typedbutton.scss +0 -53
- package/src/styles/06-components/_components.testbutton.scss +0 -212
- package/src/styles/06-components/_components.testtypecheck.scss +0 -212
- package/src/styles/06-components/_components.typedbutton.scss +0 -212
package/dist/index.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
|
|
3
|
-
import React, { useState, useRef, useEffect, memo, forwardRef, useId, useMemo,
|
|
3
|
+
import React, { useState, useRef, useCallback, useEffect, memo, forwardRef, useId, useMemo, Children, isValidElement, cloneElement, createContext, useContext, useImperativeHandle, Component } from "react";
|
|
4
4
|
|
|
5
5
|
import * as PhosphorIcons from "@phosphor-icons/react";
|
|
6
6
|
|
|
@@ -8,6 +8,10 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
|
|
|
8
8
|
|
|
9
9
|
import { createPortal } from "react-dom";
|
|
10
10
|
|
|
11
|
+
import { existsSync } from "fs";
|
|
12
|
+
|
|
13
|
+
import { join } from "path";
|
|
14
|
+
|
|
11
15
|
var commonjsGlobal = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {};
|
|
12
16
|
|
|
13
17
|
function getDefaultExportFromCjs(x) {
|
|
@@ -1965,19 +1969,19 @@ function useAccordion(initialProps) {
|
|
|
1965
1969
|
disabled: !1,
|
|
1966
1970
|
iconPosition: "right",
|
|
1967
1971
|
...initialProps
|
|
1968
|
-
}, isControlled = "boolean" == typeof defaultProps.isOpen, [internalOpen, setInternalOpen] = useState(defaultProps.defaultOpen || !1), isOpen = isControlled ? defaultProps.isOpen : internalOpen, [panelHeight, setPanelHeight] = useState(isOpen ? "auto" : "0px"), panelRef = useRef(null), contentRef = useRef(null), updatePanelHeight = () => {
|
|
1972
|
+
}, isControlled = "boolean" == typeof defaultProps.isOpen, [internalOpen, setInternalOpen] = useState(defaultProps.defaultOpen || !1), isOpen = isControlled ? defaultProps.isOpen : internalOpen, [panelHeight, setPanelHeight] = useState(isOpen ? "auto" : "0px"), panelRef = useRef(null), contentRef = useRef(null), updatePanelHeight = useCallback((() => {
|
|
1969
1973
|
if (contentRef.current && panelRef.current) {
|
|
1970
1974
|
const height = isOpen ? `${contentRef.current.clientHeight}px` : "0px";
|
|
1971
1975
|
panelRef.current.style.setProperty(ACCORDION.CSS_VARS.PANEL_HEIGHT, height), setPanelHeight(height);
|
|
1972
1976
|
}
|
|
1973
|
-
};
|
|
1977
|
+
}), [ isOpen ]);
|
|
1974
1978
|
// Controlled/uncontrolled open state
|
|
1975
1979
|
/**
|
|
1976
1980
|
* Effect to update panel height when open state changes
|
|
1977
1981
|
*/
|
|
1978
1982
|
return useEffect((() => {
|
|
1979
1983
|
updatePanelHeight();
|
|
1980
|
-
}), [ isOpen ]),
|
|
1984
|
+
}), [ isOpen, updatePanelHeight ]),
|
|
1981
1985
|
/**
|
|
1982
1986
|
* Effect to handle window resize and update panel height
|
|
1983
1987
|
*/
|
|
@@ -1986,7 +1990,7 @@ function useAccordion(initialProps) {
|
|
|
1986
1990
|
isOpen && updatePanelHeight();
|
|
1987
1991
|
};
|
|
1988
1992
|
return window.addEventListener("resize", handleResize), () => window.removeEventListener("resize", handleResize);
|
|
1989
|
-
}), [ isOpen ]), {
|
|
1993
|
+
}), [ isOpen, updatePanelHeight ]), {
|
|
1990
1994
|
state: {
|
|
1991
1995
|
isOpen: isOpen,
|
|
1992
1996
|
panelHeight: panelHeight
|
|
@@ -3562,7 +3566,7 @@ function useResponsiveGlass({baseParams: baseParams, breakpoints: breakpoints =
|
|
|
3562
3566
|
* @param config Monitor configuration
|
|
3563
3567
|
* @returns Performance metrics and controls
|
|
3564
3568
|
*/
|
|
3565
|
-
function usePerformanceMonitor(config = {}) {
|
|
3569
|
+
function usePerformanceMonitor$1(config = {}) {
|
|
3566
3570
|
const {enabled: enabled = !0, targetFps: targetFps = 60, minFps: minFps = 45, scaleUpThreshold: scaleUpThreshold = 58, lowFpsFrames: lowFpsFrames = 3, highFpsFrames: highFpsFrames = 10, debug: debug = !1, showOverlay: showOverlay = !1} = config, [metrics, setMetrics] = useState({
|
|
3567
3571
|
fps: 0,
|
|
3568
3572
|
frameTime: 0,
|
|
@@ -4118,7 +4122,7 @@ function getDevicePreset(presetName) {
|
|
|
4118
4122
|
debug: !1
|
|
4119
4123
|
});
|
|
4120
4124
|
// Performance monitoring - tracks FPS, frame time, memory usage
|
|
4121
|
-
const {metrics: performanceMetrics, toggleMonitoring: toggleMonitoring} = usePerformanceMonitor({
|
|
4125
|
+
const {metrics: performanceMetrics, toggleMonitoring: toggleMonitoring} = usePerformanceMonitor$1({
|
|
4122
4126
|
enabled: debugPerformance,
|
|
4123
4127
|
// Enable when debugPerformance is true
|
|
4124
4128
|
debug: !1,
|
|
@@ -5111,7 +5115,7 @@ const BreadcrumbItem = forwardRef((({children: children, href: href, active: ac
|
|
|
5111
5115
|
|
|
5112
5116
|
BreadcrumbItem.displayName = "BreadcrumbItem";
|
|
5113
5117
|
|
|
5114
|
-
const
|
|
5118
|
+
const BreadcrumbComponent = memo((function({items: items, divider: divider, className: className = "", "aria-label": ariaLabel = "Breadcrumb", linkComponent: linkComponent, style: style, children: children}) {
|
|
5115
5119
|
const breadcrumbClasses = [ BREADCRUMB.CLASSES.BASE, className ].filter(Boolean).join(" ");
|
|
5116
5120
|
let content;
|
|
5117
5121
|
if (items && items.length > 0)
|
|
@@ -5151,7 +5155,7 @@ const Breadcrumb = memo((function({items: items, divider: divider, className: c
|
|
|
5151
5155
|
children: content
|
|
5152
5156
|
})
|
|
5153
5157
|
});
|
|
5154
|
-
}));
|
|
5158
|
+
})), Breadcrumb = BreadcrumbComponent;
|
|
5155
5159
|
|
|
5156
5160
|
/**
|
|
5157
5161
|
* Spinner state and functionality
|
|
@@ -5311,7 +5315,152 @@ class ThemeNaming {
|
|
|
5311
5315
|
|
|
5312
5316
|
ThemeNaming.prefix = "atomix";
|
|
5313
5317
|
|
|
5314
|
-
|
|
5318
|
+
var aCallable = aCallable$3, toObject = toObject$2, IndexedObject = indexedObject, lengthOfArrayLike = lengthOfArrayLike$2, $TypeError = TypeError, REDUCE_EMPTY = "Reduce of empty array with no initial value", createMethod = function(IS_RIGHT) {
|
|
5319
|
+
return function(that, callbackfn, argumentsLength, memo) {
|
|
5320
|
+
var O = toObject(that), self = IndexedObject(O), length = lengthOfArrayLike(O);
|
|
5321
|
+
if (aCallable(callbackfn), 0 === length && argumentsLength < 2) throw new $TypeError(REDUCE_EMPTY);
|
|
5322
|
+
var index = IS_RIGHT ? length - 1 : 0, i = IS_RIGHT ? -1 : 1;
|
|
5323
|
+
if (argumentsLength < 2) for (;;) {
|
|
5324
|
+
if (index in self) {
|
|
5325
|
+
memo = self[index], index += i;
|
|
5326
|
+
break;
|
|
5327
|
+
}
|
|
5328
|
+
if (index += i, IS_RIGHT ? index < 0 : length <= index) throw new $TypeError(REDUCE_EMPTY);
|
|
5329
|
+
}
|
|
5330
|
+
for (;IS_RIGHT ? index >= 0 : length > index; index += i) index in self && (memo = callbackfn(memo, self[index], index, O));
|
|
5331
|
+
return memo;
|
|
5332
|
+
};
|
|
5333
|
+
}, arrayReduce = {
|
|
5334
|
+
// `Array.prototype.reduce` method
|
|
5335
|
+
// https://tc39.es/ecma262/#sec-array.prototype.reduce
|
|
5336
|
+
left: createMethod(!1),
|
|
5337
|
+
// `Array.prototype.reduceRight` method
|
|
5338
|
+
// https://tc39.es/ecma262/#sec-array.prototype.reduceright
|
|
5339
|
+
right: createMethod(!0)
|
|
5340
|
+
}, fails = fails$9, globalThis$1 = globalThis_1, userAgent = environmentUserAgent, classof = classofRaw$2, userAgentStartsWith = function(string) {
|
|
5341
|
+
return userAgent.slice(0, string.length) === string;
|
|
5342
|
+
}, environment = userAgentStartsWith("Bun/") ? "BUN" : userAgentStartsWith("Cloudflare-Workers") ? "CLOUDFLARE" : userAgentStartsWith("Deno/") ? "DENO" : userAgentStartsWith("Node.js/") ? "NODE" : globalThis$1.Bun && "string" == typeof Bun.version ? "BUN" : globalThis$1.Deno && "object" == typeof Deno.version ? "DENO" : "process" === classof(globalThis$1.process) ? "NODE" : globalThis$1.window && globalThis$1.document ? "BROWSER" : "REST", $reduce = arrayReduce.left;
|
|
5343
|
+
|
|
5344
|
+
// `Array.prototype.reduce` method
|
|
5345
|
+
// https://tc39.es/ecma262/#sec-array.prototype.reduce
|
|
5346
|
+
_export({
|
|
5347
|
+
target: "Array",
|
|
5348
|
+
proto: !0,
|
|
5349
|
+
forced: !("NODE" === environment) && environmentV8Version > 79 && environmentV8Version < 83 || !function(METHOD_NAME, argument) {
|
|
5350
|
+
var method = [][METHOD_NAME];
|
|
5351
|
+
return !!method && fails((function() {
|
|
5352
|
+
// eslint-disable-next-line no-useless-call -- required for testing
|
|
5353
|
+
method.call(null, argument || function() {
|
|
5354
|
+
return 1;
|
|
5355
|
+
}, 1);
|
|
5356
|
+
}));
|
|
5357
|
+
}("reduce")
|
|
5358
|
+
}, {
|
|
5359
|
+
reduce: function(callbackfn /* , initialValue */) {
|
|
5360
|
+
var length = arguments.length;
|
|
5361
|
+
return $reduce(this, callbackfn, length, length > 1 ? arguments[1] : void 0);
|
|
5362
|
+
}
|
|
5363
|
+
});
|
|
5364
|
+
|
|
5365
|
+
var reduce$3 = getBuiltInPrototypeMethod$3("Array", "reduce"), isPrototypeOf = objectIsPrototypeOf, method = reduce$3, ArrayPrototype = Array.prototype;
|
|
5366
|
+
|
|
5367
|
+
const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
5368
|
+
var own = it.reduce;
|
|
5369
|
+
return it === ArrayPrototype || isPrototypeOf(ArrayPrototype, it) && own === ArrayPrototype.reduce ? method : own;
|
|
5370
|
+
}));
|
|
5371
|
+
|
|
5372
|
+
/**
|
|
5373
|
+
* Render a slot with the given props
|
|
5374
|
+
*
|
|
5375
|
+
* Priority order:
|
|
5376
|
+
* 1. render function
|
|
5377
|
+
* 2. component
|
|
5378
|
+
* 3. children
|
|
5379
|
+
* 4. fallback
|
|
5380
|
+
*
|
|
5381
|
+
* @example
|
|
5382
|
+
* renderSlot(
|
|
5383
|
+
* { render: (props) => <CustomButton {...props} /> },
|
|
5384
|
+
* { onClick: handleClick, children: 'Click me' }
|
|
5385
|
+
* )
|
|
5386
|
+
*/ function renderSlot(slot, props, fallback) {
|
|
5387
|
+
// No slot provided, use fallback
|
|
5388
|
+
if (!slot) return fallback;
|
|
5389
|
+
// Slot is a plain React node
|
|
5390
|
+
if ( React.isValidElement(slot) || "string" == typeof slot || "number" == typeof slot) return slot;
|
|
5391
|
+
// Slot is an object with rendering options
|
|
5392
|
+
if ("object" == typeof slot && null !== slot) {
|
|
5393
|
+
const slotObj = slot;
|
|
5394
|
+
// Priority 1: render function
|
|
5395
|
+
if (slotObj.render && "function" == typeof slotObj.render) return slotObj.render(props);
|
|
5396
|
+
// Priority 2: component
|
|
5397
|
+
if (slotObj.component) {
|
|
5398
|
+
const Component = slotObj.component;
|
|
5399
|
+
return jsx(Component, {
|
|
5400
|
+
...props
|
|
5401
|
+
});
|
|
5402
|
+
}
|
|
5403
|
+
// Priority 3: children
|
|
5404
|
+
if (void 0 !== slotObj.children) return slotObj.children;
|
|
5405
|
+
}
|
|
5406
|
+
// Fallback
|
|
5407
|
+
return fallback;
|
|
5408
|
+
}
|
|
5409
|
+
|
|
5410
|
+
/**
|
|
5411
|
+
* Check if a value is a slot configuration
|
|
5412
|
+
*/ function isSlot(value) {
|
|
5413
|
+
return "object" == typeof value && null !== value && ("render" in value || "component" in value || "children" in value);
|
|
5414
|
+
}
|
|
5415
|
+
|
|
5416
|
+
/**
|
|
5417
|
+
* Merge multiple slot configurations
|
|
5418
|
+
* Later slots override earlier ones
|
|
5419
|
+
*/ function mergeSlots(...slots) {
|
|
5420
|
+
const filtered = slots.filter((s => void 0 !== s));
|
|
5421
|
+
if (0 !== filtered.length) return 1 === filtered.length ? filtered[0] : _reduceInstanceProperty(filtered).call(filtered, ((acc, slot) => ({
|
|
5422
|
+
...acc,
|
|
5423
|
+
...slot
|
|
5424
|
+
})));
|
|
5425
|
+
}
|
|
5426
|
+
|
|
5427
|
+
/**
|
|
5428
|
+
* Create a slot wrapper component
|
|
5429
|
+
*
|
|
5430
|
+
* @example
|
|
5431
|
+
* const ButtonSlot = createSlotComponent<ButtonSlotProps>('button')
|
|
5432
|
+
*
|
|
5433
|
+
* <ButtonSlot slot={customSlot} {...props}>
|
|
5434
|
+
* Default content
|
|
5435
|
+
* </ButtonSlot>
|
|
5436
|
+
*/ function createSlotComponent(defaultElement = "div") {
|
|
5437
|
+
return function({slot: slot, children: children, ...props}) {
|
|
5438
|
+
const slotProps = props;
|
|
5439
|
+
return slot ? jsx(Fragment, {
|
|
5440
|
+
children: renderSlot(slot, slotProps, children)
|
|
5441
|
+
}) : jsx(defaultElement, "string" == typeof defaultElement ? {
|
|
5442
|
+
...props,
|
|
5443
|
+
children: children
|
|
5444
|
+
} : {
|
|
5445
|
+
...slotProps,
|
|
5446
|
+
children: children
|
|
5447
|
+
});
|
|
5448
|
+
};
|
|
5449
|
+
}
|
|
5450
|
+
|
|
5451
|
+
/**
|
|
5452
|
+
* Utility to create typed slot props
|
|
5453
|
+
*/ function createSlotProps(props) {
|
|
5454
|
+
return props;
|
|
5455
|
+
}
|
|
5456
|
+
|
|
5457
|
+
/**
|
|
5458
|
+
* Hook to manage slot rendering
|
|
5459
|
+
*/ function useSlot(slot, props, fallback) {
|
|
5460
|
+
return React.useMemo((() => renderSlot(slot, props, fallback)), [ slot, props, fallback ]);
|
|
5461
|
+
}
|
|
5462
|
+
|
|
5463
|
+
const Button = React.memo( forwardRef((({label: label, children: children, onClick: onClick, variant: variant = "primary", size: size = "md", disabled: disabled = !1, loading: loading = !1, loadingText: loadingText, icon: icon, iconName: iconName, iconSize: iconSize = "sm", iconPosition: iconPosition = "start", iconOnly: iconOnly = !1, rounded: rounded = !1, fullWidth: fullWidth = !1, block: block = !1, active: active = !1, selected: selected = !1, type: type = "button", className: className = "", as: Component = "button", href: href, target: target, glass: glass, onHover: onHover, onFocus: onFocus, onBlur: onBlur, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, tabIndex: tabIndex, style: style, linkComponent: linkComponent, slots: slots, ...props}, ref) => {
|
|
5315
5464
|
const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href), iconElement = iconName ? jsx(Icon, {
|
|
5316
5465
|
name: iconName,
|
|
5317
5466
|
size: iconSize
|
|
@@ -5327,17 +5476,28 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
|
|
|
5327
5476
|
children: [ loading && jsx("span", {
|
|
5328
5477
|
className: ThemeNaming.bemClass(THEME_NAMING.BUTTON_PREFIX, THEME_NAMING.SPINNER_ELEMENT),
|
|
5329
5478
|
"aria-hidden": "true",
|
|
5330
|
-
children:
|
|
5479
|
+
children: renderSlot(slots?.spinner, {
|
|
5480
|
+
className: ThemeNaming.bemClass(THEME_NAMING.BUTTON_PREFIX, THEME_NAMING.SPINNER_ELEMENT),
|
|
5331
5481
|
size: spinnerSize,
|
|
5332
5482
|
variant: "link" === variant || "string" == typeof variant && variant.startsWith("outline-") ? "primary" : "danger" === variant ? "error" : variant
|
|
5333
|
-
}
|
|
5483
|
+
}, jsx(Spinner, {
|
|
5484
|
+
size: spinnerSize,
|
|
5485
|
+
variant: "link" === variant || "string" == typeof variant && variant.startsWith("outline-") ? "primary" : "danger" === variant ? "error" : variant
|
|
5486
|
+
}))
|
|
5334
5487
|
}), iconElement && !loading && jsx("span", {
|
|
5335
5488
|
className: ThemeNaming.bemClass(THEME_NAMING.BUTTON_PREFIX, THEME_NAMING.ICON_ELEMENT),
|
|
5336
5489
|
"aria-hidden": "true",
|
|
5337
|
-
children:
|
|
5490
|
+
children: renderSlot(slots?.icon, {
|
|
5491
|
+
className: ThemeNaming.bemClass(THEME_NAMING.BUTTON_PREFIX, THEME_NAMING.ICON_ELEMENT),
|
|
5492
|
+
children: iconElement,
|
|
5493
|
+
size: iconSize
|
|
5494
|
+
}, iconElement)
|
|
5338
5495
|
}), !iconOnly && buttonText && jsx("span", {
|
|
5339
5496
|
className: ThemeNaming.bemClass(THEME_NAMING.BUTTON_PREFIX, THEME_NAMING.LABEL_ELEMENT),
|
|
5340
|
-
children:
|
|
5497
|
+
children: renderSlot(slots?.label, {
|
|
5498
|
+
className: ThemeNaming.bemClass(THEME_NAMING.BUTTON_PREFIX, THEME_NAMING.LABEL_ELEMENT),
|
|
5499
|
+
children: buttonText
|
|
5500
|
+
}, buttonText)
|
|
5341
5501
|
}) ]
|
|
5342
5502
|
}), buttonProps = {
|
|
5343
5503
|
className: buttonClass,
|
|
@@ -5354,48 +5514,59 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
|
|
|
5354
5514
|
tabIndex: void 0 !== tabIndex ? tabIndex : isDisabled ? -1 : 0,
|
|
5355
5515
|
style: style,
|
|
5356
5516
|
...props
|
|
5357
|
-
}
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5517
|
+
}, buttonChildren = renderSlot(slots?.root, {
|
|
5518
|
+
className: buttonClass,
|
|
5519
|
+
children: buttonContent,
|
|
5520
|
+
disabled: isDisabled,
|
|
5521
|
+
loading: loading,
|
|
5522
|
+
onClick: handleClickEvent,
|
|
5523
|
+
type: type,
|
|
5524
|
+
"aria-label": safeAriaLabel,
|
|
5525
|
+
"aria-disabled": isDisabled,
|
|
5526
|
+
"aria-busy": loading
|
|
5527
|
+
}, (() => {
|
|
5528
|
+
// Render as anchor if href is provided
|
|
5529
|
+
if (shouldRenderAsLink) {
|
|
5530
|
+
// Use custom linkComponent if provided (e.g., Next.js Link)
|
|
5531
|
+
if (linkComponent) {
|
|
5532
|
+
const LinkComp = linkComponent, linkProps = {
|
|
5533
|
+
...buttonProps,
|
|
5534
|
+
ref: ref,
|
|
5535
|
+
// linkComponent usually forwards ref to anchor
|
|
5536
|
+
href: isDisabled ? void 0 : href,
|
|
5537
|
+
to: isDisabled ? void 0 : href,
|
|
5538
|
+
target: target,
|
|
5539
|
+
rel: "_blank" === target ? "noopener noreferrer" : void 0
|
|
5540
|
+
};
|
|
5541
|
+
return jsx(LinkComp, {
|
|
5542
|
+
...linkProps,
|
|
5543
|
+
children: buttonContent
|
|
5544
|
+
});
|
|
5545
|
+
}
|
|
5546
|
+
// Fallback to regular anchor tag
|
|
5547
|
+
return jsx("a", {
|
|
5548
|
+
...buttonProps,
|
|
5549
|
+
ref: ref,
|
|
5550
|
+
href: isDisabled ? void 0 : href,
|
|
5551
|
+
target: target,
|
|
5552
|
+
rel: "_blank" === target ? "noopener noreferrer" : void 0,
|
|
5553
|
+
children: buttonContent
|
|
5554
|
+
});
|
|
5555
|
+
}
|
|
5556
|
+
// Default button rendering
|
|
5557
|
+
return jsx(Component, {
|
|
5368
5558
|
...buttonProps,
|
|
5369
5559
|
ref: ref,
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
to: isDisabled ? void 0 : href,
|
|
5373
|
-
target: target,
|
|
5374
|
-
rel: "_blank" === target ? "noopener noreferrer" : void 0
|
|
5375
|
-
};
|
|
5376
|
-
content = jsx(LinkComp, {
|
|
5377
|
-
...linkProps,
|
|
5560
|
+
type: "button" === Component ? type : void 0,
|
|
5561
|
+
disabled: isDisabled,
|
|
5378
5562
|
children: buttonContent
|
|
5379
5563
|
});
|
|
5380
|
-
}
|
|
5381
|
-
//
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
target: target,
|
|
5387
|
-
rel: "_blank" === target ? "noopener noreferrer" : void 0,
|
|
5388
|
-
children: buttonContent
|
|
5389
|
-
}); else
|
|
5390
|
-
// Default button rendering
|
|
5391
|
-
content = jsx(Component, {
|
|
5392
|
-
...buttonProps,
|
|
5393
|
-
ref: ref,
|
|
5394
|
-
type: "button" === Component ? type : void 0,
|
|
5395
|
-
disabled: isDisabled,
|
|
5396
|
-
children: buttonContent
|
|
5397
|
-
});
|
|
5398
|
-
if (glass) {
|
|
5564
|
+
})());
|
|
5565
|
+
// Determine if we should render as a link
|
|
5566
|
+
// If disabled, we still check href, but we might want to render as button or anchor with aria-disabled
|
|
5567
|
+
// The previous logic was Boolean(href && !isDisabled). This meant if disabled, it renders as <button>.
|
|
5568
|
+
// This is a safe fallback for disabled links.
|
|
5569
|
+
if (glass) {
|
|
5399
5570
|
// Default glass props
|
|
5400
5571
|
const defaultGlassProps = {
|
|
5401
5572
|
displacementScale: 20,
|
|
@@ -5408,10 +5579,10 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
|
|
|
5408
5579
|
};
|
|
5409
5580
|
return jsx(AtomixGlass, {
|
|
5410
5581
|
...glassProps,
|
|
5411
|
-
children:
|
|
5582
|
+
children: buttonChildren
|
|
5412
5583
|
});
|
|
5413
5584
|
}
|
|
5414
|
-
return
|
|
5585
|
+
return buttonChildren;
|
|
5415
5586
|
})));
|
|
5416
5587
|
|
|
5417
5588
|
Button.displayName = "Button";
|
|
@@ -5923,67 +6094,12 @@ const ElevationCard = ({elevationClass: elevationClass = "is-elevated", classNam
|
|
|
5923
6094
|
});
|
|
5924
6095
|
};
|
|
5925
6096
|
|
|
5926
|
-
ElevationCard.displayName = "ElevationCard";
|
|
5927
|
-
|
|
5928
|
-
var aCallable = aCallable$3, toObject = toObject$2, IndexedObject = indexedObject, lengthOfArrayLike = lengthOfArrayLike$2, $TypeError = TypeError, REDUCE_EMPTY = "Reduce of empty array with no initial value", createMethod = function(IS_RIGHT) {
|
|
5929
|
-
return function(that, callbackfn, argumentsLength, memo) {
|
|
5930
|
-
var O = toObject(that), self = IndexedObject(O), length = lengthOfArrayLike(O);
|
|
5931
|
-
if (aCallable(callbackfn), 0 === length && argumentsLength < 2) throw new $TypeError(REDUCE_EMPTY);
|
|
5932
|
-
var index = IS_RIGHT ? length - 1 : 0, i = IS_RIGHT ? -1 : 1;
|
|
5933
|
-
if (argumentsLength < 2) for (;;) {
|
|
5934
|
-
if (index in self) {
|
|
5935
|
-
memo = self[index], index += i;
|
|
5936
|
-
break;
|
|
5937
|
-
}
|
|
5938
|
-
if (index += i, IS_RIGHT ? index < 0 : length <= index) throw new $TypeError(REDUCE_EMPTY);
|
|
5939
|
-
}
|
|
5940
|
-
for (;IS_RIGHT ? index >= 0 : length > index; index += i) index in self && (memo = callbackfn(memo, self[index], index, O));
|
|
5941
|
-
return memo;
|
|
5942
|
-
};
|
|
5943
|
-
}, arrayReduce = {
|
|
5944
|
-
// `Array.prototype.reduce` method
|
|
5945
|
-
// https://tc39.es/ecma262/#sec-array.prototype.reduce
|
|
5946
|
-
left: createMethod(!1),
|
|
5947
|
-
// `Array.prototype.reduceRight` method
|
|
5948
|
-
// https://tc39.es/ecma262/#sec-array.prototype.reduceright
|
|
5949
|
-
right: createMethod(!0)
|
|
5950
|
-
}, fails = fails$9, globalThis$1 = globalThis_1, userAgent = environmentUserAgent, classof = classofRaw$2, userAgentStartsWith = function(string) {
|
|
5951
|
-
return userAgent.slice(0, string.length) === string;
|
|
5952
|
-
}, environment = userAgentStartsWith("Bun/") ? "BUN" : userAgentStartsWith("Cloudflare-Workers") ? "CLOUDFLARE" : userAgentStartsWith("Deno/") ? "DENO" : userAgentStartsWith("Node.js/") ? "NODE" : globalThis$1.Bun && "string" == typeof Bun.version ? "BUN" : globalThis$1.Deno && "object" == typeof Deno.version ? "DENO" : "process" === classof(globalThis$1.process) ? "NODE" : globalThis$1.window && globalThis$1.document ? "BROWSER" : "REST", $reduce = arrayReduce.left;
|
|
5953
|
-
|
|
5954
|
-
// `Array.prototype.reduce` method
|
|
5955
|
-
// https://tc39.es/ecma262/#sec-array.prototype.reduce
|
|
5956
|
-
_export({
|
|
5957
|
-
target: "Array",
|
|
5958
|
-
proto: !0,
|
|
5959
|
-
forced: !("NODE" === environment) && environmentV8Version > 79 && environmentV8Version < 83 || !function(METHOD_NAME, argument) {
|
|
5960
|
-
var method = [][METHOD_NAME];
|
|
5961
|
-
return !!method && fails((function() {
|
|
5962
|
-
// eslint-disable-next-line no-useless-call -- required for testing
|
|
5963
|
-
method.call(null, argument || function() {
|
|
5964
|
-
return 1;
|
|
5965
|
-
}, 1);
|
|
5966
|
-
}));
|
|
5967
|
-
}("reduce")
|
|
5968
|
-
}, {
|
|
5969
|
-
reduce: function(callbackfn /* , initialValue */) {
|
|
5970
|
-
var length = arguments.length;
|
|
5971
|
-
return $reduce(this, callbackfn, length, length > 1 ? arguments[1] : void 0);
|
|
5972
|
-
}
|
|
5973
|
-
});
|
|
5974
|
-
|
|
5975
|
-
var reduce$3 = getBuiltInPrototypeMethod$3("Array", "reduce"), isPrototypeOf = objectIsPrototypeOf, method = reduce$3, ArrayPrototype = Array.prototype;
|
|
5976
|
-
|
|
5977
|
-
const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
5978
|
-
var own = it.reduce;
|
|
5979
|
-
return it === ArrayPrototype || isPrototypeOf(ArrayPrototype, it) && own === ArrayPrototype.reduce ? method : own;
|
|
5980
|
-
}));
|
|
5981
|
-
|
|
5982
6097
|
/**
|
|
5983
6098
|
* Comprehensive chart hook with shared functionality
|
|
5984
6099
|
* @param initialProps - Initial chart properties
|
|
5985
6100
|
* @returns Chart state and methods
|
|
5986
|
-
*/
|
|
6101
|
+
*/
|
|
6102
|
+
function useChart(initialProps) {
|
|
5987
6103
|
const [interactionState, setInteractionState] = useState({
|
|
5988
6104
|
hoveredPoint: null,
|
|
5989
6105
|
selectedPoints: [],
|
|
@@ -6015,8 +6131,11 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
6015
6131
|
}), animationFrameRef = useRef(null);
|
|
6016
6132
|
// Default chart properties
|
|
6017
6133
|
// Cleanup animation frame on unmount
|
|
6018
|
-
useEffect((() =>
|
|
6019
|
-
|
|
6134
|
+
useEffect((() => {
|
|
6135
|
+
const currentRef = animationFrameRef.current;
|
|
6136
|
+
return () => {
|
|
6137
|
+
currentRef && cancelAnimationFrame(currentRef);
|
|
6138
|
+
};
|
|
6020
6139
|
}), []);
|
|
6021
6140
|
/**
|
|
6022
6141
|
* Point interaction handlers
|
|
@@ -6407,7 +6526,9 @@ function getDatasetBounds(data) {
|
|
|
6407
6526
|
|
|
6408
6527
|
/**
|
|
6409
6528
|
* Hook for managing chart toolbar state and generating chart-specific configurations
|
|
6410
|
-
*/
|
|
6529
|
+
*/ ElevationCard.displayName = "ElevationCard";
|
|
6530
|
+
|
|
6531
|
+
const ChartToolbar = memo( forwardRef((({chartType: chartType = "line", groups: groups = [], enableDefaults: enableDefaults = !0, defaults: defaults = {
|
|
6411
6532
|
refresh: !0,
|
|
6412
6533
|
export: !0,
|
|
6413
6534
|
fullscreen: !0,
|
|
@@ -6897,8 +7018,8 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
|
|
|
6897
7018
|
}), [ chartType ]), finalDefaults = useMemo((() => ({
|
|
6898
7019
|
...getChartDefaults(),
|
|
6899
7020
|
...defaults
|
|
6900
|
-
})), [ getChartDefaults, defaults ]), enhancedHandlers = {
|
|
6901
|
-
onRefresh:
|
|
7021
|
+
})), [ getChartDefaults, defaults ]), enhancedHandlers = useMemo((() => ({
|
|
7022
|
+
onRefresh: () => {
|
|
6902
7023
|
setState((prev => ({
|
|
6903
7024
|
...prev,
|
|
6904
7025
|
isRefreshing: !0
|
|
@@ -6908,8 +7029,8 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
|
|
|
6908
7029
|
isRefreshing: !1
|
|
6909
7030
|
})));
|
|
6910
7031
|
}), 1e3);
|
|
6911
|
-
}
|
|
6912
|
-
onExport:
|
|
7032
|
+
},
|
|
7033
|
+
onExport: async format => {
|
|
6913
7034
|
setState((prev => ({
|
|
6914
7035
|
...prev,
|
|
6915
7036
|
isExporting: !0
|
|
@@ -6922,70 +7043,70 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
|
|
|
6922
7043
|
isExporting: !1
|
|
6923
7044
|
})));
|
|
6924
7045
|
}
|
|
6925
|
-
}
|
|
6926
|
-
onFullscreen:
|
|
7046
|
+
},
|
|
7047
|
+
onFullscreen: isFullscreen => {
|
|
6927
7048
|
setState((prev => ({
|
|
6928
7049
|
...prev,
|
|
6929
7050
|
isFullscreen: isFullscreen
|
|
6930
7051
|
}))), handlers.onFullscreen?.(isFullscreen);
|
|
6931
|
-
}
|
|
6932
|
-
onZoomIn:
|
|
7052
|
+
},
|
|
7053
|
+
onZoomIn: () => {
|
|
6933
7054
|
setState((prev => ({
|
|
6934
7055
|
...prev,
|
|
6935
7056
|
zoomLevel: Math.min(1.2 * prev.zoomLevel, 5)
|
|
6936
7057
|
}))), handlers.onZoomIn?.();
|
|
6937
|
-
}
|
|
6938
|
-
onZoomOut:
|
|
7058
|
+
},
|
|
7059
|
+
onZoomOut: () => {
|
|
6939
7060
|
setState((prev => ({
|
|
6940
7061
|
...prev,
|
|
6941
7062
|
zoomLevel: Math.max(prev.zoomLevel / 1.2, .2)
|
|
6942
7063
|
}))), handlers.onZoomOut?.();
|
|
6943
|
-
}
|
|
6944
|
-
onZoomReset:
|
|
7064
|
+
},
|
|
7065
|
+
onZoomReset: () => {
|
|
6945
7066
|
setState((prev => ({
|
|
6946
7067
|
...prev,
|
|
6947
7068
|
zoomLevel: 1
|
|
6948
7069
|
}))), handlers.onZoomReset?.();
|
|
6949
|
-
}
|
|
6950
|
-
onPanToggle:
|
|
7070
|
+
},
|
|
7071
|
+
onPanToggle: enabled => {
|
|
6951
7072
|
setState((prev => ({
|
|
6952
7073
|
...prev,
|
|
6953
7074
|
panEnabled: enabled
|
|
6954
7075
|
}))), handlers.onPanToggle?.(enabled);
|
|
6955
|
-
}
|
|
6956
|
-
onReset:
|
|
7076
|
+
},
|
|
7077
|
+
onReset: () => {
|
|
6957
7078
|
setState((prev => ({
|
|
6958
7079
|
...prev,
|
|
6959
7080
|
zoomLevel: 1,
|
|
6960
7081
|
panEnabled: !1
|
|
6961
7082
|
}))), handlers.onReset?.();
|
|
6962
|
-
}
|
|
6963
|
-
onGridToggle:
|
|
7083
|
+
},
|
|
7084
|
+
onGridToggle: show => {
|
|
6964
7085
|
setState((prev => ({
|
|
6965
7086
|
...prev,
|
|
6966
7087
|
showGrid: show
|
|
6967
7088
|
}))), handlers.onGridToggle?.(show);
|
|
6968
|
-
}
|
|
6969
|
-
onLegendToggle:
|
|
7089
|
+
},
|
|
7090
|
+
onLegendToggle: show => {
|
|
6970
7091
|
setState((prev => ({
|
|
6971
7092
|
...prev,
|
|
6972
7093
|
showLegend: show
|
|
6973
7094
|
}))), handlers.onLegendToggle?.(show);
|
|
6974
|
-
}
|
|
6975
|
-
onTooltipsToggle:
|
|
7095
|
+
},
|
|
7096
|
+
onTooltipsToggle: show => {
|
|
6976
7097
|
setState((prev => ({
|
|
6977
7098
|
...prev,
|
|
6978
7099
|
showTooltips: show
|
|
6979
7100
|
}))), handlers.onTooltipsToggle?.(show);
|
|
6980
|
-
}
|
|
6981
|
-
onAnimationsToggle:
|
|
7101
|
+
},
|
|
7102
|
+
onAnimationsToggle: enabled => {
|
|
6982
7103
|
setState((prev => ({
|
|
6983
7104
|
...prev,
|
|
6984
7105
|
animationsEnabled: enabled
|
|
6985
7106
|
}))), handlers.onAnimationsToggle?.(enabled);
|
|
6986
|
-
}
|
|
6987
|
-
onSettings:
|
|
6988
|
-
}, generateToolbarGroups = useCallback((() => {
|
|
7107
|
+
},
|
|
7108
|
+
onSettings: () => {}
|
|
7109
|
+
})), [ handlers ]), generateToolbarGroups = useCallback((() => {
|
|
6989
7110
|
const groups = [], dataActions = [];
|
|
6990
7111
|
// Data actions group
|
|
6991
7112
|
finalDefaults.refresh && dataActions.push({
|
|
@@ -7110,7 +7231,7 @@ toolbarConfig: toolbarConfig, customToolbarActions: customToolbarActions, custom
|
|
|
7110
7231
|
actions: customActions
|
|
7111
7232
|
});
|
|
7112
7233
|
return groups;
|
|
7113
|
-
}), [
|
|
7234
|
+
}), [ finalDefaults, state, enhancedHandlers, customActions, customGroups ]);
|
|
7114
7235
|
// Keyboard shortcuts
|
|
7115
7236
|
return useEffect((() => {
|
|
7116
7237
|
const handleKeyDown = event => {
|
|
@@ -7702,7 +7823,7 @@ const ChartRenderer = memo( forwardRef((({datasets: datasets = [], config: conf
|
|
|
7702
7823
|
announcement: announcement,
|
|
7703
7824
|
focusedPoint: focusedPoint,
|
|
7704
7825
|
getAccessibleDescription: () => "Chart description"
|
|
7705
|
-
})), [ announcement, focusedPoint ]), transform = useMemo((() => chartContext ? `translate(${chartContext.panOffset.x}px, ${chartContext.panOffset.y}px) scale(${chartContext.zoomLevel})` : ""), [ chartContext
|
|
7826
|
+
})), [ announcement, focusedPoint ]), transform = useMemo((() => chartContext ? `translate(${chartContext.panOffset.x}px, ${chartContext.panOffset.y}px) scale(${chartContext.zoomLevel})` : ""), [ chartContext ]), chartData = useMemo((() => {
|
|
7706
7827
|
// Return null if dimensions not ready to prevent calculation with invalid dimensions
|
|
7707
7828
|
if (!isInitialized || 0 === dimensions.width || 0 === dimensions.height) return null;
|
|
7708
7829
|
const scales = calculateScales(processedData, dimensions.width, dimensions.height, void 0, config);
|
|
@@ -8115,7 +8236,7 @@ function useBarChart(datasets, options = {}) {
|
|
|
8115
8236
|
opacity: .4
|
|
8116
8237
|
} ]
|
|
8117
8238
|
};
|
|
8118
|
-
})) : []), [ options.useGradients ]), formatValue = useCallback((value => options.valueFormatter ? options.valueFormatter(value) : value.toString()), [ options
|
|
8239
|
+
})) : []), [ options.useGradients ]), formatValue = useCallback((value => options.valueFormatter ? options.valueFormatter(value) : value.toString()), [ options ]);
|
|
8119
8240
|
return {
|
|
8120
8241
|
// State
|
|
8121
8242
|
hoveredBar: hoveredBar,
|
|
@@ -8141,7 +8262,7 @@ function useBarChart(datasets, options = {}) {
|
|
|
8141
8262
|
y: horizontal ? y + height / 2 : y - 5
|
|
8142
8263
|
};
|
|
8143
8264
|
}
|
|
8144
|
-
}), [ options
|
|
8265
|
+
}), [ options ]),
|
|
8145
8266
|
// Handlers
|
|
8146
8267
|
handleBarHover: handleBarHover,
|
|
8147
8268
|
handleBarLeave: handleBarLeave,
|
|
@@ -8450,13 +8571,13 @@ const DonutChart = memo( forwardRef((({datasets: datasets = [], config: config
|
|
|
8450
8571
|
roundedCorners: !0
|
|
8451
8572
|
}, onDataPointClick: onDataPointClick, ...props}, ref) => {
|
|
8452
8573
|
// Use the first dataset for donut chart
|
|
8453
|
-
const dataset = datasets.length > 0 ? datasets[0] : {
|
|
8574
|
+
const dataset = useMemo((() => datasets.length > 0 ? datasets[0] : {
|
|
8454
8575
|
label: "",
|
|
8455
8576
|
data: []
|
|
8456
|
-
}, chartData = useMemo((() => {
|
|
8577
|
+
}), [ datasets ]), chartData = useMemo((() => {
|
|
8457
8578
|
if (!dataset?.data?.length) return null;
|
|
8458
8579
|
// Filter out invalid data points
|
|
8459
|
-
const validDataPoints = dataset?.data
|
|
8580
|
+
const validDataPoints = (dataset?.data || []).filter((point => "number" == typeof point.value && !isNaN(point.value) && isFinite(point.value) && point.value > 0));
|
|
8460
8581
|
return validDataPoints.length ? {
|
|
8461
8582
|
validDataPoints: validDataPoints
|
|
8462
8583
|
} : null;
|
|
@@ -9412,7 +9533,7 @@ function usePieChart(data, options = {}) {
|
|
|
9412
9533
|
const parts = [];
|
|
9413
9534
|
return !1 !== options.showLabels && parts.push(slice.label), options.showPercentages && parts.push(`${Math.round(slice.percentage)}%`),
|
|
9414
9535
|
options.showValues && parts.push(slice.value.toString()), parts.join(" - ");
|
|
9415
|
-
}), [ options
|
|
9536
|
+
}), [ options ]), getSliceTransform = useCallback(((slice, isHovered) => isHovered && options.enableHoverEffects && options.hoverOffset ? `translate(${Math.cos(slice.midAngle) * options.hoverOffset}, ${Math.sin(slice.midAngle) * options.hoverOffset})` : ""), [ options.enableHoverEffects, options.hoverOffset ]), isSliceSelected = useCallback((index => selectedSlices.has(index)), [ selectedSlices ]);
|
|
9416
9537
|
return {
|
|
9417
9538
|
// Data
|
|
9418
9539
|
processedData: processedData,
|
|
@@ -10839,7 +10960,7 @@ const DataTable = memo((({data: data, columns: columns, className: className, s
|
|
|
10839
10960
|
const newOrder = columns.map((col => col.key)), currentOrderSet = new Set(columnOrder), newOrderSet = new Set(newOrder);
|
|
10840
10961
|
// Only update if there are actual differences
|
|
10841
10962
|
newOrder.length === columnOrder.length && newOrder.every((key => currentOrderSet.has(key))) && columnOrder.every((key => newOrderSet.has(key))) || setColumnOrder(newOrder);
|
|
10842
|
-
}), [ columns ]),
|
|
10963
|
+
}), [ columns, columnOrder ]),
|
|
10843
10964
|
// Update column visibility when columns prop changes
|
|
10844
10965
|
useEffect((() => {
|
|
10845
10966
|
setColumnVisibility((prev => {
|
|
@@ -11384,7 +11505,7 @@ function formatDate(date, format) {
|
|
|
11384
11505
|
/**
|
|
11385
11506
|
* Check if a date is within a min and max range
|
|
11386
11507
|
*/ function useDatePicker({value: value, onChange: onChange, selectionMode: selectionMode = "single", startDate: startDate, endDate: endDate, onRangeChange: onRangeChange, format: format = "MM/dd/yyyy", minDate: minDate, maxDate: maxDate, inline: inline = !1} = {}) {
|
|
11387
|
-
const [isOpen, setIsOpen] = useState(inline), [inputValue, setInputValue] = useState(value ? formatDate(value, format) : ""), [rangeInputValue, setRangeInputValue] = useState(startDate && endDate ? `${formatDate(startDate, format)} - ${formatDate(endDate, format)}` : startDate ? `${formatDate(startDate, format)} - Select end date` : ""), [viewDate, setViewDate] = useState(value || startDate || new Date), [viewMode, setViewMode] = useState("days"), [rangeSelectionState, setRangeSelectionState] = useState(!startDate || startDate && endDate ? "start" : "end"), datePickerRef = useRef(null), inputRef = useRef(null), today = new Date, currentMonth = viewDate.getMonth(), currentYear = viewDate.getFullYear(), daysInMonth = getDaysInMonth(currentYear, currentMonth), firstDayOfMonth = new Date(currentYear, currentMonth, 1).getDay();
|
|
11508
|
+
const [isOpen, setIsOpen] = useState(inline), [inputValue, setInputValue] = useState(value ? formatDate(value, format) : ""), [rangeInputValue, setRangeInputValue] = useState(startDate && endDate ? `${formatDate(startDate, format)} - ${formatDate(endDate, format)}` : startDate ? `${formatDate(startDate, format)} - Select end date` : ""), [viewDate, setViewDate] = useState(value || startDate || new Date), [viewMode, setViewMode] = useState("days"), [rangeSelectionState, setRangeSelectionState] = useState(!startDate || startDate && endDate ? "start" : "end"), datePickerRef = useRef(null), inputRef = useRef(null), today = useMemo((() => new Date), []), currentMonth = viewDate.getMonth(), currentYear = viewDate.getFullYear(), daysInMonth = getDaysInMonth(currentYear, currentMonth), firstDayOfMonth = new Date(currentYear, currentMonth, 1).getDay();
|
|
11388
11509
|
// Update input value when value or range dates change externally
|
|
11389
11510
|
useEffect((() => {
|
|
11390
11511
|
"single" === selectionMode ? setInputValue(value ? formatDate(value, format) : "") : (setRangeInputValue(startDate && endDate ? `${formatDate(startDate, format)} - ${formatDate(endDate, format)}` : startDate ? `${formatDate(startDate, format)} - Select end date` : ""),
|
|
@@ -11907,21 +12028,11 @@ const DatePicker = forwardRef((({value: value, onChange: onChange, selectionMod
|
|
|
11907
12028
|
* @returns EdgePanel state and methods
|
|
11908
12029
|
*/
|
|
11909
12030
|
function useEdgePanel(initialProps) {
|
|
11910
|
-
|
|
11911
|
-
|
|
11912
|
-
position
|
|
11913
|
-
mode: "slide",
|
|
11914
|
-
isOpen: !1,
|
|
11915
|
-
backdrop: !0,
|
|
11916
|
-
closeOnBackdropClick: !0,
|
|
11917
|
-
closeOnEscape: !0,
|
|
11918
|
-
glass: void 0,
|
|
11919
|
-
...initialProps
|
|
11920
|
-
}, [isOpen, setIsOpen] = useState(defaultProps.isOpen || !1), containerRef = useRef(null), backdropRef = useRef(null), adjustBodyPadding = useCallback((() => {
|
|
11921
|
-
if (!containerRef.current || "push" !== defaultProps.mode) return;
|
|
11922
|
-
const {position: position} = defaultProps, size = "top" === position || "bottom" === position ? containerRef.current.clientHeight : containerRef.current.clientWidth;
|
|
12031
|
+
const {position: position = "start", mode: mode = "slide", isOpen: propIsOpen = !1, backdrop: backdrop = !0, closeOnBackdropClick: closeOnBackdropClick = !0, closeOnEscape: closeOnEscape = !0, glass: glass, onOpenChange: onOpenChange, className: className = ""} = initialProps || {}, [isOpen, setIsOpen] = useState(propIsOpen || !1), containerRef = useRef(null), backdropRef = useRef(null), adjustBodyPadding = useCallback((() => {
|
|
12032
|
+
if (!containerRef.current || "push" !== mode) return;
|
|
12033
|
+
const size = "top" === position || "bottom" === position ? containerRef.current.clientHeight : containerRef.current.clientWidth;
|
|
11923
12034
|
// Map position to CSS padding property
|
|
11924
|
-
|
|
12035
|
+
let paddingProperty;
|
|
11925
12036
|
switch (position) {
|
|
11926
12037
|
case "start":
|
|
11927
12038
|
paddingProperty = "paddingLeft";
|
|
@@ -11936,9 +12047,8 @@ function useEdgePanel(initialProps) {
|
|
|
11936
12047
|
paddingProperty = `padding${position.charAt(0).toUpperCase() + position.slice(1)}`;
|
|
11937
12048
|
}
|
|
11938
12049
|
document.body.style[paddingProperty] = `${size}px`, document.body.classList.add("is-pushed");
|
|
11939
|
-
}), [
|
|
11940
|
-
if ("push" !==
|
|
11941
|
-
const {position: position} = defaultProps;
|
|
12050
|
+
}), [ mode, position ]), resetBodyPadding = useCallback((() => {
|
|
12051
|
+
if ("push" !== mode) return;
|
|
11942
12052
|
// Map position to CSS padding property
|
|
11943
12053
|
let paddingProperty;
|
|
11944
12054
|
switch (position) {
|
|
@@ -11955,11 +12065,10 @@ function useEdgePanel(initialProps) {
|
|
|
11955
12065
|
paddingProperty = `padding${position.charAt(0).toUpperCase() + position.slice(1)}`;
|
|
11956
12066
|
}
|
|
11957
12067
|
document.body.style[paddingProperty] = "", document.body.classList.remove("is-pushed");
|
|
11958
|
-
}), [
|
|
12068
|
+
}), [ mode, position ]), openPanel = useCallback(((useFadeAnimation = !1) => {
|
|
11959
12069
|
if (setIsOpen(!0), document.body.classList.add("is-edgepanel-open"), containerRef.current) {
|
|
11960
|
-
const {mode: mode} = defaultProps;
|
|
11961
12070
|
// Only add animation if not in 'none' mode
|
|
11962
|
-
|
|
12071
|
+
if ("none" !== mode) if (useFadeAnimation) {
|
|
11963
12072
|
// Add fade animation class
|
|
11964
12073
|
containerRef.current.classList.add("is-fade-animating"), containerRef.current.offsetHeight;
|
|
11965
12074
|
// Remove animation class after animation completes
|
|
@@ -11979,14 +12088,13 @@ function useEdgePanel(initialProps) {
|
|
|
11979
12088
|
// Set transform or opacity based on animation type
|
|
11980
12089
|
useFadeAnimation ? (containerRef.current.style.opacity = "1", containerRef.current.style.transform = "") : containerRef.current.style.transform = "translate(0)",
|
|
11981
12090
|
// If push mode, adjust body padding
|
|
11982
|
-
"push" ===
|
|
12091
|
+
"push" === mode && adjustBodyPadding();
|
|
11983
12092
|
}
|
|
11984
|
-
|
|
11985
|
-
}), [
|
|
12093
|
+
onOpenChange && onOpenChange(!0);
|
|
12094
|
+
}), [ mode, adjustBodyPadding, onOpenChange ]), closePanel = useCallback(((useFadeAnimation = !1) => {
|
|
11986
12095
|
if (containerRef.current) {
|
|
11987
|
-
const {position: position, mode: mode} = defaultProps;
|
|
11988
12096
|
// Only add animation if not in 'none' mode
|
|
11989
|
-
|
|
12097
|
+
if ("none" !== mode) if (useFadeAnimation) {
|
|
11990
12098
|
// Add fade out animation class
|
|
11991
12099
|
containerRef.current.classList.add("is-fade-animating-out");
|
|
11992
12100
|
// Capture container for setTimeout
|
|
@@ -12008,46 +12116,42 @@ function useEdgePanel(initialProps) {
|
|
|
12008
12116
|
// Then set transform
|
|
12009
12117
|
containerRef.current.style.transform = position ? EDGE_PANEL.TRANSFORM_VALUES[position] : "",
|
|
12010
12118
|
// Reset body padding if push mode
|
|
12011
|
-
"push" ===
|
|
12012
|
-
setIsOpen(!1), document.body.classList.remove("is-edgepanel-open"),
|
|
12119
|
+
"push" === mode && resetBodyPadding(), setTimeout((() => {
|
|
12120
|
+
setIsOpen(!1), document.body.classList.remove("is-edgepanel-open"), onOpenChange && onOpenChange(!1);
|
|
12013
12121
|
}), "none" === mode ? 0 : EDGE_PANEL.ANIMATION_DURATION);
|
|
12014
|
-
} else setIsOpen(!1), document.body.classList.remove("is-edgepanel-open"),
|
|
12015
|
-
}), [
|
|
12016
|
-
|
|
12017
|
-
}), [ closePanel,
|
|
12018
|
-
|
|
12019
|
-
}), [ closePanel,
|
|
12122
|
+
} else setIsOpen(!1), document.body.classList.remove("is-edgepanel-open"), onOpenChange && onOpenChange(!1);
|
|
12123
|
+
}), [ mode, position, onOpenChange, resetBodyPadding ]), handleEscapeKey = useCallback((event => {
|
|
12124
|
+
closeOnEscape && "Escape" === event.key && isOpen && closePanel();
|
|
12125
|
+
}), [ closePanel, closeOnEscape, isOpen ]), handleBackdropClick = useCallback((event => {
|
|
12126
|
+
closeOnBackdropClick && event.target === event.currentTarget && closePanel();
|
|
12127
|
+
}), [ closePanel, closeOnBackdropClick ]);
|
|
12020
12128
|
/**
|
|
12021
12129
|
* Set up event listeners for keyboard events
|
|
12022
12130
|
*/
|
|
12023
|
-
return useEffect((() => (isOpen &&
|
|
12131
|
+
return useEffect((() => (isOpen && closeOnEscape && document.addEventListener("keydown", handleEscapeKey),
|
|
12024
12132
|
() => {
|
|
12025
12133
|
document.removeEventListener("keydown", handleEscapeKey);
|
|
12026
|
-
})), [ isOpen, handleEscapeKey,
|
|
12134
|
+
})), [ isOpen, handleEscapeKey, closeOnEscape ]),
|
|
12027
12135
|
/**
|
|
12028
12136
|
* Set initial transform values
|
|
12029
12137
|
*/
|
|
12030
12138
|
useEffect((() => {
|
|
12031
|
-
|
|
12032
|
-
|
|
12033
|
-
|
|
12034
|
-
|
|
12035
|
-
defaultProps.glass && (containerRef.current.style.opacity = "0"));
|
|
12036
|
-
}
|
|
12037
|
-
}), [ defaultProps.mode, defaultProps.position, defaultProps.glass, isOpen ]),
|
|
12139
|
+
containerRef.current && (isOpen || "slide" !== mode && "push" !== mode || !position || (containerRef.current.style.transform = EDGE_PANEL.TRANSFORM_VALUES[position],
|
|
12140
|
+
// Set initial opacity for fade animations
|
|
12141
|
+
glass && (containerRef.current.style.opacity = "0")));
|
|
12142
|
+
}), [ mode, position, glass, isOpen ]),
|
|
12038
12143
|
/**
|
|
12039
12144
|
* Sync with prop changes
|
|
12040
12145
|
*/
|
|
12041
12146
|
useEffect((() => {
|
|
12042
|
-
void 0 !==
|
|
12043
|
-
}), [
|
|
12044
|
-
{
|
|
12147
|
+
void 0 !== propIsOpen && propIsOpen !== isOpen && (propIsOpen ? openPanel(!!glass) : closePanel(!!glass));
|
|
12148
|
+
}), [ propIsOpen, closePanel, isOpen, openPanel, glass ]), {
|
|
12045
12149
|
isOpen: isOpen,
|
|
12046
12150
|
containerRef: containerRef,
|
|
12047
12151
|
backdropRef: backdropRef,
|
|
12048
12152
|
generateEdgePanelClass: props => {
|
|
12049
|
-
const {position:
|
|
12050
|
-
return `${baseClass} ${
|
|
12153
|
+
const {position: propPosition = position, className: propClassName = className, isOpen: argIsOpen} = props, baseClass = EDGE_PANEL.CLASSES.BASE;
|
|
12154
|
+
return `${baseClass} ${propPosition ? `${baseClass}--${propPosition}` : ""} ${argIsOpen ?? isOpen ? EDGE_PANEL.CLASSES.IS_OPEN : ""} ${propClassName}`.trim();
|
|
12051
12155
|
},
|
|
12052
12156
|
openPanel: openPanel,
|
|
12053
12157
|
closePanel: closePanel,
|
|
@@ -12429,7 +12533,7 @@ function useHero(initialProps) {
|
|
|
12429
12533
|
* @returns Slider state and methods
|
|
12430
12534
|
*/
|
|
12431
12535
|
function(config) {
|
|
12432
|
-
const {slides: slides, autoplay: autoplay, loop: loop = !0, transition: transition = "fade", transitionDuration: transitionDuration = 1e3} = config, [currentIndex, setCurrentIndex] = useState(0), [isTransitioning, setIsTransitioning] = useState(!1), autoplayRef = useRef(null), isPausedRef = useRef(!1), callbackRef = useRef(), slideRefs = useMemo((() => slides.map((() => React.createRef()))), [ slides
|
|
12536
|
+
const {slides: slides, autoplay: autoplay, loop: loop = !0, transition: transition = "fade", transitionDuration: transitionDuration = 1e3} = config, [currentIndex, setCurrentIndex] = useState(0), [isTransitioning, setIsTransitioning] = useState(!1), autoplayRef = useRef(null), isPausedRef = useRef(!1), callbackRef = useRef(void 0), slideRefs = useMemo((() => slides.map((() => React.createRef()))), [ slides ]), videoRefs = useMemo((() => slides.map((() => React.createRef()))), [ slides ]), handleSlideTransition = useCallback((nextIndex => {
|
|
12433
12537
|
if (nextIndex === currentIndex || isTransitioning) return;
|
|
12434
12538
|
if (nextIndex < 0 || nextIndex >= slides.length) return;
|
|
12435
12539
|
setIsTransitioning(!0),
|
|
@@ -12748,22 +12852,15 @@ function useHero(initialProps) {
|
|
|
12748
12852
|
* @param initialProps - Initial side menu properties
|
|
12749
12853
|
* @returns SideMenu state and methods
|
|
12750
12854
|
*/ function useSideMenu(initialProps) {
|
|
12751
|
-
|
|
12752
|
-
const defaultProps = {
|
|
12753
|
-
collapsible: !0,
|
|
12754
|
-
collapsibleDesktop: !1,
|
|
12755
|
-
defaultCollapsedDesktop: !1,
|
|
12756
|
-
isOpen: !1,
|
|
12757
|
-
...initialProps
|
|
12758
|
-
}, [isOpenState, setIsOpenState] = useState(void 0 !== defaultProps.defaultCollapsedDesktop ? !defaultProps.defaultCollapsedDesktop : defaultProps.isOpen || !1), wrapperRef = useRef(null), innerRef = useRef(null), sideMenuRef = useRef(null);
|
|
12855
|
+
const {collapsible: collapsible = !0, collapsibleDesktop: collapsibleDesktop = !1, defaultCollapsedDesktop: defaultCollapsedDesktop = !1, isOpen: isOpen, onToggle: onToggle, disabled: disabled = !1} = initialProps || {}, [isOpenState, setIsOpenState] = useState(void 0 !== defaultCollapsedDesktop ? !defaultCollapsedDesktop : isOpen || !1), wrapperRef = useRef(null), innerRef = useRef(null), sideMenuRef = useRef(null);
|
|
12759
12856
|
// Local open state for when not controlled externally
|
|
12760
12857
|
// Update local state when external state changes
|
|
12761
12858
|
useEffect((() => {
|
|
12762
|
-
void 0 !==
|
|
12763
|
-
}), [
|
|
12859
|
+
void 0 !== isOpen ? setIsOpenState(isOpen) : void 0 !== defaultCollapsedDesktop && setIsOpenState(!defaultCollapsedDesktop);
|
|
12860
|
+
}), [ isOpen, defaultCollapsedDesktop ]),
|
|
12764
12861
|
// Set initial height on mount
|
|
12765
12862
|
useEffect((() => {
|
|
12766
|
-
const shouldCollapse = window.innerWidth < 768 ?
|
|
12863
|
+
const shouldCollapse = window.innerWidth < 768 ? collapsible : collapsibleDesktop, currentOpen = void 0 !== isOpen ? isOpen : isOpenState;
|
|
12767
12864
|
if (shouldCollapse && wrapperRef.current && innerRef.current) {
|
|
12768
12865
|
// Use setTimeout to ensure DOM is fully rendered
|
|
12769
12866
|
const timeoutId = setTimeout((() => {
|
|
@@ -12772,14 +12869,14 @@ function useHero(initialProps) {
|
|
|
12772
12869
|
return () => clearTimeout(timeoutId);
|
|
12773
12870
|
}
|
|
12774
12871
|
!shouldCollapse && wrapperRef.current && (wrapperRef.current.style.height = "auto");
|
|
12775
|
-
}), [
|
|
12872
|
+
}), [ collapsible, collapsibleDesktop, isOpen, isOpenState ]),
|
|
12776
12873
|
// Handle responsive behavior - vertical collapse for both mobile and desktop
|
|
12777
12874
|
useEffect((() => {
|
|
12778
12875
|
const handleResize = () => {
|
|
12779
|
-
if (window.innerWidth < 768 ?
|
|
12876
|
+
if (window.innerWidth < 768 ? collapsible : collapsibleDesktop) {
|
|
12780
12877
|
if (wrapperRef.current && innerRef.current) {
|
|
12781
12878
|
// Set proper height for vertical animation (both mobile and desktop)
|
|
12782
|
-
const currentOpen = void 0 !==
|
|
12879
|
+
const currentOpen = void 0 !== isOpen ? isOpen : isOpenState;
|
|
12783
12880
|
// Use requestAnimationFrame to ensure DOM is ready
|
|
12784
12881
|
requestAnimationFrame((() => {
|
|
12785
12882
|
wrapperRef.current && innerRef.current && (wrapperRef.current.style.height = currentOpen ? `${innerRef.current.scrollHeight}px` : "0px");
|
|
@@ -12793,12 +12890,12 @@ function useHero(initialProps) {
|
|
|
12793
12890
|
return window.addEventListener("resize", handleResize), () => {
|
|
12794
12891
|
clearTimeout(timeoutId), window.removeEventListener("resize", handleResize);
|
|
12795
12892
|
};
|
|
12796
|
-
}), [
|
|
12893
|
+
}), [ collapsible, collapsibleDesktop, isOpen, onToggle, isOpenState ]),
|
|
12797
12894
|
// Update wrapper height when open state changes (both mobile and desktop)
|
|
12798
12895
|
useEffect((() => {
|
|
12799
|
-
const shouldCollapse = window.innerWidth < 768 ?
|
|
12896
|
+
const shouldCollapse = window.innerWidth < 768 ? collapsible : collapsibleDesktop;
|
|
12800
12897
|
if (shouldCollapse && wrapperRef.current && innerRef.current) {
|
|
12801
|
-
const currentOpen = void 0 !==
|
|
12898
|
+
const currentOpen = void 0 !== isOpen ? isOpen : isOpenState;
|
|
12802
12899
|
// Use requestAnimationFrame to ensure DOM is ready
|
|
12803
12900
|
requestAnimationFrame((() => {
|
|
12804
12901
|
wrapperRef.current && innerRef.current && (wrapperRef.current.style.height = currentOpen ? `${innerRef.current.scrollHeight}px` : "0px");
|
|
@@ -12806,26 +12903,25 @@ function useHero(initialProps) {
|
|
|
12806
12903
|
} else !shouldCollapse && wrapperRef.current && (
|
|
12807
12904
|
// Not collapsible - always show content
|
|
12808
12905
|
wrapperRef.current.style.height = "auto");
|
|
12809
|
-
}), [
|
|
12906
|
+
}), [ isOpen, isOpenState, collapsible, collapsibleDesktop ]);
|
|
12810
12907
|
/**
|
|
12811
12908
|
* Generate side menu class based on properties
|
|
12812
12909
|
* @param props - Side menu properties
|
|
12813
12910
|
* @returns Class string
|
|
12814
12911
|
*/
|
|
12815
12912
|
const handleToggle = () => {
|
|
12816
|
-
if (
|
|
12817
|
-
const newState = void 0 !==
|
|
12818
|
-
"function" == typeof
|
|
12913
|
+
if (disabled) return;
|
|
12914
|
+
const newState = void 0 !== isOpen ? !isOpen : !isOpenState;
|
|
12915
|
+
"function" == typeof onToggle ?
|
|
12819
12916
|
// Controlled component
|
|
12820
|
-
|
|
12917
|
+
onToggle(newState) :
|
|
12821
12918
|
// Uncontrolled component
|
|
12822
12919
|
setIsOpenState(newState);
|
|
12823
|
-
}, getCurrentOpenState = () => void 0 !==
|
|
12920
|
+
}, getCurrentOpenState = () => void 0 !== isOpen ? isOpen : isOpenState;
|
|
12824
12921
|
/**
|
|
12825
12922
|
* Generate wrapper class
|
|
12826
12923
|
* @returns Class string
|
|
12827
12924
|
*/ return {
|
|
12828
|
-
defaultProps: defaultProps,
|
|
12829
12925
|
isOpenState: getCurrentOpenState(),
|
|
12830
12926
|
wrapperRef: wrapperRef,
|
|
12831
12927
|
innerRef: innerRef,
|
|
@@ -13410,21 +13506,21 @@ function useTodo(initialProps) {
|
|
|
13410
13506
|
const [interaction, setInteraction] = useState({
|
|
13411
13507
|
hoveredIndex: null,
|
|
13412
13508
|
selectedIndex: null
|
|
13413
|
-
})
|
|
13509
|
+
}), handlePointHover = useCallback((index => {
|
|
13510
|
+
setInteraction((prev => ({
|
|
13511
|
+
...prev,
|
|
13512
|
+
hoveredIndex: index
|
|
13513
|
+
})));
|
|
13514
|
+
}), []), handlePointClick = useCallback((index => {
|
|
13515
|
+
setInteraction((prev => ({
|
|
13516
|
+
...prev,
|
|
13517
|
+
selectedIndex: prev.selectedIndex === index ? null : index
|
|
13518
|
+
})));
|
|
13519
|
+
}), []);
|
|
13414
13520
|
return {
|
|
13415
13521
|
interaction: interaction,
|
|
13416
|
-
handlePointHover:
|
|
13417
|
-
|
|
13418
|
-
...prev,
|
|
13419
|
-
hoveredIndex: index
|
|
13420
|
-
})));
|
|
13421
|
-
}), []),
|
|
13422
|
-
handlePointClick: useCallback((index => {
|
|
13423
|
-
setInteraction((prev => ({
|
|
13424
|
-
...prev,
|
|
13425
|
-
selectedIndex: prev.selectedIndex === index ? null : index
|
|
13426
|
-
})));
|
|
13427
|
-
}), []),
|
|
13522
|
+
handlePointHover: handlePointHover,
|
|
13523
|
+
handlePointClick: handlePointClick,
|
|
13428
13524
|
clearInteraction: useCallback((() => {
|
|
13429
13525
|
setInteraction({
|
|
13430
13526
|
hoveredIndex: null,
|
|
@@ -13467,7 +13563,7 @@ const composablesImport = Object.freeze( Object.defineProperty({
|
|
|
13467
13563
|
useNavDropdown: useNavDropdown,
|
|
13468
13564
|
useNavItem: useNavItem,
|
|
13469
13565
|
useNavbar: useNavbar,
|
|
13470
|
-
usePerformanceMonitor: usePerformanceMonitor,
|
|
13566
|
+
usePerformanceMonitor: usePerformanceMonitor$1,
|
|
13471
13567
|
usePieChart: usePieChart,
|
|
13472
13568
|
useRadio: useRadio,
|
|
13473
13569
|
useResponsiveGlass: useResponsiveGlass,
|
|
@@ -13530,7 +13626,7 @@ SelectOption.displayName = "SelectOption";
|
|
|
13530
13626
|
/**
|
|
13531
13627
|
* Select - A component for dropdown selection
|
|
13532
13628
|
*/
|
|
13533
|
-
const
|
|
13629
|
+
const SelectComponentBase = ({options: options, value: value, onChange: onChange, onBlur: onBlur, onFocus: onFocus, placeholder: placeholder = "Select an option", className: className = "", style: style, disabled: disabled = !1, required: required = !1, id: id, name: name, size: size = "md", invalid: invalid = !1, valid: valid = !1, multiple: multiple = !1, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, glass: glass, children: children}) => {
|
|
13534
13630
|
const {generateSelectClass: generateSelectClass} = useSelect({
|
|
13535
13631
|
size: size,
|
|
13536
13632
|
disabled: disabled,
|
|
@@ -13721,7 +13817,7 @@ const Select = memo((({options: options, value: value, onChange: onChange, onBl
|
|
|
13721
13817
|
});
|
|
13722
13818
|
}
|
|
13723
13819
|
return selectContent;
|
|
13724
|
-
})
|
|
13820
|
+
}, Select = memo(SelectComponentBase);
|
|
13725
13821
|
|
|
13726
13822
|
Select.displayName = "Select", Select.Option = SelectOption;
|
|
13727
13823
|
|
|
@@ -14288,7 +14384,7 @@ Footer.displayName = "Footer";
|
|
|
14288
14384
|
*/
|
|
14289
14385
|
const MasonryGrid = forwardRef((({children: children, className: className = "", xs: xs = 1, sm: sm, md: md, lg: lg, xl: xl, xxl: xxl, gap: gap = 16, animate: animate = !0, imagesLoaded: imagesLoaded = !0, onLayoutComplete: onLayoutComplete, onImageLoad: onImageLoad, ...props}, ref) => {
|
|
14290
14386
|
// === REFS & STATE ===
|
|
14291
|
-
const [columns, setColumns] = useState(xs), [positions, setPositions] = useState([]), [
|
|
14387
|
+
const [columns, setColumns] = useState(xs), [positions, setPositions] = useState([]), [, setLayoutComplete] = useState(!1), [loadingImages, setLoadingImages] = useState(!1), containerRef = useRef(null), columnHeights = useRef([]), imagesLoadedCount = useRef(0), totalImagesCount = useRef(0), imageElements = useRef(new Map);
|
|
14292
14388
|
useEffect((() => {
|
|
14293
14389
|
setLoadingImages(!!imagesLoaded);
|
|
14294
14390
|
}), [ columns, imagesLoaded ]),
|
|
@@ -14317,34 +14413,45 @@ const MasonryGrid = forwardRef((({children: children, className: className = ""
|
|
|
14317
14413
|
});
|
|
14318
14414
|
})), setItems(newItems);
|
|
14319
14415
|
}), [ children ]);
|
|
14320
|
-
// ===
|
|
14321
|
-
const
|
|
14322
|
-
if (!
|
|
14323
|
-
|
|
14324
|
-
|
|
14325
|
-
|
|
14326
|
-
|
|
14327
|
-
|
|
14416
|
+
// === MANAGE ITEM LAYOUT ===
|
|
14417
|
+
const calculateLayout = useCallback((() => {
|
|
14418
|
+
if (!containerRef.current || 0 === items.length) return;
|
|
14419
|
+
const colWidth = (containerRef.current.offsetWidth - gap * (columns - 1)) / columns;
|
|
14420
|
+
columnHeights.current = Array(columns).fill(0);
|
|
14421
|
+
const newPositions = [];
|
|
14422
|
+
items.forEach(((item, index) => {
|
|
14423
|
+
if (item.ref.current) {
|
|
14424
|
+
// Find the shortest column
|
|
14425
|
+
const shortestCol = columnHeights.current.indexOf(Math.min(...columnHeights.current)), left = shortestCol * (colWidth + gap), top = columnHeights.current[shortestCol] ?? 0, height = item.ref.current.offsetHeight;
|
|
14426
|
+
columnHeights.current[shortestCol] = top + height + gap, newPositions[index] = {
|
|
14427
|
+
left: left,
|
|
14428
|
+
top: top,
|
|
14429
|
+
width: colWidth,
|
|
14430
|
+
height: height
|
|
14431
|
+
};
|
|
14328
14432
|
}
|
|
14329
|
-
|
|
14330
|
-
|
|
14331
|
-
|
|
14332
|
-
|
|
14333
|
-
|
|
14334
|
-
|
|
14335
|
-
|
|
14336
|
-
|
|
14337
|
-
setLoadingImages(!1), // This ensures the loading class is removed *immediately* after images load
|
|
14338
|
-
// Force a double requestAnimationFrame for final layout calculation after all images are loaded (guarantees DOM paint)
|
|
14339
|
-
requestAnimationFrame((() => {
|
|
14340
|
-
requestAnimationFrame((() => {
|
|
14341
|
-
calculateLayout(),
|
|
14342
|
-
// As a failsafe, if still present for some render lag, force another setLoadingImages(false)
|
|
14343
|
-
setLoadingImages(!1);
|
|
14344
|
-
}));
|
|
14345
|
-
})), onLayoutComplete?.());
|
|
14433
|
+
})), setPositions(newPositions);
|
|
14434
|
+
}), [ items, columns, gap ]), handleImageLoad = useCallback((img => {
|
|
14435
|
+
if (imageElements.current.get(img)) return;
|
|
14436
|
+
// Add loaded class for animation
|
|
14437
|
+
if (imageElements.current.set(img, !0), imagesLoadedCount.current += 1, containerRef.current && imagesLoaded) {
|
|
14438
|
+
const itemElement = img.closest(".o-masonry-grid > div");
|
|
14439
|
+
itemElement && (itemElement.offsetHeight, itemElement.classList.add("o-masonry-grid__item-loaded"),
|
|
14440
|
+
itemElement.classList.remove("o-masonry-grid__item-loading"));
|
|
14346
14441
|
}
|
|
14347
|
-
|
|
14442
|
+
// Schedule layout recalculation after next paint to prevent overlap
|
|
14443
|
+
const scheduleLayoutUpdate = () => {
|
|
14444
|
+
const frameId = requestAnimationFrame((() => {
|
|
14445
|
+
onImageLoad?.(imagesLoadedCount.current, totalImagesCount.current), calculateLayout();
|
|
14446
|
+
}));
|
|
14447
|
+
return () => cancelAnimationFrame(frameId);
|
|
14448
|
+
}, cleanup = scheduleLayoutUpdate();
|
|
14449
|
+
// Clean up previous scheduled updates
|
|
14450
|
+
// If all images have loaded, update loading state and complete layout
|
|
14451
|
+
imagesLoadedCount.current >= totalImagesCount.current && totalImagesCount.current > 0 && (setLayoutComplete(!0),
|
|
14452
|
+
setLoadingImages(!1), setTimeout((() => cleanup()), 0), // Clean up after current execution
|
|
14453
|
+
scheduleLayoutUpdate(), onLayoutComplete?.());
|
|
14454
|
+
}), [ onImageLoad, onLayoutComplete, imagesLoaded, calculateLayout ]), trackImages = useCallback((() => {
|
|
14348
14455
|
if (!imagesLoaded || !containerRef.current) return;
|
|
14349
14456
|
imageElements.current.clear(), imagesLoadedCount.current = 0;
|
|
14350
14457
|
const images = containerRef.current.querySelectorAll("img");
|
|
@@ -14363,30 +14470,21 @@ const MasonryGrid = forwardRef((({children: children, className: className = ""
|
|
|
14363
14470
|
img.removeEventListener("error", masonryImg._masonryLoadHandler), delete masonryImg._masonryLoadHandler);
|
|
14364
14471
|
}));
|
|
14365
14472
|
});
|
|
14366
|
-
}), [ imagesLoaded, handleImageLoad, onLayoutComplete ])
|
|
14367
|
-
|
|
14368
|
-
|
|
14369
|
-
columnHeights.current = Array(columns).fill(0);
|
|
14370
|
-
const newPositions = [];
|
|
14371
|
-
items.forEach(((item, index) => {
|
|
14372
|
-
if (item.ref.current) {
|
|
14373
|
-
// Find the shortest column
|
|
14374
|
-
const shortestCol = columnHeights.current.indexOf(Math.min(...columnHeights.current)), left = shortestCol * (colWidth + gap), top = columnHeights.current[shortestCol] ?? 0, height = item.ref.current.offsetHeight;
|
|
14375
|
-
columnHeights.current[shortestCol] = top + height + gap, newPositions[index] = {
|
|
14376
|
-
left: left,
|
|
14377
|
-
top: top,
|
|
14378
|
-
width: colWidth,
|
|
14379
|
-
height: height
|
|
14380
|
-
};
|
|
14381
|
-
}
|
|
14382
|
-
})), setPositions(newPositions);
|
|
14383
|
-
}), [ items, columns, gap ]);
|
|
14384
|
-
// === OBSERVE CONTAINER RESIZE ===
|
|
14473
|
+
}), [ imagesLoaded, handleImageLoad, onLayoutComplete ]);
|
|
14474
|
+
// === TRACK & MANAGE IMAGES ===
|
|
14475
|
+
// === OBSERVE CONTAINER RESIZE ===
|
|
14385
14476
|
useEffect((() => {
|
|
14386
14477
|
if (!containerRef.current) return;
|
|
14387
|
-
let animationFrame = null;
|
|
14388
|
-
const observer = new ResizeObserver((
|
|
14389
|
-
|
|
14478
|
+
let animationFrame = null, lastWidth = 0;
|
|
14479
|
+
const observer = new ResizeObserver((entries => {
|
|
14480
|
+
const entry = entries[0];
|
|
14481
|
+
if (!entry) return;
|
|
14482
|
+
const currentWidth = entry.contentRect.width;
|
|
14483
|
+
// Only recalculate if width actually changed (prevents excessive calculations)
|
|
14484
|
+
Math.abs(currentWidth - lastWidth) > 1 && (animationFrame && cancelAnimationFrame(animationFrame),
|
|
14485
|
+
animationFrame = requestAnimationFrame((() => {
|
|
14486
|
+
calculateLayout(), lastWidth = currentWidth;
|
|
14487
|
+
})));
|
|
14390
14488
|
}));
|
|
14391
14489
|
return observer.observe(containerRef.current), () => {
|
|
14392
14490
|
observer.disconnect(), animationFrame && cancelAnimationFrame(animationFrame);
|
|
@@ -14397,24 +14495,21 @@ const MasonryGrid = forwardRef((({children: children, className: className = ""
|
|
|
14397
14495
|
setLayoutComplete(!0), void setLoadingImages(!1))
|
|
14398
14496
|
// Only reset layoutComplete when items or columns change
|
|
14399
14497
|
), [ items, columns, calculateLayout, imagesLoaded, trackImages ]),
|
|
14400
|
-
// ===
|
|
14498
|
+
// === ADD RESIZEOBSERVERS TO GRID ITEMS FOR DYNAMIC CONTENT MEASUREMENT ===
|
|
14401
14499
|
React.useEffect((() => {
|
|
14402
|
-
// Clean up old observers if items ever change
|
|
14403
14500
|
const observers = [];
|
|
14501
|
+
let animationFrame = null;
|
|
14502
|
+
// Debounced layout calculation for item resize events
|
|
14503
|
+
const debouncedCalculateLayout = () => {
|
|
14504
|
+
animationFrame && cancelAnimationFrame(animationFrame), animationFrame = requestAnimationFrame(calculateLayout);
|
|
14505
|
+
};
|
|
14404
14506
|
return items.forEach((item => {
|
|
14405
14507
|
if (item.ref.current) {
|
|
14406
|
-
const obs = new ResizeObserver(
|
|
14407
|
-
// Double rAF: ensures layout only runs after DOM/paint/async renders
|
|
14408
|
-
requestAnimationFrame((() => {
|
|
14409
|
-
requestAnimationFrame((() => {
|
|
14410
|
-
calculateLayout();
|
|
14411
|
-
}));
|
|
14412
|
-
}));
|
|
14413
|
-
}));
|
|
14508
|
+
const obs = new ResizeObserver(debouncedCalculateLayout);
|
|
14414
14509
|
obs.observe(item.ref.current), observers.push(obs);
|
|
14415
14510
|
}
|
|
14416
14511
|
})), () => {
|
|
14417
|
-
observers.forEach((obs => obs.disconnect()));
|
|
14512
|
+
observers.forEach((obs => obs.disconnect())), animationFrame && cancelAnimationFrame(animationFrame);
|
|
14418
14513
|
};
|
|
14419
14514
|
}), [ items, calculateLayout ]);
|
|
14420
14515
|
// Ensure loadingImages state resets when items/columns/imagesLoaded change
|
|
@@ -15851,12 +15946,12 @@ const SideMenu = forwardRef((({title: title, children: children, menuItems: men
|
|
|
15851
15946
|
const index = Number(key);
|
|
15852
15947
|
index >= currentLength && (delete nestedWrapperRefs.current[index], delete nestedInnerRefs.current[index]);
|
|
15853
15948
|
})));
|
|
15854
|
-
}), [ menuItems
|
|
15949
|
+
}), [ menuItems ]);
|
|
15855
15950
|
// Helper function to update nested wrapper height
|
|
15856
|
-
const updateNestedHeight = (index, isOpen) => {
|
|
15951
|
+
const updateNestedHeight = useCallback(((index, isOpen) => {
|
|
15857
15952
|
const wrapper = nestedWrapperRefs.current[index], inner = nestedInnerRefs.current[index];
|
|
15858
15953
|
wrapper && inner && (wrapper.style.height = isOpen ? `${inner.scrollHeight}px` : "0px");
|
|
15859
|
-
};
|
|
15954
|
+
}), []);
|
|
15860
15955
|
// Set initial heights for nested wrappers on mount and when menuItems change
|
|
15861
15956
|
useEffect((() => {
|
|
15862
15957
|
if (!menuItems?.length) return;
|
|
@@ -15870,7 +15965,7 @@ const SideMenu = forwardRef((({title: title, children: children, menuItems: men
|
|
|
15870
15965
|
// Only run when menuItems change, nestedItemStates is read but not in deps to avoid loops
|
|
15871
15966
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
15872
15967
|
;
|
|
15873
|
-
}), [ menuItems
|
|
15968
|
+
}), [ menuItems, updateNestedHeight ]),
|
|
15874
15969
|
// Update nested wrapper heights when state changes
|
|
15875
15970
|
useEffect((() => {
|
|
15876
15971
|
if (!menuItems?.length) return;
|
|
@@ -15883,7 +15978,7 @@ const SideMenu = forwardRef((({title: title, children: children, menuItems: men
|
|
|
15883
15978
|
})), () => {
|
|
15884
15979
|
frameIds.forEach((id => cancelAnimationFrame(id)));
|
|
15885
15980
|
};
|
|
15886
|
-
}), [ nestedItemStates, menuItems
|
|
15981
|
+
}), [ nestedItemStates, menuItems, updateNestedHeight ]);
|
|
15887
15982
|
// Combine refs using utility
|
|
15888
15983
|
const combinedRef = useForkRef(sideMenuRef, ref), sideMenuClass = generateSideMenuClass({
|
|
15889
15984
|
className: className,
|
|
@@ -16770,7 +16865,7 @@ useEffect((() => {
|
|
|
16770
16865
|
}
|
|
16771
16866
|
};
|
|
16772
16867
|
}));
|
|
16773
|
-
}), [
|
|
16868
|
+
}), [ currentIndex, calculateBounds, constrainPosition ]), setImagePosition = useCallback((position => {
|
|
16774
16869
|
setImageStates((prev => {
|
|
16775
16870
|
const currentState = prev[currentIndex] || {
|
|
16776
16871
|
zoomLevel: 1,
|
|
@@ -16820,7 +16915,7 @@ useEffect((() => {
|
|
|
16820
16915
|
}
|
|
16821
16916
|
};
|
|
16822
16917
|
}));
|
|
16823
|
-
}), [
|
|
16918
|
+
}), [ currentIndex, calculateBounds, constrainPosition ]), handleWheel = useCallback((event => {
|
|
16824
16919
|
var _context;
|
|
16825
16920
|
if (!isMounted || !event || !event.currentTarget) return;
|
|
16826
16921
|
// Additional safety check for the target element
|
|
@@ -17177,7 +17272,7 @@ useEffect((() => {
|
|
|
17177
17272
|
}
|
|
17178
17273
|
return prev;
|
|
17179
17274
|
}));
|
|
17180
|
-
}), [
|
|
17275
|
+
}), [ enableGestures, isDragging, startDragPosition, currentIndex, constrainPosition, calculateBounds ]), handleTouchEnd = useCallback((() => {
|
|
17181
17276
|
setIsDragging(!1), lastDistanceRef.current = null, lastMidpointRef.current = null;
|
|
17182
17277
|
}), []), currentState = imageStates[currentIndex] || {
|
|
17183
17278
|
zoomLevel: 1,
|
|
@@ -17381,9 +17476,9 @@ const PopoverContext = createContext({
|
|
|
17381
17476
|
triggerType: "click"
|
|
17382
17477
|
}), Popover = ({content: content, position: position = "top", trigger: trigger = "click", className: className = "", style: style, delay: delay = 0, offset: offset = 12, defaultOpen: defaultOpen = !1, isOpen: controlledIsOpen, onOpenChange: onOpenChange, closeOnClickOutside: closeOnClickOutside = !0, closeOnEscape: closeOnEscape = !0, id: id, children: children, glass: glass}) => {
|
|
17383
17478
|
const {isOpen: isOpen, setIsOpen: setIsOpen, triggerRef: triggerRef, popoverRef: popoverRef, arrowRef: arrowRef, popoverId: popoverId, currentPosition: currentPosition, updatePosition: updatePosition} = (({position: position = "top", trigger: trigger = "click", offset: offset = 12, delay: delay = 0, defaultOpen: defaultOpen = !1, isOpen: controlledIsOpen, onOpenChange: onOpenChange, closeOnClickOutside: closeOnClickOutside = !0, closeOnEscape: closeOnEscape = !0, id: id}) => {
|
|
17384
|
-
const [isOpen, setIsOpenState] = useState(defaultOpen), [currentPosition, setCurrentPosition] = useState("auto" === position ? "top" : position), triggerRef = useRef(null), popoverRef = useRef(null), arrowRef = useRef(null), timeoutRef = useRef(null), popoverId = id || `popover-${Math.random().toString(36).slice(2, 11)}`, isControlled = void 0 !== controlledIsOpen, isOpenState = isControlled ? controlledIsOpen : isOpen, setIsOpen = newIsOpen => {
|
|
17479
|
+
const [isOpen, setIsOpenState] = useState(defaultOpen), [currentPosition, setCurrentPosition] = useState("auto" === position ? "top" : position), triggerRef = useRef(null), popoverRef = useRef(null), arrowRef = useRef(null), timeoutRef = useRef(null), popoverId = id || `popover-${Math.random().toString(36).slice(2, 11)}`, isControlled = void 0 !== controlledIsOpen, isOpenState = isControlled ? controlledIsOpen : isOpen, setIsOpen = useCallback((newIsOpen => {
|
|
17385
17480
|
isControlled || setIsOpenState(newIsOpen), onOpenChange && onOpenChange(newIsOpen);
|
|
17386
|
-
};
|
|
17481
|
+
}), [ isControlled, onOpenChange ]);
|
|
17387
17482
|
// Handle hover events if trigger is hover
|
|
17388
17483
|
useEffect((() => {
|
|
17389
17484
|
if ("hover" !== trigger || !triggerRef.current || !popoverRef.current) return;
|
|
@@ -17403,17 +17498,16 @@ const PopoverContext = createContext({
|
|
|
17403
17498
|
setIsOpen(!1);
|
|
17404
17499
|
};
|
|
17405
17500
|
// Add hover event listeners
|
|
17406
|
-
|
|
17407
|
-
|
|
17408
|
-
|
|
17409
|
-
|
|
17410
|
-
|
|
17411
|
-
|
|
17412
|
-
|
|
17413
|
-
null !== timeoutRef.current && window.clearTimeout(timeoutRef.current);
|
|
17501
|
+
triggerRef.current.addEventListener("mouseenter", handleTriggerMouseEnter), triggerRef.current.addEventListener("mouseleave", handleTriggerMouseLeave),
|
|
17502
|
+
popoverRef.current.addEventListener("mouseenter", handlePopoverMouseEnter), popoverRef.current.addEventListener("mouseleave", handlePopoverMouseLeave);
|
|
17503
|
+
const currentTrigger = triggerRef.current, currentPopover = popoverRef.current;
|
|
17504
|
+
return () => {
|
|
17505
|
+
currentTrigger && (currentTrigger.removeEventListener("mouseenter", handleTriggerMouseEnter),
|
|
17506
|
+
currentTrigger.removeEventListener("mouseleave", handleTriggerMouseLeave)), currentPopover && (currentPopover.removeEventListener("mouseenter", handlePopoverMouseEnter),
|
|
17507
|
+
currentPopover.removeEventListener("mouseleave", handlePopoverMouseLeave)), null !== timeoutRef.current && window.clearTimeout(timeoutRef.current);
|
|
17414
17508
|
};
|
|
17415
|
-
}), [ trigger, delay, isOpenState ]);
|
|
17416
|
-
const updatePosition = event => {
|
|
17509
|
+
}), [ trigger, delay, isOpenState, setIsOpen ]);
|
|
17510
|
+
const updatePosition = useCallback((event => {
|
|
17417
17511
|
if (!triggerRef.current || !popoverRef.current) return;
|
|
17418
17512
|
const triggerRect = triggerRef.current.getBoundingClientRect(), popoverRect = popoverRef.current.getBoundingClientRect(), viewportWidth = window.innerWidth, viewportHeight = window.innerHeight, isNearViewportEdge = triggerRect.top < 50 || triggerRect.bottom > viewportHeight - 50 || triggerRect.left < 50 || triggerRect.right > viewportWidth - 50;
|
|
17419
17513
|
// If this is a scroll update and trigger isn't near edges, skip repositioning
|
|
@@ -17474,9 +17568,9 @@ const PopoverContext = createContext({
|
|
|
17474
17568
|
// Add scroll position to convert viewport coordinates to absolute position
|
|
17475
17569
|
const absoluteTop = top + window.scrollY, absoluteLeft = left + window.scrollX;
|
|
17476
17570
|
// Apply position using absolute positioning to follow when scrolling
|
|
17477
|
-
popoverRef.current.style.position = "absolute", popoverRef.current.style.top = `${absoluteTop}px`,
|
|
17478
|
-
popoverRef.current.style.left = `${absoluteLeft}px
|
|
17479
|
-
};
|
|
17571
|
+
popoverRef.current && (popoverRef.current.style.position = "absolute", popoverRef.current.style.top = `${absoluteTop}px`,
|
|
17572
|
+
popoverRef.current.style.left = `${absoluteLeft}px`);
|
|
17573
|
+
}), [ position, offset ]);
|
|
17480
17574
|
// Position the popover
|
|
17481
17575
|
return useEffect((() => {
|
|
17482
17576
|
if (!isOpenState || !triggerRef.current || !popoverRef.current) return;
|
|
@@ -17502,7 +17596,7 @@ const PopoverContext = createContext({
|
|
|
17502
17596
|
window.removeEventListener("resize", updatePosition), window.removeEventListener("scroll", handleScroll),
|
|
17503
17597
|
scrollTimeout && clearTimeout(scrollTimeout), clearInterval(intervalId);
|
|
17504
17598
|
};
|
|
17505
|
-
}), [ isOpenState,
|
|
17599
|
+
}), [ isOpenState, updatePosition ]),
|
|
17506
17600
|
// Handle click outside to close popover
|
|
17507
17601
|
useEffect((() => {
|
|
17508
17602
|
if (!isOpenState || !closeOnClickOutside) return;
|
|
@@ -17512,7 +17606,7 @@ const PopoverContext = createContext({
|
|
|
17512
17606
|
return document.addEventListener("mousedown", handleClickOutside), () => {
|
|
17513
17607
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
17514
17608
|
};
|
|
17515
|
-
}), [ isOpenState, closeOnClickOutside ]),
|
|
17609
|
+
}), [ isOpenState, closeOnClickOutside, setIsOpen ]),
|
|
17516
17610
|
// Handle escape key to close popover
|
|
17517
17611
|
useEffect((() => {
|
|
17518
17612
|
if (!isOpenState || !closeOnEscape) return;
|
|
@@ -17522,7 +17616,7 @@ const PopoverContext = createContext({
|
|
|
17522
17616
|
return document.addEventListener("keydown", handleEscapeKey), () => {
|
|
17523
17617
|
document.removeEventListener("keydown", handleEscapeKey);
|
|
17524
17618
|
};
|
|
17525
|
-
}), [ isOpenState, closeOnEscape ]),
|
|
17619
|
+
}), [ isOpenState, closeOnEscape, setIsOpen ]),
|
|
17526
17620
|
// Clean up on unmount
|
|
17527
17621
|
useEffect((() => () => {
|
|
17528
17622
|
null !== timeoutRef.current && window.clearTimeout(timeoutRef.current);
|
|
@@ -17703,10 +17797,11 @@ const calculateStarValue = (e, starValue, allowHalf) => {
|
|
|
17703
17797
|
}), [ readOnly, onChange, allowHalf ]);
|
|
17704
17798
|
// Use vanilla JS implementation if specified
|
|
17705
17799
|
useEffect((() => {
|
|
17706
|
-
if (useVanillaJS
|
|
17800
|
+
if (!useVanillaJS || "undefined" == typeof window || !internalRef.current) return;
|
|
17801
|
+
const currentInstance = ratingInstance.current;
|
|
17707
17802
|
// Cleanup on unmount
|
|
17708
|
-
|
|
17709
|
-
|
|
17803
|
+
return () => {
|
|
17804
|
+
currentInstance && currentInstance.destroy();
|
|
17710
17805
|
};
|
|
17711
17806
|
}), [ useVanillaJS, valueProp, defaultValue, maxValue, allowHalf, readOnly, size, variant, onChange ]),
|
|
17712
17807
|
// Update vanilla JS implementation when props change
|
|
@@ -17827,10 +17922,11 @@ const ProductReview = ({productName: productName, productImage: productImage, in
|
|
|
17827
17922
|
const [rating, setRating] = useState(initialRating), [comment, setComment] = useState(""), [submitted, setSubmitted] = useState(!1), reviewRef = useRef(null), reviewInstance = useRef(null);
|
|
17828
17923
|
useEffect((() => {
|
|
17829
17924
|
// Only run on client-side
|
|
17830
|
-
if ("undefined"
|
|
17925
|
+
if ("undefined" == typeof window || !reviewRef.current) return;
|
|
17926
|
+
const currentInstance = reviewInstance.current;
|
|
17831
17927
|
// Cleanup on unmount
|
|
17832
|
-
|
|
17833
|
-
|
|
17928
|
+
return () => {
|
|
17929
|
+
currentInstance && currentInstance.destroy();
|
|
17834
17930
|
};
|
|
17835
17931
|
}), [ productName, productImage, initialRating, maxRating, allowHalf, ratingColor, onSubmit ]);
|
|
17836
17932
|
const handleSubmit = e => {
|
|
@@ -18075,10 +18171,11 @@ const SectionIntro = ({title: title, label: label, text: text, actions: actions,
|
|
|
18075
18171
|
const sectionIntroRef = useRef(null), sectionIntroInstance = useRef(null);
|
|
18076
18172
|
useEffect((() => {
|
|
18077
18173
|
// Only run on client-side
|
|
18078
|
-
if ("undefined"
|
|
18174
|
+
if ("undefined" == typeof window || !sectionIntroRef.current) return;
|
|
18175
|
+
const currentInstance = sectionIntroInstance.current;
|
|
18079
18176
|
// Cleanup on unmount
|
|
18080
|
-
|
|
18081
|
-
|
|
18177
|
+
return () => {
|
|
18178
|
+
currentInstance && currentInstance.destroy();
|
|
18082
18179
|
};
|
|
18083
18180
|
}), [ alignment, backgroundImageSrc, showOverlay, size, skeleton ]);
|
|
18084
18181
|
// Determine CSS classes
|
|
@@ -18162,7 +18259,7 @@ SectionIntro.displayName = "SectionIntro";
|
|
|
18162
18259
|
|
|
18163
18260
|
const Slider = forwardRef(((props, ref) => {
|
|
18164
18261
|
const {slides: slides = [], height: height = 300, width: width = "100%", slidesToShow: slidesToShow = 1, spaceBetween: spaceBetween = 0, loop: loop = !1, initialSlide: initialSlide = 0, direction: direction = "horizontal", speed: speed = 300, allowTouchMove: allowTouchMove = !0, threshold: threshold = 50, grabCursor: grabCursor = !0, autoplay: autoplay, navigation: navigation, pagination: pagination, className: className, style: style, onSlideChange: onSlideChange, ...rest} = props, validSlides = Array.isArray(slides) ? slides : [], slider = function(options) {
|
|
18165
|
-
const {slides: rawSlides, slidesToShow: slidesToShow = 1, spaceBetween: spaceBetween = 0, loop: loop = !1, initialSlide: initialSlide = 0, direction: direction = "horizontal", speed: speed = 300, allowTouchMove: allowTouchMove = !0, threshold: threshold = 50, autoplay: autoplay, onSlideChange: onSlideChange} = options, slides = Array.isArray(rawSlides) ? rawSlides : [], containerRef = useRef(null), wrapperRef = useRef(null), repositioningRef = useRef(!1), autoplayRef = useRef(null), [autoplayRunning, setAutoplayRunning] = useState(!1), sliderStateRef = useRef({
|
|
18262
|
+
const {slides: rawSlides, slidesToShow: slidesToShow = 1, spaceBetween: spaceBetween = 0, loop: loop = !1, initialSlide: initialSlide = 0, direction: direction = "horizontal", speed: speed = 300, allowTouchMove: allowTouchMove = !0, threshold: threshold = 50, autoplay: autoplay, onSlideChange: onSlideChange} = options, slides = useMemo((() => Array.isArray(rawSlides) ? rawSlides : []), [ rawSlides ]), containerRef = useRef(null), wrapperRef = useRef(null), repositioningRef = useRef(!1), autoplayRef = useRef(null), [autoplayRunning, setAutoplayRunning] = useState(!1), sliderStateRef = useRef({
|
|
18166
18263
|
isTransitioning: !1,
|
|
18167
18264
|
loop: loop,
|
|
18168
18265
|
slides: slides,
|
|
@@ -18297,7 +18394,7 @@ const Slider = forwardRef(((props, ref) => {
|
|
|
18297
18394
|
setIsTransitioning(!1), onSlideChange?.(nextIndex);
|
|
18298
18395
|
}), speed);
|
|
18299
18396
|
}
|
|
18300
|
-
}), [ realIndex, internalIndex, slides.length, slidesToShow, loop, isTransitioning, speed, onSlideChange,
|
|
18397
|
+
}), [ realIndex, internalIndex, slides.length, slidesToShow, loop, isTransitioning, speed, onSlideChange, autoplay ]), slidePrev = useCallback((() => {
|
|
18301
18398
|
if (!isTransitioning) if (
|
|
18302
18399
|
// Stop autoplay on interaction if disableOnInteraction is true
|
|
18303
18400
|
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
@@ -18319,7 +18416,7 @@ const Slider = forwardRef(((props, ref) => {
|
|
|
18319
18416
|
setIsTransitioning(!1), onSlideChange?.(prevIndex);
|
|
18320
18417
|
}), speed);
|
|
18321
18418
|
}
|
|
18322
|
-
}), [ realIndex, internalIndex, slides.length, loop, isTransitioning, speed, onSlideChange,
|
|
18419
|
+
}), [ realIndex, internalIndex, slides.length, loop, isTransitioning, speed, onSlideChange, autoplay ]), goToSlide = useCallback((index => {
|
|
18323
18420
|
isTransitioning || index === realIndex || (
|
|
18324
18421
|
// Stop autoplay on interaction if disableOnInteraction is true
|
|
18325
18422
|
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
@@ -18327,7 +18424,7 @@ const Slider = forwardRef(((props, ref) => {
|
|
|
18327
18424
|
setRealIndex(index), setInternalIndex(loop ? slides.length + index : index), setTimeout((() => {
|
|
18328
18425
|
setIsTransitioning(!1), onSlideChange?.(index);
|
|
18329
18426
|
}), speed));
|
|
18330
|
-
}), [ realIndex, isTransitioning, speed, onSlideChange, loop,
|
|
18427
|
+
}), [ realIndex, isTransitioning, speed, onSlideChange, loop, slides.length, autoplay ]), handleTouchStart = useCallback((e => {
|
|
18331
18428
|
if (!allowTouchMove) return;
|
|
18332
18429
|
// Stop autoplay on interaction if disableOnInteraction is true
|
|
18333
18430
|
autoplay && "object" == typeof autoplay && autoplay.disableOnInteraction && autoplayRef.current && (clearInterval(autoplayRef.current),
|
|
@@ -18582,7 +18679,7 @@ const Steps = ({items: items, activeIndex: activeIndex = 0, vertical: vertical =
|
|
|
18582
18679
|
let content;
|
|
18583
18680
|
useEffect((() => {
|
|
18584
18681
|
currentStep !== activeIndex && setCurrentStep(activeIndex);
|
|
18585
|
-
}), [ activeIndex ]),
|
|
18682
|
+
}), [ activeIndex, currentStep ]),
|
|
18586
18683
|
// Legacy rendering
|
|
18587
18684
|
content = items && items.length > 0 ? items.map(((item, index) => jsx(StepsItem, {
|
|
18588
18685
|
index: index,
|
|
@@ -18726,7 +18823,7 @@ const TabsPanel = forwardRef((({children: children, className: className = "",
|
|
|
18726
18823
|
|
|
18727
18824
|
TabsPanel.displayName = "TabsPanel";
|
|
18728
18825
|
|
|
18729
|
-
const
|
|
18826
|
+
const TabsComponentBase = ({items: items, activeIndex: activeIndex = TAB.DEFAULTS.ACTIVE_INDEX, onTabChange: onTabChange, className: className = "", style: style, glass: glass, children: children}) => {
|
|
18730
18827
|
const [currentTab, setCurrentTab] = useState(activeIndex), handleTabClick = index => {
|
|
18731
18828
|
setCurrentTab(index), onTabChange && onTabChange(index);
|
|
18732
18829
|
}, handleKeyDown = (event, totalTabs) => {
|
|
@@ -18842,7 +18939,7 @@ const Tabs = memo((({items: items, activeIndex: activeIndex = TAB.DEFAULTS.ACTI
|
|
|
18842
18939
|
});
|
|
18843
18940
|
}
|
|
18844
18941
|
return wrapper;
|
|
18845
|
-
})
|
|
18942
|
+
}, Tabs = memo(TabsComponentBase);
|
|
18846
18943
|
|
|
18847
18944
|
Tabs.displayName = "Tabs", Tabs.List = TabsList, Tabs.Trigger = TabsTrigger, Tabs.Panels = TabsPanels,
|
|
18848
18945
|
Tabs.Panel = TabsPanel;
|
|
@@ -18854,10 +18951,11 @@ const Testimonial = ({quote: quote, author: author, size: size = "", skeleton: s
|
|
|
18854
18951
|
const testimonialRef = useRef(null), testimonialInstance = useRef(null);
|
|
18855
18952
|
useEffect((() => {
|
|
18856
18953
|
// Only run on client-side
|
|
18857
|
-
if ("undefined"
|
|
18954
|
+
if ("undefined" == typeof window || !testimonialRef.current) return;
|
|
18955
|
+
const currentInstance = testimonialInstance.current;
|
|
18858
18956
|
// Cleanup on unmount
|
|
18859
|
-
|
|
18860
|
-
|
|
18957
|
+
return () => {
|
|
18958
|
+
currentInstance && currentInstance.destroy();
|
|
18861
18959
|
};
|
|
18862
18960
|
}), [ size, skeleton ]);
|
|
18863
18961
|
// Determine CSS classes
|
|
@@ -19998,11 +20096,13 @@ const VideoPlayer = forwardRef((({src: src, type: type = "video", youtubeId: yo
|
|
|
19998
20096
|
detectBorderRadius();
|
|
19999
20097
|
// Create ResizeObserver to watch for style changes
|
|
20000
20098
|
let resizeObserver = null;
|
|
20001
|
-
|
|
20099
|
+
"undefined" != typeof ResizeObserver && containerRef.current && (resizeObserver = new ResizeObserver(detectBorderRadius),
|
|
20002
20100
|
resizeObserver.observe(containerRef.current)),
|
|
20003
20101
|
// Also listen for window resize (in case styles change)
|
|
20004
|
-
window.addEventListener("resize", detectBorderRadius)
|
|
20005
|
-
|
|
20102
|
+
window.addEventListener("resize", detectBorderRadius);
|
|
20103
|
+
const currentContainer = containerRef.current;
|
|
20104
|
+
return () => {
|
|
20105
|
+
window.removeEventListener("resize", detectBorderRadius), resizeObserver && currentContainer && (resizeObserver.unobserve(currentContainer),
|
|
20006
20106
|
resizeObserver.disconnect());
|
|
20007
20107
|
};
|
|
20008
20108
|
}), []);
|
|
@@ -20757,7 +20857,51 @@ const components = Object.freeze( Object.defineProperty({
|
|
|
20757
20857
|
"breakpoint-md": "768px",
|
|
20758
20858
|
"breakpoint-lg": "992px",
|
|
20759
20859
|
"breakpoint-xl": "1200px",
|
|
20760
|
-
"breakpoint-xxl": "1440px"
|
|
20860
|
+
"breakpoint-xxl": "1440px",
|
|
20861
|
+
// Advanced Features - Interactive Effects (Phase 2)
|
|
20862
|
+
"interactive-vortex-enabled": "false",
|
|
20863
|
+
"interactive-vortex-strength": "0.5",
|
|
20864
|
+
"interactive-vortex-radius": "100",
|
|
20865
|
+
"interactive-vortex-decay": "0.8",
|
|
20866
|
+
"interactive-chromatic-enabled": "false",
|
|
20867
|
+
"interactive-chromatic-mode": "lateral",
|
|
20868
|
+
"interactive-chromatic-red-shift": "0.02",
|
|
20869
|
+
"interactive-chromatic-green-shift": "0",
|
|
20870
|
+
"interactive-chromatic-blue-shift": "-0.02",
|
|
20871
|
+
"interactive-chromatic-edge-only": "false",
|
|
20872
|
+
"interactive-chromatic-edge-threshold": "0.5",
|
|
20873
|
+
"interactive-mouse-sensitivity": "1.0",
|
|
20874
|
+
"interactive-mouse-trail-effect": "false",
|
|
20875
|
+
"interactive-animation-speed-base": "1.0",
|
|
20876
|
+
"interactive-animation-speed-multiplier": "1.0",
|
|
20877
|
+
// Advanced Features - Optimization (Phase 3)
|
|
20878
|
+
"optimization-breakpoint-mobile": "0px",
|
|
20879
|
+
"optimization-breakpoint-tablet": "768px",
|
|
20880
|
+
"optimization-breakpoint-desktop": "1024px",
|
|
20881
|
+
"optimization-breakpoint-wide": "1440px",
|
|
20882
|
+
"optimization-device-scaling-mobile": "0.5",
|
|
20883
|
+
"optimization-device-scaling-tablet": "0.75",
|
|
20884
|
+
"optimization-device-scaling-desktop": "1.0",
|
|
20885
|
+
"optimization-performance-fps-target": "60",
|
|
20886
|
+
"optimization-auto-scaling-enabled": "false",
|
|
20887
|
+
"optimization-auto-scaling-low-end": "0.5",
|
|
20888
|
+
"optimization-auto-scaling-mid-range": "0.75",
|
|
20889
|
+
"optimization-auto-scaling-high-end": "1.0",
|
|
20890
|
+
// Advanced Features - Visual Polish (Phase 4)
|
|
20891
|
+
"visual-polish-border-iridescent-glow": "false",
|
|
20892
|
+
"visual-polish-border-shimmer-effect": "false",
|
|
20893
|
+
"visual-polish-border-beveled-edges": "false",
|
|
20894
|
+
"visual-polish-border-pulsing-glow": "false",
|
|
20895
|
+
"visual-polish-content-aware-blur-enabled": "false",
|
|
20896
|
+
"visual-polish-content-aware-depth-detection": "false",
|
|
20897
|
+
"visual-polish-content-aware-edge-preservation": "false",
|
|
20898
|
+
"visual-polish-content-aware-variable-radius": "false",
|
|
20899
|
+
"visual-polish-holographic-enabled": "false",
|
|
20900
|
+
"visual-polish-holographic-rainbow-diffraction": "false",
|
|
20901
|
+
"visual-polish-holographic-scanline-animation": "false",
|
|
20902
|
+
"visual-polish-holographic-grid-overlay": "false",
|
|
20903
|
+
"visual-polish-holographic-data-stream": "false",
|
|
20904
|
+
"visual-polish-holographic-pulse-rings": "false"
|
|
20761
20905
|
};
|
|
20762
20906
|
|
|
20763
20907
|
// Export all component types
|
|
@@ -20839,202 +20983,644 @@ function createTokens(overrides) {
|
|
|
20839
20983
|
}
|
|
20840
20984
|
|
|
20841
20985
|
/**
|
|
20842
|
-
* Theme
|
|
20986
|
+
* Theme Adapter
|
|
20843
20987
|
*
|
|
20844
|
-
*
|
|
20845
|
-
* Provides custom error classes and logging utilities.
|
|
20988
|
+
* Converts between Theme objects and DesignTokens
|
|
20846
20989
|
*/
|
|
20847
20990
|
/**
|
|
20848
|
-
* Theme
|
|
20849
|
-
*/
|
|
20850
|
-
|
|
20851
|
-
|
|
20852
|
-
|
|
20853
|
-
|
|
20854
|
-
|
|
20855
|
-
|
|
20856
|
-
|
|
20857
|
-
|
|
20858
|
-
|
|
20859
|
-
|
|
20860
|
-
|
|
20861
|
-
|
|
20862
|
-
|
|
20863
|
-
|
|
20864
|
-
|
|
20865
|
-
|
|
20866
|
-
|
|
20867
|
-
|
|
20868
|
-
|
|
20869
|
-
|
|
20870
|
-
|
|
20871
|
-
|
|
20872
|
-
|
|
20873
|
-
|
|
20874
|
-
|
|
20875
|
-
|
|
20876
|
-
|
|
20877
|
-
|
|
20878
|
-
|
|
20879
|
-
ThemeErrorCode.INVALID_TOKEN_TYPE = "INVALID_TOKEN_TYPE",
|
|
20880
|
-
/** Unknown error */
|
|
20881
|
-
ThemeErrorCode.UNKNOWN_ERROR = "UNKNOWN_ERROR";
|
|
20882
|
-
}(ThemeErrorCode || (ThemeErrorCode = {}));
|
|
20883
|
-
|
|
20884
|
-
/**
|
|
20885
|
-
* Custom error class for theme-related errors
|
|
20886
|
-
*/
|
|
20887
|
-
class ThemeError extends Error {
|
|
20888
|
-
constructor(message, code = ThemeErrorCode.UNKNOWN_ERROR, context) {
|
|
20889
|
-
super(message), this.name = "ThemeError", this.code = code, this.context = context,
|
|
20890
|
-
this.timestamp = Date.now(),
|
|
20891
|
-
// Maintains proper stack trace for where our error was thrown (only available on V8)
|
|
20892
|
-
Error.captureStackTrace && Error.captureStackTrace(this, ThemeError);
|
|
20991
|
+
* Convert a Theme object to DesignTokens
|
|
20992
|
+
*/ function themeToDesignTokens(theme) {
|
|
20993
|
+
const tokens = {};
|
|
20994
|
+
// Convert colors
|
|
20995
|
+
if (theme.palette) {
|
|
20996
|
+
// Primary color
|
|
20997
|
+
if (theme.palette.primary) {
|
|
20998
|
+
const primaryMain = theme.palette.primary.main;
|
|
20999
|
+
tokens.primary = primaryMain;
|
|
21000
|
+
const rgb = hexToRgb$2(primaryMain);
|
|
21001
|
+
rgb && (tokens["primary-rgb"] = rgb);
|
|
21002
|
+
}
|
|
21003
|
+
// Secondary color
|
|
21004
|
+
if (theme.palette.secondary) {
|
|
21005
|
+
const secondaryMain = theme.palette.secondary.main;
|
|
21006
|
+
tokens.secondary = secondaryMain;
|
|
21007
|
+
const rgb = hexToRgb$2(secondaryMain);
|
|
21008
|
+
rgb && (tokens["secondary-rgb"] = rgb);
|
|
21009
|
+
}
|
|
21010
|
+
// Other colors
|
|
21011
|
+
const colorKeys = [ "error", "warning", "info", "success" ];
|
|
21012
|
+
for (const key of colorKeys) if (theme.palette[key]) {
|
|
21013
|
+
const colorMain = theme.palette[key].main;
|
|
21014
|
+
tokens[key] = colorMain;
|
|
21015
|
+
const rgb = hexToRgb$2(colorMain);
|
|
21016
|
+
rgb && (tokens[`${key}-rgb`] = rgb);
|
|
21017
|
+
}
|
|
21018
|
+
// Background colors
|
|
21019
|
+
theme.palette.background && (tokens["body-bg"] = theme.palette.background.default),
|
|
21020
|
+
// Text colors
|
|
21021
|
+
theme.palette.text && (tokens["body-color"] = theme.palette.text.primary);
|
|
20893
21022
|
}
|
|
20894
|
-
|
|
20895
|
-
|
|
20896
|
-
|
|
20897
|
-
|
|
20898
|
-
|
|
20899
|
-
|
|
20900
|
-
|
|
20901
|
-
|
|
20902
|
-
|
|
20903
|
-
|
|
20904
|
-
|
|
21023
|
+
// Convert typography
|
|
21024
|
+
// Convert border radius
|
|
21025
|
+
if (theme.typography && (tokens["body-font-family"] = theme.typography.fontFamily,
|
|
21026
|
+
tokens["body-font-size"] = `${theme.typography.fontSize}px`, tokens["font-weight-normal"] = `${theme.typography.fontWeightRegular}`,
|
|
21027
|
+
tokens["font-weight-bold"] = `${theme.typography.fontWeightBold}`),
|
|
21028
|
+
// Convert spacing
|
|
21029
|
+
"function" == typeof theme.spacing && (
|
|
21030
|
+
// If spacing is a function, call it with some values to get results
|
|
21031
|
+
tokens["spacing-1"] = theme.spacing(1), tokens["spacing-2"] = theme.spacing(2),
|
|
21032
|
+
tokens["spacing-4"] = theme.spacing(4)),
|
|
21033
|
+
// Convert breakpoints
|
|
21034
|
+
theme.breakpoints?.values && (tokens["breakpoint-xs"] = `${theme.breakpoints.values.xs}px`,
|
|
21035
|
+
tokens["breakpoint-sm"] = `${theme.breakpoints.values.sm}px`, tokens["breakpoint-md"] = `${theme.breakpoints.values.md}px`,
|
|
21036
|
+
tokens["breakpoint-lg"] = `${theme.breakpoints.values.lg}px`, tokens["breakpoint-xl"] = `${theme.breakpoints.values.xl}px`),
|
|
21037
|
+
// Convert shadows
|
|
21038
|
+
theme.shadows && (tokens["box-shadow"] = theme.shadows[2], // Use a moderate shadow
|
|
21039
|
+
tokens["box-shadow-sm"] = theme.shadows[1], tokens["box-shadow-lg"] = theme.shadows[3]),
|
|
21040
|
+
// Convert transitions
|
|
21041
|
+
theme.transitions && (tokens["transition-duration-base"] = `${theme.transitions.duration.standard}ms`),
|
|
21042
|
+
// Convert z-index
|
|
21043
|
+
theme.zIndex && (tokens["z-modal"] = `${theme.zIndex.modal}`, tokens["z-popover"] = `${theme.zIndex.popover}`,
|
|
21044
|
+
tokens["z-tooltip"] = `${theme.zIndex.tooltip}`), theme.borderRadius) {
|
|
21045
|
+
const baseRadius = theme.borderRadius.base;
|
|
21046
|
+
tokens["border-radius"] = "number" == typeof baseRadius ? `${baseRadius}px` : baseRadius;
|
|
21047
|
+
}
|
|
21048
|
+
// Add advanced feature tokens if available in theme
|
|
21049
|
+
if (theme.custom) {
|
|
21050
|
+
// Interactive Effects (Phase 2)
|
|
21051
|
+
if (theme.custom.interactiveEffects) {
|
|
21052
|
+
const ie = theme.custom.interactiveEffects;
|
|
21053
|
+
// Vortex effects
|
|
21054
|
+
ie.vortex && (tokens["interactive-vortex-enabled"] = String(ie.vortex.enabled ?? !1),
|
|
21055
|
+
tokens["interactive-vortex-strength"] = String(ie.vortex.strength ?? .5), tokens["interactive-vortex-radius"] = String(ie.vortex.radius ?? 100),
|
|
21056
|
+
tokens["interactive-vortex-decay"] = String(ie.vortex.decay ?? .8)),
|
|
21057
|
+
// Chromatic aberration
|
|
21058
|
+
ie.chromaticAberration && (tokens["interactive-chromatic-enabled"] = String(ie.chromaticAberration.enabled ?? !1),
|
|
21059
|
+
tokens["interactive-chromatic-mode"] = ie.chromaticAberration.mode ?? "lateral",
|
|
21060
|
+
tokens["interactive-chromatic-red-shift"] = String(ie.chromaticAberration.redShift ?? .02),
|
|
21061
|
+
tokens["interactive-chromatic-green-shift"] = String(ie.chromaticAberration.greenShift ?? 0),
|
|
21062
|
+
tokens["interactive-chromatic-blue-shift"] = String(ie.chromaticAberration.blueShift ?? -.02),
|
|
21063
|
+
tokens["interactive-chromatic-edge-only"] = String(ie.chromaticAberration.edgeOnly ?? !1),
|
|
21064
|
+
tokens["interactive-chromatic-edge-threshold"] = String(ie.chromaticAberration.edgeThreshold ?? .5)),
|
|
21065
|
+
// Mouse interaction
|
|
21066
|
+
ie.mouseInteraction && (tokens["interactive-mouse-sensitivity"] = String(ie.mouseInteraction.sensitivity ?? 1),
|
|
21067
|
+
tokens["interactive-mouse-trail-effect"] = String(ie.mouseInteraction.trailEffect ?? !1)),
|
|
21068
|
+
// Animation speed
|
|
21069
|
+
ie.animationSpeed && (tokens["interactive-animation-speed-base"] = String(ie.animationSpeed.base ?? 1),
|
|
21070
|
+
tokens["interactive-animation-speed-multiplier"] = String(ie.animationSpeed.timeMultiplier ?? 1));
|
|
21071
|
+
}
|
|
21072
|
+
// Optimization (Phase 3)
|
|
21073
|
+
if (theme.custom.optimization) {
|
|
21074
|
+
const opt = theme.custom.optimization;
|
|
21075
|
+
// Responsive breakpoints
|
|
21076
|
+
opt.responsive && (opt.responsive.breakpoints && (tokens["optimization-breakpoint-mobile"] = opt.responsive.breakpoints.mobile ?? "0px",
|
|
21077
|
+
tokens["optimization-breakpoint-tablet"] = opt.responsive.breakpoints.tablet ?? "768px",
|
|
21078
|
+
tokens["optimization-breakpoint-desktop"] = opt.responsive.breakpoints.desktop ?? "1024px",
|
|
21079
|
+
tokens["optimization-breakpoint-wide"] = opt.responsive.breakpoints.wide ?? "1440px"),
|
|
21080
|
+
opt.responsive.deviceScaling && (tokens["optimization-device-scaling-mobile"] = String(opt.responsive.deviceScaling.mobile ?? .5),
|
|
21081
|
+
tokens["optimization-device-scaling-tablet"] = String(opt.responsive.deviceScaling.tablet ?? .75),
|
|
21082
|
+
tokens["optimization-device-scaling-desktop"] = String(opt.responsive.deviceScaling.desktop ?? 1))),
|
|
21083
|
+
// Performance settings
|
|
21084
|
+
opt.performance && (tokens["optimization-performance-fps-target"] = String(opt.performance.fpsTarget ?? 60),
|
|
21085
|
+
tokens["optimization-auto-scaling-enabled"] = String(opt.performance.autoScaling ?? !1)),
|
|
21086
|
+
// Auto-scaling settings
|
|
21087
|
+
opt.autoScaling && (tokens["optimization-auto-scaling-enabled"] = String(opt.autoScaling.enabled ?? !1),
|
|
21088
|
+
tokens["optimization-auto-scaling-low-end"] = String(opt.autoScaling.qualityThresholds?.lowEnd ?? .5),
|
|
21089
|
+
tokens["optimization-auto-scaling-mid-range"] = String(opt.autoScaling.qualityThresholds?.midRange ?? .75),
|
|
21090
|
+
tokens["optimization-auto-scaling-high-end"] = String(opt.autoScaling.qualityThresholds?.highEnd ?? 1));
|
|
21091
|
+
}
|
|
21092
|
+
// Visual Polish (Phase 4)
|
|
21093
|
+
if (theme.custom.visualPolish) {
|
|
21094
|
+
const vp = theme.custom.visualPolish;
|
|
21095
|
+
vp.borders && (tokens["visual-polish-border-iridescent-glow"] = String(vp.borders.iridescentGlow ?? !1),
|
|
21096
|
+
tokens["visual-polish-border-shimmer-effect"] = String(vp.borders.shimmerEffect ?? !1),
|
|
21097
|
+
tokens["visual-polish-border-beveled-edges"] = String(vp.borders.beveledEdges ?? !1),
|
|
21098
|
+
tokens["visual-polish-border-pulsing-glow"] = String(vp.borders.pulsingGlow ?? !1)),
|
|
21099
|
+
vp.contentAwareBlur && (tokens["visual-polish-content-aware-blur-enabled"] = String(vp.contentAwareBlur.enabled ?? !1),
|
|
21100
|
+
tokens["visual-polish-content-aware-depth-detection"] = String(vp.contentAwareBlur.depthDetection ?? !1),
|
|
21101
|
+
tokens["visual-polish-content-aware-edge-preservation"] = String(vp.contentAwareBlur.edgePreservation ?? !1),
|
|
21102
|
+
tokens["visual-polish-content-aware-variable-radius"] = String(vp.contentAwareBlur.variableRadius ?? !1)),
|
|
21103
|
+
vp.holographicEffects && (tokens["visual-polish-holographic-enabled"] = String(vp.holographicEffects.enabled ?? !1),
|
|
21104
|
+
tokens["visual-polish-holographic-rainbow-diffraction"] = String(vp.holographicEffects.rainbowDiffraction ?? !1),
|
|
21105
|
+
tokens["visual-polish-holographic-scanline-animation"] = String(vp.holographicEffects.scanlineAnimation ?? !1),
|
|
21106
|
+
tokens["visual-polish-holographic-grid-overlay"] = String(vp.holographicEffects.gridOverlay ?? !1),
|
|
21107
|
+
tokens["visual-polish-holographic-data-stream"] = String(vp.holographicEffects.dataStream ?? !1),
|
|
21108
|
+
tokens["visual-polish-holographic-pulse-rings"] = String(vp.holographicEffects.pulseRings ?? !1));
|
|
21109
|
+
}
|
|
20905
21110
|
}
|
|
21111
|
+
// Create full tokens object with defaults
|
|
21112
|
+
return createTokens(tokens);
|
|
20906
21113
|
}
|
|
20907
21114
|
|
|
20908
21115
|
/**
|
|
20909
|
-
*
|
|
20910
|
-
*/ !function(LogLevel) {
|
|
20911
|
-
LogLevel[LogLevel.ERROR = 0] = "ERROR", LogLevel[LogLevel.WARN = 1] = "WARN", LogLevel[LogLevel.INFO = 2] = "INFO",
|
|
20912
|
-
LogLevel[LogLevel.DEBUG = 3] = "DEBUG";
|
|
20913
|
-
}(LogLevel || (LogLevel = {}));
|
|
20914
|
-
|
|
20915
|
-
/**
|
|
20916
|
-
* Theme Logger
|
|
21116
|
+
* Converts an AtomixConfig to DesignTokens
|
|
20917
21117
|
*
|
|
20918
|
-
*
|
|
20919
|
-
*
|
|
20920
|
-
|
|
20921
|
-
|
|
20922
|
-
|
|
20923
|
-
|
|
20924
|
-
|
|
20925
|
-
|
|
20926
|
-
|
|
20927
|
-
|
|
20928
|
-
|
|
20929
|
-
|
|
20930
|
-
|
|
20931
|
-
|
|
20932
|
-
|
|
20933
|
-
|
|
20934
|
-
|
|
20935
|
-
|
|
20936
|
-
|
|
20937
|
-
|
|
20938
|
-
|
|
20939
|
-
|
|
20940
|
-
|
|
20941
|
-
|
|
20942
|
-
|
|
20943
|
-
|
|
20944
|
-
|
|
20945
|
-
|
|
20946
|
-
|
|
20947
|
-
|
|
20948
|
-
|
|
20949
|
-
|
|
20950
|
-
|
|
20951
|
-
|
|
20952
|
-
|
|
20953
|
-
|
|
20954
|
-
|
|
20955
|
-
|
|
20956
|
-
|
|
20957
|
-
|
|
20958
|
-
|
|
20959
|
-
|
|
20960
|
-
|
|
20961
|
-
|
|
21118
|
+
* This function maps the configuration from the user-facing format
|
|
21119
|
+
* to the internal DesignTokens format used by the theme system.
|
|
21120
|
+
*
|
|
21121
|
+
* @param config - The configuration object to convert
|
|
21122
|
+
* @returns DesignTokens object ready for theme generation
|
|
21123
|
+
*
|
|
21124
|
+
* @example
|
|
21125
|
+
* ```typescript
|
|
21126
|
+
* import { configToTokens } from '@shohojdhara/atomix/theme';
|
|
21127
|
+
*
|
|
21128
|
+
* const config = {
|
|
21129
|
+
* prefix: 'myapp',
|
|
21130
|
+
* theme: { extend: { colors: { primary: { main: '#7AFFD7' } } } }
|
|
21131
|
+
* };
|
|
21132
|
+
* const tokens = configToTokens(config);
|
|
21133
|
+
* ```
|
|
21134
|
+
*/ function configToTokens(config) {
|
|
21135
|
+
const prefix = config.prefix || "atomix", theme = config.theme || {};
|
|
21136
|
+
// Start with default tokens
|
|
21137
|
+
let tokens = {
|
|
21138
|
+
...defaultTokens
|
|
21139
|
+
};
|
|
21140
|
+
// Apply theme extensions
|
|
21141
|
+
// Apply advanced features if available in config
|
|
21142
|
+
if (theme.extend &&
|
|
21143
|
+
// Apply extensions to tokens
|
|
21144
|
+
Object.entries(theme.extend).forEach((([category, values]) => {
|
|
21145
|
+
"object" == typeof values && null !== values && Object.entries(values).forEach((([key, value]) => {
|
|
21146
|
+
// Map theme categories to token names
|
|
21147
|
+
const tokenName = `${category}-${key}`;
|
|
21148
|
+
"string" == typeof value || "number" == typeof value ? tokens[tokenName] = String(value) : "object" == typeof value && null !== value &&
|
|
21149
|
+
// Handle nested objects like color scales
|
|
21150
|
+
Object.entries(value).forEach((([nestedKey, nestedValue]) => {
|
|
21151
|
+
"string" != typeof nestedValue && "number" != typeof nestedValue || (tokens[`${tokenName}-${nestedKey}`] = String(nestedValue));
|
|
21152
|
+
}));
|
|
21153
|
+
}));
|
|
21154
|
+
})),
|
|
21155
|
+
// Apply theme tokens if provided (completely replacing defaults)
|
|
21156
|
+
theme.tokens && (tokens = {
|
|
21157
|
+
...tokens,
|
|
21158
|
+
...theme.tokens
|
|
21159
|
+
}), config) {
|
|
21160
|
+
// Interactive Effects (Phase 2)
|
|
21161
|
+
if (config.interactiveEffects) {
|
|
21162
|
+
const ie = config.interactiveEffects;
|
|
21163
|
+
// Vortex effects
|
|
21164
|
+
ie.vortex && (tokens["interactive-vortex-enabled"] = String(ie.vortex.enabled ?? !1),
|
|
21165
|
+
tokens["interactive-vortex-strength"] = String(ie.vortex.strength ?? .5), tokens["interactive-vortex-radius"] = String(ie.vortex.radius ?? 100),
|
|
21166
|
+
tokens["interactive-vortex-decay"] = String(ie.vortex.decay ?? .8), tokens["interactive-vortex-curl-noise"] = String(ie.vortex.curlNoise ?? !1),
|
|
21167
|
+
tokens["interactive-vortex-velocity-tracking"] = String(ie.vortex.velocityTracking ?? !1)),
|
|
21168
|
+
// Chromatic aberration
|
|
21169
|
+
ie.chromaticAberration && (tokens["interactive-chromatic-enabled"] = String(ie.chromaticAberration.enabled ?? !1),
|
|
21170
|
+
tokens["interactive-chromatic-mode"] = ie.chromaticAberration.mode ?? "lateral",
|
|
21171
|
+
tokens["interactive-chromatic-red-shift"] = String(ie.chromaticAberration.redShift ?? .02),
|
|
21172
|
+
tokens["interactive-chromatic-green-shift"] = String(ie.chromaticAberration.greenShift ?? 0),
|
|
21173
|
+
tokens["interactive-chromatic-blue-shift"] = String(ie.chromaticAberration.blueShift ?? -.02),
|
|
21174
|
+
tokens["interactive-chromatic-edge-only"] = String(ie.chromaticAberration.edgeOnly ?? !1),
|
|
21175
|
+
tokens["interactive-chromatic-edge-threshold"] = String(ie.chromaticAberration.edgeThreshold ?? .5)),
|
|
21176
|
+
// Mouse interaction
|
|
21177
|
+
ie.mouseInteraction && (tokens["interactive-mouse-sensitivity"] = String(ie.mouseInteraction.sensitivity ?? 1),
|
|
21178
|
+
tokens["interactive-mouse-trail-effect"] = String(ie.mouseInteraction.trailEffect ?? !1),
|
|
21179
|
+
tokens["interactive-mouse-pressure-sensitivity"] = String(ie.mouseInteraction.pressureSensitivity ?? !1)),
|
|
21180
|
+
// Animation speed
|
|
21181
|
+
ie.animationSpeed && (tokens["interactive-animation-speed-base"] = String(ie.animationSpeed.base ?? 1),
|
|
21182
|
+
tokens["interactive-animation-speed-multiplier"] = String(ie.animationSpeed.timeMultiplier ?? 1));
|
|
21183
|
+
}
|
|
21184
|
+
// Optimization (Phase 3)
|
|
21185
|
+
if (config.optimization) {
|
|
21186
|
+
const opt = config.optimization;
|
|
21187
|
+
// Responsive breakpoints
|
|
21188
|
+
opt.responsive && (opt.responsive.breakpoints && (tokens["optimization-breakpoint-mobile"] = opt.responsive.breakpoints.mobile ?? "0px",
|
|
21189
|
+
tokens["optimization-breakpoint-tablet"] = opt.responsive.breakpoints.tablet ?? "768px",
|
|
21190
|
+
tokens["optimization-breakpoint-desktop"] = opt.responsive.breakpoints.desktop ?? "1024px",
|
|
21191
|
+
tokens["optimization-breakpoint-wide"] = opt.responsive.breakpoints.wide ?? "1440px"),
|
|
21192
|
+
opt.responsive.deviceScaling && (tokens["optimization-device-scaling-mobile"] = String(opt.responsive.deviceScaling.mobile ?? .5),
|
|
21193
|
+
tokens["optimization-device-scaling-tablet"] = String(opt.responsive.deviceScaling.tablet ?? .75),
|
|
21194
|
+
tokens["optimization-device-scaling-desktop"] = String(opt.responsive.deviceScaling.desktop ?? 1))),
|
|
21195
|
+
// Performance settings
|
|
21196
|
+
opt.performance && (tokens["optimization-performance-fps-target"] = String(opt.performance.fpsTarget ?? 60),
|
|
21197
|
+
tokens["optimization-auto-scaling-enabled"] = String(opt.performance.autoScaling ?? !1),
|
|
21198
|
+
tokens["optimization-monitor-dashboard-enabled"] = String(opt.performance.monitorDashboard ?? !1)),
|
|
21199
|
+
// Auto-scaling settings
|
|
21200
|
+
opt.autoScaling && (tokens["optimization-auto-scaling-enabled"] = String(opt.autoScaling.enabled ?? !1),
|
|
21201
|
+
tokens["optimization-auto-scaling-low-end"] = String(opt.autoScaling.qualityThresholds?.lowEnd ?? .5),
|
|
21202
|
+
tokens["optimization-auto-scaling-mid-range"] = String(opt.autoScaling.qualityThresholds?.midRange ?? .75),
|
|
21203
|
+
tokens["optimization-auto-scaling-high-end"] = String(opt.autoScaling.qualityThresholds?.highEnd ?? 1));
|
|
21204
|
+
}
|
|
21205
|
+
// Visual Polish (Phase 4)
|
|
21206
|
+
if (config.visualPolish) {
|
|
21207
|
+
const vp = config.visualPolish;
|
|
21208
|
+
vp.borders && (tokens["visual-polish-border-iridescent-glow"] = String(vp.borders.iridescentGlow ?? !1),
|
|
21209
|
+
tokens["visual-polish-border-shimmer-effect"] = String(vp.borders.shimmerEffect ?? !1),
|
|
21210
|
+
tokens["visual-polish-border-beveled-edges"] = String(vp.borders.beveledEdges ?? !1),
|
|
21211
|
+
tokens["visual-polish-border-pulsing-glow"] = String(vp.borders.pulsingGlow ?? !1)),
|
|
21212
|
+
vp.contentAwareBlur && (tokens["visual-polish-content-aware-blur-enabled"] = String(vp.contentAwareBlur.enabled ?? !1),
|
|
21213
|
+
tokens["visual-polish-content-aware-depth-detection"] = String(vp.contentAwareBlur.depthDetection ?? !1),
|
|
21214
|
+
tokens["visual-polish-content-aware-edge-preservation"] = String(vp.contentAwareBlur.edgePreservation ?? !1),
|
|
21215
|
+
tokens["visual-polish-content-aware-variable-radius"] = String(vp.contentAwareBlur.variableRadius ?? !1)),
|
|
21216
|
+
vp.holographicEffects && (tokens["visual-polish-holographic-enabled"] = String(vp.holographicEffects.enabled ?? !1),
|
|
21217
|
+
tokens["visual-polish-holographic-rainbow-diffraction"] = String(vp.holographicEffects.rainbowDiffraction ?? !1),
|
|
21218
|
+
tokens["visual-polish-holographic-scanline-animation"] = String(vp.holographicEffects.scanlineAnimation ?? !1),
|
|
21219
|
+
tokens["visual-polish-holographic-grid-overlay"] = String(vp.holographicEffects.gridOverlay ?? !1),
|
|
21220
|
+
tokens["visual-polish-holographic-data-stream"] = String(vp.holographicEffects.dataStream ?? !1),
|
|
21221
|
+
tokens["visual-polish-holographic-pulse-rings"] = String(vp.holographicEffects.pulseRings ?? !1));
|
|
21222
|
+
}
|
|
20962
21223
|
}
|
|
21224
|
+
// Apply prefix to all tokens
|
|
21225
|
+
const prefixedTokens = {};
|
|
21226
|
+
return Object.entries(tokens).forEach((([key, value]) => {
|
|
21227
|
+
// If the token key already starts with the prefix, use as-is
|
|
21228
|
+
// Otherwise, add the prefix
|
|
21229
|
+
const prefixedKey = key.startsWith(prefix) ? key : `${prefix}-${key}`;
|
|
21230
|
+
prefixedTokens[prefixedKey] = value;
|
|
21231
|
+
})), prefixedTokens;
|
|
20963
21232
|
}
|
|
20964
21233
|
|
|
20965
21234
|
/**
|
|
20966
|
-
*
|
|
20967
|
-
*/
|
|
21235
|
+
* Convert hex color to RGB
|
|
21236
|
+
*/ function hexToRgb$2(hex) {
|
|
21237
|
+
hex = hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, ((m, r, g, b) => r + r + g + g + b + b));
|
|
21238
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
21239
|
+
return result && result[1] && result[2] && result[3] ? `${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}` : "0, 0, 0";
|
|
21240
|
+
}
|
|
20968
21241
|
|
|
20969
21242
|
/**
|
|
20970
|
-
*
|
|
20971
|
-
|
|
20972
|
-
|
|
21243
|
+
* Converts DesignTokens to CSS variables
|
|
21244
|
+
*
|
|
21245
|
+
* @param tokens - The tokens to convert
|
|
21246
|
+
* @returns A record of CSS variable names and values
|
|
21247
|
+
*/ function designTokensToCSSVars(tokens) {
|
|
21248
|
+
const cssVars = {};
|
|
21249
|
+
return Object.entries(tokens).forEach((([key, value]) => {
|
|
21250
|
+
void 0 !== value && (cssVars[`--atomix-${key}`] = String(value));
|
|
21251
|
+
})), cssVars;
|
|
20973
21252
|
}
|
|
20974
21253
|
|
|
20975
21254
|
/**
|
|
20976
|
-
*
|
|
20977
|
-
*
|
|
20978
|
-
*
|
|
20979
|
-
*
|
|
21255
|
+
* Load theme from config file (synchronous, Node.js only)
|
|
21256
|
+
* @param configPath - Path to config file (default: atomix.config.ts)
|
|
21257
|
+
* @returns DesignTokens from theme configuration
|
|
21258
|
+
* @throws Error if config loading is not available in browser environment
|
|
20980
21259
|
*/
|
|
20981
21260
|
/**
|
|
20982
|
-
*
|
|
21261
|
+
* Validate Atomix configuration structure
|
|
20983
21262
|
*
|
|
20984
|
-
*
|
|
21263
|
+
* Performs basic validation to catch common configuration errors early.
|
|
21264
|
+
* Returns warnings for potential issues.
|
|
20985
21265
|
*
|
|
20986
|
-
* @param
|
|
20987
|
-
* @
|
|
20988
|
-
* @returns CSS string with custom properties
|
|
20989
|
-
* @throws Error if config loading fails when no input is provided
|
|
21266
|
+
* @param config - Configuration object to validate
|
|
21267
|
+
* @returns Array of validation warnings (empty if valid)
|
|
20990
21268
|
*
|
|
20991
21269
|
* @example
|
|
20992
21270
|
* ```typescript
|
|
20993
|
-
*
|
|
20994
|
-
* const css = createTheme();
|
|
20995
|
-
*
|
|
20996
|
-
* // Using DesignTokens
|
|
20997
|
-
* const css = createTheme({
|
|
20998
|
-
* 'primary': '#7c3aed',
|
|
20999
|
-
* 'spacing-4': '1rem',
|
|
21000
|
-
* });
|
|
21271
|
+
* import { loadAtomixConfig, validateConfig } from '@shohojdhara/atomix/config';
|
|
21001
21272
|
*
|
|
21002
|
-
*
|
|
21003
|
-
* const
|
|
21273
|
+
* const config = loadAtomixConfig();
|
|
21274
|
+
* const warnings = validateConfig(config);
|
|
21275
|
+
* warnings.forEach(w => console.warn(w));
|
|
21004
21276
|
* ```
|
|
21005
|
-
*/
|
|
21006
|
-
|
|
21007
|
-
|
|
21008
|
-
|
|
21009
|
-
|
|
21010
|
-
|
|
21011
|
-
|
|
21012
|
-
|
|
21277
|
+
*/
|
|
21278
|
+
function validateConfig$1(config) {
|
|
21279
|
+
const warnings = [];
|
|
21280
|
+
// Check prefix format
|
|
21281
|
+
// Check theme structure
|
|
21282
|
+
if (config.prefix && (/^[a-zA-Z][a-zA-Z0-9-]*$/.test(config.prefix) || warnings.push(`Invalid prefix "${config.prefix}". Prefix should start with a letter and contain only letters, numbers, and hyphens.\nExample: "myapp", "brand-ui", "enterprise"`),
|
|
21283
|
+
config.prefix.length < 2 && warnings.push(`Prefix "${config.prefix}" is too short. Use at least 2 characters for clarity.\nExample: "app" instead of "a"`)),
|
|
21284
|
+
config.theme && (
|
|
21285
|
+
// Warn if both extend and tokens are provided
|
|
21286
|
+
config.theme.extend && config.theme.tokens && warnings.push("Both theme.extend and theme.tokens are defined. theme.tokens will take precedence and completely replace the default token system.\nIf you want to extend defaults, remove theme.tokens and use only theme.extend."),
|
|
21287
|
+
config.theme.extend)) {
|
|
21288
|
+
const extend = config.theme.extend, validThemeKeys = [ "colors", "typography", "spacing", "borderRadius", "shadows", "zIndex", "transitions", "breakpoints" ];
|
|
21289
|
+
// Check for common typos in theme properties
|
|
21290
|
+
Object.keys(extend).forEach((key => {
|
|
21291
|
+
_includesInstanceProperty(validThemeKeys).call(validThemeKeys, key) || warnings.push(`Unknown theme property: "${key}"\nValid properties: ${validThemeKeys.join(", ")}\nDid you mean one of these? Check for typos.`);
|
|
21292
|
+
}));
|
|
21013
21293
|
}
|
|
21014
|
-
// Validate
|
|
21015
|
-
if (
|
|
21016
|
-
|
|
21017
|
-
|
|
21018
|
-
|
|
21019
|
-
|
|
21020
|
-
|
|
21021
|
-
// Validate
|
|
21022
|
-
|
|
21023
|
-
|
|
21024
|
-
|
|
21025
|
-
//
|
|
21026
|
-
|
|
21294
|
+
// Validate advanced features
|
|
21295
|
+
if (config.interactiveEffects) {
|
|
21296
|
+
const ie = config.interactiveEffects;
|
|
21297
|
+
// Validate vortex settings
|
|
21298
|
+
ie.vortex && (ie.vortex.strength && (ie.vortex.strength < 0 || ie.vortex.strength > 10) && warnings.push("Vortex strength should be between 0 and 10 for optimal performance"),
|
|
21299
|
+
ie.vortex.radius && ie.vortex.radius < 0 && warnings.push("Vortex radius should be a positive number"),
|
|
21300
|
+
ie.vortex.decay && (ie.vortex.decay <= 0 || ie.vortex.decay > 1) && warnings.push("Vortex decay should be between 0 and 1")),
|
|
21301
|
+
// Validate chromatic aberration settings
|
|
21302
|
+
ie.chromaticAberration && (ie.chromaticAberration.redShift && Math.abs(ie.chromaticAberration.redShift) > .1 && warnings.push("Chromatic red shift value seems unusually high (>0.1), verify this is intended"),
|
|
21303
|
+
ie.chromaticAberration.blueShift && Math.abs(ie.chromaticAberration.blueShift) > .1 && warnings.push("Chromatic blue shift value seems unusually high (>0.1), verify this is intended"),
|
|
21304
|
+
ie.chromaticAberration.edgeThreshold && (ie.chromaticAberration.edgeThreshold < 0 || ie.chromaticAberration.edgeThreshold > 1) && warnings.push("Chromatic edge threshold should be between 0 and 1")),
|
|
21305
|
+
// Validate mouse interaction settings
|
|
21306
|
+
ie.mouseInteraction && ie.mouseInteraction.sensitivity && ie.mouseInteraction.sensitivity < 0 && warnings.push("Mouse sensitivity should be a positive number"),
|
|
21307
|
+
// Validate animation speed settings
|
|
21308
|
+
ie.animationSpeed && (ie.animationSpeed.base && ie.animationSpeed.base <= 0 && warnings.push("Animation base speed should be greater than 0"),
|
|
21309
|
+
ie.animationSpeed.timeMultiplier && ie.animationSpeed.timeMultiplier <= 0 && warnings.push("Animation time multiplier should be greater than 0"));
|
|
21310
|
+
}
|
|
21311
|
+
// Validate optimization settings
|
|
21312
|
+
if (config.optimization) {
|
|
21313
|
+
const opt = config.optimization;
|
|
21314
|
+
// Validate responsive breakpoints
|
|
21315
|
+
if (opt.responsive && opt.responsive.breakpoints) {
|
|
21316
|
+
const breakpoints = opt.responsive.breakpoints;
|
|
21317
|
+
breakpoints.mobile && !isValidCSSLength(breakpoints.mobile) && warnings.push("Mobile breakpoint value is not a valid CSS length"),
|
|
21318
|
+
breakpoints.tablet && !isValidCSSLength(breakpoints.tablet) && warnings.push("Tablet breakpoint value is not a valid CSS length"),
|
|
21319
|
+
breakpoints.desktop && !isValidCSSLength(breakpoints.desktop) && warnings.push("Desktop breakpoint value is not a valid CSS length"),
|
|
21320
|
+
breakpoints.wide && !isValidCSSLength(breakpoints.wide) && warnings.push("Wide breakpoint value is not a valid CSS length");
|
|
21321
|
+
}
|
|
21322
|
+
// Validate device scaling
|
|
21323
|
+
if (opt.responsive && opt.responsive.deviceScaling) {
|
|
21324
|
+
const scaling = opt.responsive.deviceScaling;
|
|
21325
|
+
scaling.mobile && (scaling.mobile <= 0 || scaling.mobile > 1) && warnings.push("Mobile device scaling should be between 0 and 1"),
|
|
21326
|
+
scaling.tablet && (scaling.tablet <= 0 || scaling.tablet > 1) && warnings.push("Tablet device scaling should be between 0 and 1"),
|
|
21327
|
+
scaling.desktop && (scaling.desktop <= 0 || scaling.desktop > 1) && warnings.push("Desktop device scaling should be between 0 and 1");
|
|
21328
|
+
}
|
|
21329
|
+
// Validate performance settings
|
|
21330
|
+
// Validate auto-scaling thresholds
|
|
21331
|
+
if (opt.performance && opt.performance.fpsTarget && (opt.performance.fpsTarget <= 0 || opt.performance.fpsTarget > 240) && warnings.push("FPS target should be a reasonable value (typically 30-120)"),
|
|
21332
|
+
opt.autoScaling && opt.autoScaling.qualityThresholds) {
|
|
21333
|
+
const thresholds = opt.autoScaling.qualityThresholds;
|
|
21334
|
+
thresholds.lowEnd && (thresholds.lowEnd < 0 || thresholds.lowEnd > 1) && warnings.push("Auto-scaling low-end threshold should be between 0 and 1"),
|
|
21335
|
+
thresholds.midRange && (thresholds.midRange < 0 || thresholds.midRange > 1) && warnings.push("Auto-scaling mid-range threshold should be between 0 and 1"),
|
|
21336
|
+
thresholds.highEnd && (thresholds.highEnd < 0 || thresholds.highEnd > 1) && warnings.push("Auto-scaling high-end threshold should be between 0 and 1");
|
|
21337
|
+
}
|
|
21338
|
+
}
|
|
21339
|
+
// Validate visual polish settings
|
|
21340
|
+
if (config.visualPolish) {
|
|
21341
|
+
const vp = config.visualPolish;
|
|
21342
|
+
// Validate content aware blur settings
|
|
21343
|
+
vp.contentAwareBlur && (void 0 !== vp.contentAwareBlur.edgePreservation && "boolean" != typeof vp.contentAwareBlur.edgePreservation && warnings.push("Content-aware blur edge preservation should be a boolean value"),
|
|
21344
|
+
void 0 !== vp.contentAwareBlur.depthDetection && "boolean" != typeof vp.contentAwareBlur.depthDetection && warnings.push("Content-aware blur depth detection should be a boolean value")),
|
|
21345
|
+
// Validate holographic effects settings
|
|
21346
|
+
vp.holographicEffects && (void 0 !== vp.holographicEffects.enabled && "boolean" != typeof vp.holographicEffects.enabled && warnings.push("Holographic effects enabled should be a boolean value"),
|
|
21347
|
+
void 0 !== vp.holographicEffects.rainbowDiffraction && "boolean" != typeof vp.holographicEffects.rainbowDiffraction && warnings.push("Holographic rainbow diffraction should be a boolean value"));
|
|
21348
|
+
}
|
|
21349
|
+
// Validate AI settings
|
|
21350
|
+
var _context;
|
|
21351
|
+
return config.ai && (config.ai.provider && !_includesInstanceProperty(_context = [ "openai", "anthropic" ]).call(_context, config.ai.provider) && warnings.push(`Unknown AI provider: "${config.ai.provider}". Supported: openai, anthropic`),
|
|
21352
|
+
config.ai.temperature && (config.ai.temperature < 0 || config.ai.temperature > 1) && warnings.push("AI temperature should be between 0 and 1"),
|
|
21353
|
+
config.ai.maxTokens && config.ai.maxTokens < 100 && warnings.push("AI maxTokens should typically be 100 or more"),
|
|
21354
|
+
config.ai.rateLimit && (config.ai.rateLimit.requests <= 0 && warnings.push("AI rate limit requests should be greater than 0"),
|
|
21355
|
+
config.ai.rateLimit.windowMs <= 0 && warnings.push("AI rate limit window should be greater than 0"))),
|
|
21356
|
+
// Validate telemetry settings
|
|
21357
|
+
config.telemetry && config.telemetry.path && !config.telemetry.path.endsWith(".json") && warnings.push("Telemetry path should typically end with .json"),
|
|
21358
|
+
warnings;
|
|
21359
|
+
}
|
|
21360
|
+
|
|
21361
|
+
/**
|
|
21362
|
+
* Helper function to validate CSS length values
|
|
21363
|
+
*/ function isValidCSSLength(value) {
|
|
21364
|
+
return /^(\d+(\.\d+)?)(px|em|rem|%|vw|vh|vmin|vmax|cm|mm|in|pt|pc|ex|ch)?$/.test(value);
|
|
21365
|
+
}
|
|
21366
|
+
|
|
21367
|
+
/**
|
|
21368
|
+
* Load Atomix configuration from project root
|
|
21369
|
+
*
|
|
21370
|
+
* Attempts to load atomix.config.ts, atomix.config.js, or atomix.config.json from the current working directory.
|
|
21371
|
+
* Falls back to default config if file doesn't exist.
|
|
21372
|
+
*
|
|
21373
|
+
* @param options - Loader options
|
|
21374
|
+
* @returns Loaded configuration or default
|
|
21375
|
+
*
|
|
21376
|
+
* @example
|
|
21377
|
+
* ```typescript
|
|
21378
|
+
* import { loadAtomixConfig } from '@shohojdhara/atomix/config';
|
|
21379
|
+
* import { createTheme } from '@shohojdhara/atomix/theme';
|
|
21380
|
+
*
|
|
21381
|
+
* const config = loadAtomixConfig();
|
|
21382
|
+
* const theme = createTheme(config.theme?.tokens || {});
|
|
21383
|
+
* ```
|
|
21384
|
+
*/ function loadAtomixConfig(options = {}) {
|
|
21385
|
+
const {configPath: configPath, required: required = !1} = options, defaultConfig = {
|
|
21386
|
+
prefix: "atomix",
|
|
21387
|
+
theme: {
|
|
21388
|
+
extend: {}
|
|
21389
|
+
}
|
|
21390
|
+
};
|
|
21391
|
+
// Default config
|
|
21392
|
+
// In browser environments, config loading is not supported
|
|
21393
|
+
if ("undefined" != typeof window) {
|
|
21394
|
+
if (required) throw new Error('Config loading requires Node.js file system access.\n\nSolutions:\n1. Provide tokens explicitly to createTheme():\n const css = createTheme({ "--brand-primary": "#6366f1" });\n\n2. Use SSR framework (Next.js, Remix, Astro)\n\n3. Load config on server and pass to client\n\nSee examples/config-examples/browser-only.config.ts');
|
|
21395
|
+
return defaultConfig;
|
|
21396
|
+
}
|
|
21397
|
+
// If a specific config path is provided, try to load it directly
|
|
21398
|
+
if (configPath) return loadConfigAtPath(configPath, required, defaultConfig);
|
|
21399
|
+
// Otherwise, try standard locations in order of preference
|
|
21400
|
+
const possiblePaths = [ "atomix.config.ts", "atomix.config.js", "atomix.config.json" ];
|
|
21401
|
+
for (const path of possiblePaths) {
|
|
21402
|
+
const config = loadConfigAtPath(path, !1, defaultConfig);
|
|
21403
|
+
// If we found a valid config, return it
|
|
21404
|
+
if (JSON.stringify(config) !== JSON.stringify(defaultConfig)) return config;
|
|
21405
|
+
}
|
|
21406
|
+
// If no config file was found or all contained only defaults, return default config
|
|
21407
|
+
if (required) throw new Error('No Atomix configuration file found in project root.\n\nExpected one of:\n - atomix.config.ts (recommended)\n - atomix.config.js\n - atomix.config.json\n\nQuick Fix:\n1. Create a config file in your project root:\n touch atomix.config.ts\n\n2. Add basic configuration:\n import { defineConfig } from "@shohojdhara/atomix/config";\n export default defineConfig({ prefix: "myapp" });\n\n3. Or copy an example:\n cp node_modules/@shohojdhara/atomix/examples/config-examples/standard.config.ts ./atomix.config.ts');
|
|
21408
|
+
return defaultConfig;
|
|
21409
|
+
}
|
|
21410
|
+
|
|
21411
|
+
/**
|
|
21412
|
+
* Helper function to load config from a specific path
|
|
21413
|
+
*/ function loadConfigAtPath(path, required, defaultConfig) {
|
|
21414
|
+
try {
|
|
21415
|
+
// Use dynamic import for ESM compatibility
|
|
21416
|
+
const configModule = require(path), config = configModule.default || configModule;
|
|
21417
|
+
// Validate it's an AtomixConfig
|
|
21418
|
+
if (config && "object" == typeof config) return config;
|
|
21419
|
+
throw new Error("Invalid config format");
|
|
21420
|
+
} catch (error) {
|
|
21421
|
+
if (required) throw new Error(`Failed to load config from ${path}: ${error.message}`);
|
|
21422
|
+
// Return default config if not required
|
|
21423
|
+
return defaultConfig;
|
|
21424
|
+
}
|
|
21425
|
+
}
|
|
21426
|
+
|
|
21427
|
+
/**
|
|
21428
|
+
* Resolve config path
|
|
21429
|
+
*
|
|
21430
|
+
* Finds atomix.config.ts in the project, checking common locations.
|
|
21431
|
+
* Returns null in browser environments where file system access is not available.
|
|
21432
|
+
*
|
|
21433
|
+
* This function is designed to help tools identify if a config exists without loading it.
|
|
21434
|
+
*
|
|
21435
|
+
* @param configPath - Optional custom path to check
|
|
21436
|
+
* @returns Absolute path to config file or null if not found
|
|
21437
|
+
*/ function resolveConfigPath(configPath) {
|
|
21438
|
+
// In browser environments, config resolution is not possible
|
|
21439
|
+
if ("undefined" != typeof window) return null;
|
|
21440
|
+
// If a specific config path is provided, check if it exists
|
|
21441
|
+
if (configPath) {
|
|
21442
|
+
const absPath = join(process.cwd(), configPath);
|
|
21443
|
+
return existsSync(absPath) ? absPath : null;
|
|
21444
|
+
}
|
|
21445
|
+
// Otherwise, check standard locations
|
|
21446
|
+
const possiblePaths = [ join(process.cwd(), "atomix.config.ts"), join(process.cwd(), "atomix.config.js"), join(process.cwd(), "atomix.config.json") ];
|
|
21447
|
+
for (const path of possiblePaths) if (existsSync(path)) return path;
|
|
21448
|
+
return null;
|
|
21449
|
+
}
|
|
21450
|
+
|
|
21451
|
+
/**
|
|
21452
|
+
* Core Theme Functions
|
|
21453
|
+
*
|
|
21454
|
+
* Unified theme system that handles both DesignTokens and Theme objects.
|
|
21455
|
+
* Config-first approach: loads from atomix.config.ts when no input is provided.
|
|
21456
|
+
* Config-first approach: loads advanced features from config when available.
|
|
21457
|
+
*/
|
|
21458
|
+
/**
|
|
21459
|
+
* Create theme CSS from tokens or Theme object
|
|
21460
|
+
*
|
|
21461
|
+
* **Config-First Approach**: If no input is provided, loads from `atomix.config.ts`.
|
|
21462
|
+
* Config file is required for automatic loading.
|
|
21463
|
+
*
|
|
21464
|
+
* @param input - DesignTokens (partial), Theme object, or undefined (loads from config)
|
|
21465
|
+
* @param options - CSS generation options (prefix is automatically read from config if not provided)
|
|
21466
|
+
* @returns CSS string with custom properties
|
|
21467
|
+
* @throws Error if config loading fails when no input is provided
|
|
21468
|
+
*
|
|
21469
|
+
* @example
|
|
21470
|
+
* ```typescript
|
|
21471
|
+
* // Loads from atomix.config.ts (config file required)
|
|
21472
|
+
* const css = createTheme();
|
|
21473
|
+
*
|
|
21474
|
+
* // Using DesignTokens
|
|
21475
|
+
* const css = createTheme({
|
|
21476
|
+
* 'primary': '#7c3aed',
|
|
21477
|
+
* 'spacing-4': '1rem',
|
|
21478
|
+
* });
|
|
21479
|
+
*
|
|
21480
|
+
* // Using Theme object
|
|
21481
|
+
* const theme = createThemeObject({ palette: { primary: { main: '#7c3aed' } } });
|
|
21482
|
+
* const css = createTheme(theme);
|
|
21483
|
+
*
|
|
21484
|
+
* // With custom options
|
|
21485
|
+
* const css = createTheme(undefined, { prefix: 'myapp', selector: ':root' });
|
|
21486
|
+
* ```
|
|
21487
|
+
*/ function createTheme(input, options) {
|
|
21488
|
+
let tokens, configPrefix;
|
|
21489
|
+
// If no input provided, load from config (required)
|
|
21490
|
+
if (input)
|
|
21491
|
+
// Convert Theme object to DesignTokens
|
|
21492
|
+
tokens = !0 === input.__isJSTheme || input.palette && input.typography ? themeToDesignTokens(input) : input; else {
|
|
21493
|
+
const configTokens = function() {
|
|
21494
|
+
// Check if we're in a browser environment
|
|
21495
|
+
if ("undefined" != typeof window) throw new Error("loadThemeFromConfigSync: Not available in browser environment. Config loading requires Node.js/SSR environment.");
|
|
21496
|
+
// Use dynamic import to load the config loader
|
|
21497
|
+
// This allows bundlers to handle external dependencies properly
|
|
21498
|
+
let loadAtomixConfig;
|
|
21499
|
+
try {
|
|
21500
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
21501
|
+
const {loadAtomixConfig: loader} = require("../../config/loader");
|
|
21502
|
+
loadAtomixConfig = loader;
|
|
21503
|
+
} catch (error) {
|
|
21504
|
+
throw new Error("Config loader module not available");
|
|
21505
|
+
}
|
|
21506
|
+
const config = loadAtomixConfig({
|
|
21507
|
+
configPath: undefined,
|
|
21508
|
+
required: !0
|
|
21509
|
+
});
|
|
21510
|
+
if (!config?.theme) return createTokens({});
|
|
21511
|
+
if ((obj = config.theme) && "object" == typeof obj && (obj.palette || obj.typography || obj.spacing || obj.breakpoints || obj.colors)) return themeToDesignTokens(config.theme);
|
|
21512
|
+
// Handle the config.theme object which has extend/tokens/themes properties
|
|
21513
|
+
// Extract the actual tokens from the theme configuration
|
|
21514
|
+
// Helper type guard function
|
|
21515
|
+
var obj;
|
|
21516
|
+
const themeConfig = config.theme;
|
|
21517
|
+
let tokensToApply = {};
|
|
21518
|
+
return themeConfig.tokens ?
|
|
21519
|
+
// If tokens is provided, use it as the base
|
|
21520
|
+
tokensToApply = themeConfig.tokens : themeConfig.extend && (
|
|
21521
|
+
// If only extend is provided, use it as overrides
|
|
21522
|
+
tokensToApply = themeConfig.extend),
|
|
21523
|
+
// Apply advanced feature configurations as tokens
|
|
21524
|
+
config.interactiveEffects && (
|
|
21525
|
+
// Vortex effects
|
|
21526
|
+
config.interactiveEffects.vortex && (tokensToApply = {
|
|
21527
|
+
...tokensToApply,
|
|
21528
|
+
"interactive-vortex-enabled": String(config.interactiveEffects.vortex.enabled ?? !1),
|
|
21529
|
+
"interactive-vortex-strength": String(config.interactiveEffects.vortex.strength ?? .5),
|
|
21530
|
+
"interactive-vortex-radius": String(config.interactiveEffects.vortex.radius ?? 100),
|
|
21531
|
+
"interactive-vortex-decay": String(config.interactiveEffects.vortex.decay ?? .8)
|
|
21532
|
+
}),
|
|
21533
|
+
// Chromatic aberration
|
|
21534
|
+
config.interactiveEffects.chromaticAberration && (tokensToApply = {
|
|
21535
|
+
...tokensToApply,
|
|
21536
|
+
"interactive-chromatic-enabled": String(config.interactiveEffects.chromaticAberration.enabled ?? !1),
|
|
21537
|
+
"interactive-chromatic-mode": config.interactiveEffects.chromaticAberration.mode ?? "lateral",
|
|
21538
|
+
"interactive-chromatic-red-shift": String(config.interactiveEffects.chromaticAberration.redShift ?? .02),
|
|
21539
|
+
"interactive-chromatic-green-shift": String(config.interactiveEffects.chromaticAberration.greenShift ?? 0),
|
|
21540
|
+
"interactive-chromatic-blue-shift": String(config.interactiveEffects.chromaticAberration.blueShift ?? -.02),
|
|
21541
|
+
"interactive-chromatic-edge-only": String(config.interactiveEffects.chromaticAberration.edgeOnly ?? !1),
|
|
21542
|
+
"interactive-chromatic-edge-threshold": String(config.interactiveEffects.chromaticAberration.edgeThreshold ?? .5)
|
|
21543
|
+
}),
|
|
21544
|
+
// Mouse interaction
|
|
21545
|
+
config.interactiveEffects.mouseInteraction && (tokensToApply = {
|
|
21546
|
+
...tokensToApply,
|
|
21547
|
+
"interactive-mouse-sensitivity": String(config.interactiveEffects.mouseInteraction.sensitivity ?? 1),
|
|
21548
|
+
"interactive-mouse-trail-effect": String(config.interactiveEffects.mouseInteraction.trailEffect ?? !1)
|
|
21549
|
+
}),
|
|
21550
|
+
// Animation speed
|
|
21551
|
+
config.interactiveEffects.animationSpeed && (tokensToApply = {
|
|
21552
|
+
...tokensToApply,
|
|
21553
|
+
"interactive-animation-speed-base": String(config.interactiveEffects.animationSpeed.base ?? 1),
|
|
21554
|
+
"interactive-animation-speed-multiplier": String(config.interactiveEffects.animationSpeed.timeMultiplier ?? 1)
|
|
21555
|
+
})),
|
|
21556
|
+
// Apply optimization configurations as tokens
|
|
21557
|
+
config.optimization && (
|
|
21558
|
+
// Responsive breakpoints
|
|
21559
|
+
config.optimization.responsive && (config.optimization.responsive.breakpoints && (tokensToApply = {
|
|
21560
|
+
...tokensToApply,
|
|
21561
|
+
"optimization-breakpoint-mobile": config.optimization.responsive.breakpoints.mobile ?? "0px",
|
|
21562
|
+
"optimization-breakpoint-tablet": config.optimization.responsive.breakpoints.tablet ?? "768px",
|
|
21563
|
+
"optimization-breakpoint-desktop": config.optimization.responsive.breakpoints.desktop ?? "1024px",
|
|
21564
|
+
"optimization-breakpoint-wide": config.optimization.responsive.breakpoints.wide ?? "1440px"
|
|
21565
|
+
}), config.optimization.responsive.deviceScaling && (tokensToApply = {
|
|
21566
|
+
...tokensToApply,
|
|
21567
|
+
"optimization-device-scaling-mobile": String(config.optimization.responsive.deviceScaling.mobile ?? .5),
|
|
21568
|
+
"optimization-device-scaling-tablet": String(config.optimization.responsive.deviceScaling.tablet ?? .75),
|
|
21569
|
+
"optimization-device-scaling-desktop": String(config.optimization.responsive.deviceScaling.desktop ?? 1)
|
|
21570
|
+
})),
|
|
21571
|
+
// Performance settings
|
|
21572
|
+
config.optimization.performance && (tokensToApply = {
|
|
21573
|
+
...tokensToApply,
|
|
21574
|
+
"optimization-performance-fps-target": String(config.optimization.performance.fpsTarget ?? 60),
|
|
21575
|
+
"optimization-auto-scaling-enabled": String(config.optimization.performance.autoScaling ?? !1)
|
|
21576
|
+
}),
|
|
21577
|
+
// Auto-scaling settings
|
|
21578
|
+
config.optimization.autoScaling && (tokensToApply = {
|
|
21579
|
+
...tokensToApply,
|
|
21580
|
+
"optimization-auto-scaling-enabled": String(config.optimization.autoScaling.enabled ?? !1),
|
|
21581
|
+
"optimization-auto-scaling-low-end": String(config.optimization.autoScaling.qualityThresholds?.lowEnd ?? .5),
|
|
21582
|
+
"optimization-auto-scaling-mid-range": String(config.optimization.autoScaling.qualityThresholds?.midRange ?? .75),
|
|
21583
|
+
"optimization-auto-scaling-high-end": String(config.optimization.autoScaling.qualityThresholds?.highEnd ?? 1)
|
|
21584
|
+
})),
|
|
21585
|
+
// Apply visual polish configurations as tokens
|
|
21586
|
+
config.visualPolish && (config.visualPolish.borders && (tokensToApply = {
|
|
21587
|
+
...tokensToApply,
|
|
21588
|
+
"visual-polish-border-iridescent-glow": String(config.visualPolish.borders.iridescentGlow ?? !1),
|
|
21589
|
+
"visual-polish-border-shimmer-effect": String(config.visualPolish.borders.shimmerEffect ?? !1),
|
|
21590
|
+
"visual-polish-border-beveled-edges": String(config.visualPolish.borders.beveledEdges ?? !1),
|
|
21591
|
+
"visual-polish-border-pulsing-glow": String(config.visualPolish.borders.pulsingGlow ?? !1)
|
|
21592
|
+
}), config.visualPolish.contentAwareBlur && (tokensToApply = {
|
|
21593
|
+
...tokensToApply,
|
|
21594
|
+
"visual-polish-content-aware-blur-enabled": String(config.visualPolish.contentAwareBlur.enabled ?? !1),
|
|
21595
|
+
"visual-polish-content-aware-depth-detection": String(config.visualPolish.contentAwareBlur.depthDetection ?? !1),
|
|
21596
|
+
"visual-polish-content-aware-edge-preservation": String(config.visualPolish.contentAwareBlur.edgePreservation ?? !1),
|
|
21597
|
+
"visual-polish-content-aware-variable-radius": String(config.visualPolish.contentAwareBlur.variableRadius ?? !1)
|
|
21598
|
+
}), config.visualPolish.holographicEffects && (tokensToApply = {
|
|
21599
|
+
...tokensToApply,
|
|
21600
|
+
"visual-polish-holographic-enabled": String(config.visualPolish.holographicEffects.enabled ?? !1),
|
|
21601
|
+
"visual-polish-holographic-rainbow-diffraction": String(config.visualPolish.holographicEffects.rainbowDiffraction ?? !1),
|
|
21602
|
+
"visual-polish-holographic-scanline-animation": String(config.visualPolish.holographicEffects.scanlineAnimation ?? !1),
|
|
21603
|
+
"visual-polish-holographic-grid-overlay": String(config.visualPolish.holographicEffects.gridOverlay ?? !1),
|
|
21604
|
+
"visual-polish-holographic-data-stream": String(config.visualPolish.holographicEffects.dataStream ?? !1),
|
|
21605
|
+
"visual-polish-holographic-pulse-rings": String(config.visualPolish.holographicEffects.pulseRings ?? !1)
|
|
21606
|
+
})), createTokens(tokensToApply);
|
|
21607
|
+
}();
|
|
21608
|
+
// Get prefix from config
|
|
21609
|
+
try {
|
|
21610
|
+
// Use the imported function directly instead of require to avoid bundling issues
|
|
21611
|
+
const config = loadAtomixConfig({
|
|
21612
|
+
configPath: "atomix.config.ts",
|
|
21613
|
+
required: !0
|
|
21614
|
+
});
|
|
21615
|
+
configPrefix = config?.prefix;
|
|
21616
|
+
} catch (error) {
|
|
21617
|
+
// Prefix loading failed, but tokens were loaded, so continue
|
|
21618
|
+
}
|
|
21619
|
+
tokens = configTokens;
|
|
21027
21620
|
}
|
|
21028
21621
|
// Merge with defaults and generate CSS
|
|
21029
|
-
|
|
21030
|
-
//
|
|
21031
|
-
// If no input is provided, we return an empty theme (using defaults only) or user must provide tokens.
|
|
21032
|
-
// This allows createTheme to be isomorphic.
|
|
21033
|
-
// Warn in development if no input provided
|
|
21034
|
-
"production" !== process.env.NODE_ENV && "undefined" != typeof window && console.warn("Atomix: createTheme() called without tokens. Using default tokens only."),
|
|
21035
|
-
tokens = {};
|
|
21036
|
-
const allTokens = createTokens(tokens), prefix = options?.prefix ?? "atomix";
|
|
21037
|
-
// Get prefix from options or use default
|
|
21622
|
+
const allTokens = createTokens(tokens), prefix = options?.prefix ?? configPrefix ?? "atomix";
|
|
21623
|
+
// Get prefix from options, config, or use default
|
|
21038
21624
|
return generateCSSVariables$1(allTokens, {
|
|
21039
21625
|
...options,
|
|
21040
21626
|
prefix: prefix
|
|
@@ -21248,12 +21834,145 @@ class ThemeLogger {
|
|
|
21248
21834
|
*/
|
|
21249
21835
|
/**
|
|
21250
21836
|
* Default storage key for theme persistence
|
|
21251
|
-
*/
|
|
21837
|
+
*/
|
|
21838
|
+
/**
|
|
21839
|
+
* Theme System Error Handling
|
|
21840
|
+
*
|
|
21841
|
+
* Centralized error handling for the Atomix theme system.
|
|
21842
|
+
* Provides custom error classes and logging utilities.
|
|
21843
|
+
*/
|
|
21844
|
+
/**
|
|
21845
|
+
* Theme error codes
|
|
21846
|
+
*/
|
|
21847
|
+
var ThemeErrorCode, LogLevel;
|
|
21848
|
+
|
|
21849
|
+
"undefined" != typeof process && process.env, function(ThemeErrorCode) {
|
|
21850
|
+
/** Theme not found in registry */
|
|
21851
|
+
ThemeErrorCode.THEME_NOT_FOUND = "THEME_NOT_FOUND",
|
|
21852
|
+
/** Theme failed to load */
|
|
21853
|
+
ThemeErrorCode.THEME_LOAD_FAILED = "THEME_LOAD_FAILED",
|
|
21854
|
+
/** Theme validation failed */
|
|
21855
|
+
ThemeErrorCode.THEME_VALIDATION_FAILED = "THEME_VALIDATION_FAILED",
|
|
21856
|
+
/** Configuration loading failed */
|
|
21857
|
+
ThemeErrorCode.CONFIG_LOAD_FAILED = "CONFIG_LOAD_FAILED",
|
|
21858
|
+
/** Configuration validation failed */
|
|
21859
|
+
ThemeErrorCode.CONFIG_VALIDATION_FAILED = "CONFIG_VALIDATION_FAILED",
|
|
21860
|
+
/** Circular dependency detected */
|
|
21861
|
+
ThemeErrorCode.CIRCULAR_DEPENDENCY = "CIRCULAR_DEPENDENCY",
|
|
21862
|
+
/** Missing dependency */
|
|
21863
|
+
ThemeErrorCode.MISSING_DEPENDENCY = "MISSING_DEPENDENCY",
|
|
21864
|
+
/** Storage operation failed */
|
|
21865
|
+
ThemeErrorCode.STORAGE_ERROR = "STORAGE_ERROR",
|
|
21866
|
+
/** Invalid theme name */
|
|
21867
|
+
ThemeErrorCode.INVALID_THEME_NAME = "INVALID_THEME_NAME",
|
|
21868
|
+
/** CSS injection failed */
|
|
21869
|
+
ThemeErrorCode.CSS_INJECTION_FAILED = "CSS_INJECTION_FAILED",
|
|
21870
|
+
/** Invalid color format */
|
|
21871
|
+
ThemeErrorCode.INVALID_COLOR_FORMAT = "INVALID_COLOR_FORMAT",
|
|
21872
|
+
/** Missing required token */
|
|
21873
|
+
ThemeErrorCode.MISSING_REQUIRED_TOKEN = "MISSING_REQUIRED_TOKEN",
|
|
21874
|
+
/** Accessibility contrast violation */
|
|
21875
|
+
ThemeErrorCode.CONTRAST_VIOLATION = "CONTRAST_VIOLATION",
|
|
21876
|
+
/** Invalid token type */
|
|
21877
|
+
ThemeErrorCode.INVALID_TOKEN_TYPE = "INVALID_TOKEN_TYPE",
|
|
21878
|
+
/** Unknown error */
|
|
21879
|
+
ThemeErrorCode.UNKNOWN_ERROR = "UNKNOWN_ERROR";
|
|
21880
|
+
}(ThemeErrorCode || (ThemeErrorCode = {}));
|
|
21252
21881
|
|
|
21253
21882
|
/**
|
|
21254
|
-
*
|
|
21883
|
+
* Custom error class for theme-related errors
|
|
21255
21884
|
*/
|
|
21256
|
-
|
|
21885
|
+
class ThemeError extends Error {
|
|
21886
|
+
constructor(message, code = ThemeErrorCode.UNKNOWN_ERROR, context) {
|
|
21887
|
+
super(message), this.name = "ThemeError", this.code = code, this.context = context,
|
|
21888
|
+
this.timestamp = Date.now(),
|
|
21889
|
+
// Maintains proper stack trace for where our error was thrown (only available on V8)
|
|
21890
|
+
Error.captureStackTrace && Error.captureStackTrace(this, ThemeError);
|
|
21891
|
+
}
|
|
21892
|
+
/**
|
|
21893
|
+
* Convert error to JSON for logging
|
|
21894
|
+
*/ toJSON() {
|
|
21895
|
+
return {
|
|
21896
|
+
name: this.name,
|
|
21897
|
+
message: this.message,
|
|
21898
|
+
code: this.code,
|
|
21899
|
+
context: this.context,
|
|
21900
|
+
timestamp: this.timestamp,
|
|
21901
|
+
stack: this.stack
|
|
21902
|
+
};
|
|
21903
|
+
}
|
|
21904
|
+
}
|
|
21905
|
+
|
|
21906
|
+
/**
|
|
21907
|
+
* Log level
|
|
21908
|
+
*/ !function(LogLevel) {
|
|
21909
|
+
LogLevel[LogLevel.ERROR = 0] = "ERROR", LogLevel[LogLevel.WARN = 1] = "WARN", LogLevel[LogLevel.INFO = 2] = "INFO",
|
|
21910
|
+
LogLevel[LogLevel.DEBUG = 3] = "DEBUG";
|
|
21911
|
+
}(LogLevel || (LogLevel = {}));
|
|
21912
|
+
|
|
21913
|
+
/**
|
|
21914
|
+
* Theme Logger
|
|
21915
|
+
*
|
|
21916
|
+
* Centralized logging for the theme system.
|
|
21917
|
+
* Replaces console statements with structured logging.
|
|
21918
|
+
*/
|
|
21919
|
+
class ThemeLogger {
|
|
21920
|
+
constructor(config = {}) {
|
|
21921
|
+
this.config = {
|
|
21922
|
+
level: config.level ?? ("undefined" != typeof process && "production" === process.env?.NODE_ENV ? LogLevel.WARN : LogLevel.INFO),
|
|
21923
|
+
enableConsole: config.enableConsole ?? !0,
|
|
21924
|
+
onError: config.onError,
|
|
21925
|
+
onWarn: config.onWarn,
|
|
21926
|
+
onInfo: config.onInfo,
|
|
21927
|
+
onDebug: config.onDebug
|
|
21928
|
+
};
|
|
21929
|
+
}
|
|
21930
|
+
/**
|
|
21931
|
+
* Log an error
|
|
21932
|
+
*/ error(message, error, context) {
|
|
21933
|
+
if (this.config.level < LogLevel.ERROR) return;
|
|
21934
|
+
const errorObj = error instanceof Error ? error : new Error(message), themeError = error instanceof ThemeError ? error : new ThemeError(message, ThemeErrorCode.UNKNOWN_ERROR, context);
|
|
21935
|
+
this.config.enableConsole && console.error(`[ThemeError] ${message}`, {
|
|
21936
|
+
error: errorObj,
|
|
21937
|
+
context: {
|
|
21938
|
+
...context,
|
|
21939
|
+
...themeError.context
|
|
21940
|
+
},
|
|
21941
|
+
code: themeError.code
|
|
21942
|
+
}), this.config.onError?.(themeError, context);
|
|
21943
|
+
}
|
|
21944
|
+
/**
|
|
21945
|
+
* Log a warning
|
|
21946
|
+
*/ warn(message, context) {
|
|
21947
|
+
this.config.level < LogLevel.WARN || (this.config.enableConsole && console.warn(`[ThemeWarning] ${message}`, context || {}),
|
|
21948
|
+
this.config.onWarn?.(message, context));
|
|
21949
|
+
}
|
|
21950
|
+
/**
|
|
21951
|
+
* Log an info message
|
|
21952
|
+
*/ info(message, context) {
|
|
21953
|
+
this.config.level < LogLevel.INFO || (this.config.enableConsole && console.info(`[ThemeInfo] ${message}`, context || {}),
|
|
21954
|
+
this.config.onInfo?.(message, context));
|
|
21955
|
+
}
|
|
21956
|
+
/**
|
|
21957
|
+
* Log a debug message
|
|
21958
|
+
*/ debug(message, context) {
|
|
21959
|
+
this.config.level < LogLevel.DEBUG || (this.config.enableConsole, this.config.onDebug?.(message, context));
|
|
21960
|
+
}
|
|
21961
|
+
}
|
|
21962
|
+
|
|
21963
|
+
/**
|
|
21964
|
+
* Default logger instance
|
|
21965
|
+
*/ let defaultLogger = null;
|
|
21966
|
+
|
|
21967
|
+
/**
|
|
21968
|
+
* Get or create default logger
|
|
21969
|
+
*/ function getLogger() {
|
|
21970
|
+
return defaultLogger || (defaultLogger = new ThemeLogger), defaultLogger;
|
|
21971
|
+
}
|
|
21972
|
+
|
|
21973
|
+
/**
|
|
21974
|
+
* Check if code is running in a browser environment
|
|
21975
|
+
*/ const isBrowser = () => "undefined" != typeof window && "undefined" != typeof document, isServer = () => !isBrowser(), sanitizePath = path => path.replace(/[<>"']/g, "").replace(/\.\./g, "").replace(/\/+/g, "/").replace(/^\/+|\/+$/g, "") // Trim leading/trailing slashes
|
|
21257
21976
|
, buildThemePath = (themeName, basePath = "/themes", useMinified = !1, cdnPath = null) => {
|
|
21258
21977
|
// Validate theme name to prevent path injection
|
|
21259
21978
|
if (!isValidThemeName(themeName)) throw new ThemeError(`Invalid theme name: "${themeName}". Theme names must be lowercase alphanumeric with hyphens (e.g., "my-theme").`, ThemeErrorCode.INVALID_THEME_NAME, {
|
|
@@ -21338,106 +22057,428 @@ const isBrowser = () => "undefined" != typeof window && "undefined" != typeof do
|
|
|
21338
22057
|
/**
|
|
21339
22058
|
* Check if code is running on the server (SSR)
|
|
21340
22059
|
*/
|
|
22060
|
+
// ============================================================================
|
|
22061
|
+
// Theme Mode Switching
|
|
22062
|
+
// ============================================================================
|
|
21341
22063
|
/**
|
|
21342
|
-
*
|
|
22064
|
+
* Switch between light and dark themes
|
|
22065
|
+
*
|
|
22066
|
+
* Automatically toggles a class on the root element and persists the choice.
|
|
22067
|
+
*
|
|
22068
|
+
* @param mode - Theme mode ('light', 'dark', or 'system')
|
|
22069
|
+
* @param options - Configuration options
|
|
22070
|
+
*
|
|
22071
|
+
* @example
|
|
22072
|
+
* ```typescript
|
|
22073
|
+
* import { switchTheme } from '@shohojdhara/atomix/theme/utils';
|
|
22074
|
+
*
|
|
22075
|
+
* // Switch to dark mode
|
|
22076
|
+
* switchTheme('dark');
|
|
21343
22077
|
*
|
|
21344
|
-
*
|
|
21345
|
-
*
|
|
22078
|
+
* // Toggle between light/dark
|
|
22079
|
+
* const current = getCurrentTheme();
|
|
22080
|
+
* switchTheme(current === 'dark' ? 'light' : 'dark');
|
|
22081
|
+
* ```
|
|
21346
22082
|
*/
|
|
22083
|
+
function switchTheme(mode, options = {}) {
|
|
22084
|
+
const {selector: selector = ":root", storageKey: storageKey = "atomix-theme", enableTransition: enableTransition = !0, transitionDuration: transitionDuration = 300} = options, resolvedMode = "system" === mode ? getSystemTheme() : mode, root = ":root" === selector ? document.documentElement : document.querySelector(selector);
|
|
22085
|
+
// Determine actual mode (resolve 'system')
|
|
22086
|
+
if (root) {
|
|
22087
|
+
// Add transition class if enabled
|
|
22088
|
+
if (enableTransition) {
|
|
22089
|
+
const htmlRoot = root;
|
|
22090
|
+
htmlRoot.style.transition = `all ${transitionDuration}ms ease-in-out`,
|
|
22091
|
+
// Remove transition after it completes
|
|
22092
|
+
setTimeout((() => {
|
|
22093
|
+
htmlRoot.style.transition = "";
|
|
22094
|
+
}), transitionDuration);
|
|
22095
|
+
}
|
|
22096
|
+
// Apply theme class
|
|
22097
|
+
root.classList.remove("atomix-theme-light", "atomix-theme-dark"), root.classList.add(`atomix-theme-${resolvedMode}`),
|
|
22098
|
+
// Set data attribute for CSS selectors
|
|
22099
|
+
root.setAttribute("data-theme", resolvedMode),
|
|
22100
|
+
// Persist choice
|
|
22101
|
+
persistTheme(resolvedMode, {
|
|
22102
|
+
storageKey: storageKey
|
|
22103
|
+
}),
|
|
22104
|
+
// Dispatch custom event for listeners
|
|
22105
|
+
window.dispatchEvent(new CustomEvent("atomix-theme-change", {
|
|
22106
|
+
detail: {
|
|
22107
|
+
mode: resolvedMode
|
|
22108
|
+
}
|
|
22109
|
+
}));
|
|
22110
|
+
}
|
|
22111
|
+
}
|
|
22112
|
+
|
|
22113
|
+
/**
|
|
22114
|
+
* Toggle between light and dark themes
|
|
22115
|
+
*
|
|
22116
|
+
* @param options - Configuration options
|
|
22117
|
+
* @returns The new theme mode
|
|
22118
|
+
*
|
|
22119
|
+
* @example
|
|
22120
|
+
* ```typescript
|
|
22121
|
+
* const newMode = toggleTheme();
|
|
22122
|
+
* console.log('Switched to:', newMode);
|
|
22123
|
+
* ```
|
|
22124
|
+
*/ function toggleTheme(options = {}) {
|
|
22125
|
+
const next = "dark" === getCurrentTheme(options.storageKey) ? "light" : "dark";
|
|
22126
|
+
return switchTheme(next, options), next;
|
|
22127
|
+
}
|
|
22128
|
+
|
|
22129
|
+
/**
|
|
22130
|
+
* Get current theme mode
|
|
22131
|
+
*
|
|
22132
|
+
* @param storageKey - Storage key (default: 'atomix-theme')
|
|
22133
|
+
* @returns Current theme mode or 'light' if not set
|
|
22134
|
+
*/ function getCurrentTheme(storageKey = "atomix-theme") {
|
|
22135
|
+
return "undefined" == typeof window ? "light" : localStorage.getItem(storageKey) || "light";
|
|
22136
|
+
}
|
|
22137
|
+
|
|
22138
|
+
/**
|
|
22139
|
+
* Get system theme preference
|
|
22140
|
+
*
|
|
22141
|
+
* @returns 'dark' if system prefers dark mode, 'light' otherwise
|
|
22142
|
+
*/ function getSystemTheme() {
|
|
22143
|
+
return "undefined" == typeof window ? "light" : window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
22144
|
+
}
|
|
22145
|
+
|
|
22146
|
+
/**
|
|
22147
|
+
* Initialize theme based on saved preference or system preference
|
|
22148
|
+
*
|
|
22149
|
+
* Call this once at app startup.
|
|
22150
|
+
*
|
|
22151
|
+
* @param options - Configuration options
|
|
22152
|
+
* @returns The initialized theme mode
|
|
22153
|
+
*
|
|
22154
|
+
* @example
|
|
22155
|
+
* ```typescript
|
|
22156
|
+
* // In your app entry point
|
|
22157
|
+
* import { initializeTheme } from '@shohojdhara/atomix/theme/utils';
|
|
22158
|
+
*
|
|
22159
|
+
* const theme = initializeTheme();
|
|
22160
|
+
* console.log('Theme initialized:', theme);
|
|
22161
|
+
* ```
|
|
22162
|
+
*/ function initializeTheme(options = {}) {
|
|
22163
|
+
const saved = getCurrentTheme(options.storageKey);
|
|
22164
|
+
// If no saved preference, use system preference
|
|
22165
|
+
if (!saved || "system" === saved) {
|
|
22166
|
+
const system = getSystemTheme();
|
|
22167
|
+
return switchTheme(system, options), system;
|
|
22168
|
+
}
|
|
22169
|
+
// Use saved preference
|
|
22170
|
+
return switchTheme(saved, options), saved;
|
|
22171
|
+
}
|
|
22172
|
+
|
|
22173
|
+
/**
|
|
22174
|
+
* Listen for system theme changes
|
|
22175
|
+
*
|
|
22176
|
+
* @param callback - Function to call when system theme changes
|
|
22177
|
+
* @returns Cleanup function to stop listening
|
|
22178
|
+
*
|
|
22179
|
+
* @example
|
|
22180
|
+
* ```typescript
|
|
22181
|
+
* const cleanup = listenToSystemTheme((mode) => {
|
|
22182
|
+
* console.log('System theme changed to:', mode);
|
|
22183
|
+
* switchTheme(mode);
|
|
22184
|
+
* });
|
|
22185
|
+
*
|
|
22186
|
+
* // Later, when component unmounts
|
|
22187
|
+
* cleanup();
|
|
22188
|
+
* ```
|
|
22189
|
+
*/ function listenToSystemTheme(callback) {
|
|
22190
|
+
if ("undefined" == typeof window) return () => {};
|
|
22191
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"), handler = e => {
|
|
22192
|
+
callback(e.matches ? "dark" : "light");
|
|
22193
|
+
};
|
|
22194
|
+
// Modern browsers
|
|
22195
|
+
return mediaQuery.addEventListener ? (mediaQuery.addEventListener("change", handler),
|
|
22196
|
+
() => mediaQuery.removeEventListener("change", handler)) : (
|
|
22197
|
+
// Fallback for older browsers
|
|
22198
|
+
mediaQuery.addListener(handler), () => mediaQuery.removeListener(handler));
|
|
22199
|
+
}
|
|
22200
|
+
|
|
21347
22201
|
// ============================================================================
|
|
21348
|
-
//
|
|
22202
|
+
// Theme Persistence
|
|
21349
22203
|
// ============================================================================
|
|
21350
22204
|
/**
|
|
21351
|
-
*
|
|
21352
|
-
|
|
21353
|
-
|
|
21354
|
-
|
|
21355
|
-
|
|
21356
|
-
|
|
21357
|
-
|
|
21358
|
-
|
|
21359
|
-
|
|
22205
|
+
* Save theme preference to storage
|
|
22206
|
+
*
|
|
22207
|
+
* @param mode - Theme mode to save
|
|
22208
|
+
* @param options - Persistence options
|
|
22209
|
+
*/ function persistTheme(mode, options = {}) {
|
|
22210
|
+
if ("undefined" == typeof window) return;
|
|
22211
|
+
const {storageKey: storageKey = "atomix-theme", storageType: storageType = "localStorage"} = options;
|
|
22212
|
+
("localStorage" === storageType ? localStorage : sessionStorage).setItem(storageKey, mode);
|
|
22213
|
+
}
|
|
22214
|
+
|
|
22215
|
+
/**
|
|
22216
|
+
* Clear saved theme preference
|
|
22217
|
+
*
|
|
22218
|
+
* @param options - Persistence options
|
|
22219
|
+
*/ function clearThemePreference(options = {}) {
|
|
22220
|
+
if ("undefined" == typeof window) return;
|
|
22221
|
+
const {storageKey: storageKey = "atomix-theme", storageType: storageType = "localStorage"} = options;
|
|
22222
|
+
("localStorage" === storageType ? localStorage : sessionStorage).removeItem(storageKey);
|
|
22223
|
+
}
|
|
22224
|
+
|
|
22225
|
+
// ============================================================================
|
|
22226
|
+
// Theme Tokens Manipulation
|
|
22227
|
+
// ============================================================================
|
|
22228
|
+
/**
|
|
22229
|
+
* Merge multiple token sets
|
|
22230
|
+
*
|
|
22231
|
+
* Deep merges token objects, with later tokens overriding earlier ones.
|
|
22232
|
+
*
|
|
22233
|
+
* @param tokens - Token objects to merge
|
|
22234
|
+
* @returns Merged tokens
|
|
22235
|
+
*
|
|
22236
|
+
* @example
|
|
22237
|
+
* ```typescript
|
|
22238
|
+
* const merged = mergeTokens(
|
|
22239
|
+
* baseTokens,
|
|
22240
|
+
* { colors: { primary: { main: '#custom' } } }
|
|
22241
|
+
* );
|
|
22242
|
+
* ```
|
|
22243
|
+
*/ function mergeTokens(...tokens) {
|
|
22244
|
+
return _reduceInstanceProperty(tokens).call(tokens, ((acc, current) => deepMerge(acc, current)), {});
|
|
22245
|
+
}
|
|
22246
|
+
|
|
22247
|
+
/**
|
|
22248
|
+
* Override specific tokens
|
|
22249
|
+
*
|
|
22250
|
+
* Creates a new token object with specific overrides.
|
|
22251
|
+
*
|
|
22252
|
+
* @param base - Base tokens
|
|
22253
|
+
* @param overrides - Tokens to override
|
|
22254
|
+
* @returns New tokens with overrides applied
|
|
22255
|
+
*
|
|
22256
|
+
* @example
|
|
22257
|
+
* ```typescript
|
|
22258
|
+
* const customized = overrideTokens(defaultTokens, {
|
|
22259
|
+
* colors: {
|
|
22260
|
+
* primary: { main: '#ff0000' }
|
|
22261
|
+
* }
|
|
22262
|
+
* });
|
|
22263
|
+
* ```
|
|
22264
|
+
*/ function overrideTokens(base, overrides) {
|
|
22265
|
+
return deepMerge({
|
|
22266
|
+
...base
|
|
22267
|
+
}, overrides);
|
|
22268
|
+
}
|
|
22269
|
+
|
|
22270
|
+
/**
|
|
22271
|
+
* Pick specific token categories
|
|
22272
|
+
*
|
|
22273
|
+
* Extracts only the specified categories from tokens.
|
|
22274
|
+
*
|
|
22275
|
+
* @param tokens - Source tokens
|
|
22276
|
+
* @param categories - Categories to pick
|
|
22277
|
+
* @returns Tokens with only selected categories
|
|
22278
|
+
*
|
|
22279
|
+
* @example
|
|
22280
|
+
* ```typescript
|
|
22281
|
+
* const colorTokens = pickTokens(allTokens, ['colors']);
|
|
22282
|
+
* ```
|
|
22283
|
+
*/ function pickTokens(tokens, categories) {
|
|
22284
|
+
const result = {};
|
|
22285
|
+
return categories.forEach((category => {
|
|
22286
|
+
tokens[category] && (result[category] = tokens[category]);
|
|
22287
|
+
})), result;
|
|
21360
22288
|
}
|
|
21361
22289
|
|
|
21362
22290
|
/**
|
|
21363
|
-
*
|
|
22291
|
+
* Omit specific token categories
|
|
22292
|
+
*
|
|
22293
|
+
* Removes specified categories from tokens.
|
|
22294
|
+
*
|
|
22295
|
+
* @param tokens - Source tokens
|
|
22296
|
+
* @param categories - Categories to omit
|
|
22297
|
+
* @returns Tokens without omitted categories
|
|
22298
|
+
*
|
|
22299
|
+
* @example
|
|
22300
|
+
* ```typescript
|
|
22301
|
+
* const withoutColors = omitTokens(allTokens, ['colors']);
|
|
22302
|
+
* ```
|
|
22303
|
+
*/ function omitTokens(tokens, categories) {
|
|
22304
|
+
const result = {
|
|
22305
|
+
...tokens
|
|
22306
|
+
};
|
|
22307
|
+
return categories.forEach((category => {
|
|
22308
|
+
delete result[category];
|
|
22309
|
+
})), result;
|
|
22310
|
+
}
|
|
22311
|
+
|
|
22312
|
+
// ============================================================================
|
|
22313
|
+
// Color Utilities
|
|
22314
|
+
// ============================================================================
|
|
22315
|
+
/**
|
|
22316
|
+
* Convert hex color to RGB
|
|
22317
|
+
*
|
|
22318
|
+
* @param hex - Hex color (with or without #)
|
|
22319
|
+
* @returns RGB object { r, g, b }
|
|
22320
|
+
*/ function hexToRgb$1(hex) {
|
|
22321
|
+
// Validate
|
|
22322
|
+
if (
|
|
22323
|
+
// Remove # if present
|
|
22324
|
+
// Handle shorthand hex
|
|
22325
|
+
3 === (hex = hex.replace(/^#/, "")).length && (hex = hex.split("").map((c => c + c)).join("")),
|
|
22326
|
+
6 !== hex.length) return null;
|
|
22327
|
+
const num = parseInt(hex, 16);
|
|
22328
|
+
return {
|
|
22329
|
+
r: num >> 16 & 255,
|
|
22330
|
+
g: num >> 8 & 255,
|
|
22331
|
+
b: 255 & num
|
|
22332
|
+
};
|
|
22333
|
+
}
|
|
22334
|
+
|
|
22335
|
+
/**
|
|
22336
|
+
* Convert RGB to hex
|
|
22337
|
+
*
|
|
22338
|
+
* @param r - Red (0-255)
|
|
22339
|
+
* @param g - Green (0-255)
|
|
22340
|
+
* @param b - Blue (0-255)
|
|
22341
|
+
* @returns Hex color with #
|
|
21364
22342
|
*/ function rgbToHex(r, g, b) {
|
|
21365
|
-
|
|
21366
|
-
|
|
22343
|
+
return "#" + [ r, g, b ].map((x => {
|
|
22344
|
+
const hex = x.toString(16);
|
|
22345
|
+
return 1 === hex.length ? "0" + hex : hex;
|
|
22346
|
+
})).join("");
|
|
21367
22347
|
}
|
|
21368
22348
|
|
|
21369
22349
|
/**
|
|
21370
|
-
* Calculate
|
|
21371
|
-
*
|
|
21372
|
-
|
|
21373
|
-
|
|
22350
|
+
* Calculate luminance of a color
|
|
22351
|
+
*
|
|
22352
|
+
* Used for determining contrast ratios.
|
|
22353
|
+
*
|
|
22354
|
+
* @param hex - Hex color
|
|
22355
|
+
* @returns Luminance value (0-1)
|
|
22356
|
+
*/ function getLuminance(hex) {
|
|
22357
|
+
const rgb = hexToRgb$1(hex);
|
|
21374
22358
|
if (!rgb) return 0;
|
|
21375
|
-
const
|
|
21376
|
-
|
|
21377
|
-
|
|
21378
|
-
|
|
21379
|
-
|
|
22359
|
+
const [r, g, b] = [ rgb.r, rgb.g, rgb.b ].map((v => (v /= 255) <= .03928 ? v / 12.92 : Math.pow((v + .055) / 1.055, 2.4)));
|
|
22360
|
+
return .2126 * (r ?? 0) + .7152 * (g ?? 0) + .0722 * (b ?? 0);
|
|
22361
|
+
}
|
|
22362
|
+
|
|
22363
|
+
/**
|
|
22364
|
+
* Calculate contrast ratio between two colors
|
|
22365
|
+
*
|
|
22366
|
+
* @param hex1 - First hex color
|
|
22367
|
+
* @param hex2 - Second hex color
|
|
22368
|
+
* @returns Contrast ratio (1-21)
|
|
22369
|
+
*/ function getContrastRatio(hex1, hex2) {
|
|
22370
|
+
const lum1 = getLuminance(hex1), lum2 = getLuminance(hex2);
|
|
22371
|
+
return (Math.max(lum1, lum2) + .05) / (Math.min(lum1, lum2) + .05);
|
|
21380
22372
|
}
|
|
21381
22373
|
|
|
21382
22374
|
/**
|
|
21383
|
-
*
|
|
21384
|
-
|
|
21385
|
-
|
|
21386
|
-
|
|
22375
|
+
* Check if text color passes WCAG AA standard
|
|
22376
|
+
*
|
|
22377
|
+
* @param textColor - Text color hex
|
|
22378
|
+
* @param backgroundColor - Background color hex
|
|
22379
|
+
* @param size - Font size ('small' or 'large')
|
|
22380
|
+
* @returns true if passes WCAG AA
|
|
22381
|
+
*/ function isAccessible(textColor, backgroundColor, size = "small") {
|
|
22382
|
+
return getContrastRatio(textColor, backgroundColor) >= ("large" === size ? 3 : 4.5);
|
|
21387
22383
|
}
|
|
21388
22384
|
|
|
21389
22385
|
/**
|
|
21390
|
-
* Get appropriate
|
|
21391
|
-
|
|
21392
|
-
|
|
21393
|
-
|
|
22386
|
+
* Get appropriate text color (black or white) for a background
|
|
22387
|
+
*
|
|
22388
|
+
* @param backgroundColor - Background hex color
|
|
22389
|
+
* @param threshold - Contrast threshold (default: 3)
|
|
22390
|
+
* @returns '#000000' or '#FFFFFF'
|
|
22391
|
+
*/ function getContrastText(backgroundColor, threshold = 3) {
|
|
22392
|
+
return getContrastRatio(backgroundColor, "#FFFFFF") >= threshold ? "#FFFFFF" : "#000000";
|
|
21394
22393
|
}
|
|
21395
22394
|
|
|
21396
22395
|
/**
|
|
21397
|
-
* Lighten a color
|
|
22396
|
+
* Lighten a color
|
|
21398
22397
|
*
|
|
21399
|
-
* @param
|
|
21400
|
-
* @param amount - Amount to lighten (0-1)
|
|
22398
|
+
* @param hex - Base hex color
|
|
22399
|
+
* @param amount - Amount to lighten (0-1)
|
|
21401
22400
|
* @returns Lightened hex color
|
|
21402
|
-
*/ function lighten(
|
|
21403
|
-
const rgb = hexToRgb$1(
|
|
21404
|
-
if (!rgb) return
|
|
21405
|
-
|
|
21406
|
-
|
|
22401
|
+
*/ function lighten(hex, amount = 0) {
|
|
22402
|
+
const rgb = hexToRgb$1(hex);
|
|
22403
|
+
if (!rgb) return hex;
|
|
22404
|
+
// Use amount directly as factor (0-1)
|
|
22405
|
+
const factor = Math.max(0, Math.min(1, amount)), r = Math.round(rgb.r + (255 - rgb.r) * factor), g = Math.round(rgb.g + (255 - rgb.g) * factor), b = Math.round(rgb.b + (255 - rgb.b) * factor);
|
|
22406
|
+
return rgbToHex(Math.min(255, r), Math.min(255, g), Math.min(255, b));
|
|
21407
22407
|
}
|
|
21408
22408
|
|
|
21409
22409
|
/**
|
|
21410
|
-
* Darken a color
|
|
22410
|
+
* Darken a color
|
|
21411
22411
|
*
|
|
21412
|
-
* @param
|
|
21413
|
-
* @param amount - Amount to darken (0-1)
|
|
22412
|
+
* @param hex - Base hex color
|
|
22413
|
+
* @param amount - Amount to darken (0-1)
|
|
21414
22414
|
* @returns Darkened hex color
|
|
21415
|
-
*/ function darken(
|
|
21416
|
-
const rgb = hexToRgb$1(
|
|
21417
|
-
if (!rgb) return
|
|
21418
|
-
|
|
21419
|
-
|
|
22415
|
+
*/ function darken(hex, amount = 0) {
|
|
22416
|
+
const rgb = hexToRgb$1(hex);
|
|
22417
|
+
if (!rgb) return hex;
|
|
22418
|
+
// Use amount directly as factor (0-1)
|
|
22419
|
+
const factor = Math.max(0, Math.min(1, amount)), r = Math.round(rgb.r * (1 - factor)), g = Math.round(rgb.g * (1 - factor)), b = Math.round(rgb.b * (1 - factor));
|
|
22420
|
+
return rgbToHex(Math.max(0, r), Math.max(0, g), Math.max(0, b));
|
|
21420
22421
|
}
|
|
21421
22422
|
|
|
21422
22423
|
/**
|
|
21423
|
-
* Add alpha
|
|
22424
|
+
* Add alpha to a color
|
|
21424
22425
|
*
|
|
21425
|
-
* @param
|
|
22426
|
+
* @param hex - Hex color
|
|
21426
22427
|
* @param opacity - Opacity value (0-1)
|
|
21427
22428
|
* @returns RGBA color string
|
|
21428
|
-
*/ function alpha(
|
|
21429
|
-
const rgb = hexToRgb$1(
|
|
21430
|
-
if (!rgb) return
|
|
21431
|
-
const
|
|
21432
|
-
return `rgba(${r}, ${g}, ${b}, ${
|
|
22429
|
+
*/ function alpha(hex, opacity) {
|
|
22430
|
+
const rgb = hexToRgb$1(hex);
|
|
22431
|
+
if (!rgb) return hex;
|
|
22432
|
+
const validOpacity = Math.max(0, Math.min(1, opacity));
|
|
22433
|
+
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${validOpacity})`;
|
|
21433
22434
|
}
|
|
21434
22435
|
|
|
21435
22436
|
/**
|
|
21436
22437
|
* Emphasize a color (lighten if dark, darken if light)
|
|
21437
22438
|
*
|
|
21438
|
-
* @param
|
|
21439
|
-
* @param
|
|
22439
|
+
* @param hex - Hex color
|
|
22440
|
+
* @param amount - Amount to emphasize (0-1)
|
|
21440
22441
|
* @returns Emphasized hex color
|
|
22442
|
+
*/ function emphasize(hex, amount = .15) {
|
|
22443
|
+
return getLuminance(hex) > .5 ? darken(hex, amount) : lighten(hex, amount);
|
|
22444
|
+
}
|
|
22445
|
+
|
|
22446
|
+
/**
|
|
22447
|
+
* Create a spacing utility
|
|
22448
|
+
*
|
|
22449
|
+
* @param spacingInput - Spacing configuration
|
|
22450
|
+
* @returns Spacing function
|
|
22451
|
+
*/ function createSpacing(spacingInput = 4) {
|
|
22452
|
+
return (...values) => 0 === values.length ? "0px" : "function" == typeof spacingInput ? spacingInput(...values) : values.map((value => {
|
|
22453
|
+
if ("number" == typeof spacingInput) return value * spacingInput + "px";
|
|
22454
|
+
if (Array.isArray(spacingInput)) {
|
|
22455
|
+
const scaled = spacingInput[value];
|
|
22456
|
+
return "number" == typeof scaled ? `${scaled}px` : `${value}px`;
|
|
22457
|
+
}
|
|
22458
|
+
return `${value}px`;
|
|
22459
|
+
})).join(" ");
|
|
22460
|
+
}
|
|
22461
|
+
|
|
22462
|
+
/**
|
|
22463
|
+
* CSS Variable Generator
|
|
22464
|
+
*
|
|
22465
|
+
* Generates CSS custom properties from theme objects and injects them into the DOM.
|
|
22466
|
+
*
|
|
22467
|
+
* **Token Naming Alignment:**
|
|
22468
|
+
* This generator produces CSS variables that match the SCSS token naming pattern exactly:
|
|
22469
|
+
* - Colors: --atomix-primary, --atomix-primary-1 through --atomix-primary-10
|
|
22470
|
+
* - Spacing: --atomix-spacing-1, --atomix-spacing-4, etc.
|
|
22471
|
+
* - Typography: --atomix-font-size-base, --atomix-font-weight-normal, etc.
|
|
22472
|
+
* - Shadows: --atomix-box-shadow, --atomix-box-shadow-sm, etc.
|
|
22473
|
+
*
|
|
22474
|
+
* All tokens follow the flat structure pattern used in SCSS (not nested like --atomix-palette-primary-main).
|
|
22475
|
+
* This ensures compatibility between SCSS themes and JavaScript themes.
|
|
22476
|
+
*
|
|
22477
|
+
* @see src/styles/03-generic/_generic.root.scss for SCSS token definitions
|
|
22478
|
+
*/
|
|
22479
|
+
/**
|
|
22480
|
+
* Convert a nested object to flat CSS variable declarations
|
|
22481
|
+
* Uses iterative approach for better performance with large objects
|
|
21441
22482
|
*/
|
|
21442
22483
|
/**
|
|
21443
22484
|
* Generate a color scale from a base color (1-10 steps)
|
|
@@ -21505,18 +22546,7 @@ function generateCSSVariables(theme, options = {}) {
|
|
|
21505
22546
|
color.dark && (vars[`${prefix}-${key}-hover`] = color.dark),
|
|
21506
22547
|
// Generate semantic color variants (matches SCSS patterns)
|
|
21507
22548
|
// Text emphasis: emphasized version of the color for text (--atomix-primary-text-emphasis)
|
|
21508
|
-
vars[`${prefix}-${key}-text-emphasis`] =
|
|
21509
|
-
return getLuminance(color) > .5 ? darken(color, coefficient) : lighten(color, coefficient);
|
|
21510
|
-
}
|
|
21511
|
-
// ============================================================================
|
|
21512
|
-
// Spacing Utilities
|
|
21513
|
-
// ============================================================================
|
|
21514
|
-
/**
|
|
21515
|
-
* Create a spacing function from various input types
|
|
21516
|
-
*
|
|
21517
|
-
* @param spacingInput - Spacing configuration (number, array, or function), default 4
|
|
21518
|
-
* @returns Spacing function
|
|
21519
|
-
*/ (color.main, .15),
|
|
22549
|
+
vars[`${prefix}-${key}-text-emphasis`] = emphasize(color.main, .15),
|
|
21520
22550
|
// Background subtle: very light version for backgrounds (--atomix-primary-bg-subtle)
|
|
21521
22551
|
vars[`${prefix}-${key}-bg-subtle`] = alpha(color.main, .1),
|
|
21522
22552
|
// Border subtle: light version for borders (--atomix-primary-border-subtle)
|
|
@@ -21861,29 +22891,7 @@ function generateCSSVariables(theme, options = {}) {
|
|
|
21861
22891
|
return vars[`${prefix}-focus-ring-width`] = "3px", vars[`${prefix}-focus-ring-offset`] = "2px",
|
|
21862
22892
|
vars[`${prefix}-focus-ring-opacity`] = "0.25", vars;
|
|
21863
22893
|
}(theme.palette, prefix)), theme.custom && Object.keys(theme.custom).length > 0) {
|
|
21864
|
-
const customVars =
|
|
21865
|
-
/**
|
|
21866
|
-
* CSS Variable Generator
|
|
21867
|
-
*
|
|
21868
|
-
* Generates CSS custom properties from theme objects and injects them into the DOM.
|
|
21869
|
-
*
|
|
21870
|
-
* **Token Naming Alignment:**
|
|
21871
|
-
* This generator produces CSS variables that match the SCSS token naming pattern exactly:
|
|
21872
|
-
* - Colors: --atomix-primary, --atomix-primary-1 through --atomix-primary-10
|
|
21873
|
-
* - Spacing: --atomix-spacing-1, --atomix-spacing-4, etc.
|
|
21874
|
-
* - Typography: --atomix-font-size-base, --atomix-font-weight-normal, etc.
|
|
21875
|
-
* - Shadows: --atomix-box-shadow, --atomix-box-shadow-sm, etc.
|
|
21876
|
-
*
|
|
21877
|
-
* All tokens follow the flat structure pattern used in SCSS (not nested like --atomix-palette-primary-main).
|
|
21878
|
-
* This ensures compatibility between SCSS themes and JavaScript themes.
|
|
21879
|
-
*
|
|
21880
|
-
* @see src/styles/03-generic/_generic.root.scss for SCSS token definitions
|
|
21881
|
-
*/
|
|
21882
|
-
/**
|
|
21883
|
-
* Convert a nested object to flat CSS variable declarations
|
|
21884
|
-
* Uses iterative approach for better performance with large objects
|
|
21885
|
-
*/
|
|
21886
|
-
function(obj, prefix = "", result = {}) {
|
|
22894
|
+
const customVars = function(obj, prefix = "", result = {}) {
|
|
21887
22895
|
// Use iterative approach with stack to avoid deep recursion
|
|
21888
22896
|
const stack = [ {
|
|
21889
22897
|
obj: obj,
|
|
@@ -22337,19 +23345,29 @@ const logger = getLogger(), ThemeProvider = ({children: children, defaultTheme:
|
|
|
22337
23345
|
// Check storage first
|
|
22338
23346
|
if (enablePersistence && storageAdapter.isAvailable()) {
|
|
22339
23347
|
const stored = storageAdapter.getItem(storageKey);
|
|
22340
|
-
if (stored)
|
|
23348
|
+
if (stored) {
|
|
23349
|
+
// If it looks like a JSON object, parse it
|
|
23350
|
+
if (stored.trim().startsWith("{")) try {
|
|
23351
|
+
return JSON.parse(stored);
|
|
23352
|
+
} catch (e) {
|
|
23353
|
+
return logger.error("Failed to parse stored theme tokens", e), stored;
|
|
23354
|
+
}
|
|
23355
|
+
return stored;
|
|
23356
|
+
}
|
|
22341
23357
|
}
|
|
22342
23358
|
// If defaultTheme is provided, use it
|
|
22343
23359
|
return null != defaultTheme ? defaultTheme : "default";
|
|
22344
23360
|
// Default fallback
|
|
22345
|
-
}), [ defaultTheme, enablePersistence, storageKey ]), [currentTheme, setCurrentTheme] = useState((() => "string" == typeof initialDefaultTheme ? initialDefaultTheme : "tokens-theme")), [activeTokens, setActiveTokens] = useState((() => {
|
|
22346
|
-
//
|
|
22347
|
-
if (
|
|
23361
|
+
}), [ defaultTheme, enablePersistence, storageKey, storageAdapter ]), [currentTheme, setCurrentTheme] = useState((() => "string" == typeof initialDefaultTheme ? initialDefaultTheme : "tokens-theme")), [activeTokens, setActiveTokens] = useState((() => {
|
|
23362
|
+
// 1. Check if initialDefaultTheme (from storage) is an object
|
|
23363
|
+
if (initialDefaultTheme && "string" != typeof initialDefaultTheme) {
|
|
23364
|
+
const {tokens: tokens, validation: validation} = validateAndMergeTokens(initialDefaultTheme);
|
|
23365
|
+
if (validation.valid) return tokens;
|
|
23366
|
+
}
|
|
23367
|
+
// 2. Check if defaultTheme prop is an object
|
|
23368
|
+
if (defaultTheme && "string" != typeof defaultTheme) {
|
|
22348
23369
|
const {tokens: tokens, validation: validation} = validateAndMergeTokens(defaultTheme);
|
|
22349
|
-
|
|
22350
|
-
errors: validation.errors,
|
|
22351
|
-
warnings: validation.warnings
|
|
22352
|
-
}), createTokens({}));
|
|
23370
|
+
if (validation.valid) return tokens;
|
|
22353
23371
|
}
|
|
22354
23372
|
return null;
|
|
22355
23373
|
})), [isLoading, setIsLoading] = useState(!1), [error, setError] = useState(null), loadedThemesRef = useRef(new Set), themePromisesRef = useRef({}), abortControllerRef = useRef(null);
|
|
@@ -22361,10 +23379,14 @@ const logger = getLogger(), ThemeProvider = ({children: children, defaultTheme:
|
|
|
22361
23379
|
useEffect((() => {
|
|
22362
23380
|
isServer() || applyThemeAttributes(String(currentTheme), dataAttribute);
|
|
22363
23381
|
}), [ currentTheme, dataAttribute ]),
|
|
22364
|
-
// Handle
|
|
23382
|
+
// Handle persistence
|
|
22365
23383
|
useEffect((() => {
|
|
22366
|
-
enablePersistence && storageAdapter.isAvailable() &&
|
|
22367
|
-
|
|
23384
|
+
enablePersistence && storageAdapter.isAvailable() && ("tokens-theme" === currentTheme ?
|
|
23385
|
+
// Only persist if we have actual tokens to store
|
|
23386
|
+
activeTokens && storageAdapter.setItem(storageKey, JSON.stringify(activeTokens)) :
|
|
23387
|
+
// Persist named theme string
|
|
23388
|
+
storageAdapter.setItem(storageKey, String(currentTheme)));
|
|
23389
|
+
}), [ currentTheme, activeTokens, enablePersistence, storageKey, storageAdapter ]),
|
|
22368
23390
|
// Cleanup: Remove completed promises and abort controllers on unmount
|
|
22369
23391
|
useEffect((() => () => {
|
|
22370
23392
|
// Cancel any in-flight theme loads
|
|
@@ -22503,20 +23525,21 @@ const logger = getLogger(), ThemeProvider = ({children: children, defaultTheme:
|
|
|
22503
23525
|
setIsLoading(!1);
|
|
22504
23526
|
}
|
|
22505
23527
|
}
|
|
22506
|
-
}), [ themes, isThemeLoaded, handleError, basePath, useMinified, cdnPath ]), themeManager = useMemo((() => ({})), []), availableThemes = useMemo((() => Object.entries(themes).map((([name, metadata]) => ({
|
|
23528
|
+
}), [ themes, isThemeLoaded, handleError, basePath, useMinified, cdnPath ]), updateTheme = useCallback((async (sectionOrTokens, values) => setTheme("string" == typeof sectionOrTokens && values ? values : sectionOrTokens)), [ setTheme ]), themeManager = useMemo((() => ({})), []), availableThemes = useMemo((() => Object.entries(themes).map((([name, metadata]) => ({
|
|
22507
23529
|
...metadata,
|
|
22508
23530
|
name: name
|
|
22509
23531
|
})))), [ themes ]), contextValue = useMemo((() => ({
|
|
22510
23532
|
theme: currentTheme,
|
|
22511
23533
|
activeTokens: activeTokens,
|
|
22512
23534
|
setTheme: setTheme,
|
|
23535
|
+
updateTheme: updateTheme,
|
|
22513
23536
|
availableThemes: availableThemes,
|
|
22514
23537
|
isLoading: isLoading,
|
|
22515
23538
|
error: error,
|
|
22516
23539
|
isThemeLoaded: isThemeLoaded,
|
|
22517
23540
|
preloadTheme: preloadTheme,
|
|
22518
23541
|
themeManager: themeManager
|
|
22519
|
-
})), [ currentTheme, activeTokens, setTheme, availableThemes,
|
|
23542
|
+
})), [ currentTheme, activeTokens, setTheme, updateTheme, availableThemes,
|
|
22520
23543
|
// Use memoized value
|
|
22521
23544
|
isLoading, error, isThemeLoaded, preloadTheme, themeManager ]);
|
|
22522
23545
|
// Check if theme is loaded
|
|
@@ -22570,6 +23593,7 @@ function useTheme() {
|
|
|
22570
23593
|
theme: context.theme,
|
|
22571
23594
|
activeTokens: context.activeTokens,
|
|
22572
23595
|
setTheme: context.setTheme,
|
|
23596
|
+
updateTheme: context.updateTheme,
|
|
22573
23597
|
availableThemes: context.availableThemes,
|
|
22574
23598
|
isLoading: context.isLoading,
|
|
22575
23599
|
error: context.error,
|
|
@@ -22805,6 +23829,389 @@ function useThemeTokens() {
|
|
|
22805
23829
|
}
|
|
22806
23830
|
}
|
|
22807
23831
|
|
|
23832
|
+
/**
|
|
23833
|
+
* useThemeSwitcher Hook
|
|
23834
|
+
*
|
|
23835
|
+
* React hook for managing theme switching with persistence and system preference detection.
|
|
23836
|
+
* Provides an easy-to-use API for dark/light mode toggling.
|
|
23837
|
+
*
|
|
23838
|
+
* @example
|
|
23839
|
+
* ```tsx
|
|
23840
|
+
* import { useThemeSwitcher } from '@shohojdhara/atomix/theme';
|
|
23841
|
+
*
|
|
23842
|
+
* function ThemeToggle() {
|
|
23843
|
+
* const { mode, toggle, setMode, isDark } = useThemeSwitcher();
|
|
23844
|
+
*
|
|
23845
|
+
* return (
|
|
23846
|
+
* <button onClick={toggle}>
|
|
23847
|
+
* {isDark ? '☀️ Light' : '🌙 Dark'}
|
|
23848
|
+
* </button>
|
|
23849
|
+
* );
|
|
23850
|
+
* }
|
|
23851
|
+
* ```
|
|
23852
|
+
*/
|
|
23853
|
+
/**
|
|
23854
|
+
* Hook for managing theme switching
|
|
23855
|
+
*
|
|
23856
|
+
* @param options - Configuration options
|
|
23857
|
+
* @returns Theme switcher controls
|
|
23858
|
+
*/ function useThemeSwitcher(options = {}) {
|
|
23859
|
+
const {initialMode: initialMode = "system", syncWithSystem: syncWithSystem = !1, storageKey: storageKey = "atomix-theme", enableTransition: enableTransition = !0, transitionDuration: transitionDuration = 300} = options, [mode, setModeState] = useState((() => {
|
|
23860
|
+
if ("undefined" == typeof window) return initialMode;
|
|
23861
|
+
// Check for saved preference first
|
|
23862
|
+
const saved = getCurrentTheme(storageKey);
|
|
23863
|
+
return saved && "system" !== saved ? saved : "system" === initialMode ? getSystemTheme() : initialMode;
|
|
23864
|
+
// Fall back to initial mode or system
|
|
23865
|
+
}));
|
|
23866
|
+
// State for current mode
|
|
23867
|
+
// Initialize theme on mount
|
|
23868
|
+
return useEffect((() => {
|
|
23869
|
+
"undefined" != typeof window && (
|
|
23870
|
+
// Initialize with proper theme application
|
|
23871
|
+
initializeTheme({
|
|
23872
|
+
storageKey: storageKey,
|
|
23873
|
+
enableTransition: enableTransition,
|
|
23874
|
+
transitionDuration: transitionDuration
|
|
23875
|
+
}),
|
|
23876
|
+
// Update state to match initialized theme
|
|
23877
|
+
setModeState(getCurrentTheme(storageKey)));
|
|
23878
|
+
}), [ storageKey, enableTransition, transitionDuration ]),
|
|
23879
|
+
// Listen for system theme changes if enabled
|
|
23880
|
+
useEffect((() => {
|
|
23881
|
+
if (syncWithSystem) return listenToSystemTheme((newMode => {
|
|
23882
|
+
setModeState(newMode), switchTheme(newMode, {
|
|
23883
|
+
storageKey: storageKey,
|
|
23884
|
+
enableTransition: enableTransition,
|
|
23885
|
+
transitionDuration: transitionDuration
|
|
23886
|
+
});
|
|
23887
|
+
}));
|
|
23888
|
+
}), [ syncWithSystem, storageKey, enableTransition, transitionDuration ]), {
|
|
23889
|
+
mode: mode,
|
|
23890
|
+
isDark: "dark" === mode,
|
|
23891
|
+
isLight: "light" === mode,
|
|
23892
|
+
toggle: useCallback((() => {
|
|
23893
|
+
const newMode = toggleTheme({
|
|
23894
|
+
storageKey: storageKey,
|
|
23895
|
+
enableTransition: enableTransition,
|
|
23896
|
+
transitionDuration: transitionDuration
|
|
23897
|
+
});
|
|
23898
|
+
return setModeState(newMode), newMode;
|
|
23899
|
+
}), [ storageKey, enableTransition, transitionDuration ]),
|
|
23900
|
+
setMode: useCallback((newMode => {
|
|
23901
|
+
switchTheme(newMode, {
|
|
23902
|
+
storageKey: storageKey,
|
|
23903
|
+
enableTransition: enableTransition,
|
|
23904
|
+
transitionDuration: transitionDuration
|
|
23905
|
+
}), setModeState(newMode);
|
|
23906
|
+
}), [ storageKey, enableTransition, transitionDuration ]),
|
|
23907
|
+
resetToSystem: useCallback((() => {
|
|
23908
|
+
const systemMode = getSystemTheme();
|
|
23909
|
+
switchTheme(systemMode, {
|
|
23910
|
+
storageKey: storageKey,
|
|
23911
|
+
enableTransition: enableTransition,
|
|
23912
|
+
transitionDuration: transitionDuration
|
|
23913
|
+
}), setModeState(systemMode);
|
|
23914
|
+
}), [ storageKey, enableTransition, transitionDuration ]),
|
|
23915
|
+
clearPreference: useCallback((() => {
|
|
23916
|
+
"undefined" != typeof window && localStorage.removeItem(storageKey);
|
|
23917
|
+
}), [ storageKey ])
|
|
23918
|
+
};
|
|
23919
|
+
}
|
|
23920
|
+
|
|
23921
|
+
/**
|
|
23922
|
+
* ThemeToggle component with multiple variants
|
|
23923
|
+
*/ const ThemeToggle = ({className: className = "", showLabel: showLabel = !1, lightLabel: lightLabel = "Light", darkLabel: darkLabel = "Dark", iconSize: iconSize = 20, variant: variant = "icon", render: render, ariaLabel: ariaLabel = "Toggle theme", ...hookOptions}) => {
|
|
23924
|
+
const {mode: mode, isDark: isDark, toggle: toggle} = useThemeSwitcher(hookOptions);
|
|
23925
|
+
// Custom render
|
|
23926
|
+
return render ? jsx(Fragment, {
|
|
23927
|
+
children: render({
|
|
23928
|
+
isDark: isDark,
|
|
23929
|
+
toggle: toggle,
|
|
23930
|
+
mode: mode
|
|
23931
|
+
})
|
|
23932
|
+
}) :
|
|
23933
|
+
// Icon-only variant (default)
|
|
23934
|
+
"icon" === variant ? jsx("button", {
|
|
23935
|
+
onClick: toggle,
|
|
23936
|
+
className: `theme-toggle theme-toggle-icon ${className}`,
|
|
23937
|
+
"aria-label": ariaLabel,
|
|
23938
|
+
title: isDark ? darkLabel : lightLabel,
|
|
23939
|
+
style: {
|
|
23940
|
+
background: "none",
|
|
23941
|
+
border: "none",
|
|
23942
|
+
cursor: "pointer",
|
|
23943
|
+
padding: "8px",
|
|
23944
|
+
borderRadius: "50%",
|
|
23945
|
+
display: "flex",
|
|
23946
|
+
alignItems: "center",
|
|
23947
|
+
justifyContent: "center",
|
|
23948
|
+
transition: "all 0.3s ease-in-out"
|
|
23949
|
+
},
|
|
23950
|
+
children: isDark ? jsxs("svg", {
|
|
23951
|
+
width: iconSize,
|
|
23952
|
+
height: iconSize,
|
|
23953
|
+
viewBox: "0 0 24 24",
|
|
23954
|
+
fill: "none",
|
|
23955
|
+
stroke: "currentColor",
|
|
23956
|
+
strokeWidth: "2",
|
|
23957
|
+
strokeLinecap: "round",
|
|
23958
|
+
strokeLinejoin: "round",
|
|
23959
|
+
children: [ jsx("circle", {
|
|
23960
|
+
cx: "12",
|
|
23961
|
+
cy: "12",
|
|
23962
|
+
r: "5"
|
|
23963
|
+
}), jsx("line", {
|
|
23964
|
+
x1: "12",
|
|
23965
|
+
y1: "1",
|
|
23966
|
+
x2: "12",
|
|
23967
|
+
y2: "3"
|
|
23968
|
+
}), jsx("line", {
|
|
23969
|
+
x1: "12",
|
|
23970
|
+
y1: "21",
|
|
23971
|
+
x2: "12",
|
|
23972
|
+
y2: "23"
|
|
23973
|
+
}), jsx("line", {
|
|
23974
|
+
x1: "4.22",
|
|
23975
|
+
y1: "4.22",
|
|
23976
|
+
x2: "5.64",
|
|
23977
|
+
y2: "5.64"
|
|
23978
|
+
}), jsx("line", {
|
|
23979
|
+
x1: "18.36",
|
|
23980
|
+
y1: "18.36",
|
|
23981
|
+
x2: "19.78",
|
|
23982
|
+
y2: "19.78"
|
|
23983
|
+
}), jsx("line", {
|
|
23984
|
+
x1: "1",
|
|
23985
|
+
y1: "12",
|
|
23986
|
+
x2: "3",
|
|
23987
|
+
y2: "12"
|
|
23988
|
+
}), jsx("line", {
|
|
23989
|
+
x1: "21",
|
|
23990
|
+
y1: "12",
|
|
23991
|
+
x2: "23",
|
|
23992
|
+
y2: "12"
|
|
23993
|
+
}), jsx("line", {
|
|
23994
|
+
x1: "4.22",
|
|
23995
|
+
y1: "19.78",
|
|
23996
|
+
x2: "5.64",
|
|
23997
|
+
y2: "18.36"
|
|
23998
|
+
}), jsx("line", {
|
|
23999
|
+
x1: "18.36",
|
|
24000
|
+
y1: "5.64",
|
|
24001
|
+
x2: "19.78",
|
|
24002
|
+
y2: "4.22"
|
|
24003
|
+
}) ]
|
|
24004
|
+
}) : jsx("svg", {
|
|
24005
|
+
width: iconSize,
|
|
24006
|
+
height: iconSize,
|
|
24007
|
+
viewBox: "0 0 24 24",
|
|
24008
|
+
fill: "none",
|
|
24009
|
+
stroke: "currentColor",
|
|
24010
|
+
strokeWidth: "2",
|
|
24011
|
+
strokeLinecap: "round",
|
|
24012
|
+
strokeLinejoin: "round",
|
|
24013
|
+
children: jsx("path", {
|
|
24014
|
+
d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"
|
|
24015
|
+
})
|
|
24016
|
+
})
|
|
24017
|
+
}) :
|
|
24018
|
+
// Button variant with text
|
|
24019
|
+
"button" === variant ? jsxs("button", {
|
|
24020
|
+
onClick: toggle,
|
|
24021
|
+
className: `theme-toggle theme-toggle-button ${className}`,
|
|
24022
|
+
"aria-label": ariaLabel,
|
|
24023
|
+
style: {
|
|
24024
|
+
display: "flex",
|
|
24025
|
+
alignItems: "center",
|
|
24026
|
+
gap: "8px",
|
|
24027
|
+
padding: "8px 16px",
|
|
24028
|
+
borderRadius: "8px",
|
|
24029
|
+
border: "1px solid currentColor",
|
|
24030
|
+
background: "transparent",
|
|
24031
|
+
color: "inherit",
|
|
24032
|
+
cursor: "pointer",
|
|
24033
|
+
fontSize: "14px",
|
|
24034
|
+
fontWeight: "500",
|
|
24035
|
+
transition: "all 0.3s ease-in-out"
|
|
24036
|
+
},
|
|
24037
|
+
children: [ isDark ? jsxs("svg", {
|
|
24038
|
+
width: iconSize,
|
|
24039
|
+
height: iconSize,
|
|
24040
|
+
viewBox: "0 0 24 24",
|
|
24041
|
+
fill: "none",
|
|
24042
|
+
stroke: "currentColor",
|
|
24043
|
+
strokeWidth: "2",
|
|
24044
|
+
strokeLinecap: "round",
|
|
24045
|
+
strokeLinejoin: "round",
|
|
24046
|
+
children: [ jsx("circle", {
|
|
24047
|
+
cx: "12",
|
|
24048
|
+
cy: "12",
|
|
24049
|
+
r: "5"
|
|
24050
|
+
}), jsx("line", {
|
|
24051
|
+
x1: "12",
|
|
24052
|
+
y1: "1",
|
|
24053
|
+
x2: "12",
|
|
24054
|
+
y2: "3"
|
|
24055
|
+
}), jsx("line", {
|
|
24056
|
+
x1: "12",
|
|
24057
|
+
y1: "21",
|
|
24058
|
+
x2: "12",
|
|
24059
|
+
y2: "23"
|
|
24060
|
+
}), jsx("line", {
|
|
24061
|
+
x1: "4.22",
|
|
24062
|
+
y1: "4.22",
|
|
24063
|
+
x2: "5.64",
|
|
24064
|
+
y2: "5.64"
|
|
24065
|
+
}), jsx("line", {
|
|
24066
|
+
x1: "18.36",
|
|
24067
|
+
y1: "18.36",
|
|
24068
|
+
x2: "19.78",
|
|
24069
|
+
y2: "19.78"
|
|
24070
|
+
}), jsx("line", {
|
|
24071
|
+
x1: "1",
|
|
24072
|
+
y1: "12",
|
|
24073
|
+
x2: "3",
|
|
24074
|
+
y2: "12"
|
|
24075
|
+
}), jsx("line", {
|
|
24076
|
+
x1: "21",
|
|
24077
|
+
y1: "12",
|
|
24078
|
+
x2: "23",
|
|
24079
|
+
y2: "12"
|
|
24080
|
+
}), jsx("line", {
|
|
24081
|
+
x1: "4.22",
|
|
24082
|
+
y1: "19.78",
|
|
24083
|
+
x2: "5.64",
|
|
24084
|
+
y2: "18.36"
|
|
24085
|
+
}), jsx("line", {
|
|
24086
|
+
x1: "18.36",
|
|
24087
|
+
y1: "5.64",
|
|
24088
|
+
x2: "19.78",
|
|
24089
|
+
y2: "4.22"
|
|
24090
|
+
}) ]
|
|
24091
|
+
}) : jsx("svg", {
|
|
24092
|
+
width: iconSize,
|
|
24093
|
+
height: iconSize,
|
|
24094
|
+
viewBox: "0 0 24 24",
|
|
24095
|
+
fill: "none",
|
|
24096
|
+
stroke: "currentColor",
|
|
24097
|
+
strokeWidth: "2",
|
|
24098
|
+
strokeLinecap: "round",
|
|
24099
|
+
strokeLinejoin: "round",
|
|
24100
|
+
children: jsx("path", {
|
|
24101
|
+
d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"
|
|
24102
|
+
})
|
|
24103
|
+
}), showLabel && jsx("span", {
|
|
24104
|
+
children: isDark ? darkLabel : lightLabel
|
|
24105
|
+
}) ]
|
|
24106
|
+
}) :
|
|
24107
|
+
// Switch/toggle variant
|
|
24108
|
+
"switch" === variant ? jsx("div", {
|
|
24109
|
+
className: `theme-toggle theme-toggle-switch ${className}`,
|
|
24110
|
+
role: "button",
|
|
24111
|
+
tabIndex: 0,
|
|
24112
|
+
onClick: toggle,
|
|
24113
|
+
onKeyDown: e => "Enter" === e.key && toggle(),
|
|
24114
|
+
"aria-label": ariaLabel,
|
|
24115
|
+
style: {
|
|
24116
|
+
position: "relative",
|
|
24117
|
+
width: "56px",
|
|
24118
|
+
height: "28px",
|
|
24119
|
+
borderRadius: "14px",
|
|
24120
|
+
background: isDark ? "#4b5563" : "#d1d5db",
|
|
24121
|
+
cursor: "pointer",
|
|
24122
|
+
transition: "background 0.3s ease-in-out",
|
|
24123
|
+
display: "flex",
|
|
24124
|
+
alignItems: "center",
|
|
24125
|
+
padding: "2px"
|
|
24126
|
+
},
|
|
24127
|
+
children: jsx("div", {
|
|
24128
|
+
style: {
|
|
24129
|
+
position: "absolute",
|
|
24130
|
+
left: isDark ? "auto" : "2px",
|
|
24131
|
+
right: isDark ? "2px" : "auto",
|
|
24132
|
+
width: "24px",
|
|
24133
|
+
height: "24px",
|
|
24134
|
+
borderRadius: "50%",
|
|
24135
|
+
background: "white",
|
|
24136
|
+
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.2)",
|
|
24137
|
+
transition: "all 0.3s ease-in-out",
|
|
24138
|
+
display: "flex",
|
|
24139
|
+
alignItems: "center",
|
|
24140
|
+
justifyContent: "center"
|
|
24141
|
+
},
|
|
24142
|
+
children: isDark ? jsx("svg", {
|
|
24143
|
+
width: "14",
|
|
24144
|
+
height: "14",
|
|
24145
|
+
viewBox: "0 0 24 24",
|
|
24146
|
+
fill: "none",
|
|
24147
|
+
stroke: "#4b5563",
|
|
24148
|
+
strokeWidth: "2",
|
|
24149
|
+
strokeLinecap: "round",
|
|
24150
|
+
strokeLinejoin: "round",
|
|
24151
|
+
children: jsx("path", {
|
|
24152
|
+
d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"
|
|
24153
|
+
})
|
|
24154
|
+
}) : jsxs("svg", {
|
|
24155
|
+
width: "14",
|
|
24156
|
+
height: "14",
|
|
24157
|
+
viewBox: "0 0 24 24",
|
|
24158
|
+
fill: "none",
|
|
24159
|
+
stroke: "#f59e0b",
|
|
24160
|
+
strokeWidth: "2",
|
|
24161
|
+
strokeLinecap: "round",
|
|
24162
|
+
strokeLinejoin: "round",
|
|
24163
|
+
children: [ jsx("circle", {
|
|
24164
|
+
cx: "12",
|
|
24165
|
+
cy: "12",
|
|
24166
|
+
r: "5"
|
|
24167
|
+
}), jsx("line", {
|
|
24168
|
+
x1: "12",
|
|
24169
|
+
y1: "1",
|
|
24170
|
+
x2: "12",
|
|
24171
|
+
y2: "3"
|
|
24172
|
+
}), jsx("line", {
|
|
24173
|
+
x1: "12",
|
|
24174
|
+
y1: "21",
|
|
24175
|
+
x2: "12",
|
|
24176
|
+
y2: "23"
|
|
24177
|
+
}), jsx("line", {
|
|
24178
|
+
x1: "4.22",
|
|
24179
|
+
y1: "4.22",
|
|
24180
|
+
x2: "5.64",
|
|
24181
|
+
y2: "5.64"
|
|
24182
|
+
}), jsx("line", {
|
|
24183
|
+
x1: "18.36",
|
|
24184
|
+
y1: "18.36",
|
|
24185
|
+
x2: "19.78",
|
|
24186
|
+
y2: "19.78"
|
|
24187
|
+
}), jsx("line", {
|
|
24188
|
+
x1: "1",
|
|
24189
|
+
y1: "12",
|
|
24190
|
+
x2: "3",
|
|
24191
|
+
y2: "12"
|
|
24192
|
+
}), jsx("line", {
|
|
24193
|
+
x1: "21",
|
|
24194
|
+
y1: "12",
|
|
24195
|
+
x2: "23",
|
|
24196
|
+
y2: "12"
|
|
24197
|
+
}), jsx("line", {
|
|
24198
|
+
x1: "4.22",
|
|
24199
|
+
y1: "19.78",
|
|
24200
|
+
x2: "5.64",
|
|
24201
|
+
y2: "18.36"
|
|
24202
|
+
}), jsx("line", {
|
|
24203
|
+
x1: "18.36",
|
|
24204
|
+
y1: "5.64",
|
|
24205
|
+
x2: "19.78",
|
|
24206
|
+
y2: "4.22"
|
|
24207
|
+
}) ]
|
|
24208
|
+
})
|
|
24209
|
+
})
|
|
24210
|
+
}) : null;
|
|
24211
|
+
};
|
|
24212
|
+
|
|
24213
|
+
ThemeToggle.displayName = "ThemeToggle";
|
|
24214
|
+
|
|
22808
24215
|
/**
|
|
22809
24216
|
* Theme Applicator
|
|
22810
24217
|
*
|
|
@@ -22817,7 +24224,8 @@ function useThemeTokens() {
|
|
|
22817
24224
|
* Theme applicator class for runtime theme application
|
|
22818
24225
|
*
|
|
22819
24226
|
* Uses the unified theme system for efficient CSS variable generation and injection.
|
|
22820
|
-
*/
|
|
24227
|
+
*/
|
|
24228
|
+
class ThemeApplicator {
|
|
22821
24229
|
constructor(root = document.documentElement) {
|
|
22822
24230
|
this.styleId = "atomix-theme-applicator", this.root = root;
|
|
22823
24231
|
}
|
|
@@ -23643,7 +25051,7 @@ class ThemeValidator {
|
|
|
23643
25051
|
*
|
|
23644
25052
|
* Provides detailed inspection and debugging information for themes
|
|
23645
25053
|
*/ const ThemeInspector = ({theme: theme, showValidation: showValidation = !0, showCSSVariables: showCSSVariables = !0, showStructure: showStructure = !0, className: className, style: style}) => {
|
|
23646
|
-
const [activeTab, setActiveTab] = useState("overview"), [expandedSections, setExpandedSections] = useState(new Set([ "palette" ])), [searchQuery, setSearchQuery] = useState(""), [debouncedSearchQuery, setDebouncedSearchQuery] = useState(""), [copiedPath, setCopiedPath] = useState(null), searchTimeoutRef = useRef();
|
|
25054
|
+
const [activeTab, setActiveTab] = useState("overview"), [expandedSections, setExpandedSections] = useState(new Set([ "palette" ])), [searchQuery, setSearchQuery] = useState(""), [debouncedSearchQuery, setDebouncedSearchQuery] = useState(""), [copiedPath, setCopiedPath] = useState(null), searchTimeoutRef = useRef(void 0);
|
|
23647
25055
|
// Debounce search query
|
|
23648
25056
|
useEffect((() => (searchTimeoutRef.current && clearTimeout(searchTimeoutRef.current),
|
|
23649
25057
|
searchTimeoutRef.current = setTimeout((() => {
|
|
@@ -24049,7 +25457,7 @@ class ThemeValidator {
|
|
|
24049
25457
|
}) ]
|
|
24050
25458
|
});
|
|
24051
25459
|
}, ThemeComparator = ({themeA: themeA, themeB: themeB, showOnlyDifferences: showOnlyDifferences = !1, className: className, style: style}) => {
|
|
24052
|
-
const [searchQuery, setSearchQuery] = useState(""), [debouncedSearchQuery, setDebouncedSearchQuery] = useState(""), [filterType, setFilterType] = useState("all"), [filterCategory, setFilterCategory] = useState("all"), searchTimeoutRef = useRef();
|
|
25460
|
+
const [searchQuery, setSearchQuery] = useState(""), [debouncedSearchQuery, setDebouncedSearchQuery] = useState(""), [filterType, setFilterType] = useState("all"), [filterCategory, setFilterCategory] = useState("all"), searchTimeoutRef = useRef(void 0);
|
|
24053
25461
|
// Debounce search query
|
|
24054
25462
|
useEffect((() => (searchTimeoutRef.current && clearTimeout(searchTimeoutRef.current),
|
|
24055
25463
|
searchTimeoutRef.current = setTimeout((() => {
|
|
@@ -24556,13 +25964,13 @@ class ThemeValidator {
|
|
|
24556
25964
|
function createPaletteColor(color) {
|
|
24557
25965
|
return "string" == typeof color ? {
|
|
24558
25966
|
main: color,
|
|
24559
|
-
light: lighten(color),
|
|
24560
|
-
dark: darken(color),
|
|
25967
|
+
light: lighten(color, .15),
|
|
25968
|
+
dark: darken(color, .15),
|
|
24561
25969
|
contrastText: getContrastText(color)
|
|
24562
25970
|
} : {
|
|
24563
25971
|
main: color.main || "#000000",
|
|
24564
|
-
light: color.light || lighten(color.main || "#000000"),
|
|
24565
|
-
dark: color.dark || darken(color.main || "#000000"),
|
|
25972
|
+
light: color.light || lighten(color.main || "#000000", .15),
|
|
25973
|
+
dark: color.dark || darken(color.main || "#000000", .15),
|
|
24566
25974
|
contrastText: color.contrastText || getContrastText(color.main || "#000000")
|
|
24567
25975
|
};
|
|
24568
25976
|
}
|
|
@@ -24597,23 +26005,19 @@ function createThemeObject(...options) {
|
|
|
24597
26005
|
},
|
|
24598
26006
|
background: {
|
|
24599
26007
|
default: mergedOptions.palette?.background?.default || DEFAULT_PALETTE.background.default,
|
|
26008
|
+
paper: mergedOptions.palette?.background?.paper || DEFAULT_PALETTE.background.paper,
|
|
24600
26009
|
subtle: mergedOptions.palette?.background?.subtle || DEFAULT_PALETTE.background.subtle
|
|
24601
26010
|
},
|
|
24602
26011
|
text: {
|
|
24603
26012
|
primary: mergedOptions.palette?.text?.primary || DEFAULT_PALETTE.text.primary,
|
|
24604
26013
|
secondary: mergedOptions.palette?.text?.secondary || DEFAULT_PALETTE.text.secondary,
|
|
24605
26014
|
disabled: mergedOptions.palette?.text?.disabled || DEFAULT_PALETTE.text.disabled
|
|
24606
|
-
}
|
|
26015
|
+
},
|
|
26016
|
+
// Spread other palette properties
|
|
26017
|
+
...mergedOptions.palette
|
|
24607
26018
|
}, typography = deepMerge({
|
|
24608
26019
|
...DEFAULT_TYPOGRAPHY
|
|
24609
|
-
}, mergedOptions.typography || {}), spacing =
|
|
24610
|
-
// If it's already a function, return it
|
|
24611
|
-
return "function" == typeof spacingInput ? spacingInput :
|
|
24612
|
-
// If it's a number, create a function that multiplies by that number
|
|
24613
|
-
"number" == typeof spacingInput ? (...values) => 0 === values.length ? "0px" : values.map((value => value * spacingInput + "px")).join(" ") :
|
|
24614
|
-
// If it's an array, use it as a scale
|
|
24615
|
-
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(" ");
|
|
24616
|
-
}(mergedOptions.spacing), breakpoints = function(breakpointsInput) {
|
|
26020
|
+
}, mergedOptions.typography || {}), spacing = createSpacing(mergedOptions.spacing), breakpoints = function(breakpointsInput) {
|
|
24617
26021
|
const values = {
|
|
24618
26022
|
xs: 0,
|
|
24619
26023
|
sm: 576,
|
|
@@ -24845,7 +26249,7 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
|
|
|
24845
26249
|
} catch (err) {
|
|
24846
26250
|
setError(err instanceof Error ? err.message : "Invalid JSON");
|
|
24847
26251
|
}
|
|
24848
|
-
}), [ updateTheme ]), jsonUpdateTimeoutRef = useRef();
|
|
26252
|
+
}), [ updateTheme ]), jsonUpdateTimeoutRef = useRef(void 0);
|
|
24849
26253
|
// Debounced JSON update to history
|
|
24850
26254
|
useEffect((() => {
|
|
24851
26255
|
if (!error) {
|
|
@@ -25434,48 +26838,360 @@ const ThemeLiveEditor = ({initialTheme: initialTheme, onChange: onChange, classN
|
|
|
25434
26838
|
};
|
|
25435
26839
|
|
|
25436
26840
|
/**
|
|
25437
|
-
* Design Tokens Customizer Component
|
|
25438
|
-
*/
|
|
25439
|
-
/**
|
|
25440
|
-
* Theme
|
|
25441
|
-
*
|
|
25442
|
-
*
|
|
25443
|
-
*/
|
|
25444
|
-
/**
|
|
25445
|
-
*
|
|
26841
|
+
* Design Tokens Customizer Component
|
|
26842
|
+
*/
|
|
26843
|
+
/**
|
|
26844
|
+
* Theme Helper Functions
|
|
26845
|
+
*
|
|
26846
|
+
* Utility functions for working with DesignTokens
|
|
26847
|
+
*/
|
|
26848
|
+
/**
|
|
26849
|
+
* Check if a value is DesignTokens
|
|
26850
|
+
*
|
|
26851
|
+
* Type guard to check if an object is DesignTokens format.
|
|
26852
|
+
*
|
|
26853
|
+
* @param value - Value to check
|
|
26854
|
+
* @returns True if value is DesignTokens
|
|
26855
|
+
*/
|
|
26856
|
+
function isDesignTokens(value) {
|
|
26857
|
+
if (!value || "object" != typeof value) return !1;
|
|
26858
|
+
// DesignTokens is a flat object with string keys, no nested structures
|
|
26859
|
+
const obj = value;
|
|
26860
|
+
// Check for absence of Theme-specific properties
|
|
26861
|
+
if ("palette" in obj || "typography" in obj || "__isJSTheme" in obj) return !1;
|
|
26862
|
+
// Check if it has DesignTokens-like structure (flat string keys)
|
|
26863
|
+
const keys = Object.keys(obj);
|
|
26864
|
+
return 0 !== keys.length && keys.some((key => /^[a-z]+(-[a-z0-9]+)*$/.test(key) && "string" == typeof obj[key]));
|
|
26865
|
+
// Check if keys look like DesignTokens (kebab-case, no nesting)
|
|
26866
|
+
}
|
|
26867
|
+
|
|
26868
|
+
/**
|
|
26869
|
+
* Performance monitor class
|
|
26870
|
+
*/ class PerformanceMonitor {
|
|
26871
|
+
/**
|
|
26872
|
+
* Create a new performance monitor
|
|
26873
|
+
*
|
|
26874
|
+
* @param config Configuration options
|
|
26875
|
+
*/
|
|
26876
|
+
constructor(config) {
|
|
26877
|
+
this.frameCount = 0, this.lastSampleTime = 0, this.lastFpsUpdate = 0, this.frameTimes = [],
|
|
26878
|
+
this.animationFrameId = null, this.isActive = !1, this.startTime = 0, this.config = {
|
|
26879
|
+
fpsTarget: config?.fpsTarget ?? 60,
|
|
26880
|
+
sampleInterval: config?.sampleInterval ?? 500,
|
|
26881
|
+
onUpdate: config?.onUpdate ?? (() => {}),
|
|
26882
|
+
onDegraded: config?.onDegraded ?? (() => {}),
|
|
26883
|
+
enableMemoryMonitoring: config?.enableMemoryMonitoring ?? ("undefined" != typeof window && window.performance && window.performance.memory)
|
|
26884
|
+
};
|
|
26885
|
+
}
|
|
26886
|
+
/**
|
|
26887
|
+
* Start monitoring performance
|
|
26888
|
+
*/ start() {
|
|
26889
|
+
this.isActive || (this.isActive = !0, this.frameCount = 0, this.lastSampleTime = performance.now(),
|
|
26890
|
+
this.lastFpsUpdate = this.lastSampleTime, this.frameTimes = [], this.startTime = this.lastSampleTime,
|
|
26891
|
+
this.animationFrameId = requestAnimationFrame(this.onFrame.bind(this)));
|
|
26892
|
+
}
|
|
26893
|
+
/**
|
|
26894
|
+
* Stop monitoring performance
|
|
26895
|
+
*/ stop() {
|
|
26896
|
+
this.animationFrameId && (cancelAnimationFrame(this.animationFrameId), this.animationFrameId = null),
|
|
26897
|
+
this.isActive = !1;
|
|
26898
|
+
}
|
|
26899
|
+
/**
|
|
26900
|
+
* Get current performance metrics
|
|
26901
|
+
*/ getMetrics() {
|
|
26902
|
+
var _context;
|
|
26903
|
+
const now = performance.now(), elapsed = now - this.lastFpsUpdate, fps = elapsed > 0 ? Math.round(this.frameCount / elapsed * 1e3) : 0, avgFrameTime = this.frameTimes.length > 0 ? _reduceInstanceProperty(_context = this.frameTimes).call(_context, ((a, b) => a + b), 0) / this.frameTimes.length : 0, peakFrameTime = this.frameTimes.length > 0 ? Math.max(...this.frameTimes) : 0;
|
|
26904
|
+
// Get memory stats if available
|
|
26905
|
+
let memory;
|
|
26906
|
+
if (this.config.enableMemoryMonitoring) {
|
|
26907
|
+
const perf = window.performance;
|
|
26908
|
+
perf && perf.memory && (memory = {
|
|
26909
|
+
usedJSHeapSize: perf.memory.usedJSHeapSize,
|
|
26910
|
+
totalJSHeapSize: perf.memory.totalJSHeapSize,
|
|
26911
|
+
jsHeapSizeLimit: perf.memory.jsHeapSizeLimit
|
|
26912
|
+
});
|
|
26913
|
+
}
|
|
26914
|
+
return {
|
|
26915
|
+
fps: fps,
|
|
26916
|
+
frameTime: avgFrameTime,
|
|
26917
|
+
peakFrameTime: peakFrameTime,
|
|
26918
|
+
memory: memory,
|
|
26919
|
+
timestamp: now,
|
|
26920
|
+
isDegraded: fps < .7 * this.config.fpsTarget
|
|
26921
|
+
};
|
|
26922
|
+
}
|
|
26923
|
+
/**
|
|
26924
|
+
* Get the current FPS
|
|
26925
|
+
*/ getFps() {
|
|
26926
|
+
return this.getMetrics().fps;
|
|
26927
|
+
}
|
|
26928
|
+
/**
|
|
26929
|
+
* Check if performance is degraded
|
|
26930
|
+
*/ isPerformanceDegraded() {
|
|
26931
|
+
return this.getMetrics().isDegraded;
|
|
26932
|
+
}
|
|
26933
|
+
/**
|
|
26934
|
+
* Private method called on each animation frame
|
|
26935
|
+
*/ onFrame(timestamp) {
|
|
26936
|
+
if (!this.isActive) return;
|
|
26937
|
+
// Calculate frame time
|
|
26938
|
+
const frameTime = timestamp - this.lastSampleTime;
|
|
26939
|
+
// Check if we need to update metrics
|
|
26940
|
+
if (this.frameTimes.push(frameTime),
|
|
26941
|
+
// Keep only the last 60 frame times for averaging
|
|
26942
|
+
this.frameTimes.length > 60 && this.frameTimes.shift(), this.frameCount++, this.lastSampleTime = timestamp,
|
|
26943
|
+
timestamp - this.lastFpsUpdate >= this.config.sampleInterval) {
|
|
26944
|
+
const metrics = this.getMetrics();
|
|
26945
|
+
// Call update callback
|
|
26946
|
+
this.config.onUpdate(metrics),
|
|
26947
|
+
// Check for degradation
|
|
26948
|
+
metrics.isDegraded && this.config.onDegraded(metrics),
|
|
26949
|
+
// Reset counters
|
|
26950
|
+
this.frameCount = 0, this.lastFpsUpdate = timestamp;
|
|
26951
|
+
}
|
|
26952
|
+
this.animationFrameId = requestAnimationFrame(this.onFrame.bind(this));
|
|
26953
|
+
}
|
|
26954
|
+
/**
|
|
26955
|
+
* Run a performance test for a specific function
|
|
26956
|
+
*
|
|
26957
|
+
* @param fn Function to test
|
|
26958
|
+
* @param iterations Number of iterations (default: 100)
|
|
26959
|
+
* @returns Average execution time in ms
|
|
26960
|
+
*/ async testFunctionPerformance(fn, iterations = 100) {
|
|
26961
|
+
const times = [];
|
|
26962
|
+
for (let i = 0; i < iterations; i++) {
|
|
26963
|
+
const start = performance.now();
|
|
26964
|
+
fn();
|
|
26965
|
+
const end = performance.now();
|
|
26966
|
+
times.push(end - start);
|
|
26967
|
+
}
|
|
26968
|
+
return _reduceInstanceProperty(times).call(times, ((a, b) => a + b), 0) / times.length;
|
|
26969
|
+
}
|
|
26970
|
+
}
|
|
26971
|
+
|
|
26972
|
+
/**
|
|
26973
|
+
* Create a performance monitor instance
|
|
26974
|
+
*
|
|
26975
|
+
* @param config Configuration options
|
|
26976
|
+
* @returns PerformanceMonitor instance
|
|
26977
|
+
*
|
|
26978
|
+
* @example
|
|
26979
|
+
* ```typescript
|
|
26980
|
+
* import { createPerformanceMonitor } from '@shohojdhara/atomix/theme';
|
|
26981
|
+
*
|
|
26982
|
+
* const monitor = createPerformanceMonitor({
|
|
26983
|
+
* fpsTarget: 60,
|
|
26984
|
+
* onUpdate: (metrics) => console.log('FPS:', metrics.fps),
|
|
26985
|
+
* onDegraded: (metrics) => console.warn('Performance degraded!', metrics),
|
|
26986
|
+
* });
|
|
26987
|
+
*
|
|
26988
|
+
* monitor.start();
|
|
26989
|
+
*
|
|
26990
|
+
* // Later...
|
|
26991
|
+
* monitor.stop();
|
|
26992
|
+
* ```
|
|
26993
|
+
*/ function createPerformanceMonitor(config) {
|
|
26994
|
+
return new PerformanceMonitor(config);
|
|
26995
|
+
}
|
|
26996
|
+
|
|
26997
|
+
/**
|
|
26998
|
+
* Hook for React components to monitor performance
|
|
26999
|
+
*
|
|
27000
|
+
* @param config Configuration options
|
|
27001
|
+
* @returns Performance metrics and monitor controls
|
|
27002
|
+
*
|
|
27003
|
+
* @example
|
|
27004
|
+
* ```typescript
|
|
27005
|
+
* import { usePerformanceMonitor } from '@shohojdhara/atomix/theme';
|
|
27006
|
+
*
|
|
27007
|
+
* function MyComponent() {
|
|
27008
|
+
* const { metrics, start, stop } = usePerformanceMonitor({ fpsTarget: 60 });
|
|
27009
|
+
*
|
|
27010
|
+
* useEffect(() => {
|
|
27011
|
+
* start();
|
|
27012
|
+
* return () => stop();
|
|
27013
|
+
* }, []);
|
|
27014
|
+
*
|
|
27015
|
+
* return <div>FPS: {metrics.fps}</div>;
|
|
27016
|
+
* }
|
|
27017
|
+
* ```
|
|
27018
|
+
*/ function usePerformanceMonitor(config) {
|
|
27019
|
+
const [monitor] = React.useState((() => createPerformanceMonitor(config))), [metrics, setMetrics] = React.useState((() => "undefined" != typeof window ? monitor.getMetrics() : {
|
|
27020
|
+
fps: 0,
|
|
27021
|
+
frameTime: 0,
|
|
27022
|
+
peakFrameTime: 0,
|
|
27023
|
+
timestamp: 0,
|
|
27024
|
+
isDegraded: !1
|
|
27025
|
+
})), start = React.useCallback((() => {
|
|
27026
|
+
"undefined" != typeof window && monitor.start();
|
|
27027
|
+
}), [ monitor ]), stop = React.useCallback((() => {
|
|
27028
|
+
"undefined" != typeof window && monitor.stop();
|
|
27029
|
+
}), [ monitor ]);
|
|
27030
|
+
return React.useEffect((() => {
|
|
27031
|
+
if ("undefined" == typeof window) return;
|
|
27032
|
+
// Update metrics when monitor callbacks fire
|
|
27033
|
+
const originalOnUpdate = config?.onUpdate;
|
|
27034
|
+
return monitor.config.onUpdate = newMetrics => {
|
|
27035
|
+
setMetrics(newMetrics), originalOnUpdate?.(newMetrics);
|
|
27036
|
+
}, () => {
|
|
27037
|
+
monitor.stop();
|
|
27038
|
+
};
|
|
27039
|
+
}), [ monitor, config?.onUpdate ]), {
|
|
27040
|
+
metrics: metrics,
|
|
27041
|
+
start: start,
|
|
27042
|
+
stop: stop
|
|
27043
|
+
};
|
|
27044
|
+
}
|
|
27045
|
+
|
|
27046
|
+
/**
|
|
27047
|
+
* Responsive Utility for Atomix Theme System
|
|
27048
|
+
*
|
|
27049
|
+
* Provides responsive breakpoint detection and device-aware parameter scaling
|
|
27050
|
+
* based on configuration from the advanced optimization features.
|
|
27051
|
+
*/
|
|
27052
|
+
/**
|
|
27053
|
+
* Responsive utility class
|
|
27054
|
+
*/ class ResponsiveUtil {
|
|
27055
|
+
constructor(config) {
|
|
27056
|
+
this.currentDevice = "desktop", // Default
|
|
27057
|
+
this.resizeHandler = null, this.observer = null, this.config = config, this.currentDevice = this.getCurrentDeviceType(),
|
|
27058
|
+
// Set up resize listener
|
|
27059
|
+
this.setupResizeListener();
|
|
27060
|
+
}
|
|
27061
|
+
/**
|
|
27062
|
+
* Get the current device type based on viewport width
|
|
27063
|
+
*/ getCurrentDeviceType() {
|
|
27064
|
+
if ("undefined" == typeof window) return "desktop";
|
|
27065
|
+
// SSR fallback
|
|
27066
|
+
const width = window.innerWidth;
|
|
27067
|
+
// Parse breakpoint values to numbers
|
|
27068
|
+
this.parsePxValue(this.config.breakpoints.mobile);
|
|
27069
|
+
const tabletWidth = this.parsePxValue(this.config.breakpoints.tablet), desktopWidth = this.parsePxValue(this.config.breakpoints.desktop), wideWidth = this.parsePxValue(this.config.breakpoints.wide);
|
|
27070
|
+
return width < tabletWidth ? "mobile" : width < desktopWidth ? "tablet" : width < wideWidth ? "desktop" : "wide";
|
|
27071
|
+
}
|
|
27072
|
+
/**
|
|
27073
|
+
* Get the scaling factor for the current device
|
|
27074
|
+
*/ getCurrentScalingFactor() {
|
|
27075
|
+
// 'wide' devices use the same scaling as 'desktop'
|
|
27076
|
+
const scalingKey = "wide" === this.currentDevice ? "desktop" : this.currentDevice;
|
|
27077
|
+
return this.config.deviceScaling[scalingKey] || 1;
|
|
27078
|
+
}
|
|
27079
|
+
/**
|
|
27080
|
+
* Scale a value based on the current device's scaling factor
|
|
27081
|
+
*/ scaleValue(value) {
|
|
27082
|
+
return value * this.getCurrentScalingFactor();
|
|
27083
|
+
}
|
|
27084
|
+
/**
|
|
27085
|
+
* Check if the current device matches a specific type
|
|
27086
|
+
*/ isDevice(device) {
|
|
27087
|
+
return this.currentDevice === device;
|
|
27088
|
+
}
|
|
27089
|
+
/**
|
|
27090
|
+
* Check if the current device is mobile or smaller
|
|
27091
|
+
*/ isMobileOrSmaller() {
|
|
27092
|
+
return "mobile" === this.currentDevice;
|
|
27093
|
+
}
|
|
27094
|
+
/**
|
|
27095
|
+
* Check if the current device is tablet or smaller
|
|
27096
|
+
*/ isTabletOrSmaller() {
|
|
27097
|
+
return "mobile" === this.currentDevice || "tablet" === this.currentDevice;
|
|
27098
|
+
}
|
|
27099
|
+
/**
|
|
27100
|
+
* Check if the current device is desktop or larger
|
|
27101
|
+
*/ isDesktopOrLarger() {
|
|
27102
|
+
return "desktop" === this.currentDevice || "wide" === this.currentDevice;
|
|
27103
|
+
}
|
|
27104
|
+
/**
|
|
27105
|
+
* Update the responsive configuration
|
|
27106
|
+
*/ updateConfig(config) {
|
|
27107
|
+
this.config = config, this.currentDevice = this.getCurrentDeviceType();
|
|
27108
|
+
}
|
|
27109
|
+
/**
|
|
27110
|
+
* Destroy the responsive utility and clean up listeners
|
|
27111
|
+
*/ destroy() {
|
|
27112
|
+
this.resizeHandler && (window.removeEventListener("resize", this.resizeHandler),
|
|
27113
|
+
this.resizeHandler = null), this.observer && (this.observer.disconnect(), this.observer = null);
|
|
27114
|
+
}
|
|
27115
|
+
/**
|
|
27116
|
+
* Parse a CSS value to pixels
|
|
27117
|
+
*/ parsePxValue(value) {
|
|
27118
|
+
return value.endsWith("px") ? parseFloat(value.slice(0, -2)) :
|
|
27119
|
+
// For other units, we'll use a rough conversion assuming 16px base
|
|
27120
|
+
value.endsWith("rem") ? 16 * parseFloat(value.slice(0, -3)) : value.endsWith("em") ? 16 * parseFloat(value.slice(0, -2)) : parseFloat(value) || 0;
|
|
27121
|
+
}
|
|
27122
|
+
/**
|
|
27123
|
+
* Set up the resize listener
|
|
27124
|
+
*/ setupResizeListener() {
|
|
27125
|
+
if ("undefined" == typeof window) return;
|
|
27126
|
+
// Throttled resize handler
|
|
27127
|
+
let resizeTimeout = null;
|
|
27128
|
+
const handleResize = () => {
|
|
27129
|
+
resizeTimeout && window.clearTimeout(resizeTimeout), resizeTimeout = window.setTimeout((() => {
|
|
27130
|
+
const newDeviceType = this.getCurrentDeviceType();
|
|
27131
|
+
newDeviceType !== this.currentDevice && (this.currentDevice = newDeviceType);
|
|
27132
|
+
}), 150);
|
|
27133
|
+
} // Throttle to 150ms
|
|
27134
|
+
;
|
|
27135
|
+
this.resizeHandler = handleResize, window.addEventListener("resize", handleResize),
|
|
27136
|
+
// Also observe the document body for size changes
|
|
27137
|
+
"undefined" != typeof ResizeObserver && (this.observer = new ResizeObserver(handleResize),
|
|
27138
|
+
this.observer.observe(document.body));
|
|
27139
|
+
}
|
|
27140
|
+
}
|
|
27141
|
+
|
|
27142
|
+
/**
|
|
27143
|
+
* Create a responsive utility instance
|
|
25446
27144
|
*
|
|
25447
|
-
* @param
|
|
25448
|
-
* @returns
|
|
25449
|
-
*/
|
|
25450
|
-
|
|
25451
|
-
const cssVars = {};
|
|
25452
|
-
return Object.entries(tokens).forEach((([key, value]) => {
|
|
25453
|
-
void 0 !== value && (cssVars[`--atomix-${key}`] = String(value));
|
|
25454
|
-
})), cssVars;
|
|
27145
|
+
* @param config Responsive configuration
|
|
27146
|
+
* @returns ResponsiveUtil instance
|
|
27147
|
+
*/ function createResponsiveUtil(config) {
|
|
27148
|
+
return new ResponsiveUtil(config);
|
|
25455
27149
|
}
|
|
25456
27150
|
|
|
25457
27151
|
/**
|
|
25458
|
-
*
|
|
25459
|
-
*
|
|
25460
|
-
* Utility functions for working with DesignTokens
|
|
25461
|
-
*/
|
|
25462
|
-
/**
|
|
25463
|
-
* Check if a value is DesignTokens
|
|
25464
|
-
*
|
|
25465
|
-
* Type guard to check if an object is DesignTokens format.
|
|
27152
|
+
* Hook for React components to use responsive features
|
|
25466
27153
|
*
|
|
25467
|
-
* @param
|
|
25468
|
-
* @returns
|
|
25469
|
-
*/ function
|
|
25470
|
-
|
|
25471
|
-
|
|
25472
|
-
|
|
25473
|
-
|
|
25474
|
-
|
|
25475
|
-
|
|
25476
|
-
|
|
25477
|
-
|
|
25478
|
-
|
|
27154
|
+
* @param config Responsive configuration
|
|
27155
|
+
* @returns Current device type and utility functions
|
|
27156
|
+
*/ function useResponsive(config) {
|
|
27157
|
+
const [util] = React.useState((() => createResponsiveUtil(config))), [deviceType, setDeviceType] = React.useState((() => "undefined" != typeof window ? util.getCurrentDeviceType() : "desktop"));
|
|
27158
|
+
return React.useEffect((() => {
|
|
27159
|
+
if ("undefined" == typeof window) return;
|
|
27160
|
+
const handleResize = () => {
|
|
27161
|
+
const newDeviceType = util.getCurrentDeviceType();
|
|
27162
|
+
newDeviceType !== deviceType && setDeviceType(newDeviceType);
|
|
27163
|
+
};
|
|
27164
|
+
// Update device type on mount
|
|
27165
|
+
return setDeviceType(util.getCurrentDeviceType()),
|
|
27166
|
+
// Listen for resize events
|
|
27167
|
+
window.addEventListener("resize", handleResize), () => {
|
|
27168
|
+
window.removeEventListener("resize", handleResize), util.destroy();
|
|
27169
|
+
};
|
|
27170
|
+
}), [ util, deviceType ]), "undefined" == typeof window ? {
|
|
27171
|
+
deviceType: "desktop",
|
|
27172
|
+
isMobile: !1,
|
|
27173
|
+
isTablet: !1,
|
|
27174
|
+
isDesktop: !0,
|
|
27175
|
+
isWide: !1,
|
|
27176
|
+
scaleValue: value => value,
|
|
27177
|
+
getCurrentDeviceType: () => "desktop",
|
|
27178
|
+
getCurrentScalingFactor: () => 1,
|
|
27179
|
+
isMobileOrSmaller: () => !1,
|
|
27180
|
+
isTabletOrSmaller: () => !0,
|
|
27181
|
+
isDesktopOrLarger: () => !0
|
|
27182
|
+
} : {
|
|
27183
|
+
deviceType: deviceType,
|
|
27184
|
+
isMobile: "mobile" === deviceType,
|
|
27185
|
+
isTablet: "tablet" === deviceType,
|
|
27186
|
+
isDesktop: "desktop" === deviceType,
|
|
27187
|
+
isWide: "wide" === deviceType,
|
|
27188
|
+
scaleValue: value => util.scaleValue(value),
|
|
27189
|
+
getCurrentDeviceType: () => util.getCurrentDeviceType(),
|
|
27190
|
+
getCurrentScalingFactor: () => util.getCurrentScalingFactor(),
|
|
27191
|
+
isMobileOrSmaller: () => util.isMobileOrSmaller(),
|
|
27192
|
+
isTabletOrSmaller: () => util.isTabletOrSmaller(),
|
|
27193
|
+
isDesktopOrLarger: () => util.isDesktopOrLarger()
|
|
27194
|
+
};
|
|
25479
27195
|
}
|
|
25480
27196
|
|
|
25481
27197
|
/**
|
|
@@ -25663,6 +27379,32 @@ class RTLManager {
|
|
|
25663
27379
|
}
|
|
25664
27380
|
}
|
|
25665
27381
|
|
|
27382
|
+
/**
|
|
27383
|
+
* Create RTL manager instance
|
|
27384
|
+
*/ function createRTLManager(config) {
|
|
27385
|
+
return new RTLManager(config);
|
|
27386
|
+
}
|
|
27387
|
+
|
|
27388
|
+
/**
|
|
27389
|
+
* Check if locale is RTL
|
|
27390
|
+
*/ function isRTLLocale(locale) {
|
|
27391
|
+
return RTL_LOCALES.has(locale.toLowerCase());
|
|
27392
|
+
}
|
|
27393
|
+
|
|
27394
|
+
/**
|
|
27395
|
+
* Get direction from locale
|
|
27396
|
+
*/ function getDirectionFromLocale(locale) {
|
|
27397
|
+
return isRTLLocale(locale) ? "rtl" : "ltr";
|
|
27398
|
+
}
|
|
27399
|
+
|
|
27400
|
+
/**
|
|
27401
|
+
* RTL-aware CSS helper
|
|
27402
|
+
*
|
|
27403
|
+
* Returns appropriate CSS based on direction
|
|
27404
|
+
*/ function rtlCSS(ltrCSS, rtlCSS, direction = "ltr") {
|
|
27405
|
+
return "rtl" === direction ? rtlCSS : ltrCSS;
|
|
27406
|
+
}
|
|
27407
|
+
|
|
25666
27408
|
/**
|
|
25667
27409
|
* Theme System Exports
|
|
25668
27410
|
*
|
|
@@ -25685,8 +27427,6 @@ class RTLManager {
|
|
|
25685
27427
|
// ============================================================================
|
|
25686
27428
|
// Core Theme Functions
|
|
25687
27429
|
// ============================================================================
|
|
25688
|
-
// Create theme CSS from DesignTokens
|
|
25689
|
-
// File saving utilities removed to prevent bundling Node.js modules in browser
|
|
25690
27430
|
/**
|
|
25691
27431
|
* Inject theme CSS into DOM
|
|
25692
27432
|
*/ function injectTheme(css, id = "atomix-theme") {
|
|
@@ -25699,7 +27439,114 @@ class RTLManager {
|
|
|
25699
27439
|
removeCSS(id);
|
|
25700
27440
|
}
|
|
25701
27441
|
|
|
25702
|
-
|
|
27442
|
+
/**
|
|
27443
|
+
* Main theme module interface
|
|
27444
|
+
*/ const index = {
|
|
27445
|
+
// Core
|
|
27446
|
+
createTheme: createTheme,
|
|
27447
|
+
injectTheme: injectTheme,
|
|
27448
|
+
removeTheme: removeTheme,
|
|
27449
|
+
// Context and Provider
|
|
27450
|
+
ThemeProvider: ThemeProvider,
|
|
27451
|
+
useTheme: useTheme,
|
|
27452
|
+
useThemeTokens: useThemeTokens,
|
|
27453
|
+
ThemeContext: ThemeContext,
|
|
27454
|
+
ThemeErrorBoundary: ThemeErrorBoundary,
|
|
27455
|
+
// Adapters
|
|
27456
|
+
configToTokens: configToTokens,
|
|
27457
|
+
designTokensToCSSVars: designTokensToCSSVars,
|
|
27458
|
+
// Theme Utils
|
|
27459
|
+
switchTheme: switchTheme,
|
|
27460
|
+
toggleTheme: toggleTheme,
|
|
27461
|
+
getCurrentTheme: getCurrentTheme,
|
|
27462
|
+
getSystemTheme: getSystemTheme,
|
|
27463
|
+
initializeTheme: initializeTheme,
|
|
27464
|
+
listenToSystemTheme: listenToSystemTheme,
|
|
27465
|
+
persistTheme: persistTheme,
|
|
27466
|
+
clearThemePreference: clearThemePreference,
|
|
27467
|
+
// Token Manipulation
|
|
27468
|
+
mergeTokens: mergeTokens,
|
|
27469
|
+
overrideTokens: overrideTokens,
|
|
27470
|
+
pickTokens: pickTokens,
|
|
27471
|
+
omitTokens: omitTokens,
|
|
27472
|
+
// Color Utilities
|
|
27473
|
+
hexToRgb: hexToRgb$1,
|
|
27474
|
+
rgbToHex: rgbToHex,
|
|
27475
|
+
getLuminance: getLuminance,
|
|
27476
|
+
getContrastRatio: getContrastRatio,
|
|
27477
|
+
isAccessible: isAccessible,
|
|
27478
|
+
getContrastText: getContrastText,
|
|
27479
|
+
lighten: lighten,
|
|
27480
|
+
darken: darken,
|
|
27481
|
+
alpha: alpha,
|
|
27482
|
+
emphasize: emphasize,
|
|
27483
|
+
createSpacing: createSpacing,
|
|
27484
|
+
// Performance utilities
|
|
27485
|
+
createPerformanceMonitor: createPerformanceMonitor,
|
|
27486
|
+
usePerformanceMonitor: usePerformanceMonitor,
|
|
27487
|
+
// Responsive utilities
|
|
27488
|
+
createResponsiveUtil: createResponsiveUtil,
|
|
27489
|
+
useResponsive: useResponsive,
|
|
27490
|
+
// Components
|
|
27491
|
+
ThemeToggle: ThemeToggle,
|
|
27492
|
+
ThemeApplicator: ThemeApplicator,
|
|
27493
|
+
applyTheme: applyTheme,
|
|
27494
|
+
getThemeApplicator: getThemeApplicator,
|
|
27495
|
+
// Registry
|
|
27496
|
+
createThemeRegistry: createThemeRegistry,
|
|
27497
|
+
registerTheme: registerTheme,
|
|
27498
|
+
unregisterTheme: unregisterTheme,
|
|
27499
|
+
hasTheme: hasTheme,
|
|
27500
|
+
getTheme: getTheme,
|
|
27501
|
+
getAllThemes: getAllThemes,
|
|
27502
|
+
getThemeIds: getThemeIds,
|
|
27503
|
+
clearThemes: clearThemes,
|
|
27504
|
+
getThemeCount: getThemeCount,
|
|
27505
|
+
// Composition
|
|
27506
|
+
deepMerge: deepMerge,
|
|
27507
|
+
mergeTheme: mergeTheme,
|
|
27508
|
+
extendTheme: extendTheme,
|
|
27509
|
+
// Tokens
|
|
27510
|
+
createTokens: createTokens,
|
|
27511
|
+
defaultTokens: defaultTokens,
|
|
27512
|
+
// Generators
|
|
27513
|
+
generateCSSVariables: generateCSSVariables$1,
|
|
27514
|
+
generateCSSVariablesForSelector: generateCSSVariablesForSelector,
|
|
27515
|
+
// Naming
|
|
27516
|
+
generateClassName: generateClassName,
|
|
27517
|
+
generateCSSVariableName: generateCSSVariableName,
|
|
27518
|
+
normalizeThemeTokens: normalizeThemeTokens,
|
|
27519
|
+
camelToKebab: camelToKebab,
|
|
27520
|
+
themePropertyToCSSVar: themePropertyToCSSVar,
|
|
27521
|
+
// Component Theming
|
|
27522
|
+
getComponentThemeValue: getComponentThemeValue,
|
|
27523
|
+
generateComponentCSSVars: generateComponentCSSVars,
|
|
27524
|
+
applyComponentTheme: applyComponentTheme,
|
|
27525
|
+
useComponentTheme: useComponentTheme,
|
|
27526
|
+
// Hooks
|
|
27527
|
+
useThemeSwitcher: useThemeSwitcher,
|
|
27528
|
+
// Helpers
|
|
27529
|
+
isDesignTokens: isDesignTokens,
|
|
27530
|
+
// CSS Variable Mapper
|
|
27531
|
+
mapSCSSTokensToCSSVars: mapSCSSTokensToCSSVars,
|
|
27532
|
+
applyCSSVariables: applyCSSVariables,
|
|
27533
|
+
removeCSSVariables: removeCSSVariables,
|
|
27534
|
+
getCSSVariable: getCSSVariable,
|
|
27535
|
+
cssVarsToStyle: cssVarsToStyle,
|
|
27536
|
+
mergeCSSVars: mergeCSSVars,
|
|
27537
|
+
isValidCSSVariableName: isValidCSSVariableName,
|
|
27538
|
+
extractComponentName: extractComponentName,
|
|
27539
|
+
// Injection Utils
|
|
27540
|
+
injectCSS: injectCSS$1,
|
|
27541
|
+
removeCSS: removeCSS,
|
|
27542
|
+
isCSSInjected: isCSSInjected,
|
|
27543
|
+
// I18n
|
|
27544
|
+
RTLManager: RTLManager,
|
|
27545
|
+
createRTLManager: createRTLManager,
|
|
27546
|
+
isRTLLocale: isRTLLocale,
|
|
27547
|
+
getDirectionFromLocale: getDirectionFromLocale,
|
|
27548
|
+
rtlCSS: rtlCSS
|
|
27549
|
+
}, themeImport = Object.freeze( Object.defineProperty({
|
|
25703
27550
|
__proto__: null,
|
|
25704
27551
|
DesignTokensCustomizer: DesignTokensCustomizer,
|
|
25705
27552
|
RTLManager: RTLManager,
|
|
@@ -25711,19 +27558,30 @@ const themeImport = Object.freeze( Object.defineProperty({
|
|
|
25711
27558
|
ThemeLiveEditor: ThemeLiveEditor,
|
|
25712
27559
|
ThemePreview: ThemePreview,
|
|
25713
27560
|
ThemeProvider: ThemeProvider,
|
|
27561
|
+
ThemeToggle: ThemeToggle,
|
|
25714
27562
|
ThemeValidator: ThemeValidator,
|
|
27563
|
+
alpha: alpha,
|
|
25715
27564
|
applyCSSVariables: applyCSSVariables,
|
|
25716
27565
|
applyComponentTheme: applyComponentTheme,
|
|
25717
27566
|
applyTheme: applyTheme,
|
|
25718
27567
|
camelToKebab: camelToKebab,
|
|
27568
|
+
clearThemePreference: clearThemePreference,
|
|
25719
27569
|
clearThemes: clearThemes,
|
|
27570
|
+
configToTokens: configToTokens,
|
|
27571
|
+
createPerformanceMonitor: createPerformanceMonitor,
|
|
27572
|
+
createRTLManager: createRTLManager,
|
|
27573
|
+
createResponsiveUtil: createResponsiveUtil,
|
|
27574
|
+
createSpacing: createSpacing,
|
|
25720
27575
|
createTheme: createTheme,
|
|
25721
27576
|
createThemeRegistry: createThemeRegistry,
|
|
25722
27577
|
createTokens: createTokens,
|
|
25723
27578
|
cssVarsToStyle: cssVarsToStyle,
|
|
27579
|
+
darken: darken,
|
|
25724
27580
|
deepMerge: deepMerge,
|
|
27581
|
+
default: index,
|
|
25725
27582
|
defaultTokens: defaultTokens,
|
|
25726
27583
|
designTokensToCSSVars: designTokensToCSSVars,
|
|
27584
|
+
emphasize: emphasize,
|
|
25727
27585
|
extendTheme: extendTheme,
|
|
25728
27586
|
extractComponentName: extractComponentName,
|
|
25729
27587
|
generateCSSVariableName: generateCSSVariableName,
|
|
@@ -25734,29 +27592,53 @@ const themeImport = Object.freeze( Object.defineProperty({
|
|
|
25734
27592
|
getAllThemes: getAllThemes,
|
|
25735
27593
|
getCSSVariable: getCSSVariable,
|
|
25736
27594
|
getComponentThemeValue: getComponentThemeValue,
|
|
27595
|
+
getContrastRatio: getContrastRatio,
|
|
27596
|
+
getContrastText: getContrastText,
|
|
27597
|
+
getCurrentTheme: getCurrentTheme,
|
|
27598
|
+
getDirectionFromLocale: getDirectionFromLocale,
|
|
27599
|
+
getLuminance: getLuminance,
|
|
27600
|
+
getSystemTheme: getSystemTheme,
|
|
25737
27601
|
getTheme: getTheme,
|
|
25738
27602
|
getThemeApplicator: getThemeApplicator,
|
|
25739
27603
|
getThemeCount: getThemeCount,
|
|
25740
27604
|
getThemeIds: getThemeIds,
|
|
25741
27605
|
hasTheme: hasTheme,
|
|
27606
|
+
hexToRgb: hexToRgb$1,
|
|
27607
|
+
initializeTheme: initializeTheme,
|
|
25742
27608
|
injectCSS: injectCSS$1,
|
|
25743
27609
|
injectTheme: injectTheme,
|
|
27610
|
+
isAccessible: isAccessible,
|
|
25744
27611
|
isCSSInjected: isCSSInjected,
|
|
25745
27612
|
isDesignTokens: isDesignTokens,
|
|
27613
|
+
isRTLLocale: isRTLLocale,
|
|
25746
27614
|
isValidCSSVariableName: isValidCSSVariableName,
|
|
27615
|
+
lighten: lighten,
|
|
27616
|
+
listenToSystemTheme: listenToSystemTheme,
|
|
25747
27617
|
mapSCSSTokensToCSSVars: mapSCSSTokensToCSSVars,
|
|
25748
27618
|
mergeCSSVars: mergeCSSVars,
|
|
25749
27619
|
mergeTheme: mergeTheme,
|
|
27620
|
+
mergeTokens: mergeTokens,
|
|
25750
27621
|
normalizeThemeTokens: normalizeThemeTokens,
|
|
27622
|
+
omitTokens: omitTokens,
|
|
27623
|
+
overrideTokens: overrideTokens,
|
|
27624
|
+
persistTheme: persistTheme,
|
|
27625
|
+
pickTokens: pickTokens,
|
|
25751
27626
|
registerTheme: registerTheme,
|
|
25752
27627
|
removeCSS: removeCSS,
|
|
25753
27628
|
removeCSSVariables: removeCSSVariables,
|
|
25754
27629
|
removeTheme: removeTheme,
|
|
27630
|
+
rgbToHex: rgbToHex,
|
|
27631
|
+
rtlCSS: rtlCSS,
|
|
27632
|
+
switchTheme: switchTheme,
|
|
25755
27633
|
themePropertyToCSSVar: themePropertyToCSSVar,
|
|
27634
|
+
toggleTheme: toggleTheme,
|
|
25756
27635
|
unregisterTheme: unregisterTheme,
|
|
25757
27636
|
useComponentTheme: useComponentTheme,
|
|
25758
27637
|
useHistory: useHistory,
|
|
27638
|
+
usePerformanceMonitor: usePerformanceMonitor,
|
|
27639
|
+
useResponsive: useResponsive,
|
|
25759
27640
|
useTheme: useTheme,
|
|
27641
|
+
useThemeSwitcher: useThemeSwitcher,
|
|
25760
27642
|
useThemeTokens: useThemeTokens
|
|
25761
27643
|
}, Symbol.toStringTag, {
|
|
25762
27644
|
value: "Module"
|
|
@@ -26018,15 +27900,6 @@ const themeImport = Object.freeze( Object.defineProperty({
|
|
|
26018
27900
|
Radio: RADIO_CSS_VARS
|
|
26019
27901
|
};
|
|
26020
27902
|
|
|
26021
|
-
/**
|
|
26022
|
-
* CSS Variables Constants
|
|
26023
|
-
*
|
|
26024
|
-
* Comprehensive CSS custom property definitions for all components.
|
|
26025
|
-
* These provide type-safe access to component styling variables.
|
|
26026
|
-
*/
|
|
26027
|
-
/**
|
|
26028
|
-
* Button CSS Variables
|
|
26029
|
-
*/
|
|
26030
27903
|
/**
|
|
26031
27904
|
* Get CSS variables for a component
|
|
26032
27905
|
*/
|
|
@@ -26052,97 +27925,6 @@ function getComponentCSSVars(component) {
|
|
|
26052
27925
|
} : base : override;
|
|
26053
27926
|
}
|
|
26054
27927
|
|
|
26055
|
-
/**
|
|
26056
|
-
* Render a slot with the given props
|
|
26057
|
-
*
|
|
26058
|
-
* Priority order:
|
|
26059
|
-
* 1. render function
|
|
26060
|
-
* 2. component
|
|
26061
|
-
* 3. children
|
|
26062
|
-
* 4. fallback
|
|
26063
|
-
*
|
|
26064
|
-
* @example
|
|
26065
|
-
* renderSlot(
|
|
26066
|
-
* { render: (props) => <CustomButton {...props} /> },
|
|
26067
|
-
* { onClick: handleClick, children: 'Click me' }
|
|
26068
|
-
* )
|
|
26069
|
-
*/ function renderSlot(slot, props, fallback) {
|
|
26070
|
-
// No slot provided, use fallback
|
|
26071
|
-
if (!slot) return fallback;
|
|
26072
|
-
// Slot is a plain React node
|
|
26073
|
-
if ( React.isValidElement(slot) || "string" == typeof slot || "number" == typeof slot) return slot;
|
|
26074
|
-
// Slot is an object with rendering options
|
|
26075
|
-
if ("object" == typeof slot && null !== slot) {
|
|
26076
|
-
const slotObj = slot;
|
|
26077
|
-
// Priority 1: render function
|
|
26078
|
-
if (slotObj.render && "function" == typeof slotObj.render) return slotObj.render(props);
|
|
26079
|
-
// Priority 2: component
|
|
26080
|
-
if (slotObj.component) {
|
|
26081
|
-
const Component = slotObj.component;
|
|
26082
|
-
return jsx(Component, {
|
|
26083
|
-
...props
|
|
26084
|
-
});
|
|
26085
|
-
}
|
|
26086
|
-
// Priority 3: children
|
|
26087
|
-
if (void 0 !== slotObj.children) return slotObj.children;
|
|
26088
|
-
}
|
|
26089
|
-
// Fallback
|
|
26090
|
-
return fallback;
|
|
26091
|
-
}
|
|
26092
|
-
|
|
26093
|
-
/**
|
|
26094
|
-
* Check if a value is a slot configuration
|
|
26095
|
-
*/ function isSlot(value) {
|
|
26096
|
-
return "object" == typeof value && null !== value && ("render" in value || "component" in value || "children" in value);
|
|
26097
|
-
}
|
|
26098
|
-
|
|
26099
|
-
/**
|
|
26100
|
-
* Merge multiple slot configurations
|
|
26101
|
-
* Later slots override earlier ones
|
|
26102
|
-
*/ function mergeSlots(...slots) {
|
|
26103
|
-
const filtered = slots.filter((s => void 0 !== s));
|
|
26104
|
-
if (0 !== filtered.length) return 1 === filtered.length ? filtered[0] : _reduceInstanceProperty(filtered).call(filtered, ((acc, slot) => ({
|
|
26105
|
-
...acc,
|
|
26106
|
-
...slot
|
|
26107
|
-
})));
|
|
26108
|
-
}
|
|
26109
|
-
|
|
26110
|
-
/**
|
|
26111
|
-
* Create a slot wrapper component
|
|
26112
|
-
*
|
|
26113
|
-
* @example
|
|
26114
|
-
* const ButtonSlot = createSlotComponent<ButtonSlotProps>('button')
|
|
26115
|
-
*
|
|
26116
|
-
* <ButtonSlot slot={customSlot} {...props}>
|
|
26117
|
-
* Default content
|
|
26118
|
-
* </ButtonSlot>
|
|
26119
|
-
*/ function createSlotComponent(defaultElement = "div") {
|
|
26120
|
-
return function({slot: slot, children: children, ...props}) {
|
|
26121
|
-
const slotProps = props;
|
|
26122
|
-
return slot ? jsx(Fragment, {
|
|
26123
|
-
children: renderSlot(slot, slotProps, children)
|
|
26124
|
-
}) : jsx(defaultElement, "string" == typeof defaultElement ? {
|
|
26125
|
-
...props,
|
|
26126
|
-
children: children
|
|
26127
|
-
} : {
|
|
26128
|
-
...slotProps,
|
|
26129
|
-
children: children
|
|
26130
|
-
});
|
|
26131
|
-
};
|
|
26132
|
-
}
|
|
26133
|
-
|
|
26134
|
-
/**
|
|
26135
|
-
* Utility to create typed slot props
|
|
26136
|
-
*/ function createSlotProps(props) {
|
|
26137
|
-
return props;
|
|
26138
|
-
}
|
|
26139
|
-
|
|
26140
|
-
/**
|
|
26141
|
-
* Hook to manage slot rendering
|
|
26142
|
-
*/ function useSlot(slot, props, fallback) {
|
|
26143
|
-
return React.useMemo((() => renderSlot(slot, props, fallback)), [ slot, props, fallback ]);
|
|
26144
|
-
}
|
|
26145
|
-
|
|
26146
27928
|
/**
|
|
26147
27929
|
* Hook to merge theme overrides with component props
|
|
26148
27930
|
*
|
|
@@ -26210,59 +27992,174 @@ function getComponentCSSVars(component) {
|
|
|
26210
27992
|
}
|
|
26211
27993
|
|
|
26212
27994
|
/**
|
|
26213
|
-
*
|
|
27995
|
+
* Configuration Types
|
|
27996
|
+
*
|
|
27997
|
+
* Type definitions for the Atomix configuration system.
|
|
27998
|
+
*/
|
|
27999
|
+
/**
|
|
28000
|
+
* Helper function to define Atomix configuration with type safety
|
|
28001
|
+
*/ function defineConfig(config) {
|
|
28002
|
+
return config;
|
|
28003
|
+
}
|
|
28004
|
+
|
|
28005
|
+
/**
|
|
28006
|
+
* Configuration Validator
|
|
26214
28007
|
*
|
|
26215
|
-
*
|
|
28008
|
+
* Provides detailed validation and feedback for Atomix configurations,
|
|
28009
|
+
* especially for advanced features (Phases 2, 3, and 4).
|
|
28010
|
+
*/
|
|
28011
|
+
/**
|
|
28012
|
+
* Validate an Atomix configuration with detailed feedback
|
|
26216
28013
|
*
|
|
26217
|
-
*
|
|
26218
|
-
*
|
|
28014
|
+
* @param config - The configuration to validate
|
|
28015
|
+
* @param options - Validation options
|
|
28016
|
+
* @returns Detailed validation result
|
|
26219
28017
|
*
|
|
26220
28018
|
* @example
|
|
26221
28019
|
* ```typescript
|
|
26222
|
-
*
|
|
26223
|
-
* import { defineConfig } from '@shohojdhara/atomix/config';
|
|
28020
|
+
* import { validateConfiguration } from '@shohojdhara/atomix/config';
|
|
26224
28021
|
*
|
|
26225
|
-
*
|
|
26226
|
-
*
|
|
26227
|
-
*
|
|
26228
|
-
*
|
|
26229
|
-
*
|
|
26230
|
-
*
|
|
26231
|
-
*
|
|
26232
|
-
* },
|
|
26233
|
-
* });
|
|
28022
|
+
* const config = { /* your config *\/ };
|
|
28023
|
+
* const result = validateConfiguration(config);
|
|
28024
|
+
*
|
|
28025
|
+
* if (!result.isValid) {
|
|
28026
|
+
* console.warn('Warnings:', result.warnings);
|
|
28027
|
+
* console.info('Suggestions:', result.suggestions);
|
|
28028
|
+
* }
|
|
26234
28029
|
* ```
|
|
28030
|
+
*/ function validateConfiguration(config, options) {
|
|
28031
|
+
const {performanceAnalysis: performanceAnalysis = !0, compatibilityReport: compatibilityReport = !0} = options || {}, warnings = [], suggestions = [];
|
|
28032
|
+
let performanceImpact = "low";
|
|
28033
|
+
// Use the existing validation
|
|
28034
|
+
const baseWarnings = validateConfig$1(config);
|
|
28035
|
+
warnings.push(...baseWarnings),
|
|
28036
|
+
// Analyze advanced features for performance impact
|
|
28037
|
+
performanceAnalysis && (performanceImpact =
|
|
28038
|
+
/**
|
|
28039
|
+
* Analyze the performance impact of a configuration
|
|
26235
28040
|
*/
|
|
28041
|
+
function(config) {
|
|
28042
|
+
let impactScore = 0;
|
|
28043
|
+
// Analyze interactive effects
|
|
28044
|
+
if (config.interactiveEffects) {
|
|
28045
|
+
const ie = config.interactiveEffects;
|
|
28046
|
+
ie.vortex?.enabled && (impactScore += 2), ie.chromaticAberration?.enabled && (impactScore += 1),
|
|
28047
|
+
ie.mouseInteraction?.trailEffect && (impactScore += 1), ie.mouseInteraction?.pressureSensitivity && (impactScore += 1);
|
|
28048
|
+
}
|
|
28049
|
+
// Analyze visual polish effects
|
|
28050
|
+
if (config.visualPolish) {
|
|
28051
|
+
const vp = config.visualPolish;
|
|
28052
|
+
vp.borders?.iridescentGlow && (impactScore += 1), vp.borders?.shimmerEffect && (impactScore += 1),
|
|
28053
|
+
vp.contentAwareBlur?.enabled && (impactScore += 2), vp.holographicEffects?.enabled && (impactScore += 2),
|
|
28054
|
+
vp.holographicEffects?.scanlineAnimation && (impactScore += 1), vp.holographicEffects?.dataStream && (impactScore += 1),
|
|
28055
|
+
vp.holographicEffects?.pulseRings && (impactScore += 1);
|
|
28056
|
+
}
|
|
28057
|
+
// Analyze optimization settings
|
|
28058
|
+
return config.optimization?.autoScaling?.enabled && (impactScore -= 1),
|
|
28059
|
+
impactScore >= 6 ? "high" : impactScore >= 3 ? "medium" : "low";
|
|
28060
|
+
}
|
|
28061
|
+
/**
|
|
28062
|
+
* Generate suggestions based on the configuration
|
|
28063
|
+
*/ (config)),
|
|
28064
|
+
// Generate suggestions based on configuration
|
|
28065
|
+
function(config, suggestions) {
|
|
28066
|
+
// Suggest enabling performance optimizations if heavy effects are used
|
|
28067
|
+
(config.interactiveEffects || config.visualPolish?.holographicEffects?.enabled) && (config.optimization?.autoScaling?.enabled || suggestions.push("Consider enabling auto-scaling in optimization settings to adjust effects based on device performance: optimization.autoScaling.enabled = true"),
|
|
28068
|
+
config.optimization?.performance?.fpsTarget || suggestions.push("Set a target FPS in optimization.performance.fpsTarget to ensure smooth performance when using interactive effects")),
|
|
28069
|
+
// Suggest responsive breakpoints if optimization is partially configured
|
|
28070
|
+
config.optimization && !config.optimization.responsive && suggestions.push("Consider adding responsive breakpoints in optimization.responsive.breakpoints to adapt advanced effects based on device type"),
|
|
28071
|
+
// Suggest disabling heavy effects on lower-end devices
|
|
28072
|
+
config.visualPolish?.holographicEffects?.enabled && suggestions.push("For better performance on lower-end devices, consider conditionally disabling holographic effects based on device capabilities"),
|
|
28073
|
+
// Suggest using content-aware blur with performance considerations
|
|
28074
|
+
config.visualPolish?.contentAwareBlur?.enabled && suggestions.push("Content-aware blur can be expensive; consider setting a maximum blur radius or using simpler blur techniques for mobile devices"),
|
|
28075
|
+
// Suggest using chromatic aberration适度
|
|
28076
|
+
config.interactiveEffects?.chromaticAberration?.enabled && (config.interactiveEffects.chromaticAberration.redShift && Math.abs(config.interactiveEffects.chromaticAberration.redShift) > .05 && suggestions.push("High chromatic aberration red shift values (>0.05) may cause discomfort for some users; consider reducing to improve accessibility"),
|
|
28077
|
+
config.interactiveEffects.chromaticAberration.blueShift && Math.abs(config.interactiveEffects.chromaticAberration.blueShift) > .05 && suggestions.push("High chromatic aberration blue shift values (>0.05) may cause discomfort for some users; consider reducing to improve accessibility"));
|
|
28078
|
+
}
|
|
28079
|
+
/**
|
|
28080
|
+
* Generate a compatibility report for the configuration
|
|
28081
|
+
*/ (config, suggestions);
|
|
28082
|
+
// Determine overall validity
|
|
28083
|
+
const isValid = 0 === warnings.length, compatibility = compatibilityReport ? function(config) {
|
|
28084
|
+
return {
|
|
28085
|
+
browsers: !(config.visualPolish?.holographicEffects?.enabled || config.visualPolish?.contentAwareBlur?.enabled || config.interactiveEffects?.vortex?.enabled || config.interactiveEffects?.chromaticAberration?.enabled),
|
|
28086
|
+
// May have issues on older browsers
|
|
28087
|
+
ssr: !0,
|
|
28088
|
+
// Works fine with SSR
|
|
28089
|
+
frameworks: [ "react", "vue", "angular", "svelte", "vanillajs" ]
|
|
28090
|
+
};
|
|
28091
|
+
}
|
|
28092
|
+
/**
|
|
28093
|
+
* Print a detailed configuration report to the console
|
|
28094
|
+
*
|
|
28095
|
+
* @param config - The configuration to analyze
|
|
28096
|
+
* @param title - Optional title for the report
|
|
28097
|
+
*
|
|
28098
|
+
* @example
|
|
28099
|
+
* ```typescript
|
|
28100
|
+
* import { printConfigReport } from '@shohojdhara/atomix/config';
|
|
28101
|
+
*
|
|
28102
|
+
* const config = { /* your config *\/ };
|
|
28103
|
+
* printConfigReport(config, 'My Application Config');
|
|
28104
|
+
* ```
|
|
28105
|
+
*/ (config) : {
|
|
28106
|
+
browsers: !0,
|
|
28107
|
+
ssr: !0,
|
|
28108
|
+
frameworks: [ "react", "vue", "angular", "svelte", "vanillajs" ]
|
|
28109
|
+
};
|
|
28110
|
+
// Generate compatibility report
|
|
28111
|
+
return {
|
|
28112
|
+
isValid: isValid,
|
|
28113
|
+
warnings: warnings,
|
|
28114
|
+
suggestions: suggestions,
|
|
28115
|
+
performanceImpact: performanceImpact,
|
|
28116
|
+
compatibility: compatibility
|
|
28117
|
+
};
|
|
28118
|
+
}
|
|
28119
|
+
|
|
28120
|
+
function printConfigReport(config, title) {
|
|
28121
|
+
const result = validateConfiguration(config);
|
|
28122
|
+
result.warnings.length > 0 && result.warnings.forEach((warning => {})), result.suggestions.length > 0 && result.suggestions.forEach((suggestion => {}));
|
|
28123
|
+
const featuresDetected = [];
|
|
28124
|
+
config.interactiveEffects && featuresDetected.push("Interactive Effects"), config.optimization && featuresDetected.push("Optimization"),
|
|
28125
|
+
config.visualPolish && featuresDetected.push("Visual Polish"), config.ai && featuresDetected.push("AI Integration"),
|
|
28126
|
+
config.tokenEngine && featuresDetected.push("Token Engine"), config.generator && featuresDetected.push("Component Generator"),
|
|
28127
|
+
featuresDetected.length > 0 && featuresDetected.forEach((feature => {}));
|
|
28128
|
+
}
|
|
28129
|
+
|
|
26236
28130
|
/**
|
|
26237
|
-
*
|
|
28131
|
+
* Public API for loading and managing Atomix configuration
|
|
26238
28132
|
*
|
|
26239
|
-
*
|
|
26240
|
-
*
|
|
28133
|
+
* This module provides the public-facing API for configuration loading
|
|
28134
|
+
* in external projects.
|
|
26241
28135
|
*/
|
|
26242
28136
|
/**
|
|
26243
|
-
*
|
|
28137
|
+
* Load Atomix configuration from an external project.
|
|
26244
28138
|
*
|
|
26245
|
-
*
|
|
26246
|
-
*
|
|
26247
|
-
* @param config - Atomix configuration object
|
|
26248
|
-
* @returns The configuration object
|
|
28139
|
+
* @param options - Loading options
|
|
28140
|
+
* @returns The loaded configuration
|
|
26249
28141
|
*
|
|
26250
28142
|
* @example
|
|
26251
28143
|
* ```typescript
|
|
26252
|
-
* import {
|
|
28144
|
+
* import { loadConfig } from '@shohojdhara/atomix/config';
|
|
26253
28145
|
*
|
|
26254
|
-
*
|
|
26255
|
-
*
|
|
26256
|
-
* extend: {
|
|
26257
|
-
* colors: {
|
|
26258
|
-
* primary: { main: '#7AFFD7' },
|
|
26259
|
-
* },
|
|
26260
|
-
* },
|
|
26261
|
-
* },
|
|
26262
|
-
* });
|
|
28146
|
+
* const config = loadConfig();
|
|
28147
|
+
* console.log(config.prefix); // 'atomix' or user's custom prefix
|
|
26263
28148
|
* ```
|
|
26264
|
-
*/ function
|
|
26265
|
-
return
|
|
28149
|
+
*/ function loadConfig(options) {
|
|
28150
|
+
return loadAtomixConfig({
|
|
28151
|
+
configPath: options?.configPath,
|
|
28152
|
+
required: options?.required ?? !1
|
|
28153
|
+
});
|
|
28154
|
+
}
|
|
28155
|
+
|
|
28156
|
+
/**
|
|
28157
|
+
* Validate Atomix configuration structure.
|
|
28158
|
+
*
|
|
28159
|
+
* @param config - Configuration object to validate
|
|
28160
|
+
* @returns Array of validation warnings (empty if valid)
|
|
28161
|
+
*/ function validateConfig(config) {
|
|
28162
|
+
return validateConfig$1(config);
|
|
26266
28163
|
}
|
|
26267
28164
|
|
|
26268
28165
|
// Import and re-export as namespaces with proper typing
|
|
@@ -26411,5 +28308,5 @@ const atomix = {
|
|
|
26411
28308
|
types: types
|
|
26412
28309
|
};
|
|
26413
28310
|
|
|
26414
|
-
export { ACCORDION, ATOMIX_GLASS, AVATAR, AVATAR_GROUP, Accordion, AreaChart, AtomixGlass, AtomixLogo, Avatar, AvatarGroup, BADGE, BADGE_CSS_VARS, BALANCED_PRESET, BLOCK, BREADCRUMB, BUTTON, BUTTON_CSS_VARS, BUTTON_GROUP, Badge, BarChart, Block, Breadcrumb, BubbleChart, Button, ButtonGroup, CALLOUT, CARD, CARD_CSS_VARS, CHART, CHECKBOX_CSS_VARS, CLASS_PREFIX, CODE_SNIPPET, COMPONENT_CSS_VARS, COUNTDOWN, Callout, CandlestickChart, Card, Chart, ChartRenderer, Checkbox, ColorModeToggle, Container, Countdown, DATA_TABLE_CLASSES, DATA_TABLE_SELECTORS, DATEPICKER, DEFAULT_ATOMIX_FONTS, DEFAULT_BREAKPOINTS, DROPDOWN, DROPDOWN_CSS_VARS, DataTable, DatePicker, DesignTokensCustomizer, DeviceDetector, DonutChart, Dropdown, EDGE_PANEL, EdgePanel, ElevationCard, FOOTER, FORM, FORM_GROUP, Footer, FooterLink, FooterSection, FooterSocialLink, Form, FormGroup, FunnelChart, GaugeChart, Grid, GridCol, HERO, HeatmapChart, Hero, INPUT, INPUT_CSS_VARS, Icon, Input, LIST, LIST_GROUP, LineChart, List, ListGroup, MESSAGES, MOBILE_OPTIMIZED_BREAKPOINTS, MODAL, MODAL_CSS_VARS, MasonryGrid, MasonryGridItem, MegaMenu, MegaMenuColumn, MegaMenuLink, Menu, MenuDivider, MenuItem, Messages, Modal, MultiAxisChart, NAV, NAVBAR, Nav, NavDropdown, NavItem, Navbar, PAGINATION_DEFAULTS, PERFORMANCE_PRESET, PHOTOVIEWER, POPOVER, PROGRESS, PROGRESS_CSS_VARS, Pagination, PerformanceOverlay, PhotoViewer, PieChart, Popover, ProductReview, Progress, QUALITY_PRESET, RADIO, RADIO_CSS_VARS, RATING, RIVER, RTLManager, RadarChart, Radio, Rating, River, Row, SECTION_INTRO, SELECT, SIDE_MENU, SIZES, SLIDER, SPINNER, STEPS, ScatterChart, SectionIntro, Select, SideMenu, SideMenuItem, SideMenuList, Slider, Spinner, Steps, TAB, TABS_CSS_VARS, TESTIMONIAL, TEXTAREA, THEME_COLORS, THEME_NAMING, TODO, TOGGLE, TOOLTIP, TOOLTIP_CSS_VARS, TYPEDBUTTON, Tabs, Testimonial, Textarea, ThemeApplicator, ThemeComparator, ThemeContext, ThemeErrorBoundary, ThemeInspector, ThemeLiveEditor, ThemePreview, ThemeProvider, ThemeValidator, Todo, Toggle, Tooltip, TreemapChart, UPLOAD, Upload, VIDEO_PLAYER, VideoPlayer, WaterfallChart, applyCSSVariables, applyCSSVarsToStyle, applyComponentTheme, applyPartStyles, applyTheme, camelToKebab, clearThemes, composables, constants, createBreakpoints$1 as createBreakpoints, createCSSVarStyle, createDarkVariant, createDebugAttrs, createFontPreloadLink, createPartProps, createSlotComponent, createSlotProps, createTheme, createThemeRegistry, createTokens, cssVarsToStyle, deepMerge, atomix as default, defaultTokens, defineConfig, designTokensToCSSVars, exportTheme, extendTheme, extractComponentName, extractYouTubeId, generateCSSVariableName, generateCSSVariables$1 as generateCSSVariables, generateCSSVariablesForSelector, generateClassName, generateComponentCSSVars, generateFontPreloadTags, generateUUID, getAllThemes, getCSSVariable, getComponentCSSVars, getComponentThemeValue, getDefaultBreakpoints, getDevicePreset, getMobileOptimizedParams, getPartStyles, getQualityMultipliers, getTheme, getThemeApplicator, getThemeCount, getThemeIds, getThemeMetadata, hasCustomization, hasTheme, importTheme, injectCSS$1 as injectCSS, injectTheme, isCSSInjected, isDesignTokens, isSlot, isValidCSSVariableName, isYouTubeUrl, mapSCSSTokensToCSSVars, mergeCSSVars, mergeClassNames, mergeComponentProps, mergePartStyles, mergeSlots, mergeTheme, normalizeThemeTokens, preloadFonts, quickTheme, registerTheme, removeCSS, removeCSSVariables, removeTheme, renderSlot, sliderConstants, supportsDarkMode, theme, themePropertyToCSSVar, themeToCSS, types, unregisterTheme, useAccordion, useAtomixGlass, useBadge, useBarChart, useBlock, useChartData, useChartInteraction, useChartScale, useComponentCustomization, useComponentDefaultProps, useComponentTheme, useEdgePanel, useForm, useFormGroup, useHero, useHistory, useInput, useLineChart, useMergedProps, useNav, useNavDropdown, useNavItem, useNavbar,
|
|
28311
|
+
export { ACCORDION, ATOMIX_GLASS, AVATAR, AVATAR_GROUP, Accordion, AreaChart, AtomixGlass, AtomixLogo, Avatar, AvatarGroup, BADGE, BADGE_CSS_VARS, BALANCED_PRESET, BLOCK, BREADCRUMB, BUTTON, BUTTON_CSS_VARS, BUTTON_GROUP, Badge, BarChart, Block, Breadcrumb, BubbleChart, Button, ButtonGroup, CALLOUT, CARD, CARD_CSS_VARS, CHART, CHECKBOX_CSS_VARS, CLASS_PREFIX, CODE_SNIPPET, COMPONENT_CSS_VARS, COUNTDOWN, Callout, CandlestickChart, Card, Chart, ChartRenderer, Checkbox, ColorModeToggle, Container, Countdown, DATA_TABLE_CLASSES, DATA_TABLE_SELECTORS, DATEPICKER, DEFAULT_ATOMIX_FONTS, DEFAULT_BREAKPOINTS, DROPDOWN, DROPDOWN_CSS_VARS, DataTable, DatePicker, DesignTokensCustomizer, DeviceDetector, DonutChart, Dropdown, EDGE_PANEL, EdgePanel, ElevationCard, FOOTER, FORM, FORM_GROUP, Footer, FooterLink, FooterSection, FooterSocialLink, Form, FormGroup, FunnelChart, GaugeChart, Grid, GridCol, HERO, HeatmapChart, Hero, INPUT, INPUT_CSS_VARS, Icon, Input, LIST, LIST_GROUP, LineChart, List, ListGroup, MESSAGES, MOBILE_OPTIMIZED_BREAKPOINTS, MODAL, MODAL_CSS_VARS, MasonryGrid, MasonryGridItem, MegaMenu, MegaMenuColumn, MegaMenuLink, Menu, MenuDivider, MenuItem, Messages, Modal, MultiAxisChart, NAV, NAVBAR, Nav, NavDropdown, NavItem, Navbar, PAGINATION_DEFAULTS, PERFORMANCE_PRESET, PHOTOVIEWER, POPOVER, PROGRESS, PROGRESS_CSS_VARS, Pagination, PerformanceOverlay, PhotoViewer, PieChart, Popover, ProductReview, Progress, QUALITY_PRESET, RADIO, RADIO_CSS_VARS, RATING, RIVER, RTLManager, RadarChart, Radio, Rating, River, Row, SECTION_INTRO, SELECT, SIDE_MENU, SIZES, SLIDER, SPINNER, STEPS, ScatterChart, SectionIntro, Select, SideMenu, SideMenuItem, SideMenuList, Slider, Spinner, Steps, TAB, TABS_CSS_VARS, TESTIMONIAL, TEXTAREA, THEME_COLORS, THEME_NAMING, TODO, TOGGLE, TOOLTIP, TOOLTIP_CSS_VARS, TYPEDBUTTON, Tabs, Testimonial, Textarea, ThemeApplicator, ThemeComparator, ThemeContext, ThemeErrorBoundary, ThemeInspector, ThemeLiveEditor, ThemePreview, ThemeProvider, ThemeToggle, ThemeValidator, Todo, Toggle, Tooltip, TreemapChart, UPLOAD, Upload, VIDEO_PLAYER, VideoPlayer, WaterfallChart, alpha, applyCSSVariables, applyCSSVarsToStyle, applyComponentTheme, applyPartStyles, applyTheme, camelToKebab, clearThemePreference, clearThemes, composables, configToTokens, constants, createBreakpoints$1 as createBreakpoints, createCSSVarStyle, createDarkVariant, createDebugAttrs, createFontPreloadLink, createPartProps, createPerformanceMonitor, createRTLManager, createResponsiveUtil, createSlotComponent, createSlotProps, createSpacing, createTheme, createThemeRegistry, createTokens, cssVarsToStyle, darken, deepMerge, atomix as default, defaultTokens, defineConfig, designTokensToCSSVars, emphasize, exportTheme, extendTheme, extractComponentName, extractYouTubeId, generateCSSVariableName, generateCSSVariables$1 as generateCSSVariables, generateCSSVariablesForSelector, generateClassName, generateComponentCSSVars, generateFontPreloadTags, generateUUID, getAllThemes, getCSSVariable, getComponentCSSVars, getComponentThemeValue, getContrastRatio, getContrastText, getCurrentTheme, getDefaultBreakpoints, getDevicePreset, getDirectionFromLocale, getLuminance, getMobileOptimizedParams, getPartStyles, getQualityMultipliers, getSystemTheme, getTheme, getThemeApplicator, getThemeCount, getThemeIds, getThemeMetadata, hasCustomization, hasTheme, hexToRgb$1 as hexToRgb, importTheme, initializeTheme, injectCSS$1 as injectCSS, injectTheme, isAccessible, isCSSInjected, isDesignTokens, isRTLLocale, isSlot, isValidCSSVariableName, isYouTubeUrl, lighten, listenToSystemTheme, loadAtomixConfig, loadConfig, mapSCSSTokensToCSSVars, mergeCSSVars, mergeClassNames, mergeComponentProps, mergePartStyles, mergeSlots, mergeTheme, mergeTokens, normalizeThemeTokens, omitTokens, overrideTokens, persistTheme, pickTokens, preloadFonts, printConfigReport, quickTheme, registerTheme, removeCSS, removeCSSVariables, removeTheme, renderSlot, resolveConfigPath, rgbToHex, rtlCSS, sliderConstants, supportsDarkMode, switchTheme, theme, themePropertyToCSSVar, themeToCSS, toggleTheme, types, unregisterTheme, useAccordion, useAtomixGlass, useBadge, useBarChart, useBlock, useChartData, useChartInteraction, useChartScale, useComponentCustomization, useComponentDefaultProps, useComponentTheme, useEdgePanel, useForm, useFormGroup, useHero, useHistory, useInput, useLineChart, useMergedProps, useNav, useNavDropdown, useNavItem, useNavbar, usePieChart, useRadio, useResponsive, useResponsiveGlass, useRiver, useSelect, useSideMenu, useSideMenuItem, useSlot, useSpinner, useTextarea, useTheme, useThemeSwitcher, useThemeTokens, useTodo, utils, validateConfig, validateConfiguration, validateTheme };
|
|
26415
28312
|
//# sourceMappingURL=index.esm.js.map
|