@shohojdhara/atomix 0.6.4 → 0.6.6
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/dist/atomix.css +117 -38
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/atomix.umd.js +1 -1
- package/dist/atomix.umd.js.map +1 -1
- package/dist/atomix.umd.min.js +1 -1
- package/dist/charts.d.ts +30 -1
- package/dist/charts.js +625 -846
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +30 -1
- package/dist/core.js +659 -873
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +30 -1
- package/dist/forms.js +1171 -1402
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +31 -89
- package/dist/heavy.js +975 -1195
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +383 -140
- package/dist/index.esm.js +1567 -1679
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1556 -1667
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Accordion/Accordion.tsx +2 -5
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +14 -16
- package/src/components/AtomixGlass/AtomixGlass.tsx +137 -364
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +32 -251
- package/src/components/AtomixGlass/GlassFilter.tsx +62 -68
- package/src/components/AtomixGlass/README.md +2 -1
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +19 -18
- package/src/components/AtomixGlass/glass-border-styles.test.ts +58 -0
- package/src/components/AtomixGlass/glass-border-styles.ts +136 -0
- package/src/components/AtomixGlass/glass-utils.ts +456 -22
- package/src/components/AtomixGlass/shader-utils.ts +19 -77
- package/src/components/AtomixGlass/stories/AnimationFeatures.stories.tsx +158 -537
- package/src/components/AtomixGlass/stories/Border.stories.tsx +149 -0
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +229 -89
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +29 -340
- package/src/components/AtomixGlass/stories/argTypes.ts +30 -13
- package/src/components/AtomixGlass/stories/premium-presets.ts +206 -0
- package/src/components/AtomixGlass/stories/shared-components.tsx +52 -8
- package/src/components/Badge/Badge.tsx +4 -4
- package/src/components/Button/Button.tsx +2 -6
- package/src/components/Callout/Callout.test.tsx +4 -3
- package/src/components/Callout/Callout.tsx +2 -5
- package/src/components/Dropdown/Dropdown.tsx +3 -7
- package/src/components/Form/Checkbox.tsx +2 -8
- package/src/components/Form/Input.tsx +2 -9
- package/src/components/Form/Radio.tsx +2 -9
- package/src/components/Form/Select.test.tsx +6 -6
- package/src/components/Form/Select.tsx +2 -7
- package/src/components/Form/Textarea.stories.tsx +5 -5
- package/src/components/Form/Textarea.tsx +2 -9
- package/src/components/Messages/Messages.tsx +2 -8
- package/src/components/Modal/Modal.tsx +4 -5
- package/src/components/Navigation/Nav/Nav.tsx +2 -6
- package/src/components/Navigation/Navbar/Navbar.tsx +2 -9
- package/src/components/Navigation/SideMenu/SideMenu.tsx +2 -6
- package/src/components/Pagination/Pagination.tsx +2 -10
- package/src/components/Popover/Popover.tsx +2 -9
- package/src/components/Progress/Progress.tsx +2 -7
- package/src/components/Rating/Rating.tsx +2 -10
- package/src/components/Spinner/Spinner.tsx +2 -7
- package/src/components/Steps/Steps.tsx +2 -10
- package/src/components/Tabs/Tabs.tsx +2 -9
- package/src/components/Toggle/Toggle.tsx +2 -10
- package/src/components/Tooltip/Tooltip.tsx +2 -5
- package/src/lib/composables/useAtomixGlass.ts +42 -143
- package/src/lib/composables/useAtomixGlassStyles.ts +61 -77
- package/src/lib/composables/usePerformanceMonitor.ts +5 -66
- package/src/lib/constants/components.ts +363 -46
- package/src/lib/types/components.ts +33 -1
- package/src/styles/01-settings/_settings.atomix-glass.scss +66 -28
- package/src/styles/02-tools/_tools.button.scss +51 -42
- package/src/styles/02-tools/_tools.glass.scss +45 -3
- package/src/styles/06-components/_components.atomix-glass.scss +116 -79
- package/src/components/AtomixGlass/PerformanceDashboard.tsx +0 -171
- package/src/components/AtomixGlass/animation-system.ts +0 -578
- package/src/components/AtomixGlass/deprecated/AtomixGlass.deprecated.tsx +0 -390
package/dist/index.esm.js
CHANGED
|
@@ -1687,6 +1687,268 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1687
1687
|
NEWSLETTER_BUTTON_TEXT: "Subscribe",
|
|
1688
1688
|
BACK_TO_TOP_TEXT: "Back to Top"
|
|
1689
1689
|
}
|
|
1690
|
+
}, GLASS_DEFAULTS = {
|
|
1691
|
+
/**
|
|
1692
|
+
* Button — compact interactive element.
|
|
1693
|
+
* Low displacement + no blur override so the backdrop token handles frosting.
|
|
1694
|
+
* Zero elasticity: the button itself handles press/hover feedback.
|
|
1695
|
+
*/
|
|
1696
|
+
BUTTON: {
|
|
1697
|
+
displacementScale: 16,
|
|
1698
|
+
saturation: 180,
|
|
1699
|
+
elasticity: 0
|
|
1700
|
+
},
|
|
1701
|
+
/**
|
|
1702
|
+
* Badge — pill-shaped tag. Tiny surface, minimal distortion.
|
|
1703
|
+
* borderRadius is set dynamically at runtime; this serves as a safe fallback.
|
|
1704
|
+
*/
|
|
1705
|
+
BADGE: {
|
|
1706
|
+
displacementScale: 14,
|
|
1707
|
+
borderRadius: 16,
|
|
1708
|
+
elasticity: 0
|
|
1709
|
+
},
|
|
1710
|
+
/**
|
|
1711
|
+
* Accordion — block-level content container.
|
|
1712
|
+
* Gentle displacement; zero elasticity so open/close animation isn't jittery.
|
|
1713
|
+
*/
|
|
1714
|
+
ACCORDION: {
|
|
1715
|
+
displacementScale: 18,
|
|
1716
|
+
elasticity: 0
|
|
1717
|
+
},
|
|
1718
|
+
/**
|
|
1719
|
+
* Callout — notification / alert banner.
|
|
1720
|
+
* Slightly more frosted than Accordion to give it visual priority.
|
|
1721
|
+
*/
|
|
1722
|
+
CALLOUT: {
|
|
1723
|
+
displacementScale: 22,
|
|
1724
|
+
borderRadius: 8,
|
|
1725
|
+
elasticity: 0
|
|
1726
|
+
},
|
|
1727
|
+
/**
|
|
1728
|
+
* Dropdown — floating menu. Small surface, should feel light and airy.
|
|
1729
|
+
* No blur override — rely on the backdrop token.
|
|
1730
|
+
*/
|
|
1731
|
+
DROPDOWN: {
|
|
1732
|
+
displacementScale: 16,
|
|
1733
|
+
elasticity: 0
|
|
1734
|
+
},
|
|
1735
|
+
/**
|
|
1736
|
+
* EdgePanel — full-height side drawer.
|
|
1737
|
+
* Empty config: the panel inherits all ATOMIX_GLASS.DEFAULTS.
|
|
1738
|
+
* borderRadius and size are managed by the panel's own SCSS.
|
|
1739
|
+
*/
|
|
1740
|
+
EDGE_PANEL: {},
|
|
1741
|
+
/**
|
|
1742
|
+
* Modal — full-screen overlay dialog. Shader mode for premium refraction.
|
|
1743
|
+
* displacementScale omitted — set dynamically from modal content height at runtime.
|
|
1744
|
+
* elasticity: 0 — modals should not wobble when the user interacts with them.
|
|
1745
|
+
*/
|
|
1746
|
+
MODAL: {
|
|
1747
|
+
blurAmount: 28,
|
|
1748
|
+
elasticity: 0,
|
|
1749
|
+
mode: "shader",
|
|
1750
|
+
shaderMode: "premiumGlass"
|
|
1751
|
+
},
|
|
1752
|
+
/**
|
|
1753
|
+
* Navbar — sticky / fixed navigation bar spanning full width.
|
|
1754
|
+
* Shader gives the top edge a polished lens look.
|
|
1755
|
+
* borderRadius: 0 — navbars run edge-to-edge.
|
|
1756
|
+
* elasticity: 0 — no wobble on a fixed chrome element.
|
|
1757
|
+
*/
|
|
1758
|
+
NAVBAR: {
|
|
1759
|
+
displacementScale: 24,
|
|
1760
|
+
blurAmount: 24,
|
|
1761
|
+
borderRadius: 0,
|
|
1762
|
+
elasticity: 0,
|
|
1763
|
+
mode: "shader",
|
|
1764
|
+
shaderVariant: "premiumGlass"
|
|
1765
|
+
},
|
|
1766
|
+
/**
|
|
1767
|
+
* Nav (inline nav list) — narrower than a full Navbar, standard mode is
|
|
1768
|
+
* enough. Rounded corners to match typical pill / tab nav designs.
|
|
1769
|
+
*/
|
|
1770
|
+
NAV: {
|
|
1771
|
+
displacementScale: 24,
|
|
1772
|
+
blurAmount: 20,
|
|
1773
|
+
borderRadius: 8,
|
|
1774
|
+
elasticity: 0,
|
|
1775
|
+
mode: "shader"
|
|
1776
|
+
},
|
|
1777
|
+
/**
|
|
1778
|
+
* SideMenu — persistent sidebar navigation.
|
|
1779
|
+
* Moderate displacement; shader for depth. Zero elasticity.
|
|
1780
|
+
*/
|
|
1781
|
+
SIDE_MENU: {
|
|
1782
|
+
displacementScale: 24,
|
|
1783
|
+
blurAmount: 24,
|
|
1784
|
+
borderRadius: 0,
|
|
1785
|
+
elasticity: 0,
|
|
1786
|
+
mode: "shader"
|
|
1787
|
+
},
|
|
1788
|
+
/**
|
|
1789
|
+
* Popover — small floating card above content.
|
|
1790
|
+
* Shader mode + aberration for the characteristic lens fringe.
|
|
1791
|
+
* Low displacement so the content remains readable.
|
|
1792
|
+
*/
|
|
1793
|
+
POPOVER: {
|
|
1794
|
+
displacementScale: 22,
|
|
1795
|
+
blurAmount: 20,
|
|
1796
|
+
saturation: 180,
|
|
1797
|
+
aberrationIntensity: .35,
|
|
1798
|
+
borderRadius: 12,
|
|
1799
|
+
elasticity: 0,
|
|
1800
|
+
mode: "shader"
|
|
1801
|
+
},
|
|
1802
|
+
/**
|
|
1803
|
+
* Tooltip — tiny single-line label.
|
|
1804
|
+
* Higher displacement than other small elements because tooltips float
|
|
1805
|
+
* freely and the distortion reads as depth. No shader (too small to matter).
|
|
1806
|
+
*/
|
|
1807
|
+
TOOLTIP: {
|
|
1808
|
+
displacementScale: 18,
|
|
1809
|
+
blurAmount: 16,
|
|
1810
|
+
elasticity: 0
|
|
1811
|
+
},
|
|
1812
|
+
/**
|
|
1813
|
+
* Tabs — tabbed content panel. Shader for the nav strip refraction.
|
|
1814
|
+
*/
|
|
1815
|
+
TABS: {
|
|
1816
|
+
displacementScale: 24,
|
|
1817
|
+
blurAmount: 20,
|
|
1818
|
+
saturation: 180,
|
|
1819
|
+
aberrationIntensity: .35,
|
|
1820
|
+
borderRadius: 12,
|
|
1821
|
+
elasticity: 0,
|
|
1822
|
+
mode: "shader"
|
|
1823
|
+
},
|
|
1824
|
+
/**
|
|
1825
|
+
* Toggle — switch control. Compact, pill shape.
|
|
1826
|
+
* Relies on borderRadius from the component's own SCSS.
|
|
1827
|
+
*/
|
|
1828
|
+
TOGGLE: {
|
|
1829
|
+
displacementScale: 16,
|
|
1830
|
+
elasticity: 0
|
|
1831
|
+
},
|
|
1832
|
+
/**
|
|
1833
|
+
* Form inputs (Input, Textarea, Select, Checkbox, Radio).
|
|
1834
|
+
* Unified glass feel for all form controls — subtle displacement,
|
|
1835
|
+
* rounded corners matching the $input-border-radius token (≈ 6px).
|
|
1836
|
+
*/
|
|
1837
|
+
INPUT: {
|
|
1838
|
+
displacementScale: 18,
|
|
1839
|
+
borderRadius: 6,
|
|
1840
|
+
elasticity: 0
|
|
1841
|
+
},
|
|
1842
|
+
TEXTAREA: {
|
|
1843
|
+
displacementScale: 18,
|
|
1844
|
+
borderRadius: 6,
|
|
1845
|
+
elasticity: 0
|
|
1846
|
+
},
|
|
1847
|
+
SELECT: {
|
|
1848
|
+
displacementScale: 18,
|
|
1849
|
+
borderRadius: 6,
|
|
1850
|
+
elasticity: 0
|
|
1851
|
+
},
|
|
1852
|
+
CHECKBOX: {
|
|
1853
|
+
displacementScale: 14,
|
|
1854
|
+
borderRadius: 4,
|
|
1855
|
+
elasticity: 0
|
|
1856
|
+
},
|
|
1857
|
+
RADIO: {
|
|
1858
|
+
displacementScale: 14,
|
|
1859
|
+
borderRadius: 99,
|
|
1860
|
+
elasticity: 0
|
|
1861
|
+
},
|
|
1862
|
+
/**
|
|
1863
|
+
* Pagination — row of page buttons.
|
|
1864
|
+
* Thin, horizontal strip; low displacement so numbers stay legible.
|
|
1865
|
+
*/
|
|
1866
|
+
PAGINATION: {
|
|
1867
|
+
displacementScale: 18,
|
|
1868
|
+
borderRadius: 8,
|
|
1869
|
+
elasticity: 0
|
|
1870
|
+
},
|
|
1871
|
+
/**
|
|
1872
|
+
* Progress — horizontal bar track.
|
|
1873
|
+
* Very low displacement — the bar should not distort.
|
|
1874
|
+
*/
|
|
1875
|
+
PROGRESS: {
|
|
1876
|
+
displacementScale: 10,
|
|
1877
|
+
borderRadius: 99,
|
|
1878
|
+
elasticity: 0
|
|
1879
|
+
},
|
|
1880
|
+
/**
|
|
1881
|
+
* Rating — star picker.
|
|
1882
|
+
* Compact inline element; minimal glass, no shader needed.
|
|
1883
|
+
*/
|
|
1884
|
+
RATING: {
|
|
1885
|
+
displacementScale: 16,
|
|
1886
|
+
elasticity: 0
|
|
1887
|
+
},
|
|
1888
|
+
/**
|
|
1889
|
+
* Spinner — loading indicator.
|
|
1890
|
+
* Barely-there glass; the spinner itself provides visual interest.
|
|
1891
|
+
*/
|
|
1892
|
+
SPINNER: {
|
|
1893
|
+
displacementScale: 12,
|
|
1894
|
+
elasticity: 0
|
|
1895
|
+
},
|
|
1896
|
+
/**
|
|
1897
|
+
* Steps — horizontal / vertical stepper.
|
|
1898
|
+
* Moderate displacement so the connector lines remain crisp.
|
|
1899
|
+
*/
|
|
1900
|
+
STEPS: {
|
|
1901
|
+
displacementScale: 22,
|
|
1902
|
+
borderRadius: 8,
|
|
1903
|
+
elasticity: 0
|
|
1904
|
+
},
|
|
1905
|
+
/**
|
|
1906
|
+
* Messages / chat bubbles.
|
|
1907
|
+
* Rounded pill-like bubbles; gentle glass to aid readability.
|
|
1908
|
+
*/
|
|
1909
|
+
MESSAGES: {
|
|
1910
|
+
displacementScale: 20,
|
|
1911
|
+
borderRadius: 16,
|
|
1912
|
+
elasticity: 0
|
|
1913
|
+
}
|
|
1914
|
+
}, GLASS_BORDER_GRADIENT = {
|
|
1915
|
+
BASE_ANGLE: 135,
|
|
1916
|
+
ANGLE_MULTIPLIER: .5,
|
|
1917
|
+
VELOCITY_ANGLE_MULTIPLIER: .5,
|
|
1918
|
+
CHROMATIC_OFFSET: 1.5,
|
|
1919
|
+
STOP_1: {
|
|
1920
|
+
MIN: 10,
|
|
1921
|
+
BASE: 33,
|
|
1922
|
+
get MULTIPLIER() {
|
|
1923
|
+
return .009 * this.BASE;
|
|
1924
|
+
}
|
|
1925
|
+
},
|
|
1926
|
+
STOP_2: {
|
|
1927
|
+
MAX: 90,
|
|
1928
|
+
BASE: 66,
|
|
1929
|
+
get MULTIPLIER() {
|
|
1930
|
+
return .006 * this.BASE;
|
|
1931
|
+
}
|
|
1932
|
+
},
|
|
1933
|
+
OPACITY: {
|
|
1934
|
+
/** Matches $glass-border-1-opacity (0.08) */
|
|
1935
|
+
BASE_1: .08,
|
|
1936
|
+
get BASE_2() {
|
|
1937
|
+
return 3.33 * this.BASE_1;
|
|
1938
|
+
},
|
|
1939
|
+
get BASE_3() {
|
|
1940
|
+
return 2.66 * this.BASE_1;
|
|
1941
|
+
},
|
|
1942
|
+
get BASE_4() {
|
|
1943
|
+
return 5 * this.BASE_1;
|
|
1944
|
+
},
|
|
1945
|
+
get MULTIPLIER_LOW() {
|
|
1946
|
+
return .066 * this.BASE_1;
|
|
1947
|
+
},
|
|
1948
|
+
get MULTIPLIER_HIGH() {
|
|
1949
|
+
return .1 * this.BASE_1;
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1690
1952
|
}, ATOMIX_GLASS = {
|
|
1691
1953
|
BASE_CLASS: "c-atomix-glass",
|
|
1692
1954
|
CONTAINER_CLASS: "c-atomix-glass__container",
|
|
@@ -1698,6 +1960,22 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1698
1960
|
BORDER_BACKDROP_CLASS: "c-atomix-glass__border-backdrop",
|
|
1699
1961
|
BORDER_1_CLASS: "c-atomix-glass__border-1",
|
|
1700
1962
|
BORDER_2_CLASS: "c-atomix-glass__border-2",
|
|
1963
|
+
/** Centralized liquid glass rim configuration */
|
|
1964
|
+
BORDER: {
|
|
1965
|
+
WIDTH_CSS_VAR: "--atomix-glass-border-width",
|
|
1966
|
+
DEFAULT_WIDTH: "0.5px",
|
|
1967
|
+
GRADIENT_CSS_VARS: {
|
|
1968
|
+
GRADIENT_1: "--atomix-glass-border-gradient-1",
|
|
1969
|
+
GRADIENT_2: "--atomix-glass-border-gradient-2"
|
|
1970
|
+
},
|
|
1971
|
+
GRADIENT: GLASS_BORDER_GRADIENT,
|
|
1972
|
+
OVER_LIGHT: {
|
|
1973
|
+
opacity: .7
|
|
1974
|
+
},
|
|
1975
|
+
DARK: {
|
|
1976
|
+
opacity: .35
|
|
1977
|
+
}
|
|
1978
|
+
},
|
|
1701
1979
|
HOVER_1_CLASS: "c-atomix-glass__hover-1",
|
|
1702
1980
|
HOVER_2_CLASS: "c-atomix-glass__hover-2",
|
|
1703
1981
|
HOVER_3_CLASS: "c-atomix-glass__hover-3",
|
|
@@ -1726,25 +2004,22 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1726
2004
|
SHADER: "c-atomix-glass--shader"
|
|
1727
2005
|
},
|
|
1728
2006
|
DEFAULTS: {
|
|
1729
|
-
|
|
2007
|
+
/** Subtle refraction — Apple UI chrome avoids heavy liquid distortion */
|
|
2008
|
+
DISPLACEMENT_SCALE: 28,
|
|
1730
2009
|
get BLUR_AMOUNT() {
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
// Saturate relative to intensity
|
|
1737
|
-
},
|
|
2010
|
+
// Apple Music sidebar / player bar: ~20–40px frost (see $glass-backdrop-filter)
|
|
2011
|
+
return Math.max(20, .72 * this.DISPLACEMENT_SCALE);
|
|
2012
|
+
},
|
|
2013
|
+
/** Fixed 180% matches Apple's saturate(180%) backdrop recipe */
|
|
2014
|
+
SATURATION: 180,
|
|
1738
2015
|
get ABERRATION_INTENSITY() {
|
|
1739
|
-
return .
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
ELASTICITY: .15,
|
|
2016
|
+
return .02 * this.DISPLACEMENT_SCALE;
|
|
2017
|
+
},
|
|
2018
|
+
ELASTICITY: .05,
|
|
1743
2019
|
get CORNER_RADIUS() {
|
|
1744
2020
|
return 16;
|
|
1745
2021
|
// Use 16 to match SCSS design system (was 20)
|
|
1746
2022
|
},
|
|
1747
|
-
PADDING: "0",
|
|
1748
2023
|
MODE: "standard",
|
|
1749
2024
|
OVER_LIGHT: !1,
|
|
1750
2025
|
ENABLE_OVER_LIGHT_LAYERS: !0,
|
|
@@ -1760,19 +2035,29 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1760
2035
|
},
|
|
1761
2036
|
CONSTANTS: {
|
|
1762
2037
|
ACTIVATION_ZONE: 200,
|
|
1763
|
-
LERP_FACTOR: .
|
|
2038
|
+
LERP_FACTOR: .05,
|
|
2039
|
+
// Lower = more viscous, liquid-smooth tracking (Apple feel)
|
|
1764
2040
|
SMOOTHSTEP_POWER: 2.5,
|
|
1765
2041
|
MIN_BLUR: .1,
|
|
1766
2042
|
MOUSE_INFLUENCE_DIVISOR: 100,
|
|
1767
2043
|
EDGE_FADE_PIXELS: 2,
|
|
1768
|
-
//
|
|
1769
|
-
|
|
2044
|
+
// Interaction intensity multipliers shared by the hook and the imperative style updater
|
|
2045
|
+
INTERACTION: {
|
|
2046
|
+
HOVER_INTENSITY: 1.4,
|
|
2047
|
+
ACTIVE_INTENSITY: 1.6
|
|
2048
|
+
},
|
|
2049
|
+
// Elasticity physics constants — Apple-tuned: soft springs, fast settling, minimal stretch
|
|
2050
|
+
ELASTICITY_TRANSLATION_FACTOR: .06,
|
|
2051
|
+
// Subtler elastic shift (was 0.1)
|
|
1770
2052
|
ELASTICITY_DISTANCE_THRESHOLD: 200,
|
|
1771
2053
|
ELASTICITY_COMPRESSION_FACTOR: .3,
|
|
1772
|
-
ELASTICITY_STIFFNESS: .
|
|
1773
|
-
|
|
2054
|
+
ELASTICITY_STIFFNESS: .06,
|
|
2055
|
+
// Softer springs = gentler motion (was 0.1)
|
|
2056
|
+
ELASTICITY_DAMPING: .88,
|
|
2057
|
+
// Fast settling, no wobble (was 0.76)
|
|
1774
2058
|
ELASTICITY_VELOCITY_FACTOR: .65,
|
|
1775
|
-
ELASTICITY_STRETCH_RATIO: .
|
|
2059
|
+
ELASTICITY_STRETCH_RATIO: .25,
|
|
2060
|
+
// Less visible surface tension stretch (was 0.45)
|
|
1776
2061
|
ELASTICITY_MAGNIFICATION_BASE: 1.02,
|
|
1777
2062
|
// Note: This default must match the SCSS variable --atomix-radius-md
|
|
1778
2063
|
// @see src/styles/01-settings/_settings.global.scss
|
|
@@ -1786,55 +2071,16 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1786
2071
|
},
|
|
1787
2072
|
// Gradient calculation constants
|
|
1788
2073
|
GRADIENT: {
|
|
1789
|
-
BASE_ANGLE:
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
// Minimum percentage for border stop 1
|
|
1800
|
-
BASE: 33,
|
|
1801
|
-
// Base percentage for border stop 1
|
|
1802
|
-
get MULTIPLIER() {
|
|
1803
|
-
return .009 * this.BASE;
|
|
1804
|
-
}
|
|
1805
|
-
},
|
|
1806
|
-
BORDER_STOP_2: {
|
|
1807
|
-
MAX: 90,
|
|
1808
|
-
// Maximum percentage for border stop 2
|
|
1809
|
-
BASE: 66,
|
|
1810
|
-
// Base percentage for border stop 2
|
|
1811
|
-
get MULTIPLIER() {
|
|
1812
|
-
return .006 * this.BASE;
|
|
1813
|
-
}
|
|
1814
|
-
},
|
|
1815
|
-
BORDER_OPACITY: {
|
|
1816
|
-
BASE_1: .12,
|
|
1817
|
-
// Base opacity for border gradient 1
|
|
1818
|
-
get BASE_2() {
|
|
1819
|
-
return 3.33 * this.BASE_1;
|
|
1820
|
-
},
|
|
1821
|
-
// Base opacity for border gradient 2
|
|
1822
|
-
get BASE_3() {
|
|
1823
|
-
return 2.66 * this.BASE_1;
|
|
1824
|
-
},
|
|
1825
|
-
// Base opacity for border gradient 3
|
|
1826
|
-
get BASE_4() {
|
|
1827
|
-
return 5 * this.BASE_1;
|
|
1828
|
-
},
|
|
1829
|
-
// Base opacity for border gradient 4
|
|
1830
|
-
get MULTIPLIER_LOW() {
|
|
1831
|
-
return .066 * this.BASE_1;
|
|
1832
|
-
},
|
|
1833
|
-
// Low multiplier for mouse influence on opacity
|
|
1834
|
-
get MULTIPLIER_HIGH() {
|
|
1835
|
-
return .1 * this.BASE_1;
|
|
1836
|
-
}
|
|
1837
|
-
},
|
|
2074
|
+
BASE_ANGLE: GLASS_BORDER_GRADIENT.BASE_ANGLE,
|
|
2075
|
+
ANGLE_MULTIPLIER: GLASS_BORDER_GRADIENT.ANGLE_MULTIPLIER,
|
|
2076
|
+
VELOCITY_ANGLE_MULTIPLIER: GLASS_BORDER_GRADIENT.VELOCITY_ANGLE_MULTIPLIER,
|
|
2077
|
+
CHROMATIC_OFFSET: GLASS_BORDER_GRADIENT.CHROMATIC_OFFSET,
|
|
2078
|
+
/** @deprecated Use ATOMIX_GLASS.BORDER.GRADIENT.STOP_1 */
|
|
2079
|
+
BORDER_STOP_1: GLASS_BORDER_GRADIENT.STOP_1,
|
|
2080
|
+
/** @deprecated Use ATOMIX_GLASS.BORDER.GRADIENT.STOP_2 */
|
|
2081
|
+
BORDER_STOP_2: GLASS_BORDER_GRADIENT.STOP_2,
|
|
2082
|
+
/** @deprecated Use ATOMIX_GLASS.BORDER.GRADIENT.OPACITY */
|
|
2083
|
+
BORDER_OPACITY: GLASS_BORDER_GRADIENT.OPACITY,
|
|
1838
2084
|
CENTER_POSITION: 50,
|
|
1839
2085
|
// Center position percentage (50%)
|
|
1840
2086
|
HOVER_POSITION: {
|
|
@@ -1867,8 +2113,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1867
2113
|
return 2 * this.BLACK_STOP;
|
|
1868
2114
|
},
|
|
1869
2115
|
// End percentage for black hover 1
|
|
1870
|
-
WHITE_START: .
|
|
1871
|
-
//
|
|
2116
|
+
WHITE_START: .35,
|
|
2117
|
+
// Gentler hover flash — Apple hover is barely visible
|
|
1872
2118
|
get WHITE_STOP() {
|
|
1873
2119
|
return this.BLACK_END - 10;
|
|
1874
2120
|
}
|
|
@@ -1886,8 +2132,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1886
2132
|
return 2 * this.BLACK_STOP;
|
|
1887
2133
|
},
|
|
1888
2134
|
// End percentage for black hover 2
|
|
1889
|
-
WHITE_START:
|
|
1890
|
-
//
|
|
2135
|
+
WHITE_START: .7,
|
|
2136
|
+
// Gentler hover flash
|
|
1891
2137
|
get WHITE_STOP() {
|
|
1892
2138
|
return this.BLACK_END;
|
|
1893
2139
|
}
|
|
@@ -1905,8 +2151,8 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1905
2151
|
return 2 * this.BLACK_STOP;
|
|
1906
2152
|
},
|
|
1907
2153
|
// End percentage for black hover 3
|
|
1908
|
-
WHITE_START:
|
|
1909
|
-
//
|
|
2154
|
+
WHITE_START: .7,
|
|
2155
|
+
// Gentler hover flash
|
|
1910
2156
|
get WHITE_STOP() {
|
|
1911
2157
|
return this.BLACK_END;
|
|
1912
2158
|
}
|
|
@@ -1916,13 +2162,13 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1916
2162
|
BASE_GRADIENT: {
|
|
1917
2163
|
ANGLE: 135,
|
|
1918
2164
|
// Gradient angle in degrees
|
|
1919
|
-
BLACK_START_BASE: .
|
|
2165
|
+
BLACK_START_BASE: .1,
|
|
1920
2166
|
// Base start opacity for black
|
|
1921
2167
|
get BLACK_START_MULTIPLIER() {
|
|
1922
2168
|
return .02 * this.BLACK_START_BASE;
|
|
1923
2169
|
},
|
|
1924
2170
|
// Multiplier for mouse X influence on start
|
|
1925
|
-
BLACK_MID_BASE: .
|
|
2171
|
+
BLACK_MID_BASE: .07,
|
|
1926
2172
|
// Base mid opacity for black
|
|
1927
2173
|
get BLACK_MID_MULTIPLIER() {
|
|
1928
2174
|
return .02 * this.BLACK_MID_BASE;
|
|
@@ -1943,7 +2189,7 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1943
2189
|
}
|
|
1944
2190
|
},
|
|
1945
2191
|
OVERLAY_GRADIENT: {
|
|
1946
|
-
BLACK_START_BASE: .
|
|
2192
|
+
BLACK_START_BASE: .08,
|
|
1947
2193
|
// Base start opacity for black overlay
|
|
1948
2194
|
get BLACK_START_MULTIPLIER() {
|
|
1949
2195
|
return .025 * this.BLACK_START_BASE;
|
|
@@ -1967,14 +2213,14 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1967
2213
|
return .416 * this.BLACK_START_BASE;
|
|
1968
2214
|
}
|
|
1969
2215
|
},
|
|
1970
|
-
// Overlay highlight constants
|
|
2216
|
+
// Overlay highlight constants — Apple places specular at the top-center
|
|
1971
2217
|
OVERLAY_HIGHLIGHT: {
|
|
1972
|
-
POSITION_X:
|
|
1973
|
-
//
|
|
1974
|
-
POSITION_Y:
|
|
1975
|
-
//
|
|
1976
|
-
WHITE_OPACITY: .
|
|
1977
|
-
//
|
|
2218
|
+
POSITION_X: 50,
|
|
2219
|
+
// Centered horizontal — Apple's top-center specular
|
|
2220
|
+
POSITION_Y: 5,
|
|
2221
|
+
// Very top — catches light like a curved glass surface
|
|
2222
|
+
WHITE_OPACITY: .28,
|
|
2223
|
+
// Softer specular — visible but not glaring
|
|
1978
2224
|
get STOP() {
|
|
1979
2225
|
return 150 * this.WHITE_OPACITY;
|
|
1980
2226
|
},
|
|
@@ -1995,6 +2241,10 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
1995
2241
|
SATURATION: {
|
|
1996
2242
|
HIGH_CONTRAST: 200
|
|
1997
2243
|
},
|
|
2244
|
+
// Container shadows — hairline inner catch + soft floating lift (Apple player bar)
|
|
2245
|
+
CONTAINER_SHADOW: {
|
|
2246
|
+
LIGHT: "inset 0 0.5px 0 rgba(255, 255, 255, 0.32), inset 0 1px 2px rgba(255, 255, 255, 0.06), 0 4px 16px rgba(0, 0, 0, 0.12), 0 1px 4px rgba(0, 0, 0, 0.08)"
|
|
2247
|
+
},
|
|
1998
2248
|
// Phase 1: Animation System Constants
|
|
1999
2249
|
ANIMATION: {
|
|
2000
2250
|
// Breathing effect timing (in milliseconds)
|
|
@@ -2091,135 +2341,488 @@ function useAccordion(initialProps) {
|
|
|
2091
2341
|
};
|
|
2092
2342
|
}
|
|
2093
2343
|
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$2.MOUSE_INFLUENCE_DIVISOR;
|
|
2104
|
-
return Math.min(.8, influence);
|
|
2105
|
-
// Tighter cap to prevent blur/filter blow-out
|
|
2106
|
-
}, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$2.MIN_BLUR : Math.max(CONSTANTS$2.MIN_BLUR, Math.min(50, value)), validateGlassSize = size => size && "number" == typeof size.width && "number" == typeof size.height && size.width > 0 && size.height > 0 && size.width <= CONSTANTS$2.MAX_SIZE && size.height <= CONSTANTS$2.MAX_SIZE, parseBorderRadiusValue = value => {
|
|
2107
|
-
if ("number" == typeof value) return Math.max(0, value);
|
|
2108
|
-
if ("string" != typeof value || !value.trim()) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
2109
|
-
const trimmedValue = value.trim();
|
|
2110
|
-
// Handle px values
|
|
2111
|
-
if (trimmedValue.endsWith("px")) {
|
|
2112
|
-
const parsed = parseFloat(trimmedValue);
|
|
2113
|
-
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
|
|
2114
|
-
}
|
|
2115
|
-
// Handle rem values (assume 16px = 1rem)
|
|
2116
|
-
if (trimmedValue.endsWith("rem")) {
|
|
2117
|
-
const parsed = parseFloat(trimmedValue);
|
|
2118
|
-
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
2119
|
-
}
|
|
2120
|
-
// Handle em values (assume 16px = 1em for simplicity)
|
|
2121
|
-
if (trimmedValue.endsWith("em")) {
|
|
2122
|
-
const parsed = parseFloat(trimmedValue);
|
|
2123
|
-
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
2124
|
-
}
|
|
2125
|
-
// Handle percentage (convert to approximate px value, assuming 200px container)
|
|
2126
|
-
if (trimmedValue.endsWith("%")) {
|
|
2127
|
-
const parsed = parseFloat(trimmedValue);
|
|
2128
|
-
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
|
|
2129
|
-
}
|
|
2130
|
-
// Handle unitless numbers
|
|
2131
|
-
const numValue = parseFloat(trimmedValue);
|
|
2132
|
-
return isNaN(numValue) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
|
|
2133
|
-
}, extractBorderRadiusFromElement = element => {
|
|
2134
|
-
if (!element || !element.props) return null;
|
|
2135
|
-
// Check inline styles first (highest priority)
|
|
2136
|
-
if (element.props.style) {
|
|
2137
|
-
const radiusFromStyle = (style => {
|
|
2138
|
-
if (!style) return null;
|
|
2139
|
-
// Check various border-radius properties
|
|
2140
|
-
const borderRadius = style.borderRadius || style.borderTopLeftRadius || style.borderTopRightRadius || style.borderBottomLeftRadius || style.borderBottomRightRadius;
|
|
2141
|
-
return void 0 !== borderRadius ? parseBorderRadiusValue(borderRadius) : null;
|
|
2142
|
-
})(element.props.style);
|
|
2143
|
-
if (null !== radiusFromStyle && radiusFromStyle > 0) return radiusFromStyle;
|
|
2144
|
-
}
|
|
2145
|
-
// If element has children, recursively check them
|
|
2146
|
-
if (element.props.children) {
|
|
2147
|
-
const childRadius = extractBorderRadiusFromChildren(element.props.children);
|
|
2148
|
-
if (childRadius > 0 && childRadius !== CONSTANTS$2.DEFAULT_CORNER_RADIUS) return childRadius;
|
|
2149
|
-
}
|
|
2150
|
-
return null;
|
|
2151
|
-
}, extractBorderRadiusFromChildren = children => {
|
|
2152
|
-
if (!children) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
2153
|
-
try {
|
|
2154
|
-
const childArray = React.Children.toArray(children);
|
|
2155
|
-
for (let i = 0; i < childArray.length; i++) {
|
|
2156
|
-
const child = childArray[i];
|
|
2157
|
-
if ( React.isValidElement(child)) {
|
|
2158
|
-
const radius = extractBorderRadiusFromElement(child);
|
|
2159
|
-
if (null !== radius) return radius;
|
|
2344
|
+
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) {
|
|
2345
|
+
return function(that, callbackfn, argumentsLength, memo) {
|
|
2346
|
+
var O = toObject(that), self = IndexedObject(O), length = lengthOfArrayLike(O);
|
|
2347
|
+
if (aCallable(callbackfn), 0 === length && argumentsLength < 2) throw new $TypeError(REDUCE_EMPTY);
|
|
2348
|
+
var index = IS_RIGHT ? length - 1 : 0, i = IS_RIGHT ? -1 : 1;
|
|
2349
|
+
if (argumentsLength < 2) for (;;) {
|
|
2350
|
+
if (index in self) {
|
|
2351
|
+
memo = self[index], index += i;
|
|
2352
|
+
break;
|
|
2160
2353
|
}
|
|
2354
|
+
if (index += i, IS_RIGHT ? index < 0 : length <= index) throw new $TypeError(REDUCE_EMPTY);
|
|
2161
2355
|
}
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
}
|
|
2165
|
-
return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
2166
|
-
}, smoothstep = t => {
|
|
2167
|
-
const clamped = Math.max(0, Math.min(1, t));
|
|
2168
|
-
return clamped * clamped * (3 - 2 * clamped);
|
|
2169
|
-
}, lerp$1 = (a, b, t) => a + (b - a) * t, softClamp = (value, max) => max <= 0 ? 0 : max * (1 - Math.exp(-value / max)), calculateSpring = (current, target, velocity, stiffness = .1, damping = .8) => {
|
|
2170
|
-
const newVelocity = (velocity + (target - current) * stiffness) * damping;
|
|
2171
|
-
return {
|
|
2172
|
-
value: current + newVelocity,
|
|
2173
|
-
velocity: newVelocity
|
|
2356
|
+
for (;IS_RIGHT ? index >= 0 : length > index; index += i) index in self && (memo = callbackfn(memo, self[index], index, O));
|
|
2357
|
+
return memo;
|
|
2174
2358
|
};
|
|
2175
|
-
},
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2359
|
+
}, arrayReduce = {
|
|
2360
|
+
// `Array.prototype.reduce` method
|
|
2361
|
+
// https://tc39.es/ecma262/#sec-array.prototype.reduce
|
|
2362
|
+
left: createMethod(!1),
|
|
2363
|
+
// `Array.prototype.reduceRight` method
|
|
2364
|
+
// https://tc39.es/ecma262/#sec-array.prototype.reduceright
|
|
2365
|
+
right: createMethod(!0)
|
|
2366
|
+
}, fails = fails$9, globalThis$1 = globalThis_1, userAgent = environmentUserAgent, classof = classofRaw$2, userAgentStartsWith = function(string) {
|
|
2367
|
+
return userAgent.slice(0, string.length) === string;
|
|
2368
|
+
}, 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;
|
|
2179
2369
|
|
|
2180
|
-
|
|
2181
|
-
|
|
2370
|
+
// `Array.prototype.reduce` method
|
|
2371
|
+
// https://tc39.es/ecma262/#sec-array.prototype.reduce
|
|
2372
|
+
_export({
|
|
2373
|
+
target: "Array",
|
|
2374
|
+
proto: !0,
|
|
2375
|
+
forced: !("NODE" === environment) && environmentV8Version > 79 && environmentV8Version < 83 || !function(METHOD_NAME, argument) {
|
|
2376
|
+
var method = [][METHOD_NAME];
|
|
2377
|
+
return !!method && fails((function() {
|
|
2378
|
+
// eslint-disable-next-line no-useless-call -- required for testing
|
|
2379
|
+
method.call(null, argument || function() {
|
|
2380
|
+
return 1;
|
|
2381
|
+
}, 1);
|
|
2382
|
+
}));
|
|
2383
|
+
}("reduce")
|
|
2384
|
+
}, {
|
|
2385
|
+
reduce: function(callbackfn /* , initialValue */) {
|
|
2386
|
+
var length = arguments.length;
|
|
2387
|
+
return $reduce(this, callbackfn, length, length > 1 ? arguments[1] : void 0);
|
|
2388
|
+
}
|
|
2389
|
+
});
|
|
2182
2390
|
|
|
2183
|
-
|
|
2184
|
-
return prominentDisplacementMap;
|
|
2391
|
+
var reduce$3 = getBuiltInPrototypeMethod$3("Array", "reduce"), isPrototypeOf = objectIsPrototypeOf, method = reduce$3, ArrayPrototype = Array.prototype;
|
|
2185
2392
|
|
|
2186
|
-
|
|
2187
|
-
|
|
2393
|
+
const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
2394
|
+
var own = it.reduce;
|
|
2395
|
+
return it === ArrayPrototype || isPrototypeOf(ArrayPrototype, it) && own === ArrayPrototype.reduce ? method : own;
|
|
2396
|
+
}));
|
|
2188
2397
|
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2398
|
+
/**
|
|
2399
|
+
* Map SCSS tokens to CSS custom properties
|
|
2400
|
+
*
|
|
2401
|
+
* @example
|
|
2402
|
+
* const tokens = { '$primary-color': '#7AFFD7', '$spacing-md': '16px' }
|
|
2403
|
+
* const vars = mapSCSSTokensToCSSVars(tokens)
|
|
2404
|
+
* // Returns: { '--primary-color': '#7AFFD7', '--spacing-md': '16px' }
|
|
2405
|
+
*/ function mapSCSSTokensToCSSVars(tokens, options = {}) {
|
|
2406
|
+
const vars = {}, {prefix: prefix = "atomix", separator: separator = "-"} = options;
|
|
2407
|
+
return Object.entries(tokens).forEach((([key, value]) => {
|
|
2408
|
+
// Remove $ prefix from SCSS variables
|
|
2409
|
+
const normalizedKey = (key.startsWith("$") ? key.slice(1) : key).replace(/_/g, separator);
|
|
2410
|
+
// Convert underscores to separators
|
|
2411
|
+
vars[`--${prefix}${separator}${normalizedKey}`] = String(value);
|
|
2412
|
+
})), vars;
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
/**
|
|
2416
|
+
* Apply CSS variables to an element
|
|
2417
|
+
*
|
|
2418
|
+
* @param vars - CSS variables to apply
|
|
2419
|
+
* @param element - Target element (defaults to document.documentElement)
|
|
2420
|
+
*/ function applyCSSVariables(vars, element) {
|
|
2421
|
+
if ("undefined" == typeof window) return;
|
|
2422
|
+
// SSR safety
|
|
2423
|
+
const target = element || document.documentElement;
|
|
2424
|
+
Object.entries(vars).forEach((([key, value]) => {
|
|
2425
|
+
target.style.setProperty(key, String(value));
|
|
2426
|
+
}));
|
|
2427
|
+
}
|
|
2428
|
+
|
|
2429
|
+
/**
|
|
2430
|
+
* Remove CSS variables from an element
|
|
2431
|
+
*
|
|
2432
|
+
* @param varNames - Variable names to remove
|
|
2433
|
+
* @param element - Target element (defaults to document.documentElement)
|
|
2434
|
+
*/ function removeCSSVariables(varNames, element) {
|
|
2435
|
+
if ("undefined" == typeof window) return;
|
|
2436
|
+
// SSR safety
|
|
2437
|
+
const target = element || document.documentElement;
|
|
2438
|
+
varNames.forEach((varName => {
|
|
2439
|
+
target.style.removeProperty(varName);
|
|
2440
|
+
}));
|
|
2441
|
+
}
|
|
2442
|
+
|
|
2443
|
+
/**
|
|
2444
|
+
* Get CSS variable value from an element
|
|
2445
|
+
*
|
|
2446
|
+
* @param varName - Variable name to get
|
|
2447
|
+
* @param element - Target element (defaults to document.documentElement)
|
|
2448
|
+
* @returns Variable value or null if not found
|
|
2449
|
+
*/ function getCSSVariable(varName, element) {
|
|
2450
|
+
if ("undefined" == typeof window) return null;
|
|
2451
|
+
// SSR safety
|
|
2452
|
+
const target = element || document.documentElement;
|
|
2453
|
+
return getComputedStyle(target).getPropertyValue(varName).trim() || null;
|
|
2454
|
+
}
|
|
2455
|
+
|
|
2456
|
+
/**
|
|
2457
|
+
* Convert CSS variable object to inline style object
|
|
2458
|
+
*
|
|
2459
|
+
* @example
|
|
2460
|
+
* const vars = { '--atomix-button-bg': '#000' }
|
|
2461
|
+
* const style = cssVarsToStyle(vars)
|
|
2462
|
+
* // Returns: { '--atomix-button-bg': '#000' } as React.CSSProperties
|
|
2463
|
+
*/ function cssVarsToStyle(vars) {
|
|
2464
|
+
var _context;
|
|
2465
|
+
return _reduceInstanceProperty(_context = Object.entries(vars)).call(_context, ((acc, [key, value]) => (acc[key] = "number" == typeof value ? `${value}px` : value,
|
|
2466
|
+
acc)), {});
|
|
2467
|
+
}
|
|
2468
|
+
|
|
2469
|
+
/**
|
|
2470
|
+
* Merge multiple CSS variable objects
|
|
2471
|
+
* Later objects override earlier ones
|
|
2472
|
+
*/ function mergeCSSVars(...varObjects) {
|
|
2473
|
+
return _reduceInstanceProperty(varObjects).call(varObjects, ((acc, vars) => (vars && Object.assign(acc, vars),
|
|
2474
|
+
acc)), {});
|
|
2475
|
+
}
|
|
2476
|
+
|
|
2477
|
+
/**
|
|
2478
|
+
* Validate CSS variable name format
|
|
2479
|
+
*/ function isValidCSSVariableName(name) {
|
|
2480
|
+
return /^--[a-z0-9-]+$/.test(name);
|
|
2481
|
+
}
|
|
2482
|
+
|
|
2483
|
+
/**
|
|
2484
|
+
* Extract component name from CSS variable name
|
|
2485
|
+
*
|
|
2486
|
+
* @example
|
|
2487
|
+
* extractComponentName('--atomix-button-bg')
|
|
2488
|
+
* // Returns: 'button'
|
|
2489
|
+
*/ function extractComponentName(varName, prefix = "atomix") {
|
|
2490
|
+
const regex = new RegExp(`^--${prefix}-([a-z0-9]+)-`), match = varName.match(regex);
|
|
2491
|
+
return match ? match[1] ?? null : null;
|
|
2492
|
+
}
|
|
2493
|
+
|
|
2494
|
+
/**
|
|
2495
|
+
* Component Utilities
|
|
2496
|
+
*
|
|
2497
|
+
* Helper functions for component development with the new customization system
|
|
2498
|
+
*/
|
|
2499
|
+
/**
|
|
2500
|
+
* Merge multiple class names
|
|
2501
|
+
*/ function mergeClassNames(...classes) {
|
|
2502
|
+
return classes.filter(Boolean).join(" ");
|
|
2503
|
+
}
|
|
2504
|
+
|
|
2505
|
+
/**
|
|
2506
|
+
* Apply part styles to element props
|
|
2507
|
+
*/ function applyPartStyles(baseProps, partStyles) {
|
|
2508
|
+
return partStyles ? {
|
|
2509
|
+
...baseProps,
|
|
2510
|
+
className: mergeClassNames(baseProps.className, partStyles.className),
|
|
2511
|
+
style: {
|
|
2512
|
+
...baseProps.style,
|
|
2513
|
+
...partStyles.style
|
|
2514
|
+
}
|
|
2515
|
+
} : baseProps;
|
|
2516
|
+
}
|
|
2517
|
+
|
|
2518
|
+
/**
|
|
2519
|
+
* Create style object from CSS variables
|
|
2520
|
+
*/ function createCSSVarStyle(cssVars, baseStyle) {
|
|
2521
|
+
return cssVars ? {
|
|
2522
|
+
...cssVarsToStyle(cssVars),
|
|
2523
|
+
...baseStyle
|
|
2524
|
+
} : baseStyle || {};
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2527
|
+
function mergeComponentProps(baseProps, customization) {
|
|
2528
|
+
const {className: className, style: style, cssVars: cssVars, parts: parts} = customization, cssVarStyle = cssVars ? cssVarsToStyle(cssVars) : {};
|
|
2529
|
+
// Merge CSS variables into style
|
|
2530
|
+
return {
|
|
2531
|
+
...baseProps,
|
|
2532
|
+
className: mergeClassNames(baseProps.className, className),
|
|
2533
|
+
style: {
|
|
2534
|
+
...cssVarStyle,
|
|
2535
|
+
...baseProps.style,
|
|
2536
|
+
...style
|
|
2537
|
+
}
|
|
2538
|
+
};
|
|
2539
|
+
}
|
|
2540
|
+
|
|
2541
|
+
/**
|
|
2542
|
+
* Get part styles from parts object
|
|
2543
|
+
*/ function getPartStyles(parts, partName) {
|
|
2544
|
+
return parts?.[partName];
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
/**
|
|
2548
|
+
* Create element props with part styles
|
|
2549
|
+
*/ function createPartProps(baseClassName, partStyles, additionalProps) {
|
|
2550
|
+
return {
|
|
2551
|
+
...additionalProps,
|
|
2552
|
+
className: mergeClassNames(baseClassName, partStyles?.className),
|
|
2553
|
+
style: {
|
|
2554
|
+
...partStyles?.style,
|
|
2555
|
+
...additionalProps?.style
|
|
2556
|
+
}
|
|
2557
|
+
};
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2560
|
+
/**
|
|
2561
|
+
* Check if component has customization
|
|
2562
|
+
*/ function hasCustomization(props) {
|
|
2563
|
+
return Boolean(props.parts || props.cssVars || props.slots);
|
|
2564
|
+
}
|
|
2565
|
+
|
|
2566
|
+
/**
|
|
2567
|
+
* Create data attributes for debugging
|
|
2568
|
+
*/ function createDebugAttrs(componentName, variant) {
|
|
2569
|
+
return "undefined" == typeof process || "development" !== process.env?.NODE_ENV ? {} : {
|
|
2570
|
+
"data-component": componentName,
|
|
2571
|
+
...variant && {
|
|
2572
|
+
"data-variant": variant
|
|
2573
|
+
}
|
|
2574
|
+
};
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2577
|
+
/**
|
|
2578
|
+
* Generate a UUID v4
|
|
2579
|
+
*/ function generateUUID() {
|
|
2580
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c => {
|
|
2581
|
+
const r = 16 * Math.random() | 0;
|
|
2582
|
+
return ("x" === c ? r : 3 & r | 8).toString(16);
|
|
2583
|
+
}));
|
|
2584
|
+
}
|
|
2585
|
+
|
|
2586
|
+
/**
|
|
2587
|
+
* Check if a URL is a YouTube URL
|
|
2588
|
+
*/ function isYouTubeUrl(url) {
|
|
2589
|
+
return /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/.+/.test(url);
|
|
2590
|
+
}
|
|
2591
|
+
|
|
2592
|
+
/**
|
|
2593
|
+
* Extract YouTube video ID from URL
|
|
2594
|
+
*/ function extractYouTubeId(url) {
|
|
2595
|
+
if (!isYouTubeUrl(url)) return null;
|
|
2596
|
+
const patterns = [ /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/, /youtube\.com\/.*[?&]v=([^&\n?#]+)/ ];
|
|
2597
|
+
for (const pattern of patterns) {
|
|
2598
|
+
const match = url.match(pattern);
|
|
2599
|
+
if (match && match[1]) return match[1];
|
|
2600
|
+
}
|
|
2601
|
+
return null;
|
|
2602
|
+
}
|
|
2603
|
+
|
|
2604
|
+
/**
|
|
2605
|
+
* Utility to merge multiple React refs into one
|
|
2606
|
+
*/ function setRef(ref, value) {
|
|
2607
|
+
"function" == typeof ref ? ref(value) : ref && (
|
|
2608
|
+
// This is safe because we're checking that ref exists first
|
|
2609
|
+
ref.current = value);
|
|
2610
|
+
}
|
|
2611
|
+
|
|
2612
|
+
/**
|
|
2613
|
+
* Combines two React refs into a single ref function
|
|
2614
|
+
* This is used when you need to use and forward a ref at the same time
|
|
2615
|
+
*/ function useForkRef(refA, refB) {
|
|
2616
|
+
return React.useMemo((() => null == refA && null == refB ? null : refValue => {
|
|
2617
|
+
setRef(refA, refValue), setRef(refB, refValue);
|
|
2618
|
+
}), [ refA, refB ]);
|
|
2619
|
+
}
|
|
2620
|
+
|
|
2621
|
+
const {CONSTANTS: CONSTANTS$3} = ATOMIX_GLASS, calculateElementCenter = rect => rect ? {
|
|
2622
|
+
x: rect.left + rect.width / 2,
|
|
2623
|
+
y: rect.top + rect.height / 2
|
|
2624
|
+
} : {
|
|
2625
|
+
x: 0,
|
|
2626
|
+
y: 0
|
|
2627
|
+
}, calculateMouseInfluence = mouseOffset => {
|
|
2628
|
+
if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
|
|
2629
|
+
// Clamp influence to keep mouse response subtle and stable.
|
|
2630
|
+
const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$3.MOUSE_INFLUENCE_DIVISOR;
|
|
2631
|
+
return Math.min(.8, influence);
|
|
2632
|
+
// Tighter cap to prevent blur/filter blow-out
|
|
2633
|
+
}, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$3.MIN_BLUR : Math.max(CONSTANTS$3.MIN_BLUR, Math.min(50, value)), validateGlassSize = size => size && "number" == typeof size.width && "number" == typeof size.height && size.width > 0 && size.height > 0 && size.width <= CONSTANTS$3.MAX_SIZE && size.height <= CONSTANTS$3.MAX_SIZE, parseBorderRadiusValue = value => {
|
|
2634
|
+
if ("number" == typeof value) return Math.max(0, value);
|
|
2635
|
+
if ("string" != typeof value || !value.trim()) return CONSTANTS$3.DEFAULT_CORNER_RADIUS;
|
|
2636
|
+
const trimmedValue = value.trim();
|
|
2637
|
+
// Handle px values
|
|
2638
|
+
if (trimmedValue.endsWith("px")) {
|
|
2639
|
+
const parsed = parseFloat(trimmedValue);
|
|
2640
|
+
return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
|
|
2641
|
+
}
|
|
2642
|
+
// Handle rem values (assume 16px = 1rem)
|
|
2643
|
+
if (trimmedValue.endsWith("rem")) {
|
|
2644
|
+
const parsed = parseFloat(trimmedValue);
|
|
2645
|
+
return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
2646
|
+
}
|
|
2647
|
+
// Handle em values (assume 16px = 1em for simplicity)
|
|
2648
|
+
if (trimmedValue.endsWith("em")) {
|
|
2649
|
+
const parsed = parseFloat(trimmedValue);
|
|
2650
|
+
return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
2651
|
+
}
|
|
2652
|
+
// Handle percentage (convert to approximate px value, assuming 200px container)
|
|
2653
|
+
if (trimmedValue.endsWith("%")) {
|
|
2654
|
+
const parsed = parseFloat(trimmedValue);
|
|
2655
|
+
return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
|
|
2656
|
+
}
|
|
2657
|
+
// Handle unitless numbers
|
|
2658
|
+
const numValue = parseFloat(trimmedValue);
|
|
2659
|
+
return isNaN(numValue) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
|
|
2660
|
+
}, extractBorderRadiusFromElement = element => {
|
|
2661
|
+
if (!element || !element.props) return null;
|
|
2662
|
+
// Check inline styles first (highest priority)
|
|
2663
|
+
if (element.props.style) {
|
|
2664
|
+
const radiusFromStyle = (style => {
|
|
2665
|
+
if (!style) return null;
|
|
2666
|
+
// Check various border-radius properties
|
|
2667
|
+
const borderRadius = style.borderRadius || style.borderTopLeftRadius || style.borderTopRightRadius || style.borderBottomLeftRadius || style.borderBottomRightRadius;
|
|
2668
|
+
return void 0 !== borderRadius ? parseBorderRadiusValue(borderRadius) : null;
|
|
2669
|
+
})(element.props.style);
|
|
2670
|
+
if (null !== radiusFromStyle && radiusFromStyle > 0) return radiusFromStyle;
|
|
2671
|
+
}
|
|
2672
|
+
// If element has children, recursively check them
|
|
2673
|
+
if (element.props.children) {
|
|
2674
|
+
const childRadius = extractBorderRadiusFromChildren(element.props.children);
|
|
2675
|
+
if (childRadius > 0 && childRadius !== CONSTANTS$3.DEFAULT_CORNER_RADIUS) return childRadius;
|
|
2676
|
+
}
|
|
2677
|
+
return null;
|
|
2678
|
+
}, extractBorderRadiusFromChildren = children => {
|
|
2679
|
+
if (!children) return CONSTANTS$3.DEFAULT_CORNER_RADIUS;
|
|
2680
|
+
try {
|
|
2681
|
+
const childArray = React.Children.toArray(children);
|
|
2682
|
+
for (let i = 0; i < childArray.length; i++) {
|
|
2683
|
+
const child = childArray[i];
|
|
2684
|
+
if ( React.isValidElement(child)) {
|
|
2685
|
+
const radius = extractBorderRadiusFromElement(child);
|
|
2686
|
+
if (null !== radius) return radius;
|
|
2687
|
+
}
|
|
2688
|
+
}
|
|
2689
|
+
} catch (error) {
|
|
2690
|
+
// Silently handle errors
|
|
2691
|
+
}
|
|
2692
|
+
return CONSTANTS$3.DEFAULT_CORNER_RADIUS;
|
|
2693
|
+
}, smoothstep = t => {
|
|
2694
|
+
const clamped = Math.max(0, Math.min(1, t));
|
|
2695
|
+
return clamped * clamped * (3 - 2 * clamped);
|
|
2696
|
+
}, lerp = (a, b, t) => a + (b - a) * t, softClamp = (value, max) => max <= 0 ? 0 : max * (1 - Math.exp(-value / max)), clamp = (value, min, max) => "number" != typeof value || isNaN(value) ? min : Math.max(min, Math.min(max, value)), smoothstepEdge = (edge0, edge1, x) => "number" != typeof edge0 || "number" != typeof edge1 || "number" != typeof x ? 0 : smoothstep((x - edge0) / (edge1 - edge0)), easeInOutCubic = t => {
|
|
2697
|
+
if ("number" != typeof t || isNaN(t)) return 0;
|
|
2698
|
+
const clamped = Math.max(0, Math.min(1, t));
|
|
2699
|
+
return clamped < .5 ? 4 * clamped * clamped * clamped : 1 - Math.pow(-2 * clamped + 2, 3) / 2;
|
|
2700
|
+
}, easeOutQuart = t => {
|
|
2701
|
+
if ("number" != typeof t || isNaN(t)) return 0;
|
|
2702
|
+
const clamped = Math.max(0, Math.min(1, t));
|
|
2703
|
+
return 1 - Math.pow(1 - clamped, 4);
|
|
2704
|
+
}, vec2Length = (x, y) => {
|
|
2705
|
+
if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
|
|
2706
|
+
const maxComponent = Math.max(Math.abs(x), Math.abs(y));
|
|
2707
|
+
if (0 === maxComponent) return 0;
|
|
2708
|
+
const scaledX = x / maxComponent, scaledY = y / maxComponent;
|
|
2709
|
+
return maxComponent * Math.sqrt(scaledX * scaledX + scaledY * scaledY);
|
|
2710
|
+
}, getInteractionIntensity = (isHovered, isActive) => ({
|
|
2711
|
+
hoverIntensity: isHovered ? CONSTANTS$3.INTERACTION.HOVER_INTENSITY : 1,
|
|
2712
|
+
activeIntensity: isActive ? CONSTANTS$3.INTERACTION.ACTIVE_INTENSITY : 1
|
|
2713
|
+
})
|
|
2714
|
+
/**
|
|
2715
|
+
* Spring-damper integration helper
|
|
2716
|
+
* Calculates the next value based on velocity, stiffness, and damping.
|
|
2717
|
+
*/ , calculateSpring = (current, target, velocity, stiffness = .1, damping = .8) => {
|
|
2718
|
+
const newVelocity = (velocity + (target - current) * stiffness) * damping;
|
|
2719
|
+
return {
|
|
2720
|
+
value: current + newVelocity,
|
|
2721
|
+
velocity: newVelocity
|
|
2722
|
+
};
|
|
2723
|
+
};
|
|
2724
|
+
|
|
2725
|
+
/**
|
|
2726
|
+
* Calculate element center from bounding rect
|
|
2727
|
+
*/
|
|
2728
|
+
/**
|
|
2729
|
+
* Normalizes a layout inset for use in CSS custom properties.
|
|
2730
|
+
*
|
|
2731
|
+
* @param value - Raw inset from `style` (number, px string, or `auto`).
|
|
2732
|
+
* @param fallback - Value used when `value` is undefined.
|
|
2733
|
+
*/
|
|
2734
|
+
function formatGlassInsetValue(value, fallback = "auto") {
|
|
2735
|
+
return void 0 === value ? "number" == typeof fallback ? `${fallback}px` : String(fallback) : "auto" === value ? "auto" : "number" == typeof value ? `${value}px` : value;
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2738
|
+
/**
|
|
2739
|
+
* Determines whether the glass should use fixed/sticky layout semantics.
|
|
2740
|
+
*
|
|
2741
|
+
* @param explicit - Value of the `isFixedOrSticky` prop.
|
|
2742
|
+
* @param position - `position` from the consumer `style` object.
|
|
2743
|
+
*/
|
|
2744
|
+
/** Coerces a value to a finite number, returning `fallback` when invalid. */
|
|
2745
|
+
function toSafeNumber(value, fallback = 0) {
|
|
2746
|
+
return "number" != typeof value || isNaN(value) ? fallback : value;
|
|
2747
|
+
}
|
|
2748
|
+
|
|
2749
|
+
/**
|
|
2750
|
+
* Calculates the target frame rate for shader time-animation loops.
|
|
2751
|
+
*
|
|
2752
|
+
* Balances visual quality against distortion complexity and `animationSpeed`.
|
|
2753
|
+
*/
|
|
2754
|
+
/**
|
|
2755
|
+
* Computes per-channel displacement scale for the SVG chromatic-aberration filter.
|
|
2756
|
+
*/
|
|
2757
|
+
function getChromaticDisplacementScale(mode, displacementScale, aberrationIntensity, channelFactor) {
|
|
2758
|
+
return displacementScale * (("shader" === mode ? 1 : -1) - aberrationIntensity * channelFactor);
|
|
2759
|
+
}
|
|
2760
|
+
|
|
2761
|
+
/**
|
|
2762
|
+
* Get displacement map URL based on mode
|
|
2763
|
+
*/ const getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
|
|
2764
|
+
switch (mode) {
|
|
2765
|
+
case "standard":
|
|
2766
|
+
return displacementMap;
|
|
2767
|
+
|
|
2768
|
+
case "polar":
|
|
2769
|
+
return polarDisplacementMap;
|
|
2770
|
+
|
|
2771
|
+
case "prominent":
|
|
2772
|
+
return prominentDisplacementMap;
|
|
2773
|
+
|
|
2774
|
+
case "shader":
|
|
2775
|
+
return shaderMapUrl || displacementMap;
|
|
2776
|
+
|
|
2777
|
+
default:
|
|
2778
|
+
return console.warn("AtomixGlass: Invalid displacement mode"), displacementMap;
|
|
2779
|
+
}
|
|
2780
|
+
}, sharedShaderCache = new Map, CHROMATIC_CHANNELS = [ {
|
|
2781
|
+
result: "RED_DISPLACED",
|
|
2782
|
+
channelResult: "RED_CHANNEL",
|
|
2783
|
+
aberrationFactor: 0,
|
|
2784
|
+
colorMatrix: "1 0 0 0 0\n0 0 0 0 0\n0 0 0 0 0\n0 0 0 1 0"
|
|
2785
|
+
}, {
|
|
2786
|
+
result: "GREEN_DISPLACED",
|
|
2787
|
+
channelResult: "GREEN_CHANNEL",
|
|
2788
|
+
aberrationFactor: .02,
|
|
2789
|
+
colorMatrix: "0 0 0 0 0\n0 1 0 0 0\n0 0 0 0 0\n0 0 0 1 0"
|
|
2790
|
+
}, {
|
|
2791
|
+
result: "BLUE_DISPLACED",
|
|
2792
|
+
channelResult: "BLUE_CHANNEL",
|
|
2793
|
+
aberrationFactor: .03,
|
|
2794
|
+
colorMatrix: "0 0 0 0 0\n0 0 0 0 0\n0 0 1 0 0\n0 0 0 1 0"
|
|
2795
|
+
} ], FILTER_SVG_STYLE = {
|
|
2796
|
+
position: "absolute",
|
|
2797
|
+
width: "100%",
|
|
2798
|
+
height: "100%",
|
|
2799
|
+
inset: 0
|
|
2800
|
+
}, GlassFilterComponent = ({id: id, displacementScale: displacementScale, aberrationIntensity: aberrationIntensity, mode: mode, shaderMapUrl: shaderMapUrl, blurAmount: blurAmount}) => jsx("svg", {
|
|
2801
|
+
style: FILTER_SVG_STYLE,
|
|
2802
|
+
"aria-hidden": "true",
|
|
2803
|
+
children: jsxs("defs", {
|
|
2804
|
+
children: [ jsxs("radialGradient", {
|
|
2805
|
+
id: `${id}-edge-mask`,
|
|
2806
|
+
cx: "50%",
|
|
2807
|
+
cy: "50%",
|
|
2808
|
+
r: "50%",
|
|
2809
|
+
children: [ jsx("stop", {
|
|
2810
|
+
offset: "0%",
|
|
2811
|
+
stopColor: "black",
|
|
2812
|
+
stopOpacity: "0"
|
|
2813
|
+
}), jsx("stop", {
|
|
2814
|
+
offset: `${Math.max(30, 80 - 2 * aberrationIntensity)}%`,
|
|
2815
|
+
stopColor: "black",
|
|
2816
|
+
stopOpacity: "0"
|
|
2817
|
+
}), jsx("stop", {
|
|
2818
|
+
offset: "100%",
|
|
2819
|
+
stopColor: "white",
|
|
2820
|
+
stopOpacity: "1"
|
|
2821
|
+
}) ]
|
|
2822
|
+
}), jsxs("filter", {
|
|
2823
|
+
id: id,
|
|
2824
|
+
x: "-35%",
|
|
2825
|
+
y: "-35%",
|
|
2223
2826
|
width: "170%",
|
|
2224
2827
|
height: "170%",
|
|
2225
2828
|
colorInterpolationFilters: "sRGB",
|
|
@@ -2249,43 +2852,21 @@ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateElementCenter = rect =>
|
|
|
2249
2852
|
dx: "0",
|
|
2250
2853
|
dy: "0",
|
|
2251
2854
|
result: "CENTER_ORIGINAL"
|
|
2252
|
-
}),
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
scale: displacementScale * (("shader" === mode ? 1 : -1) - .02 * aberrationIntensity),
|
|
2268
|
-
xChannelSelector: "R",
|
|
2269
|
-
yChannelSelector: "B",
|
|
2270
|
-
result: "GREEN_DISPLACED"
|
|
2271
|
-
}), jsx("feColorMatrix", {
|
|
2272
|
-
in: "GREEN_DISPLACED",
|
|
2273
|
-
type: "matrix",
|
|
2274
|
-
values: "0 0 0 0 0\n 0 1 0 0 0\n 0 0 0 0 0\n 0 0 0 1 0",
|
|
2275
|
-
result: "GREEN_CHANNEL"
|
|
2276
|
-
}), jsx("feDisplacementMap", {
|
|
2277
|
-
in: "SourceGraphic",
|
|
2278
|
-
in2: "DISPLACEMENT_MAP",
|
|
2279
|
-
scale: displacementScale * (("shader" === mode ? 1 : -1) - .03 * aberrationIntensity),
|
|
2280
|
-
xChannelSelector: "R",
|
|
2281
|
-
yChannelSelector: "B",
|
|
2282
|
-
result: "BLUE_DISPLACED"
|
|
2283
|
-
}), jsx("feColorMatrix", {
|
|
2284
|
-
in: "BLUE_DISPLACED",
|
|
2285
|
-
type: "matrix",
|
|
2286
|
-
values: "0 0 0 0 0\n 0 0 0 0 0\n 0 0 1 0 0\n 0 0 0 1 0",
|
|
2287
|
-
result: "BLUE_CHANNEL"
|
|
2288
|
-
}), jsx("feBlend", {
|
|
2855
|
+
}), CHROMATIC_CHANNELS.map((channel => jsxs(React.Fragment, {
|
|
2856
|
+
children: [ jsx("feDisplacementMap", {
|
|
2857
|
+
in: "SourceGraphic",
|
|
2858
|
+
in2: "DISPLACEMENT_MAP",
|
|
2859
|
+
scale: getChromaticDisplacementScale(mode, displacementScale, aberrationIntensity, channel.aberrationFactor),
|
|
2860
|
+
xChannelSelector: "R",
|
|
2861
|
+
yChannelSelector: "B",
|
|
2862
|
+
result: channel.result
|
|
2863
|
+
}), jsx("feColorMatrix", {
|
|
2864
|
+
in: channel.result,
|
|
2865
|
+
type: "matrix",
|
|
2866
|
+
values: channel.colorMatrix,
|
|
2867
|
+
result: channel.channelResult
|
|
2868
|
+
}) ]
|
|
2869
|
+
}, channel.channelResult))), jsx("feBlend", {
|
|
2289
2870
|
in: "GREEN_CHANNEL",
|
|
2290
2871
|
in2: "BLUE_CHANNEL",
|
|
2291
2872
|
mode: "screen",
|
|
@@ -2326,21 +2907,22 @@ const {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateElementCenter = rect =>
|
|
|
2326
2907
|
});
|
|
2327
2908
|
|
|
2328
2909
|
/**
|
|
2329
|
-
*
|
|
2910
|
+
* Module-level LRU cache for shader displacement maps.
|
|
2911
|
+
*
|
|
2912
|
+
* Shared across all `AtomixGlassContainer` instances so identical size and
|
|
2913
|
+
* variant combinations are generated once.
|
|
2330
2914
|
*/ GlassFilterComponent.displayName = "GlassFilter";
|
|
2331
2915
|
|
|
2332
|
-
|
|
2916
|
+
/** Shallow prop comparison to avoid redundant SVG filter regeneration. */
|
|
2333
2917
|
const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevProps.id === nextProps.id && prevProps.displacementScale === nextProps.displacementScale && prevProps.aberrationIntensity === nextProps.aberrationIntensity && prevProps.mode === nextProps.mode && prevProps.shaderMapUrl === nextProps.shaderMapUrl && prevProps.blurAmount === nextProps.blurAmount)), AtomixGlassContainer = forwardRef((({children: children, className: className = "", style: style, displacementScale: displacementScale = 25, blurAmount: blurAmount = .0625, saturation: saturation = 180, aberrationIntensity: aberrationIntensity = 2, mouseOffset: mouseOffset = {
|
|
2334
2918
|
x: 0,
|
|
2335
2919
|
y: 0
|
|
2336
|
-
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0,
|
|
2920
|
+
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0, glassSize: glassSize = {
|
|
2337
2921
|
width: 0,
|
|
2338
2922
|
height: 0
|
|
2339
|
-
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, isFixedOrSticky: isFixedOrSticky = !1,
|
|
2340
|
-
// Phase 1: Animation System props
|
|
2341
|
-
shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", contentRef: contentRef}, ref) => {
|
|
2923
|
+
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, isFixedOrSticky: isFixedOrSticky = !1, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", contentRef: contentRef}, ref) => {
|
|
2342
2924
|
// React 18 useId — stable, unique, and SSR-safe (no module-level counter)
|
|
2343
|
-
const rawId = useId(), filterId = useMemo((() => `atomix-glass-filter-${rawId.replace(/:/g, "")}`), [ rawId ]), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null), shaderUpdateTimeoutRef = useRef(null), animationFrameRef = useRef(null);
|
|
2925
|
+
const rawId = useId(), filterId = useMemo((() => `atomix-glass-filter-${rawId.replace(/:/g, "")}`), [ rawId ]), containerRef = useForkRef(ref, null), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null), shaderUpdateTimeoutRef = useRef(null), animationFrameRef = useRef(null);
|
|
2344
2926
|
// Lazy load shader utilities only when shader mode is needed
|
|
2345
2927
|
useEffect((() => {
|
|
2346
2928
|
"shader" === mode ?
|
|
@@ -2418,15 +3000,23 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
2418
3000
|
shaderGeneratorRef.current = null;
|
|
2419
3001
|
}
|
|
2420
3002
|
};
|
|
2421
|
-
}), [ mode, glassSize, shaderVariant ]),
|
|
2422
|
-
// Phase 1: Time-Based Animation Loop - Continuous shader regeneration
|
|
2423
|
-
useEffect((() => {
|
|
3003
|
+
}), [ mode, glassSize, shaderVariant ]), useEffect((() => {
|
|
2424
3004
|
// Only run animations in shader mode with time animation enabled
|
|
2425
3005
|
if ("shader" !== mode || !withTimeAnimation || effectiveReducedMotion || effectiveWithoutEffects)
|
|
2426
3006
|
// Cancel any existing animation frame
|
|
2427
3007
|
return void (null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
|
|
2428
3008
|
animationFrameRef.current = null));
|
|
2429
|
-
const
|
|
3009
|
+
const targetFps = function(options) {
|
|
3010
|
+
const {distortionQuality: distortionQuality, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5} = options, baseFps = "ultra" === distortionQuality ? 60 : "high" === distortionQuality ? 30 : "medium" === distortionQuality ? 24 : 20, effectiveSpeed = Math.max(.5, Math.min(2, animationSpeed)), complexity = withMultiLayerDistortion ? Math.max(1, distortionOctaves / 3 + .25 * Math.max(0, distortionLacunarity - 2) + Math.max(0, distortionGain - .5)) : 1;
|
|
3011
|
+
return Math.max(12, Math.min(60, Math.round(baseFps * effectiveSpeed / complexity)));
|
|
3012
|
+
}({
|
|
3013
|
+
distortionQuality: distortionQuality,
|
|
3014
|
+
animationSpeed: animationSpeed,
|
|
3015
|
+
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
3016
|
+
distortionOctaves: distortionOctaves,
|
|
3017
|
+
distortionLacunarity: distortionLacunarity,
|
|
3018
|
+
distortionGain: distortionGain
|
|
3019
|
+
}), frameInterval = 1e3 / targetFps;
|
|
2430
3020
|
let lastUpdate = 0, isCancelled = !1;
|
|
2431
3021
|
const animate = currentTime => {
|
|
2432
3022
|
if (!isCancelled) {
|
|
@@ -2450,88 +3040,21 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
2450
3040
|
};
|
|
2451
3041
|
}), [ mode, withTimeAnimation, animationSpeed, displacementScale, withMultiLayerDistortion, distortionOctaves, distortionLacunarity, distortionGain, distortionQuality, effectiveReducedMotion, effectiveWithoutEffects, glassSize ]);
|
|
2452
3042
|
// Removed forced reflow to avoid layout thrash and potential feedback sizing loops
|
|
2453
|
-
const
|
|
2454
|
-
useEffect((() => {
|
|
2455
|
-
if (!ref || "function" == typeof ref) return;
|
|
2456
|
-
const element = ref.current;
|
|
2457
|
-
if (element) try {
|
|
2458
|
-
setRectCache(element.getBoundingClientRect());
|
|
2459
|
-
} catch (error) {
|
|
2460
|
-
console.warn("AtomixGlassContainer: Error getting element bounds", error), setRectCache(null);
|
|
2461
|
-
}
|
|
2462
|
-
}), [ ref, glassSize ]);
|
|
2463
|
-
const liquidBlur = useMemo((() => {
|
|
2464
|
-
const defaultBlur = {
|
|
2465
|
-
baseBlur: blurAmount,
|
|
2466
|
-
edgeBlur: 1.25 * blurAmount,
|
|
2467
|
-
centerBlur: 1.1 * blurAmount,
|
|
2468
|
-
flowBlur: 1.2 * blurAmount
|
|
2469
|
-
};
|
|
2470
|
-
// Enhanced validation for liquid blur
|
|
2471
|
-
if (!withLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
|
|
2472
|
-
try {
|
|
2473
|
-
const mouseInfluence = calculateMouseInfluence(mouseOffset), maxBlur = 2 * blurAmount, baseBlur = Math.min(maxBlur, blurAmount + mouseInfluence * blurAmount * .15), edgeIntensity = .15 * mouseInfluence, edgeBlur = Math.min(maxBlur, baseBlur * (.8 + .4 * edgeIntensity)), centerIntensity = .1 * mouseInfluence, centerBlur = Math.min(maxBlur, baseBlur * (.3 + .3 * centerIntensity)), flowBlur = Math.min(maxBlur, 1.2 * baseBlur);
|
|
2474
|
-
// NOTE: hover/active multipliers intentionally omitted here —
|
|
2475
|
-
// they belong on opacity layers, not the blur filter itself.
|
|
2476
|
-
return {
|
|
2477
|
-
baseBlur: clampBlur(baseBlur),
|
|
2478
|
-
edgeBlur: clampBlur(edgeBlur),
|
|
2479
|
-
centerBlur: clampBlur(centerBlur),
|
|
2480
|
-
flowBlur: clampBlur(flowBlur)
|
|
2481
|
-
};
|
|
2482
|
-
} catch (error) {
|
|
2483
|
-
return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
|
|
2484
|
-
defaultBlur;
|
|
2485
|
-
}
|
|
2486
|
-
}), [ withLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
|
|
2487
|
-
try {
|
|
2488
|
-
const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), validatedBaseBlur = "number" != typeof liquidBlur.baseBlur || isNaN(liquidBlur.baseBlur) ? 0 : liquidBlur.baseBlur, validatedEdgeBlur = "number" != typeof liquidBlur.edgeBlur || isNaN(liquidBlur.edgeBlur) ? 0 : liquidBlur.edgeBlur, validatedCenterBlur = "number" != typeof liquidBlur.centerBlur || isNaN(liquidBlur.centerBlur) ? 0 : liquidBlur.centerBlur, validatedFlowBlur = "number" != typeof liquidBlur.flowBlur || isNaN(liquidBlur.flowBlur) ? 0 : liquidBlur.flowBlur, area = rectCache ? rectCache.width * rectCache.height : 0;
|
|
2489
|
-
// Validate blur values before using them
|
|
2490
|
-
return !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? {
|
|
2491
|
-
backdropFilter: `blur(${clampBlur(Math.max(validatedBaseBlur, .8 * validatedEdgeBlur, 1.1 * validatedCenterBlur, .9 * validatedFlowBlur))}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1.05}) brightness(${overLightConfig?.brightness || 1.05})`
|
|
2492
|
-
} : {
|
|
2493
|
-
backdropFilter: `blur(${clampBlur(.4 * validatedBaseBlur + .25 * validatedEdgeBlur + .15 * validatedCenterBlur + .2 * validatedFlowBlur)}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1}) brightness(${overLightConfig?.brightness || 1})`
|
|
2494
|
-
};
|
|
2495
|
-
// Single-pass fallback: stronger radius to match perceived blur of multi-pass
|
|
2496
|
-
} catch (error) {
|
|
2497
|
-
return console.warn("AtomixGlassContainer: Error calculating backdrop style", error),
|
|
2498
|
-
{
|
|
2499
|
-
backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
|
|
2500
|
-
};
|
|
2501
|
-
}
|
|
2502
|
-
}), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur, overLightConfig ]), containerVars = useMemo((() => {
|
|
3043
|
+
const containerVars = useMemo((() => {
|
|
2503
3044
|
try {
|
|
2504
|
-
// Safe extraction of mouse offset values
|
|
2505
|
-
const mx = mouseOffset && "number" == typeof mouseOffset.x && !isNaN(mouseOffset.x) ? mouseOffset.x : 0, my = mouseOffset && "number" == typeof mouseOffset.y && !isNaN(mouseOffset.y) ? mouseOffset.y : 0;
|
|
2506
3045
|
return {
|
|
2507
|
-
"--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px
|
|
2508
|
-
"--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
|
|
2509
|
-
"--atomix-glass-container-shadow": overLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.4 + .002 * mx) * (overLightConfig?.shadowIntensity || 1)})`, `inset 0 -1px 0 rgba(0, 0, 0, ${(.2 + .001 * Math.abs(my)) * (overLightConfig?.shadowIntensity || 1)})`, `inset 0 0 20px rgba(0, 0, 0, ${(.08 + .001 * Math.abs(mx + my)) * (overLightConfig?.shadowIntensity || 1)})`, `0 2px 12px rgba(0, 0, 0, ${(.12 + .002 * Math.abs(my)) * (overLightConfig?.shadowIntensity || 1)})` ].join(", ") : "0 0 20px rgba(0, 0, 0, 0.15) inset, 0 4px 8px rgba(0, 0, 0, 0.08) inset",
|
|
2510
|
-
"--atomix-glass-container-shadow-opacity": effectiveWithoutEffects ? 0 : 1,
|
|
2511
|
-
// Background and shadow values use design token-aligned RGB values
|
|
2512
|
-
"--atomix-glass-container-bg": overLight ? `linear-gradient(${180 + .5 * mx}deg, rgba(255, 255, 255, 0.1) 0%, transparent 20%, transparent 80%, rgba(0, 0, 0, 0.05) 100%)` : "none",
|
|
2513
|
-
"--atomix-glass-container-text-shadow": overLight ? "0px 1px 2px rgba(255, 255, 255, 0.15)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
|
|
2514
|
-
"--atomix-glass-container-box-shadow": overLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0px 12px 40px rgba(0, 0, 0, 0.25)"
|
|
3046
|
+
"--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`
|
|
2515
3047
|
};
|
|
2516
3048
|
} catch (error) {
|
|
2517
3049
|
return console.warn("AtomixGlassContainer: Error generating container variables", error),
|
|
2518
3050
|
{
|
|
2519
|
-
"--atomix-glass-container-
|
|
2520
|
-
"--atomix-glass-container-radius": "0px",
|
|
2521
|
-
"--atomix-glass-container-backdrop": "none",
|
|
2522
|
-
"--atomix-glass-container-shadow": "none",
|
|
2523
|
-
"--atomix-glass-container-shadow-opacity": 1,
|
|
2524
|
-
"--atomix-glass-container-bg": "none",
|
|
2525
|
-
"--atomix-glass-container-text-shadow": "none"
|
|
3051
|
+
"--atomix-glass-container-radius": "0px"
|
|
2526
3052
|
};
|
|
2527
3053
|
}
|
|
2528
|
-
}), [ borderRadius
|
|
3054
|
+
}), [ borderRadius ]);
|
|
2529
3055
|
return jsx("div", {
|
|
2530
|
-
ref:
|
|
2531
|
-
|
|
2532
|
-
"function" == typeof ref ? ref(el) : ref && (ref.current = el);
|
|
2533
|
-
},
|
|
2534
|
-
className: `${ATOMIX_GLASS.CONTAINER_CLASS} ${className} ${isActive ? ATOMIX_GLASS.CLASSES.ACTIVE : ""} ${overLight ? ATOMIX_GLASS.CLASSES.OVER_LIGHT : ""}`,
|
|
3056
|
+
ref: containerRef,
|
|
3057
|
+
className: mergeClassNames(ATOMIX_GLASS.CONTAINER_CLASS, className, isActive && ATOMIX_GLASS.CLASSES.ACTIVE, overLight && ATOMIX_GLASS.CLASSES.OVER_LIGHT),
|
|
2535
3058
|
style: {
|
|
2536
3059
|
...style,
|
|
2537
3060
|
...containerVars
|
|
@@ -2549,8 +3072,8 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
2549
3072
|
blurAmount: blurAmount,
|
|
2550
3073
|
mode: mode,
|
|
2551
3074
|
id: filterId,
|
|
2552
|
-
displacementScale:
|
|
2553
|
-
aberrationIntensity:
|
|
3075
|
+
displacementScale: toSafeNumber(displacementScale),
|
|
3076
|
+
aberrationIntensity: toSafeNumber(aberrationIntensity),
|
|
2554
3077
|
shaderMapUrl: shaderMapUrl
|
|
2555
3078
|
}), jsx("div", {
|
|
2556
3079
|
className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
|
|
@@ -2572,8 +3095,12 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
2572
3095
|
});
|
|
2573
3096
|
}));
|
|
2574
3097
|
|
|
2575
|
-
|
|
2576
|
-
|
|
3098
|
+
/**
|
|
3099
|
+
* Internal glass surface that owns backdrop-filter, SVG distortion, and content.
|
|
3100
|
+
*
|
|
3101
|
+
* Layout and stacking styles are applied via the `style` prop from the parent.
|
|
3102
|
+
* The root wrapper supplies CSS custom properties only.
|
|
3103
|
+
*/ AtomixGlassContainer.displayName = "AtomixGlassContainer";
|
|
2577
3104
|
|
|
2578
3105
|
// Singleton instance
|
|
2579
3106
|
const globalMouseTracker = new
|
|
@@ -2688,28 +3215,32 @@ class {
|
|
|
2688
3215
|
*/ getSubscriberCount() {
|
|
2689
3216
|
return this.listeners.size;
|
|
2690
3217
|
}
|
|
2691
|
-
}, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
|
|
3218
|
+
}, {BORDER: BORDER, CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, BORDER_GRADIENT = BORDER.GRADIENT, WHITE = CONSTANTS$2.PALETTE.WHITE, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
|
|
2692
3219
|
if (!wrapperElement && !containerElement) return;
|
|
2693
3220
|
if (!validateGlassSize(params.glassSize)) return;
|
|
2694
|
-
const {mouseOffset: mouseOffset, globalMousePosition: globalMousePosition, glassSize: glassSize, isHovered: isHovered, isActive: isActive, isOverLight: isOverLight, baseOverLightConfig: baseOverLightConfig, effectiveBorderRadius: effectiveBorderRadius, effectiveWithoutEffects: effectiveWithoutEffects, effectiveReducedMotion: effectiveReducedMotion, elasticity: elasticity, elasticTranslation: elasticTranslation, elasticVelocity: elasticVelocity, mouseVelocity: mouseVelocity, directionalScale: directionalScale, scaleBase: scaleBase, onClick: onClick, withLiquidBlur: withLiquidBlur, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION,
|
|
3221
|
+
const {mouseOffset: mouseOffset, globalMousePosition: globalMousePosition, glassSize: glassSize, isHovered: isHovered, isActive: isActive, isOverLight: isOverLight, baseOverLightConfig: baseOverLightConfig, effectiveBorderRadius: effectiveBorderRadius, effectiveWithoutEffects: effectiveWithoutEffects, effectiveReducedMotion: effectiveReducedMotion, elasticity: elasticity, elasticTranslation: elasticTranslation, elasticVelocity: elasticVelocity, mouseVelocity: mouseVelocity, directionalScale: directionalScale, scaleBase: scaleBase, onClick: onClick, withLiquidBlur: withLiquidBlur, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, isFixedOrSticky: isFixedOrSticky = !1, borderAnimated: borderAnimated = !0, borderOpacityMultiplier: borderOpacityMultiplier = 1} = params, mouseInfluence = calculateMouseInfluence(mouseOffset), {hoverIntensity: hoverIntensity, activeIntensity: activeIntensity} = getInteractionIntensity(isHovered, isActive), overLightConfig = {
|
|
2695
3222
|
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
2696
3223
|
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
2697
3224
|
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
2698
3225
|
shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
|
|
2699
3226
|
borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
|
|
2700
3227
|
saturationBoost: baseOverLightConfig.saturationBoost
|
|
2701
|
-
}, scaleX = directionalScale.x * scaleBase, scaleY = directionalScale.y * scaleBase, transformStyle = effectiveWithoutEffects ? `scale(${scaleBase})` : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) scaleX(${scaleX}) scaleY(${scaleY})`,
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
x
|
|
2707
|
-
|
|
2708
|
-
}
|
|
3228
|
+
}, scaleX = directionalScale.x * scaleBase, scaleY = directionalScale.y * scaleBase, transformStyle = effectiveWithoutEffects ? `scale(${scaleBase})` : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) scaleX(${scaleX}) scaleY(${scaleY})`, tensionFactor =
|
|
3229
|
+
/**
|
|
3230
|
+
* Computes tension factor from elastic translation magnitude (0–1).
|
|
3231
|
+
*/
|
|
3232
|
+
function(elasticTranslation) {
|
|
3233
|
+
const magnitude = Math.hypot(elasticTranslation.x, elasticTranslation.y);
|
|
3234
|
+
return smoothstep(magnitude / 80);
|
|
3235
|
+
}
|
|
3236
|
+
/**
|
|
3237
|
+
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
3238
|
+
* to avoid React re-renders on mouse movement.
|
|
3239
|
+
*/ (elasticTranslation), lightingContrast = Math.min(1.8, overLightConfig.contrast + .2 * tensionFactor), lightingBrightness = Math.min(1.2, overLightConfig.brightness + .1 * tensionFactor);
|
|
2709
3240
|
// Calculate mouse influence
|
|
2710
3241
|
// Update Wrapper Styles (glassVars)
|
|
2711
3242
|
if (wrapperElement) {
|
|
2712
|
-
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT,
|
|
3243
|
+
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT, whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, hoverPositions = {
|
|
2713
3244
|
hover1: {
|
|
2714
3245
|
x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
|
|
2715
3246
|
y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
|
|
@@ -2726,28 +3257,55 @@ class {
|
|
|
2726
3257
|
x: GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER,
|
|
2727
3258
|
y: GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER
|
|
2728
3259
|
}, opacityValues = {
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
3260
|
+
// hover-1: ambient highlight glow — present on hover and during press
|
|
3261
|
+
hover1: isHovered || isActive ? 1 : 0,
|
|
3262
|
+
// hover-2: press depth shadow — only fires on active (mousedown)
|
|
3263
|
+
hover2: isActive ? 1 : 0,
|
|
3264
|
+
// hover-3: global soft-light surface shift — half-strength on hover, full on press
|
|
3265
|
+
hover3: isActive ? 1 : isHovered ? .55 : 0,
|
|
3266
|
+
// Dark chrome: faint smoky tint; over-light keeps stronger fill
|
|
3267
|
+
base: isOverLight ? overLightConfig.opacity : .14,
|
|
3268
|
+
over: isOverLight ? 1.1 * overLightConfig.opacity : .1
|
|
2734
3269
|
}, style = wrapperElement.style;
|
|
2735
3270
|
style.setProperty("--atomix-glass-transform", transformStyle || "none");
|
|
2736
3271
|
// Parallax for content (liquid refraction feel)
|
|
2737
3272
|
const parallaxFactor = .38 + .12 * tensionFactor;
|
|
2738
3273
|
style.setProperty("--atomix-glass-child-parallax", `translate(${elasticTranslation.x * -parallaxFactor}px, ${elasticTranslation.y * -parallaxFactor}px)`),
|
|
2739
|
-
style.setProperty("--atomix-glass-contrast", lightingContrast.toString()), style.setProperty("--atomix-glass-brightness", lightingBrightness.toString())
|
|
3274
|
+
style.setProperty("--atomix-glass-contrast", lightingContrast.toString()), style.setProperty("--atomix-glass-brightness", lightingBrightness.toString());
|
|
2740
3275
|
// ── Chromatic Rim Lighting ──────────────────────────────────────
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
3276
|
+
const borderVars = ATOMIX_GLASS.BORDER.GRADIENT_CSS_VARS;
|
|
3277
|
+
if (borderAnimated && !effectiveWithoutEffects) {
|
|
3278
|
+
const borderCssVars =
|
|
3279
|
+
/**
|
|
3280
|
+
* Builds animated chromatic rim CSS variables for border layers 1 and 2.
|
|
3281
|
+
* When empty, SCSS static conic/linear fallbacks apply.
|
|
3282
|
+
*/
|
|
3283
|
+
function(params) {
|
|
3284
|
+
const {mouseOffset: mouseOffset, mouseVelocity: mouseVelocity, elasticVelocity: elasticVelocity, borderOpacity: borderOpacity, opacityMultiplier: opacityMultiplier = 1, tensionFactor: tensionFactor = 0} = params, mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), velocityRotation = (mouseVelocity.x + elasticVelocity.x) * BORDER_GRADIENT.VELOCITY_ANGLE_MULTIPLIER, borderGradientAngle = BORDER_GRADIENT.BASE_ANGLE + mx * BORDER_GRADIENT.ANGLE_MULTIPLIER + velocityRotation, chromaticOffset = BORDER_GRADIENT.CHROMATIC_OFFSET, angleR = borderGradientAngle - chromaticOffset, angleB = borderGradientAngle + chromaticOffset, borderStop1 = Math.max(BORDER_GRADIENT.STOP_1.MIN, BORDER_GRADIENT.STOP_1.BASE + my * BORDER_GRADIENT.STOP_1.MULTIPLIER), borderStop2 = Math.min(BORDER_GRADIENT.STOP_2.MAX, BORDER_GRADIENT.STOP_2.BASE + my * BORDER_GRADIENT.STOP_2.MULTIPLIER), tensionGlow = 1 + .5 * tensionFactor, opacities = BORDER_GRADIENT.OPACITY, borderOpacities = [ (opacities.BASE_1 + absMx * opacities.MULTIPLIER_LOW) * tensionGlow, (opacities.BASE_2 + absMx * opacities.MULTIPLIER_HIGH) * tensionGlow, (opacities.BASE_3 + absMx * opacities.MULTIPLIER_LOW) * tensionGlow, (opacities.BASE_4 + absMx * opacities.MULTIPLIER_HIGH) * tensionGlow ], configBorderOpacity = borderOpacity * opacityMultiplier, gradient1 = `linear-gradient(${angleB}deg, rgba(${WHITE}, 0) 0%, rgba(${WHITE}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${WHITE}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${WHITE}, 0) 100%)`, gradient2 = `linear-gradient(${angleR}deg, rgba(${WHITE}, 0) 0%, rgba(${WHITE}, ${(borderOpacities[2] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${WHITE}, ${(borderOpacities[3] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${WHITE}, 0) 100%)`;
|
|
3285
|
+
return {
|
|
3286
|
+
[BORDER.GRADIENT_CSS_VARS.GRADIENT_1]: gradient1,
|
|
3287
|
+
[BORDER.GRADIENT_CSS_VARS.GRADIENT_2]: gradient2
|
|
3288
|
+
};
|
|
3289
|
+
}({
|
|
3290
|
+
mouseOffset: mouseOffset,
|
|
3291
|
+
mouseVelocity: mouseVelocity,
|
|
3292
|
+
elasticVelocity: elasticVelocity,
|
|
3293
|
+
borderOpacity: overLightConfig.borderOpacity,
|
|
3294
|
+
opacityMultiplier: borderOpacityMultiplier,
|
|
3295
|
+
tensionFactor: tensionFactor
|
|
3296
|
+
});
|
|
3297
|
+
style.setProperty(borderVars.GRADIENT_1, borderCssVars[borderVars.GRADIENT_1] ?? ""),
|
|
3298
|
+
style.setProperty(borderVars.GRADIENT_2, borderCssVars[borderVars.GRADIENT_2] ?? "");
|
|
3299
|
+
} else style.removeProperty(borderVars.GRADIENT_1), style.removeProperty(borderVars.GRADIENT_2);
|
|
3300
|
+
// Hover gradients — cursor-relative radial positions for realistic light tracking.
|
|
3301
|
+
// hover-1: white overlay highlight following cursor (works on both dark + light)
|
|
3302
|
+
style.setProperty("--atomix-glass-hover-1-gradient", `radial-gradient(65% 55% at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${whiteColor}, 0.24) 0%, rgba(${whiteColor}, 0.06) 45%, rgba(${whiteColor}, 0) 72%)`),
|
|
3303
|
+
// hover-2: press depth — darkens at cursor with multiply blend, isOverLight uses stronger black
|
|
3304
|
+
style.setProperty("--atomix-glass-hover-2-gradient", isOverLight ? `radial-gradient(60% 50% at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${blackColor}, 0.22) 0%, rgba(${blackColor}, 0.06) 50%, rgba(${blackColor}, 0) 72%)` : `radial-gradient(60% 50% at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${blackColor}, 0.18) 0%, rgba(${blackColor}, 0.04) 50%, rgba(${blackColor}, 0) 72%)`),
|
|
3305
|
+
// hover-3: full-surface soft-light tint; linear gradient angled with cursor X
|
|
3306
|
+
style.setProperty("--atomix-glass-hover-3-gradient", `linear-gradient(${150 + .3 * mx}deg, rgba(${whiteColor}, ${isOverLight ? .08 : .12}) 0%, rgba(${whiteColor}, 0.04) 55%, rgba(${whiteColor}, 0) 100%)`),
|
|
3307
|
+
style.setProperty("--atomix-glass-base-gradient", isOverLight ? `linear-gradient(${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.ANGLE}deg, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_BASE + mx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_BASE + my * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_MULTIPLIER}) ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_BASE + absMx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `linear-gradient(180deg, rgba(${blackColor}, 0.42) 0%, rgba(${blackColor}, 0.22) 55%, rgba(${blackColor}, 0.12) 100%)`),
|
|
3308
|
+
style.setProperty("--atomix-glass-overlay-gradient", isOverLight ? `radial-gradient(circle at ${basePosition.x}% ${basePosition.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + absMx * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_BASE + absMy * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `radial-gradient(120% 80% at 50% 0%, rgba(${whiteColor}, 0.14) 0%, rgba(${whiteColor}, 0) 55%)`),
|
|
2751
3309
|
// Opacities
|
|
2752
3310
|
style.setProperty("--atomix-glass-hover-1-opacity", opacityValues.hover1.toString()),
|
|
2753
3311
|
style.setProperty("--atomix-glass-hover-2-opacity", opacityValues.hover2.toString()),
|
|
@@ -2784,151 +3342,16 @@ class {
|
|
|
2784
3342
|
backdropFilterString = !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? `blur(${clampBlur(Math.max(liquidBlur.baseBlur, .8 * liquidBlur.edgeBlur, 1.1 * liquidBlur.centerBlur, .9 * liquidBlur.flowBlur))}px) saturate(${Math.min(dynamicSaturation, 250)}%) contrast(${lightingContrast}) brightness(${lightingBrightness})` : `blur(${clampBlur(.4 * liquidBlur.baseBlur + .25 * liquidBlur.edgeBlur + .15 * liquidBlur.centerBlur + .2 * liquidBlur.flowBlur)}px) saturate(${Math.min(dynamicSaturation, 250)}%) contrast(${lightingContrast}) brightness(${lightingBrightness})`;
|
|
2785
3343
|
// Container variables
|
|
2786
3344
|
const style = containerElement.style;
|
|
2787
|
-
style.setProperty("--atomix-glass-container-
|
|
3345
|
+
style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
|
|
2788
3346
|
style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
|
|
2789
3347
|
// Shadows
|
|
2790
|
-
style.setProperty("--atomix-glass-container-shadow", isOverLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.
|
|
3348
|
+
style.setProperty("--atomix-glass-container-shadow", isOverLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.35 + .002 * mx) * (overLightConfig.shadowIntensity || 1)})`, `inset 0 -1px 0 rgba(0, 0, 0, ${(.15 + .001 * Math.abs(my)) * (overLightConfig.shadowIntensity || 1)})`, `inset 0 0 20px rgba(0, 0, 0, ${(.06 + .001 * Math.abs(mx + my)) * (overLightConfig.shadowIntensity || 1)})`, `0 2px 12px rgba(0, 0, 0, ${(.08 + .002 * Math.abs(my)) * (overLightConfig.shadowIntensity || 1)})` ].join(", ") : ATOMIX_GLASS.CONSTANTS.CONTAINER_SHADOW.LIGHT),
|
|
2791
3349
|
style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
|
|
2792
3350
|
style.setProperty("--atomix-glass-container-bg", isOverLight ? `linear-gradient(${180 + .5 * mx}deg, rgba(255, 255, 255, 0.1) 0%, transparent 20%, transparent 80%, rgba(0, 0, 0, 0.05) 100%)` : "none"),
|
|
2793
3351
|
style.setProperty("--atomix-glass-container-text-shadow", isOverLight ? "0px 1px 2px rgba(255, 255, 255, 0.15)" : "0px 2px 12px rgba(0, 0, 0, 0.4)"),
|
|
2794
|
-
style.setProperty("--atomix-glass-container-box-shadow", isOverLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "
|
|
3352
|
+
style.setProperty("--atomix-glass-container-box-shadow", isOverLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0 4px 16px rgba(0, 0, 0, 0.14), 0 1px 4px rgba(0, 0, 0, 0.10)");
|
|
2795
3353
|
}
|
|
2796
|
-
};
|
|
2797
|
-
|
|
2798
|
-
/**
|
|
2799
|
-
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
2800
|
-
* to avoid React re-renders on mouse movement.
|
|
2801
|
-
*/
|
|
2802
|
-
/**
|
|
2803
|
-
* Animation System for AtomixGlass Component
|
|
2804
|
-
*
|
|
2805
|
-
* Implements Phase 1 features from the AtomixGlass Feature Implementation Roadmap:
|
|
2806
|
-
* - Feature 1.1: Time-Based Animation System
|
|
2807
|
-
* - Feature 1.2: Multi-Layer Distortion System (FBM)
|
|
2808
|
-
*
|
|
2809
|
-
* @packageDocumentation
|
|
2810
|
-
*/
|
|
2811
|
-
// ============================================================================
|
|
2812
|
-
// Noise Functions for FBM (Feature 1.2)
|
|
2813
|
-
// ============================================================================
|
|
2814
|
-
/**
|
|
2815
|
-
* Perlin noise implementation for smooth gradient noise
|
|
2816
|
-
*
|
|
2817
|
-
* @param x - X coordinate
|
|
2818
|
-
* @param y - Y coordinate
|
|
2819
|
-
* @returns Noise value in range [0, 1]
|
|
2820
|
-
*/
|
|
2821
|
-
function perlinNoise(x, y) {
|
|
2822
|
-
// Simplified Perlin noise using pseudo-random gradients
|
|
2823
|
-
const X = 255 & Math.floor(x), Y = 255 & Math.floor(y), xf = x - Math.floor(x), yf = y - Math.floor(y), u = fade(xf), v = fade(yf), A = p[X] + Y & 255, B = p[X + 1] + Y & 255, ga = grad(p[A], xf, yf), gb = grad(p[B], xf - 1, yf), gc = grad(p[A + 1 & 255], xf, yf - 1), gd = grad(p[B + 1 & 255], xf - 1, yf - 1), lerpX1 = lerp(ga, gb, u), lerpX2 = lerp(gc, gd, u);
|
|
2824
|
-
// Scale to [0, 1] range
|
|
2825
|
-
return (lerp(lerpX1, lerpX2, v) + 1) / 2;
|
|
2826
|
-
}
|
|
2827
|
-
|
|
2828
|
-
// ============================================================================
|
|
2829
|
-
// Fractal Brownian Motion (FBM) Engine (Feature 1.2)
|
|
2830
|
-
// ============================================================================
|
|
2831
|
-
/**
|
|
2832
|
-
* Creates an FBM engine with configurable parameters
|
|
2833
|
-
*
|
|
2834
|
-
* @param config - FBM configuration (octaves, lacunarity, gain)
|
|
2835
|
-
* @returns Object with fbm function
|
|
2836
|
-
*
|
|
2837
|
-
* @example
|
|
2838
|
-
* ```typescript
|
|
2839
|
-
* const fbmEngine = createFBMEngine({ octaves: 5, lacunarity: 2, gain: 0.5 });
|
|
2840
|
-
*
|
|
2841
|
-
* // Generate noise at position (0.5, 0.5) with time animation
|
|
2842
|
-
* const noiseValue = fbmEngine.fbm(0.5, 0.5, Date.now());
|
|
2843
|
-
* ```
|
|
2844
|
-
*/ function createFBMEngine(config) {
|
|
2845
|
-
/**
|
|
2846
|
-
* Fractal Brownian Motion function
|
|
2847
|
-
* Combines multiple octaves of noise for complex, natural patterns
|
|
2848
|
-
*
|
|
2849
|
-
* @param x - X coordinate
|
|
2850
|
-
* @param y - Y coordinate
|
|
2851
|
-
* @param time - Optional time value for animation
|
|
2852
|
-
* @returns FBM noise value in range [0, 1]
|
|
2853
|
-
*/
|
|
2854
|
-
const fbm = (x, y, time = 0) => {
|
|
2855
|
-
let value = 0, amplitude = .5, frequency = 1, phase = .001 * time;
|
|
2856
|
-
// Convert to seconds for reasonable animation speed
|
|
2857
|
-
for (let i = 0; i < config.octaves; i++)
|
|
2858
|
-
// Apply time-based phase shift to all octaves
|
|
2859
|
-
value += perlinNoise(x * frequency + phase, y * frequency + phase) * amplitude,
|
|
2860
|
-
frequency *= config.lacunarity, // Increase frequency
|
|
2861
|
-
amplitude *= config.gain;
|
|
2862
|
-
return value;
|
|
2863
|
-
};
|
|
2864
|
-
/**
|
|
2865
|
-
* Get FBM with simple time factor
|
|
2866
|
-
*/ return {
|
|
2867
|
-
fbm: fbm,
|
|
2868
|
-
fbmWithTime: (x, y, time) => fbm(x, y, time)
|
|
2869
|
-
};
|
|
2870
|
-
}
|
|
2871
|
-
|
|
2872
|
-
/**
|
|
2873
|
-
* Gets optimal FBM config based on quality preset
|
|
2874
|
-
*
|
|
2875
|
-
* @param quality - Quality preset level
|
|
2876
|
-
* @returns FBM configuration for the quality level
|
|
2877
|
-
*/ const fbmEngineCache = new Map;
|
|
2878
|
-
|
|
2879
|
-
// ============================================================================
|
|
2880
|
-
// Shader Utility Functions for Time-Based Effects
|
|
2881
|
-
// ============================================================================
|
|
2882
|
-
/**
|
|
2883
|
-
* Liquid glass distortion with time-based animation
|
|
2884
|
-
* Uses FBM to create organic, flowing liquid effects
|
|
2885
|
-
*
|
|
2886
|
-
* @param uv - UV coordinates (normalized 0-1)
|
|
2887
|
-
* @param time - Elapsed time in milliseconds
|
|
2888
|
-
* @param config - FBM configuration
|
|
2889
|
-
* @returns Distorted UV coordinates
|
|
2890
|
-
*/ function liquidGlassWithTime(uv, time, config) {
|
|
2891
|
-
const configKey = `${config.octaves}-${config.lacunarity}-${config.gain}`;
|
|
2892
|
-
let fbmEngine = fbmEngineCache.get(configKey);
|
|
2893
|
-
fbmEngine || (fbmEngine = createFBMEngine(config), fbmEngineCache.set(configKey, fbmEngine));
|
|
2894
|
-
// Animate noise with time
|
|
2895
|
-
const animatedNoise = fbmEngine.fbmWithTime(2 * uv.x + 1e-4 * time, 2 * uv.y + 15e-5 * time, time);
|
|
2896
|
-
return {
|
|
2897
|
-
x: uv.x + .04 * (animatedNoise - .5),
|
|
2898
|
-
y: uv.y + .04 * (animatedNoise - .5)
|
|
2899
|
-
};
|
|
2900
|
-
}
|
|
2901
|
-
|
|
2902
|
-
// ============================================================================
|
|
2903
|
-
// Helper Functions
|
|
2904
|
-
// ============================================================================
|
|
2905
|
-
/**
|
|
2906
|
-
* Fade curve for smooth interpolation (Perlin's fade function)
|
|
2907
|
-
*/ function fade(t) {
|
|
2908
|
-
return t * t * t * (t * (6 * t - 15) + 10);
|
|
2909
|
-
}
|
|
2910
|
-
|
|
2911
|
-
/**
|
|
2912
|
-
* Linear interpolation
|
|
2913
|
-
*/ function lerp(a, b, t) {
|
|
2914
|
-
return a + t * (b - a);
|
|
2915
|
-
}
|
|
2916
|
-
|
|
2917
|
-
/**
|
|
2918
|
-
* Gradient calculation for Perlin noise
|
|
2919
|
-
*/ function grad(hash, x, y) {
|
|
2920
|
-
const h = 15 & hash, u = h < 8 ? x : y, v = h < 4 ? y : 12 === h || 14 === h ? x : 0;
|
|
2921
|
-
return (1 & h ? -u : u) + (2 & h ? -v : v);
|
|
2922
|
-
}
|
|
2923
|
-
|
|
2924
|
-
/**
|
|
2925
|
-
* Permutation table for Perlin noise
|
|
2926
|
-
*/ const p = (() => {
|
|
2927
|
-
const permutation = [];
|
|
2928
|
-
for (let i = 0; i < 256; i++) permutation[i] = Math.floor(256 * Math.random());
|
|
2929
|
-
// Duplicate for overflow handling
|
|
2930
|
-
return [ ...permutation, ...permutation ];
|
|
2931
|
-
})(), {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
|
|
3354
|
+
}, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
|
|
2932
3355
|
|
|
2933
3356
|
const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
|
|
2934
3357
|
parentElement && backgroundDetectionCache.set(parentElement, {
|
|
@@ -2943,12 +3366,35 @@ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new Weak
|
|
|
2943
3366
|
* Composable hook for AtomixGlass component logic
|
|
2944
3367
|
* Manages all state, calculations, and event handlers
|
|
2945
3368
|
*/
|
|
2946
|
-
function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef: wrapperRef, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, onClick: onClick, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, children: children, blurAmount: blurAmount, saturation: saturation,
|
|
2947
|
-
// Default priority
|
|
2948
|
-
// Phase 1: Animation System Props
|
|
2949
|
-
withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: animationSpeed = ATOMIX_GLASS.DEFAULTS.ANIMATION_SPEED, withMultiLayerDistortion: withMultiLayerDistortion = ATOMIX_GLASS.DEFAULTS.WITH_MULTI_LAYER_DISTORTION, distortionOctaves: distortionOctaves = ATOMIX_GLASS.DEFAULTS.DISTORTION_OCTAVES, distortionLacunarity: distortionLacunarity = ATOMIX_GLASS.DEFAULTS.DISTORTION_LACUNARITY, distortionGain: distortionGain = ATOMIX_GLASS.DEFAULTS.DISTORTION_GAIN, distortionQuality: distortionQuality = ATOMIX_GLASS.DEFAULTS.DISTORTION_QUALITY}) {
|
|
3369
|
+
function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef: wrapperRef, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, border: border, withBorder: withBorder = !0, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, onClick: onClick, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, children: children, blurAmount: blurAmount, saturation: saturation, withLiquidBlur: withLiquidBlur, isFixedOrSticky: isFixedOrSticky = !1, priority: priority = 1}) {
|
|
2950
3370
|
// State
|
|
2951
|
-
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1),
|
|
3371
|
+
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), resolvedBorder = useMemo((() =>
|
|
3372
|
+
/**
|
|
3373
|
+
* Resolves `border` and legacy `withBorder` into a single configuration object.
|
|
3374
|
+
*/
|
|
3375
|
+
function(border, withBorder) {
|
|
3376
|
+
const legacyDefault = withBorder ?? !0;
|
|
3377
|
+
return void 0 === border ? {
|
|
3378
|
+
enabled: legacyDefault,
|
|
3379
|
+
width: BORDER.DEFAULT_WIDTH,
|
|
3380
|
+
opacityMultiplier: 1,
|
|
3381
|
+
animated: !0
|
|
3382
|
+
} : "boolean" == typeof border ? {
|
|
3383
|
+
enabled: border,
|
|
3384
|
+
width: BORDER.DEFAULT_WIDTH,
|
|
3385
|
+
opacityMultiplier: 1,
|
|
3386
|
+
animated: !0
|
|
3387
|
+
} : {
|
|
3388
|
+
enabled: border.enabled ?? legacyDefault,
|
|
3389
|
+
width: (value = border.width, void 0 === value ? BORDER.DEFAULT_WIDTH : "number" == typeof value ? `${value}px` : value),
|
|
3390
|
+
opacityMultiplier: border.opacity ?? 1,
|
|
3391
|
+
animated: !1 !== border.animated
|
|
3392
|
+
};
|
|
3393
|
+
/**
|
|
3394
|
+
* Formats border width for CSS custom properties.
|
|
3395
|
+
*/
|
|
3396
|
+
var value;
|
|
3397
|
+
}(border, withBorder)), [ border, withBorder ]), cachedRectRef = useRef(null), internalGlobalMousePositionRef = useRef({
|
|
2952
3398
|
x: 0,
|
|
2953
3399
|
y: 0
|
|
2954
3400
|
}), internalMouseOffsetRef = useRef({
|
|
@@ -2972,52 +3418,10 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
2972
3418
|
}), scaleVelocityRef = useRef({
|
|
2973
3419
|
x: 0,
|
|
2974
3420
|
y: 0
|
|
2975
|
-
})
|
|
2976
|
-
useRef(0);
|
|
2977
|
-
const mouseVelocityRef = useRef({
|
|
3421
|
+
}), mouseVelocityRef = useRef({
|
|
2978
3422
|
x: 0,
|
|
2979
3423
|
y: 0
|
|
2980
|
-
}), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1),
|
|
2981
|
-
// If quality preset is provided, use it as base
|
|
2982
|
-
const preset = (quality = distortionQuality, ATOMIX_GLASS.CONSTANTS.DISTORTION_QUALITY_PRESETS[quality]);
|
|
2983
|
-
// Override with custom values if provided
|
|
2984
|
-
var quality;
|
|
2985
|
-
return {
|
|
2986
|
-
octaves: distortionOctaves ?? preset.octaves,
|
|
2987
|
-
lacunarity: distortionLacunarity ?? preset.lacunarity,
|
|
2988
|
-
gain: distortionGain ?? preset.gain
|
|
2989
|
-
};
|
|
2990
|
-
}), [ distortionQuality, distortionOctaves, distortionLacunarity, distortionGain ]), fbmEngine = useMemo((() => withMultiLayerDistortion ? createFBMEngine(fbmConfig) : null), [ withMultiLayerDistortion, fbmConfig ]), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveWithTimeAnimation = useMemo((() => withTimeAnimation && !effectiveReducedMotion), [ withTimeAnimation, effectiveReducedMotion ]);
|
|
2991
|
-
/**
|
|
2992
|
-
* Animation loop for time-based effects
|
|
2993
|
-
*/
|
|
2994
|
-
useEffect((() => {
|
|
2995
|
-
if (!effectiveWithTimeAnimation || "undefined" == typeof window) return;
|
|
2996
|
-
let lastFrameTime = performance.now();
|
|
2997
|
-
/**
|
|
2998
|
-
* Animation frame handler
|
|
2999
|
-
*/ const animate = currentTime => {
|
|
3000
|
-
// Calculate delta time
|
|
3001
|
-
const deltaTime = currentTime - lastFrameTime;
|
|
3002
|
-
lastFrameTime = currentTime;
|
|
3003
|
-
// Apply animation speed multiplier
|
|
3004
|
-
const scaledDelta = deltaTime * animationSpeed;
|
|
3005
|
-
elapsedTimeRef.current += scaledDelta, shaderTimeRef.current = elapsedTimeRef.current,
|
|
3006
|
-
// Continue animation loop
|
|
3007
|
-
animationFrameIdRef.current = requestAnimationFrame(animate);
|
|
3008
|
-
};
|
|
3009
|
-
// Start animation
|
|
3010
|
-
// Cleanup
|
|
3011
|
-
return animationStartTimeRef.current = performance.now(), animationFrameIdRef.current = requestAnimationFrame(animate),
|
|
3012
|
-
() => {
|
|
3013
|
-
null !== animationFrameIdRef.current && (cancelAnimationFrame(animationFrameIdRef.current),
|
|
3014
|
-
animationFrameIdRef.current = null);
|
|
3015
|
-
};
|
|
3016
|
-
}), [ effectiveWithTimeAnimation, animationSpeed ]);
|
|
3017
|
-
/**
|
|
3018
|
-
* Get current shader time for animations
|
|
3019
|
-
*/
|
|
3020
|
-
const getShaderTime = useCallback((() => shaderTimeRef.current), []), applyTimeBasedDistortion = useCallback((uv => effectiveWithTimeAnimation && fbmEngine ? liquidGlassWithTime(uv, shaderTimeRef.current, fbmConfig) : uv), [ effectiveWithTimeAnimation, fbmEngine, fbmConfig ]), effectiveBorderRadius = useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
|
|
3424
|
+
}), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveBorderRadius = useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
|
|
3021
3425
|
const [glassSize, setGlassSize] = useState({
|
|
3022
3426
|
width: 270,
|
|
3023
3427
|
height: 69
|
|
@@ -3077,9 +3481,6 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
3077
3481
|
effectiveBorderRadius: effectiveBorderRadius,
|
|
3078
3482
|
cachedRectRef: cachedRectRef
|
|
3079
3483
|
}), effectiveHighContrast = useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveWithoutEffects = useMemo((() => withoutEffects || effectiveReducedMotion), [ withoutEffects, effectiveReducedMotion ]), globalMousePosition = externalGlobalMousePosition || internalGlobalMousePositionRef.current, mouseOffset = externalMouseOffset || internalMouseOffsetRef.current;
|
|
3080
|
-
/**
|
|
3081
|
-
* Apply time-based distortion to UV coordinates
|
|
3082
|
-
*/
|
|
3083
3484
|
// Extract border-radius from children
|
|
3084
3485
|
useEffect((() => {
|
|
3085
3486
|
const extractRadius = () => {
|
|
@@ -3239,25 +3640,26 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
3239
3640
|
* Get effective overLight value based on configuration
|
|
3240
3641
|
*/
|
|
3241
3642
|
const getEffectiveOverLight = useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []), overLightConfig = useMemo((() => {
|
|
3242
|
-
const isOverLight = getEffectiveOverLight(), hoverIntensity
|
|
3643
|
+
const isOverLight = getEffectiveOverLight(), {hoverIntensity: hoverIntensity, activeIntensity: activeIntensity} = getInteractionIntensity(isHovered, isActive), baseConfig = {
|
|
3243
3644
|
isOverLight: isOverLight,
|
|
3244
3645
|
threshold: .7,
|
|
3245
3646
|
opacity: isOverLight ? Math.min(.6, Math.max(.2, .5 * hoverIntensity * activeIntensity)) : 0,
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
shadowIntensity: .9,
|
|
3251
|
-
borderOpacity: .
|
|
3647
|
+
// Dark UI (Apple Music): neutral contrast + slight brightness lift
|
|
3648
|
+
contrast: isOverLight ? 1.4 : 1.02,
|
|
3649
|
+
brightness: isOverLight ? .9 : 1.02,
|
|
3650
|
+
saturationBoost: isOverLight ? 1.3 : 1,
|
|
3651
|
+
shadowIntensity: isOverLight ? .9 : 1,
|
|
3652
|
+
borderOpacity: isOverLight ? ATOMIX_GLASS.BORDER.OVER_LIGHT.opacity : ATOMIX_GLASS.BORDER.DARK.opacity
|
|
3252
3653
|
};
|
|
3253
3654
|
if ("object" == typeof overLight && null !== overLight) {
|
|
3254
|
-
const objConfig = overLight, validatedThreshold = validateConfigValue(objConfig.threshold, .1, 1, baseConfig.threshold), validatedOpacity = validateConfigValue(objConfig.opacity, .1, 1, baseConfig.opacity), validatedContrast = validateConfigValue(objConfig.contrast, .5, 2.5, baseConfig.contrast), validatedBrightness = validateConfigValue(objConfig.brightness, .5, 2, baseConfig.brightness), validatedSaturationBoost = validateConfigValue(objConfig.saturationBoost, .5, 3, baseConfig.saturationBoost), finalConfig = {
|
|
3655
|
+
const objConfig = overLight, validatedThreshold = validateConfigValue(objConfig.threshold, .1, 1, baseConfig.threshold), validatedOpacity = validateConfigValue(objConfig.opacity, .1, 1, baseConfig.opacity), validatedContrast = validateConfigValue(objConfig.contrast, .5, 2.5, baseConfig.contrast), validatedBrightness = validateConfigValue(objConfig.brightness, .5, 2, baseConfig.brightness), validatedSaturationBoost = validateConfigValue(objConfig.saturationBoost, .5, 3, baseConfig.saturationBoost), validatedBorderOpacity = validateConfigValue(objConfig.borderOpacity, .1, 1, baseConfig.borderOpacity), finalConfig = {
|
|
3255
3656
|
...baseConfig,
|
|
3256
3657
|
threshold: validatedThreshold,
|
|
3257
3658
|
opacity: validatedOpacity * hoverIntensity * activeIntensity,
|
|
3258
3659
|
contrast: validatedContrast,
|
|
3259
3660
|
brightness: validatedBrightness,
|
|
3260
|
-
saturationBoost: validatedSaturationBoost
|
|
3661
|
+
saturationBoost: validatedSaturationBoost,
|
|
3662
|
+
borderOpacity: validatedBorderOpacity
|
|
3261
3663
|
};
|
|
3262
3664
|
return "undefined" == typeof process || process.env, finalConfig;
|
|
3263
3665
|
}
|
|
@@ -3282,8 +3684,8 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
3282
3684
|
};
|
|
3283
3685
|
const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
|
|
3284
3686
|
internalGlobalMousePositionRef.current = {
|
|
3285
|
-
x: lerp
|
|
3286
|
-
y: lerp
|
|
3687
|
+
x: lerp(curG.x, tgtG.x, CONSTANTS.LERP_FACTOR),
|
|
3688
|
+
y: lerp(curG.y, tgtG.y, CONSTANTS.LERP_FACTOR)
|
|
3287
3689
|
};
|
|
3288
3690
|
// ── Calculate Elastic Physics ─────────────────────────────────────
|
|
3289
3691
|
let targetElasticTranslation = {
|
|
@@ -3355,12 +3757,13 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
3355
3757
|
withLiquidBlur: withLiquidBlur,
|
|
3356
3758
|
blurAmount: blurAmount,
|
|
3357
3759
|
saturation: saturation,
|
|
3358
|
-
|
|
3359
|
-
|
|
3760
|
+
isFixedOrSticky: isFixedOrSticky,
|
|
3761
|
+
borderAnimated: resolvedBorder.animated,
|
|
3762
|
+
borderOpacityMultiplier: resolvedBorder.opacityMultiplier
|
|
3360
3763
|
}), Math.abs(mouseVelocityRef.current.x) < .001 && Math.abs(mouseVelocityRef.current.y) < .001 && Math.abs(elasticVelocityRef.current.x) < .001 && Math.abs(elasticVelocityRef.current.y) < .001 && Math.abs(scaleVelocityRef.current.x) < .001 && Math.abs(scaleVelocityRef.current.y) < .001 && Math.abs(internalMouseOffsetRef.current.x - targetMouseOffsetRef.current.x) < .001 && Math.abs(internalMouseOffsetRef.current.y - targetMouseOffsetRef.current.y) < .001 ? stopLerpLoop() : lerpRafRef.current = requestAnimationFrame(tick);
|
|
3361
3764
|
};
|
|
3362
3765
|
lerpRafRef.current = requestAnimationFrame(tick);
|
|
3363
|
-
}), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation,
|
|
3766
|
+
}), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, isFixedOrSticky, resolvedBorder.animated, resolvedBorder.opacityMultiplier, stopLerpLoop ]), handleGlobalMousePosition = useCallback((globalPos => {
|
|
3364
3767
|
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
3365
3768
|
if (effectiveWithoutEffects) return;
|
|
3366
3769
|
const container = mouseContainer?.current || glassRef.current;
|
|
@@ -3424,9 +3827,10 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
3424
3827
|
withLiquidBlur: withLiquidBlur,
|
|
3425
3828
|
blurAmount: blurAmount,
|
|
3426
3829
|
saturation: saturation,
|
|
3427
|
-
|
|
3830
|
+
borderAnimated: resolvedBorder.animated,
|
|
3831
|
+
borderOpacityMultiplier: resolvedBorder.opacityMultiplier
|
|
3428
3832
|
});
|
|
3429
|
-
}), [ isHovered, isActive, glassSize, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation,
|
|
3833
|
+
}), [ isHovered, isActive, glassSize, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, resolvedBorder.animated, resolvedBorder.opacityMultiplier, onClick ]);
|
|
3430
3834
|
// Event handlers
|
|
3431
3835
|
const handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleKeyDown = useCallback((e => {
|
|
3432
3836
|
!onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
|
|
@@ -3446,9 +3850,8 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
3446
3850
|
mouseOffset: mouseOffset,
|
|
3447
3851
|
// This is now static (refs or props) unless prop changes
|
|
3448
3852
|
overLightConfig: overLightConfig,
|
|
3853
|
+
resolvedBorder: resolvedBorder,
|
|
3449
3854
|
transformStyle: transformStyle,
|
|
3450
|
-
getShaderTime: getShaderTime,
|
|
3451
|
-
applyTimeBasedDistortion: applyTimeBasedDistortion,
|
|
3452
3855
|
handleMouseEnter: handleMouseEnter,
|
|
3453
3856
|
handleMouseLeave: handleMouseLeave,
|
|
3454
3857
|
handleMouseDown: handleMouseDown,
|
|
@@ -3726,7 +4129,13 @@ function usePerformanceMonitor$1(config = {}) {
|
|
|
3726
4129
|
timestamp: 0,
|
|
3727
4130
|
isAutoScaling: !0,
|
|
3728
4131
|
lowFpsCount: 0
|
|
3729
|
-
}), [manualOverride, setManualOverride] = useState(!1), [isEnabled, setIsEnabled] = useState(enabled)
|
|
4132
|
+
}), [manualOverride, setManualOverride] = useState(!1), [isEnabled, setIsEnabled] = useState(enabled);
|
|
4133
|
+
// Sync external `enabled` prop changes into internal state
|
|
4134
|
+
useEffect((() => {
|
|
4135
|
+
setIsEnabled(enabled ?? !0);
|
|
4136
|
+
}), [ enabled ]);
|
|
4137
|
+
// Refs for frame tracking
|
|
4138
|
+
const frameCountRef = useRef(0), lastFpsUpdateRef = useRef(0), lastFrameTimeRef = useRef(0), animationFrameRef = useRef(null), lowFpsCountRef = useRef(0), highFpsCountRef = useRef(0), qualityLevelRef = useRef("medium"), updateMetrics = useCallback((newMetrics => {
|
|
3730
4139
|
setMetrics((prev => ({
|
|
3731
4140
|
...prev,
|
|
3732
4141
|
...newMetrics,
|
|
@@ -3853,157 +4262,9 @@ function usePerformanceMonitor$1(config = {}) {
|
|
|
3853
4262
|
setQualityLevel: setQualityLevel,
|
|
3854
4263
|
resetAutoScaling: resetAutoScaling,
|
|
3855
4264
|
toggleMonitoring: toggleMonitoring
|
|
3856
|
-
};
|
|
3857
|
-
}
|
|
3858
|
-
|
|
3859
|
-
/**
|
|
3860
|
-
* Debug Overlay Component (Optional)
|
|
3861
|
-
*
|
|
3862
|
-
* Shows real-time performance metrics on screen.
|
|
3863
|
-
* Only rendered when showOverlay is enabled.
|
|
3864
|
-
*/
|
|
3865
|
-
/** Map an FPS value to a semantic color token string. */
|
|
3866
|
-
const getQualityColor = quality => {
|
|
3867
|
-
switch (quality) {
|
|
3868
|
-
case "high":
|
|
3869
|
-
return "var(--atomix-color-success, #4ade80)";
|
|
3870
|
-
|
|
3871
|
-
case "medium":
|
|
3872
|
-
return "var(--atomix-color-warning, #fbbf24)";
|
|
3873
|
-
|
|
3874
|
-
case "low":
|
|
3875
|
-
return "var(--atomix-color-danger, #ef4444)";
|
|
3876
|
-
|
|
3877
|
-
default:
|
|
3878
|
-
return "#9ca3af";
|
|
3879
|
-
}
|
|
3880
|
-
}, getFpsLabel = fps => fps >= 58 ? "Optimal" : fps >= 45 ? "Warning" : "Critical";
|
|
3881
|
-
|
|
3882
|
-
/** Map a quality level string to a semantic color token string. */
|
|
3883
|
-
// Inject keyframes once
|
|
3884
|
-
if ("undefined" != typeof document) {
|
|
3885
|
-
const styleId = "perf-dashboard-keyframes";
|
|
3886
|
-
if (!document.getElementById(styleId)) {
|
|
3887
|
-
const styleEl = document.createElement("style");
|
|
3888
|
-
styleEl.id = styleId, styleEl.textContent = "\n@keyframes perf-dashboard-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n}\n",
|
|
3889
|
-
document.head.appendChild(styleEl);
|
|
3890
|
-
}
|
|
4265
|
+
};
|
|
3891
4266
|
}
|
|
3892
4267
|
|
|
3893
|
-
/**
|
|
3894
|
-
* PerformanceDashboard - Real-time performance monitoring overlay.
|
|
3895
|
-
*
|
|
3896
|
-
* Displays FPS, frame time, quality level, GPU memory, and auto-scaling status.
|
|
3897
|
-
* Rendered only when `debugPerformance={true}` on the parent `AtomixGlass`.
|
|
3898
|
-
*/ const PerformanceDashboard = memo((({metrics: metrics, isVisible: isVisible = !0, onClose: onClose}) => {
|
|
3899
|
-
if (!isVisible) return null;
|
|
3900
|
-
const fpsColor = (fps = metrics.fps) >= 58 ? "var(--atomix-color-success, #4ade80)" : fps >= 45 ? "var(--atomix-color-warning, #fbbf24)" : "var(--atomix-color-danger, #ef4444)";
|
|
3901
|
-
var fps;
|
|
3902
|
-
const isCritical = metrics.fps < 45;
|
|
3903
|
-
return jsxs("div", {
|
|
3904
|
-
className: "c-perf-dashboard u-position-fixed u-top-4 u-end-4 u-p-3 u-px-4 u-text-xs u-font-mono u-text-white u-rounded-md u-border u-border-white-alpha-10 u-shadow-lg",
|
|
3905
|
-
style: {
|
|
3906
|
-
zIndex: 9999,
|
|
3907
|
-
minWidth: "12.5rem",
|
|
3908
|
-
// 200px
|
|
3909
|
-
backgroundColor: "rgba(17, 24, 39, 0.95)",
|
|
3910
|
-
backdropFilter: "blur(8px)",
|
|
3911
|
-
transition: "opacity 0.3s ease"
|
|
3912
|
-
},
|
|
3913
|
-
children: [ jsxs("div", {
|
|
3914
|
-
className: "u-flex u-items-center u-justify-between u-mb-2 u-pb-2 u-border-b u-border-white-alpha-10",
|
|
3915
|
-
children: [ jsx("span", {
|
|
3916
|
-
className: "u-text-sm u-font-bold u-text-white",
|
|
3917
|
-
children: "Performance Monitor"
|
|
3918
|
-
}), onClose && jsx("button", {
|
|
3919
|
-
className: "u-bg-transparent u-border-none u-p-0 u-line-height-1 u-text-base u-text-gray-400 u-cursor-pointer hover:u-text-white",
|
|
3920
|
-
onClick: onClose,
|
|
3921
|
-
"aria-label": "Close performance dashboard",
|
|
3922
|
-
style: {
|
|
3923
|
-
transition: "color 0.2s ease"
|
|
3924
|
-
},
|
|
3925
|
-
children: "×"
|
|
3926
|
-
}) ]
|
|
3927
|
-
}), jsxs("div", {
|
|
3928
|
-
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
3929
|
-
children: [ jsx("span", {
|
|
3930
|
-
className: "u-text-gray-400 u-me-3",
|
|
3931
|
-
children: "FPS"
|
|
3932
|
-
}), jsx("span", {
|
|
3933
|
-
className: "u-font-bold",
|
|
3934
|
-
style: {
|
|
3935
|
-
color: fpsColor
|
|
3936
|
-
},
|
|
3937
|
-
children: Math.round(metrics.fps)
|
|
3938
|
-
}) ]
|
|
3939
|
-
}), jsxs("div", {
|
|
3940
|
-
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
3941
|
-
children: [ jsx("span", {
|
|
3942
|
-
className: "u-text-gray-400 u-me-3",
|
|
3943
|
-
children: "Frame Time"
|
|
3944
|
-
}), jsxs("span", {
|
|
3945
|
-
className: "u-font-bold",
|
|
3946
|
-
children: [ metrics.frameTime.toFixed(2), "ms" ]
|
|
3947
|
-
}) ]
|
|
3948
|
-
}), jsxs("div", {
|
|
3949
|
-
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
3950
|
-
children: [ jsx("span", {
|
|
3951
|
-
className: "u-text-gray-400 u-me-3",
|
|
3952
|
-
children: "Quality"
|
|
3953
|
-
}), jsx("span", {
|
|
3954
|
-
className: "u-font-bold u-text-uppercase",
|
|
3955
|
-
style: {
|
|
3956
|
-
fontSize: "0.6875rem",
|
|
3957
|
-
// 11px
|
|
3958
|
-
color: getQualityColor(metrics.qualityLevel)
|
|
3959
|
-
},
|
|
3960
|
-
children: metrics.qualityLevel
|
|
3961
|
-
}) ]
|
|
3962
|
-
}), metrics.gpuMemory && jsxs("div", {
|
|
3963
|
-
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
3964
|
-
children: [ jsx("span", {
|
|
3965
|
-
className: "u-text-gray-400 u-me-3",
|
|
3966
|
-
children: "GPU Memory"
|
|
3967
|
-
}), jsxs("span", {
|
|
3968
|
-
className: "u-font-bold",
|
|
3969
|
-
children: [ "~", Math.round(metrics.gpuMemory / 1024), "MB" ]
|
|
3970
|
-
}) ]
|
|
3971
|
-
}), metrics.isAutoScaling && jsx("div", {
|
|
3972
|
-
className: "u-mt-2 u-pt-2 u-border-t u-border-white-alpha-10 u-text-center",
|
|
3973
|
-
style: {
|
|
3974
|
-
fontSize: "0.625rem",
|
|
3975
|
-
// 10px
|
|
3976
|
-
color: "#6b7280"
|
|
3977
|
-
},
|
|
3978
|
-
children: "Auto-scaling active"
|
|
3979
|
-
}), jsxs("div", {
|
|
3980
|
-
className: "u-flex u-items-center u-gap-2 u-mt-2 u-pt-2 u-border-t u-border-white-alpha-10",
|
|
3981
|
-
children: [ jsx("div", {
|
|
3982
|
-
className: "u-rounded-full",
|
|
3983
|
-
style: {
|
|
3984
|
-
width: "0.5rem",
|
|
3985
|
-
height: "0.5rem",
|
|
3986
|
-
flexShrink: 0,
|
|
3987
|
-
backgroundColor: fpsColor,
|
|
3988
|
-
...isCritical && {
|
|
3989
|
-
animation: "perf-dashboard-pulse 1s infinite"
|
|
3990
|
-
}
|
|
3991
|
-
}
|
|
3992
|
-
}), jsx("span", {
|
|
3993
|
-
className: "u-text-xs",
|
|
3994
|
-
style: {
|
|
3995
|
-
fontSize: "0.625rem",
|
|
3996
|
-
// 10px
|
|
3997
|
-
color: fpsColor
|
|
3998
|
-
},
|
|
3999
|
-
children: getFpsLabel(metrics.fps)
|
|
4000
|
-
}) ]
|
|
4001
|
-
}) ]
|
|
4002
|
-
});
|
|
4003
|
-
}));
|
|
4004
|
-
|
|
4005
|
-
PerformanceDashboard.displayName = "PerformanceDashboard";
|
|
4006
|
-
|
|
4007
4268
|
/**
|
|
4008
4269
|
* Mobile optimization presets
|
|
4009
4270
|
*
|
|
@@ -4013,8 +4274,7 @@ PerformanceDashboard.displayName = "PerformanceDashboard";
|
|
|
4013
4274
|
/**
|
|
4014
4275
|
* Performance preset - Maximum FPS, reduced quality
|
|
4015
4276
|
* Best for low-end devices or when battery saving is priority
|
|
4016
|
-
*/
|
|
4017
|
-
const PERFORMANCE_PRESET = {
|
|
4277
|
+
*/ const PERFORMANCE_PRESET = {
|
|
4018
4278
|
distortionOctaves: 2,
|
|
4019
4279
|
// Minimal FBM layers
|
|
4020
4280
|
displacementScale: 50,
|
|
@@ -4177,18 +4437,13 @@ function getDevicePreset(presetName) {
|
|
|
4177
4437
|
getPixelRatio: () => "undefined" == typeof window ? 1 : window.devicePixelRatio || 1,
|
|
4178
4438
|
/** Check if device has touch support */
|
|
4179
4439
|
hasTouchSupport: () => "undefined" != typeof window && ("ontouchstart" in window || navigator.maxTouchPoints > 0)
|
|
4180
|
-
}, AtomixGlassInner = forwardRef((function({children: children, displacementScale: displacementScale = ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, aberrationIntensity: aberrationIntensity = ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer = null, className: className = "",
|
|
4181
|
-
const glassRef = useRef(null), contentRef = useRef(null), internalWrapperRef = useRef(null), mergedRef =
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
}));
|
|
4188
|
-
};
|
|
4189
|
-
}
|
|
4190
|
-
// Internal implementation with forwardRef
|
|
4191
|
-
(ref, internalWrapperRef)), [ ref ]), {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = propsIsFixedOrSticky || "fixed" === restStyle.position || "sticky" === restStyle.position, {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, getShaderTime: getShaderTime, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
|
|
4440
|
+
}, AtomixGlassInner = forwardRef((function({children: children, displacementScale: displacementScale = ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, aberrationIntensity: aberrationIntensity = ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer = null, className: className = "", overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, style: style = {}, mode: mode = ATOMIX_GLASS.DEFAULTS.MODE, onClick: onClick, shaderVariant: shaderVariant = "liquidGlass", "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, role: role, tabIndex: tabIndex, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, withLiquidBlur: withLiquidBlur = !1, border: border, withBorder: withBorder = !0, debugBorderRadius: debugBorderRadius = !1, withOverLightLayers: withOverLightLayers = ATOMIX_GLASS.DEFAULTS.ENABLE_OVER_LIGHT_LAYERS, debugPerformance: debugPerformance = !1, debugOverLight: debugOverLight = !1, height: height, width: width, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", devicePreset: devicePreset = "balanced", disableResponsiveBreakpoints: disableResponsiveBreakpoints = !1, isFixedOrSticky: propsIsFixedOrSticky, ...rest}, ref) {
|
|
4441
|
+
const glassRef = useRef(null), contentRef = useRef(null), internalWrapperRef = useRef(null), mergedRef = useForkRef(ref, internalWrapperRef), {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = (explicit = propsIsFixedOrSticky,
|
|
4442
|
+
position = restStyle.position, Boolean(explicit || "fixed" === position || "sticky" === position));
|
|
4443
|
+
var explicit, position;
|
|
4444
|
+
/**
|
|
4445
|
+
* Extracts layout-related properties from a React `CSSProperties` object.
|
|
4446
|
+
*/ const {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown, resolvedBorder: resolvedBorder} = useAtomixGlass({
|
|
4192
4447
|
glassRef: glassRef,
|
|
4193
4448
|
contentRef: contentRef,
|
|
4194
4449
|
wrapperRef: internalWrapperRef,
|
|
@@ -4208,19 +4463,12 @@ function getDevicePreset(presetName) {
|
|
|
4208
4463
|
blurAmount: blurAmount,
|
|
4209
4464
|
saturation: saturation,
|
|
4210
4465
|
withLiquidBlur: withLiquidBlur,
|
|
4211
|
-
|
|
4466
|
+
border: border,
|
|
4467
|
+
withBorder: withBorder,
|
|
4468
|
+
debugBorderRadius: debugBorderRadius,
|
|
4212
4469
|
style: style,
|
|
4213
|
-
isFixedOrSticky: isFixedOrSticky
|
|
4214
|
-
// Phase 1: Animation System props
|
|
4215
|
-
withTimeAnimation: withTimeAnimation,
|
|
4216
|
-
animationSpeed: animationSpeed,
|
|
4217
|
-
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
4218
|
-
distortionOctaves: distortionOctaves,
|
|
4219
|
-
distortionLacunarity: distortionLacunarity,
|
|
4220
|
-
distortionGain: distortionGain,
|
|
4221
|
-
distortionQuality: distortionQuality
|
|
4470
|
+
isFixedOrSticky: isFixedOrSticky
|
|
4222
4471
|
});
|
|
4223
|
-
// Responsive breakpoint system - automatically adjusts parameters based on viewport
|
|
4224
4472
|
useResponsiveGlass({
|
|
4225
4473
|
baseParams: {
|
|
4226
4474
|
...useMemo((() => getDevicePreset(devicePreset)), [ devicePreset ]),
|
|
@@ -4235,185 +4483,213 @@ function getDevicePreset(presetName) {
|
|
|
4235
4483
|
breakpoints: MOBILE_OPTIMIZED_BREAKPOINTS,
|
|
4236
4484
|
enabled: !disableResponsiveBreakpoints && "undefined" != typeof window,
|
|
4237
4485
|
debug: !1
|
|
4238
|
-
})
|
|
4239
|
-
// Performance monitoring - tracks FPS, frame time, memory usage
|
|
4240
|
-
const {metrics: performanceMetrics, toggleMonitoring: toggleMonitoring} = usePerformanceMonitor$1({
|
|
4486
|
+
}), usePerformanceMonitor$1({
|
|
4241
4487
|
enabled: debugPerformance,
|
|
4242
|
-
// Enable when debugPerformance is true
|
|
4243
4488
|
debug: !1,
|
|
4244
4489
|
showOverlay: !1
|
|
4245
4490
|
});
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
}), [ debugPerformance ]);
|
|
4251
|
-
// Re-run when debugPerformance changes
|
|
4252
|
-
const isOverLight = useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, rootLayoutStyle = useMemo((() => {
|
|
4253
|
-
if (!isFixedOrSticky) return {};
|
|
4254
|
-
const {position: p, top: t, left: l, right: r, bottom: b} = restStyle;
|
|
4255
|
-
return {
|
|
4256
|
-
...p && {
|
|
4257
|
-
position: p
|
|
4258
|
-
},
|
|
4259
|
-
...void 0 !== t && {
|
|
4260
|
-
top: t
|
|
4261
|
-
},
|
|
4262
|
-
...void 0 !== l && {
|
|
4263
|
-
left: l
|
|
4264
|
-
},
|
|
4265
|
-
...void 0 !== r && {
|
|
4266
|
-
right: r
|
|
4267
|
-
},
|
|
4268
|
-
...void 0 !== b && {
|
|
4269
|
-
bottom: b
|
|
4270
|
-
}
|
|
4271
|
-
};
|
|
4272
|
-
}), [ isFixedOrSticky, restStyle ]);
|
|
4273
|
-
// Calculate base style with transforms
|
|
4274
|
-
// When layout is hoisted to the root, strip those props from the container
|
|
4275
|
-
useMemo((() => {
|
|
4276
|
-
if (isFixedOrSticky) {
|
|
4277
|
-
const {position: _p, top: _t, left: _l, right: _r, bottom: _b, ...visualStyle} = restStyle;
|
|
4278
|
-
return {
|
|
4279
|
-
...visualStyle
|
|
4280
|
-
};
|
|
4491
|
+
const isOverLight = useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, containerStyle = useMemo((() => ({
|
|
4492
|
+
...restStyle,
|
|
4493
|
+
...void 0 !== customZIndex && {
|
|
4494
|
+
zIndex: customZIndex
|
|
4281
4495
|
}
|
|
4496
|
+
})), [ restStyle, customZIndex ]), componentClassName = mergeClassNames(ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveWithoutEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className), positionStyles = useMemo((() =>
|
|
4497
|
+
/**
|
|
4498
|
+
* Returns the internal positioning context for effect layers relative to the root.
|
|
4499
|
+
*/
|
|
4500
|
+
function(isFixedOrSticky, restStyle) {
|
|
4282
4501
|
return {
|
|
4283
|
-
|
|
4502
|
+
position: isFixedOrSticky ? "absolute" : restStyle.position || "absolute",
|
|
4503
|
+
top: 0,
|
|
4504
|
+
left: 0,
|
|
4505
|
+
right: "auto",
|
|
4506
|
+
bottom: "auto"
|
|
4284
4507
|
};
|
|
4285
|
-
}
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
})), [ isFixedOrSticky, restStyle.position, restStyle.top, restStyle.left, restStyle.right, restStyle.bottom ]), adjustedSize = useMemo((() => {
|
|
4294
|
-
// Keep a reference to positionStyles to avoid unused-variable lint,
|
|
4295
|
-
// but sizing is driven by explicit width/height or measured size.
|
|
4296
|
-
positionStyles.position;
|
|
4297
|
-
const resolveLength = (value, measured) => void 0 !== value && isFixedOrSticky ? "number" == typeof value ? `${value}px` : value : measured > 0 && isFixedOrSticky ? `${measured}px` : "100%", effectiveWidth = width ?? restStyle.width, effectiveHeight = height ?? restStyle.height;
|
|
4508
|
+
}
|
|
4509
|
+
/**
|
|
4510
|
+
* Computes `--atomix-glass-width` and `--atomix-glass-height` values.
|
|
4511
|
+
*
|
|
4512
|
+
* Fixed/sticky elements prefer explicit dimensions or measured size; in-flow
|
|
4513
|
+
* elements default to `100%`.
|
|
4514
|
+
*/ (isFixedOrSticky, restStyle)), [ isFixedOrSticky, restStyle ]), adjustedSize = useMemo((() => function(options) {
|
|
4515
|
+
const {width: width, height: height, restStyle: restStyle, glassSize: glassSize, isFixedOrSticky: isFixedOrSticky} = options, resolveLength = (value, measured) => void 0 !== value && isFixedOrSticky ? "number" == typeof value ? `${value}px` : value : measured > 0 && isFixedOrSticky ? `${measured}px` : "100%", effectiveWidth = width ?? restStyle.width, effectiveHeight = height ?? restStyle.height;
|
|
4298
4516
|
return {
|
|
4299
4517
|
width: resolveLength(effectiveWidth, glassSize.width),
|
|
4300
4518
|
height: resolveLength(effectiveHeight, glassSize.height)
|
|
4301
4519
|
};
|
|
4302
|
-
}
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4520
|
+
}
|
|
4521
|
+
/**
|
|
4522
|
+
* Builds the CSS custom properties applied to the root `.c-atomix-glass` element.
|
|
4523
|
+
*
|
|
4524
|
+
* These variables drive layer geometry, transforms, and stacking offsets. They
|
|
4525
|
+
* must not include layout properties that would interfere with backdrop-filter.
|
|
4526
|
+
*/ ({
|
|
4527
|
+
width: width,
|
|
4528
|
+
height: height,
|
|
4529
|
+
restStyle: restStyle,
|
|
4530
|
+
glassSize: glassSize,
|
|
4531
|
+
isFixedOrSticky: isFixedOrSticky
|
|
4532
|
+
})), [ width, height, restStyle, glassSize, isFixedOrSticky ]), glassVars = useMemo((() => function(input) {
|
|
4533
|
+
const {effectiveBorderRadius: effectiveBorderRadius, transformStyle: transformStyle, adjustedSize: adjustedSize, isOverLight: isOverLight, customZIndex: customZIndex, isFixedOrSticky: isFixedOrSticky, positionStyles: positionStyles, restStyle: restStyle, borderWidth: borderWidth = ATOMIX_GLASS.BORDER.DEFAULT_WIDTH} = input, layerPosition =
|
|
4534
|
+
/**
|
|
4535
|
+
* Resolves the `--atomix-glass-position` value for decorative layers.
|
|
4536
|
+
*
|
|
4537
|
+
* Fixed/sticky layers use the same positioning mode as the container; in-flow
|
|
4538
|
+
* layers default to the internal absolute positioning context.
|
|
4539
|
+
*/
|
|
4540
|
+
function(isFixedOrSticky, positionStyles, restStyle) {
|
|
4541
|
+
return isFixedOrSticky ? `${function(style) {
|
|
4542
|
+
const {position: position, top: top, left: left, right: right, bottom: bottom, inset: inset} = style;
|
|
4543
|
+
return {
|
|
4544
|
+
...null != position && {
|
|
4545
|
+
position: position
|
|
4546
|
+
},
|
|
4547
|
+
...void 0 !== top && {
|
|
4548
|
+
top: top
|
|
4549
|
+
},
|
|
4550
|
+
...void 0 !== left && {
|
|
4551
|
+
left: left
|
|
4552
|
+
},
|
|
4553
|
+
...void 0 !== right && {
|
|
4554
|
+
right: right
|
|
4555
|
+
},
|
|
4556
|
+
...void 0 !== bottom && {
|
|
4557
|
+
bottom: bottom
|
|
4558
|
+
},
|
|
4559
|
+
...void 0 !== inset && {
|
|
4560
|
+
inset: inset
|
|
4561
|
+
}
|
|
4562
|
+
};
|
|
4563
|
+
}
|
|
4564
|
+
/**
|
|
4565
|
+
* Resolves inset custom properties for decorative layers (hover, borders, backgrounds).
|
|
4566
|
+
*
|
|
4567
|
+
* For fixed and sticky modes, insets mirror the container so sibling layers remain
|
|
4568
|
+
* aligned. In-flow modes, insets follow the consumer `style` when a non-default
|
|
4569
|
+
* `position` is provided.
|
|
4570
|
+
*/ (restStyle).position ?? restStyle.position ?? "fixed"}` : `${positionStyles.position}`;
|
|
4571
|
+
}(isFixedOrSticky, positionStyles, restStyle), layerInsets = function(isFixedOrSticky, restStyle) {
|
|
4572
|
+
if (isFixedOrSticky) return {
|
|
4573
|
+
top: formatGlassInsetValue(restStyle.top, 0),
|
|
4574
|
+
left: formatGlassInsetValue(restStyle.left, 0),
|
|
4575
|
+
right: formatGlassInsetValue(restStyle.right, "auto"),
|
|
4576
|
+
bottom: formatGlassInsetValue(restStyle.bottom, "auto")
|
|
4577
|
+
};
|
|
4578
|
+
const position = restStyle.position;
|
|
4579
|
+
return null != position && "static" !== position && "relative" !== position ? {
|
|
4580
|
+
top: formatGlassInsetValue(restStyle.top, 0),
|
|
4581
|
+
left: formatGlassInsetValue(restStyle.left, 0),
|
|
4582
|
+
right: formatGlassInsetValue(restStyle.right, "auto"),
|
|
4583
|
+
bottom: formatGlassInsetValue(restStyle.bottom, "auto")
|
|
4584
|
+
} : {
|
|
4585
|
+
top: "0px",
|
|
4586
|
+
left: "0px",
|
|
4587
|
+
right: "auto",
|
|
4588
|
+
bottom: "auto"
|
|
4589
|
+
};
|
|
4590
|
+
}(isFixedOrSticky, restStyle);
|
|
4340
4591
|
return {
|
|
4341
4592
|
...void 0 !== customZIndex && {
|
|
4342
4593
|
"--atomix-glass-base-z-index": customZIndex
|
|
4343
4594
|
},
|
|
4344
4595
|
"--atomix-glass-radius": `${effectiveBorderRadius}px`,
|
|
4345
4596
|
"--atomix-glass-transform": transformStyle || "none",
|
|
4346
|
-
"--atomix-glass-container-position":
|
|
4347
|
-
"--atomix-glass-position":
|
|
4348
|
-
"--atomix-glass-top":
|
|
4349
|
-
"--atomix-glass-left":
|
|
4350
|
-
"--atomix-glass-right":
|
|
4351
|
-
"--atomix-glass-bottom":
|
|
4597
|
+
"--atomix-glass-container-position": layerPosition,
|
|
4598
|
+
"--atomix-glass-position": layerPosition,
|
|
4599
|
+
"--atomix-glass-top": layerInsets.top,
|
|
4600
|
+
"--atomix-glass-left": layerInsets.left,
|
|
4601
|
+
"--atomix-glass-right": layerInsets.right,
|
|
4602
|
+
"--atomix-glass-bottom": layerInsets.bottom,
|
|
4352
4603
|
"--atomix-glass-width": adjustedSize.width,
|
|
4353
4604
|
"--atomix-glass-height": adjustedSize.height,
|
|
4354
|
-
|
|
4355
|
-
"--atomix-glass-
|
|
4356
|
-
"--atomix-glass-
|
|
4357
|
-
|
|
4358
|
-
"--atomix-glass-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4605
|
+
// Aliases maintained for backward compatibility and consumer overrides.
|
|
4606
|
+
"--atomix-glass-container-width": adjustedSize.width,
|
|
4607
|
+
"--atomix-glass-container-height": adjustedSize.height,
|
|
4608
|
+
[ATOMIX_GLASS.BORDER.WIDTH_CSS_VAR]: borderWidth,
|
|
4609
|
+
"--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay"
|
|
4610
|
+
};
|
|
4611
|
+
}
|
|
4612
|
+
/**
|
|
4613
|
+
* Applies mode-specific multipliers and accessibility overrides to container effects.
|
|
4614
|
+
*/ ({
|
|
4615
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
4616
|
+
transformStyle: transformStyle,
|
|
4617
|
+
adjustedSize: adjustedSize,
|
|
4618
|
+
isOverLight: isOverLight,
|
|
4619
|
+
customZIndex: customZIndex,
|
|
4620
|
+
isFixedOrSticky: isFixedOrSticky,
|
|
4621
|
+
positionStyles: positionStyles,
|
|
4622
|
+
restStyle: restStyle,
|
|
4623
|
+
borderWidth: resolvedBorder.width
|
|
4624
|
+
})), [ effectiveBorderRadius, transformStyle, adjustedSize, isOverLight, customZIndex, isFixedOrSticky, positionStyles, restStyle, resolvedBorder.width ]), containerEffects = useMemo((() => function(options) {
|
|
4625
|
+
const {MULTIPLIERS: MULTIPLIERS, SATURATION: SATURATION} = ATOMIX_GLASS.CONSTANTS, zeroMouse = {
|
|
4626
|
+
x: 0,
|
|
4627
|
+
y: 0
|
|
4628
|
+
}, resolveSaturation = () => options.effectiveHighContrast ? SATURATION.HIGH_CONTRAST : options.isOverLight ? options.saturation * options.saturationBoost : options.saturation;
|
|
4629
|
+
if (options.effectiveWithoutEffects) return {
|
|
4630
|
+
displacementScale: 0,
|
|
4631
|
+
blurAmount: 0,
|
|
4632
|
+
saturation: resolveSaturation(),
|
|
4633
|
+
aberrationIntensity: 0,
|
|
4634
|
+
mouseOffset: zeroMouse,
|
|
4635
|
+
globalMousePosition: zeroMouse
|
|
4636
|
+
};
|
|
4637
|
+
let resolvedDisplacement = options.displacementScale;
|
|
4638
|
+
"shader" === options.mode ? resolvedDisplacement *= MULTIPLIERS.SHADER_DISPLACEMENT : options.isOverLight && (resolvedDisplacement *= MULTIPLIERS.OVER_LIGHT_DISPLACEMENT);
|
|
4639
|
+
let resolvedAberration = options.aberrationIntensity;
|
|
4640
|
+
return "shader" === options.mode && (resolvedAberration *= MULTIPLIERS.SHADER_ABERRATION),
|
|
4641
|
+
{
|
|
4642
|
+
displacementScale: resolvedDisplacement,
|
|
4643
|
+
blurAmount: options.blurAmount,
|
|
4644
|
+
saturation: resolveSaturation(),
|
|
4645
|
+
aberrationIntensity: resolvedAberration,
|
|
4646
|
+
mouseOffset: options.mouseOffset,
|
|
4647
|
+
globalMousePosition: options.globalMousePosition
|
|
4370
4648
|
};
|
|
4371
|
-
}
|
|
4372
|
-
|
|
4649
|
+
}({
|
|
4650
|
+
displacementScale: displacementScale,
|
|
4651
|
+
blurAmount: blurAmount,
|
|
4652
|
+
saturation: saturation,
|
|
4653
|
+
aberrationIntensity: aberrationIntensity,
|
|
4654
|
+
mode: mode,
|
|
4655
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
4656
|
+
effectiveHighContrast: effectiveHighContrast,
|
|
4657
|
+
isOverLight: isOverLight,
|
|
4658
|
+
saturationBoost: overLightConfig.saturationBoost,
|
|
4659
|
+
mouseOffset: mouseOffset,
|
|
4660
|
+
globalMousePosition: globalMousePosition
|
|
4661
|
+
})), [ displacementScale, blurAmount, saturation, aberrationIntensity, mode, effectiveWithoutEffects, effectiveHighContrast, isOverLight, overLightConfig.saturationBoost, mouseOffset, globalMousePosition ]), renderBackgroundLayer = layerType => jsx("div", {
|
|
4662
|
+
"aria-hidden": "true",
|
|
4663
|
+
className: mergeClassNames(ATOMIX_GLASS.BACKGROUND_LAYER_CLASS, "dark" === layerType ? ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS, isOverLight ? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS)
|
|
4373
4664
|
});
|
|
4374
|
-
|
|
4375
|
-
// When root is fixed/sticky, internal layers use absolute (relative to root)
|
|
4376
|
-
return jsxs("div", {
|
|
4665
|
+
return jsxs("div", {
|
|
4377
4666
|
...rest,
|
|
4378
4667
|
ref: mergedRef,
|
|
4379
4668
|
className: componentClassName,
|
|
4380
|
-
style:
|
|
4381
|
-
...glassVars
|
|
4382
|
-
},
|
|
4669
|
+
style: glassVars,
|
|
4383
4670
|
role: role || (onClick ? "button" : void 0),
|
|
4384
4671
|
tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
|
|
4385
4672
|
"aria-label": ariaLabel,
|
|
4386
4673
|
"aria-describedby": ariaDescribedBy,
|
|
4387
4674
|
"aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
|
|
4388
|
-
"aria-pressed": onClick ? isActive : void 0,
|
|
4389
4675
|
onKeyDown: onClick ? handleKeyDown : void 0,
|
|
4390
4676
|
children: [ jsx(AtomixGlassContainer, {
|
|
4391
4677
|
ref: glassRef,
|
|
4392
4678
|
contentRef: contentRef,
|
|
4393
4679
|
className: className,
|
|
4394
|
-
style:
|
|
4395
|
-
...restStyle
|
|
4396
|
-
},
|
|
4680
|
+
style: containerStyle,
|
|
4397
4681
|
borderRadius: effectiveBorderRadius,
|
|
4398
|
-
displacementScale:
|
|
4399
|
-
blurAmount:
|
|
4400
|
-
saturation:
|
|
4401
|
-
aberrationIntensity:
|
|
4682
|
+
displacementScale: containerEffects.displacementScale,
|
|
4683
|
+
blurAmount: containerEffects.blurAmount,
|
|
4684
|
+
saturation: containerEffects.saturation,
|
|
4685
|
+
aberrationIntensity: containerEffects.aberrationIntensity,
|
|
4402
4686
|
glassSize: glassSize,
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
x: 0,
|
|
4406
|
-
y: 0
|
|
4407
|
-
} : mouseOffset,
|
|
4408
|
-
globalMousePosition: effectiveWithoutEffects ? {
|
|
4409
|
-
x: 0,
|
|
4410
|
-
y: 0
|
|
4411
|
-
} : globalMousePosition,
|
|
4687
|
+
mouseOffset: containerEffects.mouseOffset,
|
|
4688
|
+
globalMousePosition: containerEffects.globalMousePosition,
|
|
4412
4689
|
onMouseEnter: handleMouseEnter,
|
|
4413
4690
|
onMouseLeave: handleMouseLeave,
|
|
4414
4691
|
onMouseDown: handleMouseDown,
|
|
4415
4692
|
onMouseUp: handleMouseUp,
|
|
4416
|
-
isHovered: isHovered,
|
|
4417
4693
|
isActive: isActive,
|
|
4418
4694
|
overLight: isOverLight,
|
|
4419
4695
|
overLightConfig: {
|
|
@@ -4429,8 +4705,6 @@ function getDevicePreset(presetName) {
|
|
|
4429
4705
|
shaderVariant: shaderVariant,
|
|
4430
4706
|
withLiquidBlur: withLiquidBlur,
|
|
4431
4707
|
isFixedOrSticky: isFixedOrSticky,
|
|
4432
|
-
// Phase 1: Animation System props
|
|
4433
|
-
shaderTime: getShaderTime(),
|
|
4434
4708
|
withTimeAnimation: withTimeAnimation,
|
|
4435
4709
|
animationSpeed: animationSpeed,
|
|
4436
4710
|
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
@@ -4441,42 +4715,129 @@ function getDevicePreset(presetName) {
|
|
|
4441
4715
|
children: children
|
|
4442
4716
|
}), Boolean(onClick) && jsxs(Fragment, {
|
|
4443
4717
|
children: [ jsx("div", {
|
|
4718
|
+
"aria-hidden": "true",
|
|
4444
4719
|
className: ATOMIX_GLASS.HOVER_1_CLASS
|
|
4445
4720
|
}), jsx("div", {
|
|
4721
|
+
"aria-hidden": "true",
|
|
4446
4722
|
className: ATOMIX_GLASS.HOVER_2_CLASS
|
|
4447
4723
|
}), jsx("div", {
|
|
4724
|
+
"aria-hidden": "true",
|
|
4448
4725
|
className: ATOMIX_GLASS.HOVER_3_CLASS
|
|
4449
4726
|
}) ]
|
|
4450
|
-
}),
|
|
4727
|
+
}), [ "dark", "black" ].map((layerType => jsx(React.Fragment, {
|
|
4728
|
+
children: renderBackgroundLayer(layerType)
|
|
4729
|
+
}, layerType))), shouldRenderOverLightLayers && jsxs(Fragment, {
|
|
4451
4730
|
children: [ jsx("div", {
|
|
4731
|
+
"aria-hidden": "true",
|
|
4452
4732
|
className: ATOMIX_GLASS.BASE_LAYER_CLASS
|
|
4453
4733
|
}), jsx("div", {
|
|
4734
|
+
"aria-hidden": "true",
|
|
4454
4735
|
className: ATOMIX_GLASS.OVERLAY_LAYER_CLASS
|
|
4455
4736
|
}), jsx("div", {
|
|
4737
|
+
"aria-hidden": "true",
|
|
4456
4738
|
className: ATOMIX_GLASS.OVERLAY_HIGHLIGHT_CLASS
|
|
4457
4739
|
}) ]
|
|
4458
|
-
}),
|
|
4740
|
+
}), resolvedBorder.enabled && jsxs(Fragment, {
|
|
4459
4741
|
children: [ jsx("span", {
|
|
4742
|
+
"aria-hidden": "true",
|
|
4460
4743
|
className: ATOMIX_GLASS.BORDER_BACKDROP_CLASS
|
|
4461
4744
|
}), jsx("span", {
|
|
4745
|
+
"aria-hidden": "true",
|
|
4462
4746
|
className: ATOMIX_GLASS.BORDER_1_CLASS
|
|
4463
4747
|
}), jsx("span", {
|
|
4748
|
+
"aria-hidden": "true",
|
|
4464
4749
|
className: ATOMIX_GLASS.BORDER_2_CLASS
|
|
4465
4750
|
}) ]
|
|
4466
|
-
}), debugPerformance && performanceMetrics && jsx(PerformanceDashboard, {
|
|
4467
|
-
metrics: performanceMetrics,
|
|
4468
|
-
isVisible: !0,
|
|
4469
|
-
onClose: () => {}
|
|
4470
4751
|
}) ]
|
|
4471
4752
|
});
|
|
4472
4753
|
}));
|
|
4473
4754
|
|
|
4474
|
-
AtomixGlassInner.displayName = "AtomixGlass";
|
|
4475
|
-
|
|
4476
4755
|
/**
|
|
4477
|
-
* AtomixGlass -
|
|
4478
|
-
*
|
|
4756
|
+
* AtomixGlass - A high-performance glass morphism component with liquid distortion effects
|
|
4757
|
+
*
|
|
4758
|
+
* Features:
|
|
4759
|
+
* - Hardware-accelerated glass effects with SVG filters
|
|
4760
|
+
* - Mouse-responsive liquid distortion
|
|
4761
|
+
* - Dynamic border-radius extraction from children CSS properties
|
|
4762
|
+
* - Automatic light/dark theme detection via overLight prop
|
|
4763
|
+
* - Accessibility and performance optimizations
|
|
4764
|
+
* - Multiple displacement modes (standard, polar, prominent, shader)
|
|
4765
|
+
* - Design token integration for consistent theming
|
|
4766
|
+
* - Focus ring support for keyboard navigation
|
|
4767
|
+
* - Responsive breakpoints for mobile optimization
|
|
4768
|
+
* - Enhanced ARIA attributes for screen readers
|
|
4769
|
+
* - Time-based animation system with FBM distortion
|
|
4770
|
+
* - Device preset optimization for performance/quality balance
|
|
4771
|
+
*
|
|
4772
|
+
* Design System Compliance:
|
|
4773
|
+
* - Uses design tokens for opacity, spacing, and colors
|
|
4774
|
+
* - Follows BEM methodology for class naming
|
|
4775
|
+
* - Implements focus-ring mixin for accessibility
|
|
4776
|
+
* - Supports reduced motion and high contrast preferences
|
|
4777
|
+
*
|
|
4778
|
+
* Style architecture:
|
|
4779
|
+
* - Root (`.c-atomix-glass`): CSS custom properties for layer geometry and motion.
|
|
4780
|
+
* - Container (`.c-atomix-glass__container`): layout, z-index, and backdrop-filter.
|
|
4781
|
+
*
|
|
4782
|
+
* @example
|
|
4783
|
+
* // Basic usage with dynamic border-radius extraction
|
|
4784
|
+
* <AtomixGlass>
|
|
4785
|
+
* <div style={{ borderRadius: '12px' }}>Content with 12px radius</div>
|
|
4786
|
+
* </AtomixGlass>
|
|
4787
|
+
*
|
|
4788
|
+
* @example
|
|
4789
|
+
* // Manual border-radius override
|
|
4790
|
+
* <AtomixGlass borderRadius={20}>
|
|
4791
|
+
* <div>Content with 20px glass radius</div>
|
|
4792
|
+
* </AtomixGlass>
|
|
4793
|
+
*
|
|
4794
|
+
* @example
|
|
4795
|
+
* // Interactive glass with click handler
|
|
4796
|
+
* <AtomixGlass onClick={() => console.log('Clicked')} aria-label="Glass card">
|
|
4797
|
+
* <div>Clickable content</div>
|
|
4798
|
+
* </AtomixGlass>
|
|
4799
|
+
*
|
|
4800
|
+
* @example
|
|
4801
|
+
* // OverLight - Boolean mode (explicit control)
|
|
4802
|
+
* <AtomixGlass overLight={true}>
|
|
4803
|
+
* <div>Content on light background</div>
|
|
4804
|
+
* </AtomixGlass>
|
|
4805
|
+
*
|
|
4806
|
+
* @example
|
|
4807
|
+
* // OverLight - Auto-detection mode
|
|
4808
|
+
* <AtomixGlass overLight="auto">
|
|
4809
|
+
* <div>Content with auto-detected background</div>
|
|
4810
|
+
* </AtomixGlass>
|
|
4811
|
+
*
|
|
4812
|
+
* @example
|
|
4813
|
+
* // OverLight - Object config with custom settings
|
|
4814
|
+
* <AtomixGlass
|
|
4815
|
+
* overLight={{
|
|
4816
|
+
* threshold: 0.8,
|
|
4817
|
+
* opacity: 0.6,
|
|
4818
|
+
* contrast: 1.8,
|
|
4819
|
+
* brightness: 1.0,
|
|
4820
|
+
* saturationBoost: 1.5
|
|
4821
|
+
* }}
|
|
4822
|
+
* >
|
|
4823
|
+
* <div>Content with custom overLight config</div>
|
|
4824
|
+
* </AtomixGlass>
|
|
4825
|
+
*
|
|
4826
|
+
* @example
|
|
4827
|
+
* // Debug mode for overLight detection
|
|
4828
|
+
* <AtomixGlass overLight="auto" debugOverLight={true}>
|
|
4829
|
+
* <div>Content with debug logging enabled</div>
|
|
4830
|
+
* </AtomixGlass>
|
|
4831
|
+
*
|
|
4832
|
+
* @example
|
|
4833
|
+
* // Performance-optimized for mobile devices
|
|
4834
|
+
* <AtomixGlass devicePreset="performance" disableResponsiveBreakpoints={false}>
|
|
4835
|
+
* <div>Mobile-optimized glass effect</div>
|
|
4836
|
+
* </AtomixGlass>
|
|
4479
4837
|
*/
|
|
4838
|
+
/** Internal implementation; ref is forwarded to the root wrapper element. */ AtomixGlassInner.displayName = "AtomixGlass";
|
|
4839
|
+
|
|
4840
|
+
/** Memoized public export. Ref targets the root `.c-atomix-glass` wrapper. */
|
|
4480
4841
|
const AtomixGlass = memo(AtomixGlassInner), DefaultIcon = () => jsx("i", {
|
|
4481
4842
|
className: "c-accordion__icon",
|
|
4482
4843
|
"aria-hidden": "true",
|
|
@@ -4604,10 +4965,7 @@ const AccordionImpl = memo((({title: title, children: children, defaultOpen: de
|
|
|
4604
4965
|
});
|
|
4605
4966
|
if (glass) {
|
|
4606
4967
|
// Default glass settings for accordions
|
|
4607
|
-
const defaultGlassProps = {
|
|
4608
|
-
displacementScale: 20,
|
|
4609
|
-
elasticity: 0
|
|
4610
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
4968
|
+
const defaultGlassProps = GLASS_DEFAULTS.ACCORDION, glassProps = !0 === glass ? defaultGlassProps : {
|
|
4611
4969
|
...defaultGlassProps,
|
|
4612
4970
|
...glass
|
|
4613
4971
|
};
|
|
@@ -4640,40 +4998,15 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
4640
4998
|
d: "M12 6c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm0 10c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z",
|
|
4641
4999
|
fill: color
|
|
4642
5000
|
}) ]
|
|
4643
|
-
}),
|
|
4644
|
-
// Add input validation
|
|
4645
|
-
if ("number" != typeof a || "number" != typeof b || "number" != typeof t) return 0;
|
|
4646
|
-
const clamped = Math.max(0, Math.min(1, (t - a) / (b - a)));
|
|
4647
|
-
return clamped * clamped * (3 - 2 * clamped);
|
|
4648
|
-
}, calculateLength = (x, y) => {
|
|
4649
|
-
// Add input validation and error handling
|
|
4650
|
-
if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
|
|
4651
|
-
// Prevent potential overflow
|
|
4652
|
-
const maxX = Math.max(Math.abs(x), Math.abs(y));
|
|
4653
|
-
if (0 === maxX) return 0;
|
|
4654
|
-
const scaledX = x / maxX, scaledY = y / maxX;
|
|
4655
|
-
return maxX * Math.sqrt(scaledX * scaledX + scaledY * scaledY);
|
|
4656
|
-
}, roundedRectSDF = (x, y, width, height, radius) => {
|
|
5001
|
+
}), roundedRectSDF = (x, y, width, height, radius) => {
|
|
4657
5002
|
// Add input validation
|
|
4658
5003
|
if ("number" != typeof x || "number" != typeof y || "number" != typeof width || "number" != typeof height || "number" != typeof radius) return 0;
|
|
4659
5004
|
const qx = Math.abs(x) - width + radius, qy = Math.abs(y) - height + radius;
|
|
4660
|
-
return Math.min(Math.max(qx, qy), 0) +
|
|
5005
|
+
return Math.min(Math.max(qx, qy), 0) + vec2Length(Math.max(qx, 0), Math.max(qy, 0)) - radius;
|
|
4661
5006
|
}, createTexture = (x, y) => ({
|
|
4662
5007
|
x: "number" != typeof x || isNaN(x) ? .5 : Math.max(0, Math.min(1, x)),
|
|
4663
5008
|
y: "number" != typeof y || isNaN(y) ? .5 : Math.max(0, Math.min(1, y))
|
|
4664
|
-
}), validateVec2 = vec => vec && "number" == typeof vec.x && "number" == typeof vec.y && !isNaN(vec.x) && !isNaN(vec.y),
|
|
4665
|
-
// Add input validation
|
|
4666
|
-
"number" != typeof value || "number" != typeof min || "number" != typeof max || isNaN(value) ? min : isNaN(min) ? 0 : isNaN(max) ? 1 : Math.max(min, Math.min(max, value)), easeInOutCubic = t => {
|
|
4667
|
-
// Add input validation
|
|
4668
|
-
if ("number" != typeof t || isNaN(t)) return 0;
|
|
4669
|
-
const clampedT = Math.max(0, Math.min(1, t));
|
|
4670
|
-
return clampedT < .5 ? 4 * clampedT * clampedT * clampedT : 1 - Math.pow(-2 * clampedT + 2, 3) / 2;
|
|
4671
|
-
}, easeOutQuart = t => {
|
|
4672
|
-
// Add input validation
|
|
4673
|
-
if ("number" != typeof t || isNaN(t)) return 0;
|
|
4674
|
-
const clampedT = Math.max(0, Math.min(1, t));
|
|
4675
|
-
return 1 - Math.pow(1 - clampedT, 4);
|
|
4676
|
-
}, noise2D = (x, y) => {
|
|
5009
|
+
}), validateVec2 = vec => vec && "number" == typeof vec.x && "number" == typeof vec.y && !isNaN(vec.x) && !isNaN(vec.y), noise2D = (x, y) => {
|
|
4677
5010
|
// Add input validation
|
|
4678
5011
|
if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
|
|
4679
5012
|
const X = 255 & Math.floor(x), Y = 255 & Math.floor(y), xf = x - Math.floor(x), yf = y - Math.floor(y), u = easeInOutCubic(xf), v = easeInOutCubic(yf), hash = (i, j) => {
|
|
@@ -4712,13 +5045,13 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
4712
5045
|
x: .5,
|
|
4713
5046
|
y: .5
|
|
4714
5047
|
};
|
|
4715
|
-
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now(), mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance =
|
|
5048
|
+
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now(), mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = vec2Length(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(2 * mouseDistance, 1)), organicFlow = fbm(12 * (ix + .5 * mouseX) + time, 12 * (iy + .5 * mouseY) + .7 * time, 3) - .5, distanceToEdge = roundedRectSDF(ix, iy, .4, .3, .35), baseDisplacement = smoothstepEdge(.8, 0, distanceToEdge - .05), radialDist = ((x, y, strength) => {
|
|
4716
5049
|
// Add input validation
|
|
4717
5050
|
if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y) || isNaN(strength)) return {
|
|
4718
5051
|
x: 0,
|
|
4719
5052
|
y: 0
|
|
4720
5053
|
};
|
|
4721
|
-
const distance =
|
|
5054
|
+
const distance = vec2Length(x, y), distortion = Math.pow(Math.min(distance, 10), 2) * strength;
|
|
4722
5055
|
// Limit distance to prevent extreme values
|
|
4723
5056
|
return {
|
|
4724
5057
|
x: x * (1 + distortion),
|
|
@@ -4730,7 +5063,7 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
4730
5063
|
x: 0,
|
|
4731
5064
|
y: 0
|
|
4732
5065
|
};
|
|
4733
|
-
const distance =
|
|
5066
|
+
const distance = vec2Length(x, y);
|
|
4734
5067
|
// Prevent division by zero and extreme values
|
|
4735
5068
|
if (0 === distance) return {
|
|
4736
5069
|
x: 0,
|
|
@@ -4741,8 +5074,8 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
4741
5074
|
x: Math.cos(angle) * distance * intensity,
|
|
4742
5075
|
y: Math.sin(angle) * distance * intensity
|
|
4743
5076
|
};
|
|
4744
|
-
})(ix, iy, .015 * baseDisplacement), scaled =
|
|
4745
|
-
return createTexture(
|
|
5077
|
+
})(ix, iy, .015 * baseDisplacement), scaled = smoothstepEdge(0, 1, 1.15 * baseDisplacement), finalX = ix + totalDistortionX + .5 * chromaticOffset.x, finalY = iy + totalDistortionY + .5 * chromaticOffset.y;
|
|
5078
|
+
return createTexture(clamp(finalX * scaled + .5, 0, 1), clamp(finalY * scaled + .5, 0, 1));
|
|
4746
5079
|
},
|
|
4747
5080
|
// Premium Apple-style fluid glass with enhanced organic flow
|
|
4748
5081
|
appleFluid: (uv, mousePosition) => {
|
|
@@ -4750,8 +5083,8 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
4750
5083
|
x: .5,
|
|
4751
5084
|
y: .5
|
|
4752
5085
|
};
|
|
4753
|
-
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .6, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance =
|
|
4754
|
-
return createTexture(
|
|
5086
|
+
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .6, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = vec2Length(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(1.5 * mouseDistance, 1)), organicX = fbm(10 * (ix + .3 * mouseX) + time, 10 * (iy + .3 * mouseY), 5) - .5, organicY = fbm(10 * (ix - .3 * mouseX), 10 * (iy - .3 * mouseY) + .8 * time, 5) - .5, distanceToEdge = roundedRectSDF(ix, iy, .42, .32, .38), mask = smoothstepEdge(.85, -.1, distanceToEdge), fluidVelocityX = Math.sin(6 * ix + 2 * time) * Math.cos(4 * iy - time) * .025, fluidVelocityY = Math.cos(4 * ix - time) * Math.sin(6 * iy + 2 * time) * .025, vortexAngle = Math.atan2(iy - mouseY, ix - mouseX), vortexStrength = mouseFalloff * mouseDistance * .08, vortexX = Math.cos(vortexAngle + time) * vortexStrength, totalY = iy + (.035 * organicY + fluidVelocityY + Math.sin(vortexAngle + time) * vortexStrength) * mask;
|
|
5087
|
+
return createTexture(clamp(ix + (.035 * organicX + fluidVelocityX + vortexX) * mask + .5, 0, 1), clamp(totalY + .5, 0, 1));
|
|
4755
5088
|
},
|
|
4756
5089
|
// High-end glass with advanced refraction and depth
|
|
4757
5090
|
premiumGlass: (uv, mousePosition) => {
|
|
@@ -4759,7 +5092,7 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
4759
5092
|
x: .5,
|
|
4760
5093
|
y: .5
|
|
4761
5094
|
};
|
|
4762
|
-
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .4, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance =
|
|
5095
|
+
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .4, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = vec2Length(mouseX, mouseY), centerDistance = vec2Length(ix, iy), refractionStrength = .3 * Math.pow(Math.min(centerDistance, 1), 1.5), refractionAngle = Math.atan2(iy, ix);
|
|
4763
5096
|
// Multi-layer depth effect
|
|
4764
5097
|
let depthX = 0, depthY = 0;
|
|
4765
5098
|
for (let layer = 0; layer < 3; layer++) {
|
|
@@ -4767,8 +5100,8 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
4767
5100
|
depthX += Math.sin(ix * layerScale + layerTime) * layerStrength, depthY += Math.cos(iy * layerScale - layerTime) * layerStrength;
|
|
4768
5101
|
}
|
|
4769
5102
|
// Glass refraction with mouse influence
|
|
4770
|
-
const refractionX = Math.cos(refractionAngle) * refractionStrength * (1 + .5 * mouseDistance), refractionY = Math.sin(refractionAngle) * refractionStrength * (1 + .5 * mouseDistance), organicNoise = fbm(8 * ix + time, 8 * iy - time, 2) - .5, distanceToEdge = roundedRectSDF(ix, iy, .43, .33, .36), edgeMask =
|
|
4771
|
-
return createTexture(
|
|
5103
|
+
const refractionX = Math.cos(refractionAngle) * refractionStrength * (1 + .5 * mouseDistance), refractionY = Math.sin(refractionAngle) * refractionStrength * (1 + .5 * mouseDistance), organicNoise = fbm(8 * ix + time, 8 * iy - time, 2) - .5, distanceToEdge = roundedRectSDF(ix, iy, .43, .33, .36), edgeMask = smoothstepEdge(.9, -.05, distanceToEdge), finalY = iy + (refractionY + depthY + .015 * organicNoise) * edgeMask;
|
|
5104
|
+
return createTexture(clamp(ix + (refractionX + depthX + .015 * organicNoise) * edgeMask + .5, 0, 1), clamp(finalY + .5, 0, 1));
|
|
4772
5105
|
},
|
|
4773
5106
|
// Metallic liquid effect with shimmer
|
|
4774
5107
|
liquidMetal: (uv, mousePosition) => {
|
|
@@ -4776,8 +5109,8 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
4776
5109
|
x: .5,
|
|
4777
5110
|
y: .5
|
|
4778
5111
|
};
|
|
4779
|
-
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * 1.2, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, wave1 = Math.sin(20 * ix + 4 * time) * Math.cos(15 * iy - 3 * time) * .02, wave2 = Math.cos(15 * ix - 2 * time) * Math.sin(20 * iy + 5 * time) * .015, shimmer = .025 * fbm(25 * ix + 2 * time, 25 * iy - 2 * time, 4), flowAngle = Math.atan2(iy - mouseY, ix - mouseX), flowDistance =
|
|
4780
|
-
return createTexture(
|
|
5112
|
+
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * 1.2, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, wave1 = Math.sin(20 * ix + 4 * time) * Math.cos(15 * iy - 3 * time) * .02, wave2 = Math.cos(15 * ix - 2 * time) * Math.sin(20 * iy + 5 * time) * .015, shimmer = .025 * fbm(25 * ix + 2 * time, 25 * iy - 2 * time, 4), flowAngle = Math.atan2(iy - mouseY, ix - mouseX), flowDistance = vec2Length(ix - mouseX, iy - mouseY), flowEffect = .02 * Math.sin(15 * flowDistance - 6 * time) * easeOutQuart(1 - Math.min(2 * flowDistance, 1)), distanceToEdge = roundedRectSDF(ix, iy, .41, .31, .37), mask = smoothstepEdge(.88, -.08, distanceToEdge), totalX = ix + (wave1 + shimmer + Math.cos(flowAngle) * flowEffect) * mask, totalY = iy + (wave2 + .8 * shimmer + Math.sin(flowAngle) * flowEffect) * mask;
|
|
5113
|
+
return createTexture(clamp(totalX + .5, 0, 1), clamp(totalY + .5, 0, 1));
|
|
4781
5114
|
},
|
|
4782
5115
|
// basiBasi - Expert Premium Glass Shader
|
|
4783
5116
|
// The most advanced shader with caustics, spectral dispersion, parallax depth, and volumetric effects
|
|
@@ -4786,7 +5119,7 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
4786
5119
|
x: .5,
|
|
4787
5120
|
y: .5
|
|
4788
5121
|
};
|
|
4789
|
-
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .5, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance =
|
|
5122
|
+
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .5, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = vec2Length(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(1.2 * mouseDistance, 1)), causticIntensity = ((x, y, time, intensity = 1) =>
|
|
4790
5123
|
// Add input validation
|
|
4791
5124
|
"number" != typeof x || "number" != typeof y || "number" != typeof time || "number" != typeof intensity || isNaN(x) || isNaN(y) || isNaN(time) || isNaN(intensity) ? .5 : .5 * (Math.sin(8 * x + 2 * time) * Math.cos(8 * y - 2 * time) * .5 + Math.sin(8 * (x + .5) * 1.3 - 2 * time * .8) * Math.cos(8 * (y - .3) * 1.3 + 2 * time * .8) * .3 + Math.sin(8 * (x - .3) * .7 + 2 * time * 1.2) * Math.cos(8 * (y + .4) * .7 - 2 * time * 1.2) * .2 + 1) * intensity)(ix, iy, time, .8), causticDistortion = .02 * (causticIntensity - .5), refractionAngle = Math.atan2(iy, ix), spectralDispersion = ((x, y, angle) => {
|
|
4792
5125
|
// Add input validation
|
|
@@ -4804,7 +5137,7 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
4804
5137
|
y: 0
|
|
4805
5138
|
}
|
|
4806
5139
|
};
|
|
4807
|
-
const distance =
|
|
5140
|
+
const distance = vec2Length(x, y), dispersionStrength = Math.min(.025 * distance, 1), redOffset = .8 * dispersionStrength, greenOffset = 1 * dispersionStrength, blueOffset = 1.2 * dispersionStrength;
|
|
4808
5141
|
return {
|
|
4809
5142
|
r: {
|
|
4810
5143
|
x: Math.cos(angle) * redOffset,
|
|
@@ -4844,8 +5177,8 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
4844
5177
|
return turbulence;
|
|
4845
5178
|
})(6 * ix, 6 * iy, time, 6), turbulenceX = .012 * Math.cos(turbulence * Math.PI * 2), turbulenceY = .012 * Math.sin(turbulence * Math.PI * 2), microSurface = ((x, y, time) =>
|
|
4846
5179
|
// Add input validation
|
|
4847
|
-
"number" != typeof x || "number" != typeof y || "number" != typeof time || isNaN(x) || isNaN(y) || isNaN(time) ? .5 : .5 * (.7 * fbm(40 * x + .3 * time, 40 * y - .3 * time, 6) + .3 * fbm(80 * x, 80 * y, 4)))(ix, iy, time), microDetailX = .008 * (microSurface - .5), microDetailY = .008 * (microSurface - .5), centerDistance =
|
|
4848
|
-
return createTexture(
|
|
5180
|
+
"number" != typeof x || "number" != typeof y || "number" != typeof time || isNaN(x) || isNaN(y) || isNaN(time) ? .5 : .5 * (.7 * fbm(40 * x + .3 * time, 40 * y - .3 * time, 6) + .3 * fbm(80 * x, 80 * y, 4)))(ix, iy, time), microDetailX = .008 * (microSurface - .5), microDetailY = .008 * (microSurface - .5), centerDistance = vec2Length(ix, iy), dynamicRefraction = .35 * Math.pow(Math.min(centerDistance, 1), 1.8) * (1 + mouseFalloff * mouseDistance * .8), refractionX = Math.cos(refractionAngle) * dynamicRefraction, refractionY = Math.sin(refractionAngle) * dynamicRefraction, vortexAngle = Math.atan2(iy - mouseY, ix - mouseX), vortexDistance = vec2Length(ix - mouseX, iy - mouseY), vortexStrength = mouseFalloff * Math.sin(10 * vortexDistance - 3 * time) * .025, vortexX = Math.cos(vortexAngle + 2 * time) * vortexStrength, vortexY = Math.sin(vortexAngle + 2 * time) * vortexStrength, fluidX = Math.sin(10 * ix + 5 * mouseX + 2.5 * time) * Math.cos(8 * iy - 2 * time) * .018, fluidY = Math.cos(8 * ix - 2 * time) * Math.sin(10 * iy + 5 * mouseY + 2.5 * time) * .018, rippleEffect = (.012 * Math.sin(15 * Math.min(centerDistance, 10) - 4 * time) + .008 * Math.cos(20 * Math.min(centerDistance, 10) + 3 * time)) * mouseFalloff, rippleX = Math.cos(refractionAngle) * rippleEffect, rippleY = Math.sin(refractionAngle) * rippleEffect, distanceToEdge = roundedRectSDF(ix, iy, .44, .34, .39), edgeMask = smoothstepEdge(.92, -.12, distanceToEdge), edgeSoftness = smoothstepEdge(.85, .1, distanceToEdge), finalY = iy + (1.2 * refractionY + .8 * spectralY + 1.5 * parallaxY + .9 * scatteringY + 1 * turbulenceY + .6 * microDetailY + 1.3 * vortexY + 1.1 * fluidY + .7 * rippleY + .8 * causticDistortion) * edgeMask * edgeSoftness * .85;
|
|
5181
|
+
return createTexture(clamp(ix + (1.2 * refractionX + .8 * spectralX + 1.5 * parallaxX + .9 * scatteringX + 1 * turbulenceX + .6 * microDetailX + 1.3 * vortexX + 1.1 * fluidX + .7 * rippleX + causticDistortion) * edgeMask * edgeSoftness * .85 + .5, 0, 1), clamp(finalY + .5, 0, 1));
|
|
4849
5182
|
},
|
|
4850
5183
|
// Aliases for compatibility
|
|
4851
5184
|
plasma: (uv, mousePosition) => fragmentShaders.premiumGlass(uv, mousePosition),
|
|
@@ -4887,8 +5220,8 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
4887
5220
|
let dx = pos.x * w - x, dy = pos.y * h - y;
|
|
4888
5221
|
// Apply edge smoothing for Apple-like effect
|
|
4889
5222
|
const edgeX = 2 * Math.min(x / w, (w - x) / w), edgeY = 2 * Math.min(y / h, (h - y) / h), edgeFactor = Math.min(edgeX, edgeY);
|
|
4890
|
-
dx *=
|
|
4891
|
-
rawValues.push(dx, dy);
|
|
5223
|
+
dx *= smoothstepEdge(0, .2, edgeFactor), dy *= smoothstepEdge(0, .2, edgeFactor),
|
|
5224
|
+
maxScale = Math.max(maxScale, Math.abs(dx), Math.abs(dy)), rawValues.push(dx, dy);
|
|
4892
5225
|
}
|
|
4893
5226
|
// Improved normalization to prevent artifacts while maintaining intensity
|
|
4894
5227
|
maxScale = Math.max(maxScale, 1);
|
|
@@ -4898,9 +5231,9 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
4898
5231
|
let rawIndex = 0;
|
|
4899
5232
|
for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
|
|
4900
5233
|
const dx = rawValues[rawIndex++] || 0, dy = rawValues[rawIndex++] || 0, edgeDistance = Math.min(x, y, w - x - 1, h - y - 1), edgeFactor = Math.min(1, edgeDistance / 2), r = dx * edgeFactor / maxScale + .5, g = dy * edgeFactor / maxScale + .5, pixelIndex = 4 * (y * w + x);
|
|
4901
|
-
data[pixelIndex] =
|
|
4902
|
-
data[pixelIndex + 1] =
|
|
4903
|
-
data[pixelIndex + 2] =
|
|
5234
|
+
data[pixelIndex] = clamp(255 * r, 0, 255), // Red channel (X displacement)
|
|
5235
|
+
data[pixelIndex + 1] = clamp(255 * g, 0, 255), // Green channel (Y displacement)
|
|
5236
|
+
data[pixelIndex + 2] = clamp(255 * g, 0, 255), // Blue channel (Y displacement for SVG filter compatibility)
|
|
4904
5237
|
data[pixelIndex + 3] = 255;
|
|
4905
5238
|
}
|
|
4906
5239
|
return this.context.putImageData(imageData, 0, 0), this.canvas.toDataURL();
|
|
@@ -4928,9 +5261,7 @@ const Accordion = AccordionWithSubcomponents, AtomixLogo = ({height: height = 24
|
|
|
4928
5261
|
return this.canvasDPI;
|
|
4929
5262
|
}
|
|
4930
5263
|
},
|
|
4931
|
-
|
|
4932
|
-
fragmentShaders: fragmentShaders,
|
|
4933
|
-
liquidGlassWithTime: liquidGlassWithTime
|
|
5264
|
+
fragmentShaders: fragmentShaders
|
|
4934
5265
|
}, Symbol.toStringTag, {
|
|
4935
5266
|
value: "Module"
|
|
4936
5267
|
})), sizeMap = {
|
|
@@ -5073,10 +5404,10 @@ const Badge = memo((({label: label, variant: variant = "primary", size: size =
|
|
|
5073
5404
|
if (glass) {
|
|
5074
5405
|
// Default glass settings for badges
|
|
5075
5406
|
const defaultGlassProps = {
|
|
5076
|
-
|
|
5077
|
-
borderRadius
|
|
5078
|
-
|
|
5079
|
-
|
|
5407
|
+
...GLASS_DEFAULTS.BADGE,
|
|
5408
|
+
// Override borderRadius dynamically if the ref is available
|
|
5409
|
+
borderRadius: ref.current?.getBoundingClientRect().width ? ref.current?.getBoundingClientRect().width / 2 : GLASS_DEFAULTS.BADGE.borderRadius,
|
|
5410
|
+
className: "c-badge--glass"
|
|
5080
5411
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
5081
5412
|
...defaultGlassProps,
|
|
5082
5413
|
...glass
|
|
@@ -5327,12 +5658,7 @@ const Spinner = memo( forwardRef((({size: size = "md", variant: variant = "prim
|
|
|
5327
5658
|
})
|
|
5328
5659
|
});
|
|
5329
5660
|
if (glass) {
|
|
5330
|
-
const defaultGlassProps = {
|
|
5331
|
-
displacementScale: 20,
|
|
5332
|
-
blurAmount: 1,
|
|
5333
|
-
borderRadius: 999,
|
|
5334
|
-
mode: "shader"
|
|
5335
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
5661
|
+
const defaultGlassProps = GLASS_DEFAULTS.SPINNER, glassProps = !0 === glass ? defaultGlassProps : {
|
|
5336
5662
|
...defaultGlassProps,
|
|
5337
5663
|
...glass
|
|
5338
5664
|
};
|
|
@@ -5434,62 +5760,6 @@ class ThemeNaming {
|
|
|
5434
5760
|
}
|
|
5435
5761
|
}
|
|
5436
5762
|
|
|
5437
|
-
ThemeNaming.prefix = "atomix";
|
|
5438
|
-
|
|
5439
|
-
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) {
|
|
5440
|
-
return function(that, callbackfn, argumentsLength, memo) {
|
|
5441
|
-
var O = toObject(that), self = IndexedObject(O), length = lengthOfArrayLike(O);
|
|
5442
|
-
if (aCallable(callbackfn), 0 === length && argumentsLength < 2) throw new $TypeError(REDUCE_EMPTY);
|
|
5443
|
-
var index = IS_RIGHT ? length - 1 : 0, i = IS_RIGHT ? -1 : 1;
|
|
5444
|
-
if (argumentsLength < 2) for (;;) {
|
|
5445
|
-
if (index in self) {
|
|
5446
|
-
memo = self[index], index += i;
|
|
5447
|
-
break;
|
|
5448
|
-
}
|
|
5449
|
-
if (index += i, IS_RIGHT ? index < 0 : length <= index) throw new $TypeError(REDUCE_EMPTY);
|
|
5450
|
-
}
|
|
5451
|
-
for (;IS_RIGHT ? index >= 0 : length > index; index += i) index in self && (memo = callbackfn(memo, self[index], index, O));
|
|
5452
|
-
return memo;
|
|
5453
|
-
};
|
|
5454
|
-
}, arrayReduce = {
|
|
5455
|
-
// `Array.prototype.reduce` method
|
|
5456
|
-
// https://tc39.es/ecma262/#sec-array.prototype.reduce
|
|
5457
|
-
left: createMethod(!1),
|
|
5458
|
-
// `Array.prototype.reduceRight` method
|
|
5459
|
-
// https://tc39.es/ecma262/#sec-array.prototype.reduceright
|
|
5460
|
-
right: createMethod(!0)
|
|
5461
|
-
}, fails = fails$9, globalThis$1 = globalThis_1, userAgent = environmentUserAgent, classof = classofRaw$2, userAgentStartsWith = function(string) {
|
|
5462
|
-
return userAgent.slice(0, string.length) === string;
|
|
5463
|
-
}, 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;
|
|
5464
|
-
|
|
5465
|
-
// `Array.prototype.reduce` method
|
|
5466
|
-
// https://tc39.es/ecma262/#sec-array.prototype.reduce
|
|
5467
|
-
_export({
|
|
5468
|
-
target: "Array",
|
|
5469
|
-
proto: !0,
|
|
5470
|
-
forced: !("NODE" === environment) && environmentV8Version > 79 && environmentV8Version < 83 || !function(METHOD_NAME, argument) {
|
|
5471
|
-
var method = [][METHOD_NAME];
|
|
5472
|
-
return !!method && fails((function() {
|
|
5473
|
-
// eslint-disable-next-line no-useless-call -- required for testing
|
|
5474
|
-
method.call(null, argument || function() {
|
|
5475
|
-
return 1;
|
|
5476
|
-
}, 1);
|
|
5477
|
-
}));
|
|
5478
|
-
}("reduce")
|
|
5479
|
-
}, {
|
|
5480
|
-
reduce: function(callbackfn /* , initialValue */) {
|
|
5481
|
-
var length = arguments.length;
|
|
5482
|
-
return $reduce(this, callbackfn, length, length > 1 ? arguments[1] : void 0);
|
|
5483
|
-
}
|
|
5484
|
-
});
|
|
5485
|
-
|
|
5486
|
-
var reduce$3 = getBuiltInPrototypeMethod$3("Array", "reduce"), isPrototypeOf = objectIsPrototypeOf, method = reduce$3, ArrayPrototype = Array.prototype;
|
|
5487
|
-
|
|
5488
|
-
const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
5489
|
-
var own = it.reduce;
|
|
5490
|
-
return it === ArrayPrototype || isPrototypeOf(ArrayPrototype, it) && own === ArrayPrototype.reduce ? method : own;
|
|
5491
|
-
}));
|
|
5492
|
-
|
|
5493
5763
|
/**
|
|
5494
5764
|
* Render a slot with the given props
|
|
5495
5765
|
*
|
|
@@ -5504,7 +5774,8 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
5504
5774
|
* { render: (props) => <CustomButton {...props} /> },
|
|
5505
5775
|
* { onClick: handleClick, children: 'Click me' }
|
|
5506
5776
|
* )
|
|
5507
|
-
*/
|
|
5777
|
+
*/
|
|
5778
|
+
function renderSlot(slot, props, fallback) {
|
|
5508
5779
|
// No slot provided, use fallback
|
|
5509
5780
|
if (!slot) return fallback;
|
|
5510
5781
|
// Slot is a plain React node
|
|
@@ -5581,6 +5852,8 @@ const _reduceInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
5581
5852
|
return React.useMemo((() => renderSlot(slot, props, fallback)), [ slot, props, fallback ]);
|
|
5582
5853
|
}
|
|
5583
5854
|
|
|
5855
|
+
ThemeNaming.prefix = "atomix";
|
|
5856
|
+
|
|
5584
5857
|
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) => {
|
|
5585
5858
|
const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href), iconElement = iconName ? jsx(Icon, {
|
|
5586
5859
|
name: iconName,
|
|
@@ -5689,11 +5962,7 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
|
|
|
5689
5962
|
// This is a safe fallback for disabled links.
|
|
5690
5963
|
if (glass) {
|
|
5691
5964
|
// Default glass props
|
|
5692
|
-
const defaultGlassProps = {
|
|
5693
|
-
displacementScale: 20,
|
|
5694
|
-
blurAmount: 0,
|
|
5695
|
-
saturation: 200
|
|
5696
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
5965
|
+
const defaultGlassProps = GLASS_DEFAULTS.BUTTON, glassProps = !0 === glass ? defaultGlassProps : {
|
|
5697
5966
|
...defaultGlassProps,
|
|
5698
5967
|
...glass
|
|
5699
5968
|
};
|
|
@@ -5892,11 +6161,7 @@ const Callout = memo((({title: title, children: children, icon: icon, variant:
|
|
|
5892
6161
|
// Determine appropriate ARIA attributes based on variant
|
|
5893
6162
|
if (glass) {
|
|
5894
6163
|
// Default glass settings for callouts
|
|
5895
|
-
const defaultGlassProps = {
|
|
5896
|
-
displacementScale: 30,
|
|
5897
|
-
borderRadius: 8,
|
|
5898
|
-
elasticity: 0
|
|
5899
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
6164
|
+
const defaultGlassProps = GLASS_DEFAULTS.CALLOUT, glassProps = !0 === glass ? defaultGlassProps : {
|
|
5900
6165
|
...defaultGlassProps,
|
|
5901
6166
|
...glass
|
|
5902
6167
|
};
|
|
@@ -10698,15 +10963,7 @@ const range = (start, end) => {
|
|
|
10698
10963
|
}) ]
|
|
10699
10964
|
});
|
|
10700
10965
|
if (glass) {
|
|
10701
|
-
|
|
10702
|
-
const defaultGlassProps = {
|
|
10703
|
-
displacementScale: 60,
|
|
10704
|
-
blurAmount: 1,
|
|
10705
|
-
saturation: 160,
|
|
10706
|
-
aberrationIntensity: .5,
|
|
10707
|
-
borderRadius: 8,
|
|
10708
|
-
mode: "shader"
|
|
10709
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
10966
|
+
const defaultGlassProps = GLASS_DEFAULTS.PAGINATION, glassProps = !0 === glass ? defaultGlassProps : {
|
|
10710
10967
|
...defaultGlassProps,
|
|
10711
10968
|
...glass
|
|
10712
10969
|
};
|
|
@@ -10770,14 +11027,7 @@ const Checkbox = React.memo( forwardRef((({label: label, checked: checked, onCh
|
|
|
10770
11027
|
style: style,
|
|
10771
11028
|
children: inputElement
|
|
10772
11029
|
}), glass) {
|
|
10773
|
-
const defaultGlassProps = {
|
|
10774
|
-
displacementScale: 40,
|
|
10775
|
-
blurAmount: 1,
|
|
10776
|
-
saturation: 160,
|
|
10777
|
-
aberrationIntensity: .3,
|
|
10778
|
-
borderRadius: 6,
|
|
10779
|
-
mode: "shader"
|
|
10780
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
11030
|
+
const defaultGlassProps = GLASS_DEFAULTS.CHECKBOX, glassProps = !0 === glass ? defaultGlassProps : {
|
|
10781
11031
|
...defaultGlassProps,
|
|
10782
11032
|
...glass
|
|
10783
11033
|
};
|
|
@@ -11038,13 +11288,8 @@ const DropdownStyleContext = createContext({}), Dropdown = memo((function({chi
|
|
|
11038
11288
|
"aria-orientation": "vertical",
|
|
11039
11289
|
"aria-hidden": !isOpen,
|
|
11040
11290
|
onKeyDown: handleKeyDown,
|
|
11041
|
-
children: glass ?
|
|
11042
|
-
|
|
11043
|
-
(() => {
|
|
11044
|
-
const defaultGlassProps = {
|
|
11045
|
-
displacementScale: 20,
|
|
11046
|
-
elasticity: 0
|
|
11047
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
11291
|
+
children: glass ? (() => {
|
|
11292
|
+
const defaultGlassProps = GLASS_DEFAULTS.DROPDOWN, glassProps = !0 === glass ? defaultGlassProps : {
|
|
11048
11293
|
...defaultGlassProps,
|
|
11049
11294
|
...glass
|
|
11050
11295
|
};
|
|
@@ -12607,17 +12852,9 @@ const Input = memo( forwardRef((({type: type = "text", value: value, defaultVal
|
|
|
12607
12852
|
style: glass ? {
|
|
12608
12853
|
...style
|
|
12609
12854
|
} : style
|
|
12610
|
-
});
|
|
12611
|
-
if (glass) {
|
|
12612
|
-
|
|
12613
|
-
const defaultGlassProps = {
|
|
12614
|
-
displacementScale: 60,
|
|
12615
|
-
blurAmount: 1,
|
|
12616
|
-
saturation: 180,
|
|
12617
|
-
aberrationIntensity: .2,
|
|
12618
|
-
borderRadius: 12,
|
|
12619
|
-
mode: "shader"
|
|
12620
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
12855
|
+
});
|
|
12856
|
+
if (glass) {
|
|
12857
|
+
const defaultGlassProps = GLASS_DEFAULTS.INPUT, glassProps = !0 === glass ? defaultGlassProps : {
|
|
12621
12858
|
...defaultGlassProps,
|
|
12622
12859
|
...glass
|
|
12623
12860
|
};
|
|
@@ -12802,497 +13039,291 @@ function useHero(initialProps) {
|
|
|
12802
13039
|
},
|
|
12803
13040
|
generateContentColClass: (size = defaultProps.contentColSize || 5, customClass) => {
|
|
12804
13041
|
const classes = [ `o-grid__col o-grid__col--md-${size}` ];
|
|
12805
|
-
// Handle mobile stacking order
|
|
12806
|
-
return defaultProps.reverseOnMobile && ("right" === defaultProps.alignment || "center" === defaultProps.alignment ? classes.push("u-order-last u-order-md-first") : classes.push("u-order-first u-order-md-last")),
|
|
12807
|
-
customClass && classes.push(customClass), classes.join(" ");
|
|
12808
|
-
},
|
|
12809
|
-
hasBackgroundImage: hasBackgroundImage,
|
|
12810
|
-
hasForegroundImage: hasForegroundImage,
|
|
12811
|
-
useGridLayout: useGridLayout,
|
|
12812
|
-
heroRef: heroRef,
|
|
12813
|
-
videoRef: videoRef,
|
|
12814
|
-
applyParallaxEffect: applyParallaxEffect,
|
|
12815
|
-
removeParallaxEffect: removeParallaxEffect,
|
|
12816
|
-
backgroundSlider: backgroundSlider,
|
|
12817
|
-
hasBackgroundSlider: hasBackgroundSlider
|
|
12818
|
-
};
|
|
12819
|
-
}
|
|
12820
|
-
|
|
12821
|
-
/**
|
|
12822
|
-
* Hook for River component functionality
|
|
12823
|
-
* @param initialProps - Initial river props
|
|
12824
|
-
* @returns River methods and state
|
|
12825
|
-
*/ function useRiver(initialProps) {
|
|
12826
|
-
const defaultProps = {
|
|
12827
|
-
center: !1,
|
|
12828
|
-
breakout: !1,
|
|
12829
|
-
reverse: !1,
|
|
12830
|
-
imageAlt: "Image",
|
|
12831
|
-
showOverlay: !0,
|
|
12832
|
-
...initialProps
|
|
12833
|
-
};
|
|
12834
|
-
/**
|
|
12835
|
-
* Check if the river has a background image
|
|
12836
|
-
*/ return {
|
|
12837
|
-
generateRiverClassNames: (baseClassName = "") => {
|
|
12838
|
-
const classes = [ RIVER.SELECTORS.RIVER.replace(".", "") ];
|
|
12839
|
-
// Add layout classes
|
|
12840
|
-
return defaultProps.center && classes.push(RIVER.CLASSES.CENTER), defaultProps.breakout && classes.push(RIVER.CLASSES.BREAKOUT),
|
|
12841
|
-
defaultProps.reverse && classes.push(RIVER.CLASSES.REVERSE), baseClassName && classes.push(baseClassName),
|
|
12842
|
-
classes.join(" ");
|
|
12843
|
-
},
|
|
12844
|
-
generateContentClass: () => RIVER.SELECTORS.CONTENT.replace(".", ""),
|
|
12845
|
-
generateVisualClass: () => RIVER.SELECTORS.VISUAL.replace(".", ""),
|
|
12846
|
-
hasBackgroundImage: !!defaultProps.backgroundImageSrc,
|
|
12847
|
-
hasForegroundImage: !!defaultProps.imageSrc,
|
|
12848
|
-
textContent: "string" == typeof defaultProps.text ? [ defaultProps.text ] : defaultProps.text || []
|
|
12849
|
-
};
|
|
12850
|
-
}
|
|
12851
|
-
|
|
12852
|
-
/**
|
|
12853
|
-
* Navbar state and functionality
|
|
12854
|
-
* @param initialProps - Initial navbar properties
|
|
12855
|
-
* @returns Navbar state and methods
|
|
12856
|
-
*/ function useNavbar(initialProps) {
|
|
12857
|
-
// Default navbar properties
|
|
12858
|
-
const defaultProps = {
|
|
12859
|
-
position: "static",
|
|
12860
|
-
collapsible: !0,
|
|
12861
|
-
backdrop: !1,
|
|
12862
|
-
closeOnOutsideClick: !0,
|
|
12863
|
-
closeOnEscape: !0,
|
|
12864
|
-
"aria-label": "Main navigation",
|
|
12865
|
-
...initialProps
|
|
12866
|
-
}, [isExpanded, setIsExpanded] = useState(defaultProps.expanded || !1);
|
|
12867
|
-
// Local expanded state for when not controlled externally
|
|
12868
|
-
return {
|
|
12869
|
-
defaultProps: defaultProps,
|
|
12870
|
-
isExpanded: isExpanded,
|
|
12871
|
-
setIsExpanded: setIsExpanded,
|
|
12872
|
-
generateNavbarClass: props => {
|
|
12873
|
-
const {position: position = defaultProps.position, variant: variant, collapsible: collapsible = defaultProps.collapsible, className: className = ""} = props;
|
|
12874
|
-
return `c-navbar ${"static" !== position ? `c-navbar--${position}` : ""} ${variant ? `c-navbar--${variant}` : ""} ${collapsible ? "c-navbar--collapsible" : ""} ${className}`.trim();
|
|
12875
|
-
},
|
|
12876
|
-
generateContainerStyle: width => width ? {
|
|
12877
|
-
maxWidth: width
|
|
12878
|
-
} : {},
|
|
12879
|
-
generateCollapseClass: expanded => ("c-navbar__collapse " + (expanded ? "is-expanded" : "")).trim(),
|
|
12880
|
-
toggleExpanded: () => {
|
|
12881
|
-
const newState = !isExpanded;
|
|
12882
|
-
setIsExpanded(newState), defaultProps.onToggle && defaultProps.onToggle(newState);
|
|
12883
|
-
},
|
|
12884
|
-
getExpandedState: controlled => void 0 !== controlled ? controlled : isExpanded
|
|
12885
|
-
};
|
|
12886
|
-
}
|
|
12887
|
-
|
|
12888
|
-
/**
|
|
12889
|
-
* Nav state and functionality
|
|
12890
|
-
* @param initialProps - Initial nav properties
|
|
12891
|
-
* @returns Nav state and methods
|
|
12892
|
-
*/ function useNav(initialProps) {
|
|
12893
|
-
// Default nav properties
|
|
12894
|
-
const defaultProps = {
|
|
12895
|
-
alignment: "start",
|
|
12896
|
-
variant: "default",
|
|
12897
|
-
...initialProps
|
|
12898
|
-
};
|
|
12899
|
-
/**
|
|
12900
|
-
* Generate nav class based on properties
|
|
12901
|
-
* @param props - Nav properties
|
|
12902
|
-
* @returns Class string
|
|
12903
|
-
*/ return {
|
|
12904
|
-
defaultProps: defaultProps,
|
|
12905
|
-
generateNavClass: props => {
|
|
12906
|
-
const {alignment: alignment = defaultProps.alignment, variant: variant = defaultProps.variant, className: className = ""} = props;
|
|
12907
|
-
return `c-nav ${"start" !== alignment ? `c-nav--${alignment}` : ""} ${"default" !== variant ? `c-nav--${variant}` : ""} ${className}`.trim();
|
|
12908
|
-
}
|
|
12909
|
-
};
|
|
12910
|
-
}
|
|
12911
|
-
|
|
12912
|
-
/**
|
|
12913
|
-
* Nav item state and functionality
|
|
12914
|
-
* @param initialProps - Initial nav item properties
|
|
12915
|
-
* @returns Nav item state and methods
|
|
12916
|
-
*/ function useNavItem(initialProps) {
|
|
12917
|
-
// Default nav item properties
|
|
12918
|
-
const defaultProps = {
|
|
12919
|
-
dropdown: !1,
|
|
12920
|
-
megaMenu: !1,
|
|
12921
|
-
active: !1,
|
|
12922
|
-
...initialProps
|
|
12923
|
-
};
|
|
12924
|
-
/**
|
|
12925
|
-
* Generate nav item class based on properties
|
|
12926
|
-
* @param props - Nav item properties
|
|
12927
|
-
* @returns Class string
|
|
12928
|
-
*/ return {
|
|
12929
|
-
defaultProps: defaultProps,
|
|
12930
|
-
generateNavItemClass: props => {
|
|
12931
|
-
const {dropdown: dropdown = defaultProps.dropdown, megaMenu: megaMenu = defaultProps.megaMenu, active: active = defaultProps.active, disabled: disabled = defaultProps.disabled, className: className = ""} = props;
|
|
12932
|
-
// Apply dropdown class only for regular dropdowns, not mega menus
|
|
12933
|
-
return `c-nav__item ${dropdown && !megaMenu ? NAV.SELECTORS.DROPDOWN.replace(".", "") : ""} ${megaMenu ? "c-nav__item--mega-menu" : ""} ${active ? NAV.CLASSES.ACTIVE : ""} ${disabled ? NAV.CLASSES.DISABLED : ""} ${className}`.trim();
|
|
12934
|
-
},
|
|
12935
|
-
generateNavLinkClass: (active = !1, disabled = !1, className = "") => `c-nav__link ${active ? NAV.CLASSES.ACTIVE : ""} ${disabled ? "c-nav__link--disabled" : ""} ${className}`.trim(),
|
|
12936
|
-
handleClick: handler => e => {
|
|
12937
|
-
!defaultProps.disabled && handler ? handler() : e.preventDefault();
|
|
12938
|
-
}
|
|
12939
|
-
};
|
|
12940
|
-
}
|
|
12941
|
-
|
|
12942
|
-
/**
|
|
12943
|
-
* Nav dropdown state and functionality
|
|
12944
|
-
* @param initialProps - Initial dropdown properties
|
|
12945
|
-
* @returns Dropdown state and methods
|
|
12946
|
-
*/ function useNavDropdown(initialProps) {
|
|
12947
|
-
// Default dropdown properties
|
|
12948
|
-
const defaultProps = {
|
|
12949
|
-
alignment: "start",
|
|
12950
|
-
megaMenu: !1,
|
|
12951
|
-
...initialProps
|
|
12952
|
-
}, isInFixedBottomNavbar = () => null !== document.querySelector(".c-navbar--fixed-bottom");
|
|
12953
|
-
/**
|
|
12954
|
-
* Generate dropdown menu class based on properties
|
|
12955
|
-
* @param props - Dropdown properties
|
|
12956
|
-
* @returns Class string
|
|
12957
|
-
*/ return {
|
|
12958
|
-
defaultProps: defaultProps,
|
|
12959
|
-
generateDropdownMenuClass: props => {
|
|
12960
|
-
const {alignment: alignment = defaultProps.alignment, megaMenu: megaMenu = defaultProps.megaMenu, className: className = ""} = props, baseClass = megaMenu ? NAV.SELECTORS.MEGA_MENU.replace(".", "") : NAV.SELECTORS.DROPDOWN_MENU.replace(".", "");
|
|
12961
|
-
// Select the base class based on mega menu or regular dropdown
|
|
12962
|
-
// Add alignment class if not default 'start'
|
|
12963
|
-
let alignmentClass = "";
|
|
12964
|
-
return "center" === alignment ? alignmentClass = `${baseClass}--center` : "end" === alignment && (alignmentClass = `${baseClass}--end`),
|
|
12965
|
-
`${baseClass} ${alignmentClass} ${className}`.trim();
|
|
12966
|
-
},
|
|
12967
|
-
isInFixedBottomNavbar: isInFixedBottomNavbar,
|
|
12968
|
-
getIconName: (isMegaMenu = !1) => isInFixedBottomNavbar() ? "CaretUp" : "CaretDown"
|
|
12969
|
-
};
|
|
12970
|
-
}
|
|
12971
|
-
|
|
12972
|
-
/**
|
|
12973
|
-
* SideMenu state and functionality
|
|
12974
|
-
* @param initialProps - Initial side menu properties
|
|
12975
|
-
* @returns SideMenu state and methods
|
|
12976
|
-
*/ function useSideMenu(initialProps) {
|
|
12977
|
-
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);
|
|
12978
|
-
// Local open state for when not controlled externally
|
|
12979
|
-
// Update local state when external state changes
|
|
12980
|
-
useEffect((() => {
|
|
12981
|
-
void 0 !== isOpen ? setIsOpenState(isOpen) : void 0 !== defaultCollapsedDesktop && setIsOpenState(!defaultCollapsedDesktop);
|
|
12982
|
-
}), [ isOpen, defaultCollapsedDesktop ]),
|
|
12983
|
-
// Set initial height on mount
|
|
12984
|
-
useEffect((() => {
|
|
12985
|
-
const shouldCollapse = window.innerWidth < 768 ? collapsible : collapsibleDesktop, currentOpen = void 0 !== isOpen ? isOpen : isOpenState;
|
|
12986
|
-
if (shouldCollapse && wrapperRef.current && innerRef.current) {
|
|
12987
|
-
// Use setTimeout to ensure DOM is fully rendered
|
|
12988
|
-
const timeoutId = setTimeout((() => {
|
|
12989
|
-
wrapperRef.current && innerRef.current && (wrapperRef.current.style.height = currentOpen ? `${innerRef.current.scrollHeight}px` : "0px");
|
|
12990
|
-
}), 0);
|
|
12991
|
-
return () => clearTimeout(timeoutId);
|
|
12992
|
-
}
|
|
12993
|
-
!shouldCollapse && wrapperRef.current && (wrapperRef.current.style.height = "auto");
|
|
12994
|
-
}), [ collapsible, collapsibleDesktop, isOpen, isOpenState ]),
|
|
12995
|
-
// Handle responsive behavior - vertical collapse for both mobile and desktop
|
|
12996
|
-
useEffect((() => {
|
|
12997
|
-
const handleResize = () => {
|
|
12998
|
-
if (window.innerWidth < 768 ? collapsible : collapsibleDesktop) {
|
|
12999
|
-
if (wrapperRef.current && innerRef.current) {
|
|
13000
|
-
// Set proper height for vertical animation (both mobile and desktop)
|
|
13001
|
-
const currentOpen = void 0 !== isOpen ? isOpen : isOpenState;
|
|
13002
|
-
// Use requestAnimationFrame to ensure DOM is ready
|
|
13003
|
-
requestAnimationFrame((() => {
|
|
13004
|
-
wrapperRef.current && innerRef.current && (wrapperRef.current.style.height = currentOpen ? `${innerRef.current.scrollHeight}px` : "0px");
|
|
13005
|
-
}));
|
|
13006
|
-
}
|
|
13007
|
-
} else
|
|
13008
|
-
// Not collapsible - always show content
|
|
13009
|
-
wrapperRef.current && (wrapperRef.current.style.height = "auto");
|
|
13010
|
-
}, timeoutId = setTimeout(handleResize, 0);
|
|
13011
|
-
// Initial call with a small delay to ensure DOM is ready
|
|
13012
|
-
return window.addEventListener("resize", handleResize), () => {
|
|
13013
|
-
clearTimeout(timeoutId), window.removeEventListener("resize", handleResize);
|
|
13014
|
-
};
|
|
13015
|
-
}), [ collapsible, collapsibleDesktop, isOpen, onToggle, isOpenState ]),
|
|
13016
|
-
// Update wrapper height when open state changes (both mobile and desktop)
|
|
13017
|
-
useEffect((() => {
|
|
13018
|
-
const shouldCollapse = window.innerWidth < 768 ? collapsible : collapsibleDesktop;
|
|
13019
|
-
if (shouldCollapse && wrapperRef.current && innerRef.current) {
|
|
13020
|
-
const currentOpen = void 0 !== isOpen ? isOpen : isOpenState;
|
|
13021
|
-
// Use requestAnimationFrame to ensure DOM is ready
|
|
13022
|
-
requestAnimationFrame((() => {
|
|
13023
|
-
wrapperRef.current && innerRef.current && (wrapperRef.current.style.height = currentOpen ? `${innerRef.current.scrollHeight}px` : "0px");
|
|
13024
|
-
}));
|
|
13025
|
-
} else !shouldCollapse && wrapperRef.current && (
|
|
13026
|
-
// Not collapsible - always show content
|
|
13027
|
-
wrapperRef.current.style.height = "auto");
|
|
13028
|
-
}), [ isOpen, isOpenState, collapsible, collapsibleDesktop ]);
|
|
13029
|
-
/**
|
|
13030
|
-
* Generate side menu class based on properties
|
|
13031
|
-
* @param props - Side menu properties
|
|
13032
|
-
* @returns Class string
|
|
13033
|
-
*/
|
|
13034
|
-
const handleToggle = () => {
|
|
13035
|
-
if (disabled) return;
|
|
13036
|
-
const newState = void 0 !== isOpen ? !isOpen : !isOpenState;
|
|
13037
|
-
"function" == typeof onToggle ?
|
|
13038
|
-
// Controlled component
|
|
13039
|
-
onToggle(newState) :
|
|
13040
|
-
// Uncontrolled component
|
|
13041
|
-
setIsOpenState(newState);
|
|
13042
|
-
}, getCurrentOpenState = () => void 0 !== isOpen ? isOpen : isOpenState;
|
|
13043
|
-
/**
|
|
13044
|
-
* Generate wrapper class
|
|
13045
|
-
* @returns Class string
|
|
13046
|
-
*/ return {
|
|
13047
|
-
isOpenState: getCurrentOpenState(),
|
|
13048
|
-
wrapperRef: wrapperRef,
|
|
13049
|
-
innerRef: innerRef,
|
|
13050
|
-
sideMenuRef: sideMenuRef,
|
|
13051
|
-
generateSideMenuClass: props => {
|
|
13052
|
-
const {className: className = "", isOpen: isOpen = !1} = props, openClass = isOpen ? SIDE_MENU.CLASSES.IS_OPEN : "";
|
|
13053
|
-
return `${SIDE_MENU.CLASSES.BASE} ${openClass} ${className}`.trim();
|
|
13054
|
-
},
|
|
13055
|
-
generateWrapperClass: () => SIDE_MENU.CLASSES.WRAPPER,
|
|
13056
|
-
handleToggle: handleToggle,
|
|
13057
|
-
handleDesktopCollapse: () => {
|
|
13058
|
-
handleToggle();
|
|
13042
|
+
// Handle mobile stacking order
|
|
13043
|
+
return defaultProps.reverseOnMobile && ("right" === defaultProps.alignment || "center" === defaultProps.alignment ? classes.push("u-order-last u-order-md-first") : classes.push("u-order-first u-order-md-last")),
|
|
13044
|
+
customClass && classes.push(customClass), classes.join(" ");
|
|
13059
13045
|
},
|
|
13060
|
-
|
|
13046
|
+
hasBackgroundImage: hasBackgroundImage,
|
|
13047
|
+
hasForegroundImage: hasForegroundImage,
|
|
13048
|
+
useGridLayout: useGridLayout,
|
|
13049
|
+
heroRef: heroRef,
|
|
13050
|
+
videoRef: videoRef,
|
|
13051
|
+
applyParallaxEffect: applyParallaxEffect,
|
|
13052
|
+
removeParallaxEffect: removeParallaxEffect,
|
|
13053
|
+
backgroundSlider: backgroundSlider,
|
|
13054
|
+
hasBackgroundSlider: hasBackgroundSlider
|
|
13061
13055
|
};
|
|
13062
13056
|
}
|
|
13063
13057
|
|
|
13064
13058
|
/**
|
|
13065
|
-
*
|
|
13066
|
-
* @param initialProps - Initial
|
|
13067
|
-
* @returns
|
|
13068
|
-
*/ function
|
|
13069
|
-
// Default side menu item properties
|
|
13059
|
+
* Hook for River component functionality
|
|
13060
|
+
* @param initialProps - Initial river props
|
|
13061
|
+
* @returns River methods and state
|
|
13062
|
+
*/ function useRiver(initialProps) {
|
|
13070
13063
|
const defaultProps = {
|
|
13071
|
-
|
|
13072
|
-
|
|
13064
|
+
center: !1,
|
|
13065
|
+
breakout: !1,
|
|
13066
|
+
reverse: !1,
|
|
13067
|
+
imageAlt: "Image",
|
|
13068
|
+
showOverlay: !0,
|
|
13073
13069
|
...initialProps
|
|
13074
13070
|
};
|
|
13075
13071
|
/**
|
|
13076
|
-
*
|
|
13077
|
-
* @returns Class string
|
|
13072
|
+
* Check if the river has a background image
|
|
13078
13073
|
*/ return {
|
|
13079
|
-
|
|
13080
|
-
|
|
13081
|
-
|
|
13082
|
-
|
|
13074
|
+
generateRiverClassNames: (baseClassName = "") => {
|
|
13075
|
+
const classes = [ RIVER.SELECTORS.RIVER.replace(".", "") ];
|
|
13076
|
+
// Add layout classes
|
|
13077
|
+
return defaultProps.center && classes.push(RIVER.CLASSES.CENTER), defaultProps.breakout && classes.push(RIVER.CLASSES.BREAKOUT),
|
|
13078
|
+
defaultProps.reverse && classes.push(RIVER.CLASSES.REVERSE), baseClassName && classes.push(baseClassName),
|
|
13079
|
+
classes.join(" ");
|
|
13083
13080
|
},
|
|
13084
|
-
|
|
13085
|
-
|
|
13086
|
-
|
|
13081
|
+
generateContentClass: () => RIVER.SELECTORS.CONTENT.replace(".", ""),
|
|
13082
|
+
generateVisualClass: () => RIVER.SELECTORS.VISUAL.replace(".", ""),
|
|
13083
|
+
hasBackgroundImage: !!defaultProps.backgroundImageSrc,
|
|
13084
|
+
hasForegroundImage: !!defaultProps.imageSrc,
|
|
13085
|
+
textContent: "string" == typeof defaultProps.text ? [ defaultProps.text ] : defaultProps.text || []
|
|
13087
13086
|
};
|
|
13088
13087
|
}
|
|
13089
13088
|
|
|
13090
13089
|
/**
|
|
13091
|
-
*
|
|
13092
|
-
*
|
|
13093
|
-
* @
|
|
13094
|
-
|
|
13095
|
-
|
|
13096
|
-
|
|
13097
|
-
|
|
13098
|
-
|
|
13099
|
-
|
|
13100
|
-
|
|
13101
|
-
|
|
13102
|
-
|
|
13103
|
-
|
|
13104
|
-
}
|
|
13105
|
-
|
|
13106
|
-
|
|
13107
|
-
|
|
13108
|
-
|
|
13109
|
-
|
|
13110
|
-
|
|
13111
|
-
|
|
13112
|
-
|
|
13113
|
-
|
|
13114
|
-
|
|
13115
|
-
|
|
13116
|
-
|
|
13117
|
-
|
|
13118
|
-
|
|
13119
|
-
|
|
13120
|
-
|
|
13121
|
-
|
|
13122
|
-
|
|
13123
|
-
|
|
13124
|
-
* @param varNames - Variable names to remove
|
|
13125
|
-
* @param element - Target element (defaults to document.documentElement)
|
|
13126
|
-
*/ function removeCSSVariables(varNames, element) {
|
|
13127
|
-
if ("undefined" == typeof window) return;
|
|
13128
|
-
// SSR safety
|
|
13129
|
-
const target = element || document.documentElement;
|
|
13130
|
-
varNames.forEach((varName => {
|
|
13131
|
-
target.style.removeProperty(varName);
|
|
13132
|
-
}));
|
|
13133
|
-
}
|
|
13134
|
-
|
|
13135
|
-
/**
|
|
13136
|
-
* Get CSS variable value from an element
|
|
13137
|
-
*
|
|
13138
|
-
* @param varName - Variable name to get
|
|
13139
|
-
* @param element - Target element (defaults to document.documentElement)
|
|
13140
|
-
* @returns Variable value or null if not found
|
|
13141
|
-
*/ function getCSSVariable(varName, element) {
|
|
13142
|
-
if ("undefined" == typeof window) return null;
|
|
13143
|
-
// SSR safety
|
|
13144
|
-
const target = element || document.documentElement;
|
|
13145
|
-
return getComputedStyle(target).getPropertyValue(varName).trim() || null;
|
|
13146
|
-
}
|
|
13147
|
-
|
|
13148
|
-
/**
|
|
13149
|
-
* Convert CSS variable object to inline style object
|
|
13150
|
-
*
|
|
13151
|
-
* @example
|
|
13152
|
-
* const vars = { '--atomix-button-bg': '#000' }
|
|
13153
|
-
* const style = cssVarsToStyle(vars)
|
|
13154
|
-
* // Returns: { '--atomix-button-bg': '#000' } as React.CSSProperties
|
|
13155
|
-
*/ function cssVarsToStyle(vars) {
|
|
13156
|
-
var _context;
|
|
13157
|
-
return _reduceInstanceProperty(_context = Object.entries(vars)).call(_context, ((acc, [key, value]) => (acc[key] = "number" == typeof value ? `${value}px` : value,
|
|
13158
|
-
acc)), {});
|
|
13159
|
-
}
|
|
13160
|
-
|
|
13161
|
-
/**
|
|
13162
|
-
* Merge multiple CSS variable objects
|
|
13163
|
-
* Later objects override earlier ones
|
|
13164
|
-
*/ function mergeCSSVars(...varObjects) {
|
|
13165
|
-
return _reduceInstanceProperty(varObjects).call(varObjects, ((acc, vars) => (vars && Object.assign(acc, vars),
|
|
13166
|
-
acc)), {});
|
|
13167
|
-
}
|
|
13168
|
-
|
|
13169
|
-
/**
|
|
13170
|
-
* Validate CSS variable name format
|
|
13171
|
-
*/ function isValidCSSVariableName(name) {
|
|
13172
|
-
return /^--[a-z0-9-]+$/.test(name);
|
|
13173
|
-
}
|
|
13174
|
-
|
|
13175
|
-
/**
|
|
13176
|
-
* Extract component name from CSS variable name
|
|
13177
|
-
*
|
|
13178
|
-
* @example
|
|
13179
|
-
* extractComponentName('--atomix-button-bg')
|
|
13180
|
-
* // Returns: 'button'
|
|
13181
|
-
*/ function extractComponentName(varName, prefix = "atomix") {
|
|
13182
|
-
const regex = new RegExp(`^--${prefix}-([a-z0-9]+)-`), match = varName.match(regex);
|
|
13183
|
-
return match ? match[1] ?? null : null;
|
|
13184
|
-
}
|
|
13185
|
-
|
|
13186
|
-
/**
|
|
13187
|
-
* Component Utilities
|
|
13188
|
-
*
|
|
13189
|
-
* Helper functions for component development with the new customization system
|
|
13190
|
-
*/
|
|
13191
|
-
/**
|
|
13192
|
-
* Merge multiple class names
|
|
13193
|
-
*/ function mergeClassNames(...classes) {
|
|
13194
|
-
return classes.filter(Boolean).join(" ");
|
|
13090
|
+
* Navbar state and functionality
|
|
13091
|
+
* @param initialProps - Initial navbar properties
|
|
13092
|
+
* @returns Navbar state and methods
|
|
13093
|
+
*/ function useNavbar(initialProps) {
|
|
13094
|
+
// Default navbar properties
|
|
13095
|
+
const defaultProps = {
|
|
13096
|
+
position: "static",
|
|
13097
|
+
collapsible: !0,
|
|
13098
|
+
backdrop: !1,
|
|
13099
|
+
closeOnOutsideClick: !0,
|
|
13100
|
+
closeOnEscape: !0,
|
|
13101
|
+
"aria-label": "Main navigation",
|
|
13102
|
+
...initialProps
|
|
13103
|
+
}, [isExpanded, setIsExpanded] = useState(defaultProps.expanded || !1);
|
|
13104
|
+
// Local expanded state for when not controlled externally
|
|
13105
|
+
return {
|
|
13106
|
+
defaultProps: defaultProps,
|
|
13107
|
+
isExpanded: isExpanded,
|
|
13108
|
+
setIsExpanded: setIsExpanded,
|
|
13109
|
+
generateNavbarClass: props => {
|
|
13110
|
+
const {position: position = defaultProps.position, variant: variant, collapsible: collapsible = defaultProps.collapsible, className: className = ""} = props;
|
|
13111
|
+
return `c-navbar ${"static" !== position ? `c-navbar--${position}` : ""} ${variant ? `c-navbar--${variant}` : ""} ${collapsible ? "c-navbar--collapsible" : ""} ${className}`.trim();
|
|
13112
|
+
},
|
|
13113
|
+
generateContainerStyle: width => width ? {
|
|
13114
|
+
maxWidth: width
|
|
13115
|
+
} : {},
|
|
13116
|
+
generateCollapseClass: expanded => ("c-navbar__collapse " + (expanded ? "is-expanded" : "")).trim(),
|
|
13117
|
+
toggleExpanded: () => {
|
|
13118
|
+
const newState = !isExpanded;
|
|
13119
|
+
setIsExpanded(newState), defaultProps.onToggle && defaultProps.onToggle(newState);
|
|
13120
|
+
},
|
|
13121
|
+
getExpandedState: controlled => void 0 !== controlled ? controlled : isExpanded
|
|
13122
|
+
};
|
|
13195
13123
|
}
|
|
13196
13124
|
|
|
13197
13125
|
/**
|
|
13198
|
-
*
|
|
13199
|
-
|
|
13200
|
-
|
|
13201
|
-
|
|
13202
|
-
|
|
13203
|
-
|
|
13204
|
-
|
|
13205
|
-
|
|
13126
|
+
* Nav state and functionality
|
|
13127
|
+
* @param initialProps - Initial nav properties
|
|
13128
|
+
* @returns Nav state and methods
|
|
13129
|
+
*/ function useNav(initialProps) {
|
|
13130
|
+
// Default nav properties
|
|
13131
|
+
const defaultProps = {
|
|
13132
|
+
alignment: "start",
|
|
13133
|
+
variant: "default",
|
|
13134
|
+
...initialProps
|
|
13135
|
+
};
|
|
13136
|
+
/**
|
|
13137
|
+
* Generate nav class based on properties
|
|
13138
|
+
* @param props - Nav properties
|
|
13139
|
+
* @returns Class string
|
|
13140
|
+
*/ return {
|
|
13141
|
+
defaultProps: defaultProps,
|
|
13142
|
+
generateNavClass: props => {
|
|
13143
|
+
const {alignment: alignment = defaultProps.alignment, variant: variant = defaultProps.variant, className: className = ""} = props;
|
|
13144
|
+
return `c-nav ${"start" !== alignment ? `c-nav--${alignment}` : ""} ${"default" !== variant ? `c-nav--${variant}` : ""} ${className}`.trim();
|
|
13206
13145
|
}
|
|
13207
|
-
}
|
|
13146
|
+
};
|
|
13208
13147
|
}
|
|
13209
13148
|
|
|
13210
13149
|
/**
|
|
13211
|
-
*
|
|
13212
|
-
|
|
13213
|
-
|
|
13214
|
-
|
|
13215
|
-
|
|
13216
|
-
|
|
13217
|
-
|
|
13218
|
-
|
|
13219
|
-
|
|
13220
|
-
|
|
13221
|
-
|
|
13222
|
-
|
|
13223
|
-
|
|
13224
|
-
|
|
13225
|
-
|
|
13226
|
-
|
|
13227
|
-
|
|
13228
|
-
|
|
13150
|
+
* Nav item state and functionality
|
|
13151
|
+
* @param initialProps - Initial nav item properties
|
|
13152
|
+
* @returns Nav item state and methods
|
|
13153
|
+
*/ function useNavItem(initialProps) {
|
|
13154
|
+
// Default nav item properties
|
|
13155
|
+
const defaultProps = {
|
|
13156
|
+
dropdown: !1,
|
|
13157
|
+
megaMenu: !1,
|
|
13158
|
+
active: !1,
|
|
13159
|
+
...initialProps
|
|
13160
|
+
};
|
|
13161
|
+
/**
|
|
13162
|
+
* Generate nav item class based on properties
|
|
13163
|
+
* @param props - Nav item properties
|
|
13164
|
+
* @returns Class string
|
|
13165
|
+
*/ return {
|
|
13166
|
+
defaultProps: defaultProps,
|
|
13167
|
+
generateNavItemClass: props => {
|
|
13168
|
+
const {dropdown: dropdown = defaultProps.dropdown, megaMenu: megaMenu = defaultProps.megaMenu, active: active = defaultProps.active, disabled: disabled = defaultProps.disabled, className: className = ""} = props;
|
|
13169
|
+
// Apply dropdown class only for regular dropdowns, not mega menus
|
|
13170
|
+
return `c-nav__item ${dropdown && !megaMenu ? NAV.SELECTORS.DROPDOWN.replace(".", "") : ""} ${megaMenu ? "c-nav__item--mega-menu" : ""} ${active ? NAV.CLASSES.ACTIVE : ""} ${disabled ? NAV.CLASSES.DISABLED : ""} ${className}`.trim();
|
|
13171
|
+
},
|
|
13172
|
+
generateNavLinkClass: (active = !1, disabled = !1, className = "") => `c-nav__link ${active ? NAV.CLASSES.ACTIVE : ""} ${disabled ? "c-nav__link--disabled" : ""} ${className}`.trim(),
|
|
13173
|
+
handleClick: handler => e => {
|
|
13174
|
+
!defaultProps.disabled && handler ? handler() : e.preventDefault();
|
|
13229
13175
|
}
|
|
13230
13176
|
};
|
|
13231
13177
|
}
|
|
13232
13178
|
|
|
13233
13179
|
/**
|
|
13234
|
-
*
|
|
13235
|
-
|
|
13236
|
-
|
|
13180
|
+
* Nav dropdown state and functionality
|
|
13181
|
+
* @param initialProps - Initial dropdown properties
|
|
13182
|
+
* @returns Dropdown state and methods
|
|
13183
|
+
*/ function useNavDropdown(initialProps) {
|
|
13184
|
+
// Default dropdown properties
|
|
13185
|
+
const defaultProps = {
|
|
13186
|
+
alignment: "start",
|
|
13187
|
+
megaMenu: !1,
|
|
13188
|
+
...initialProps
|
|
13189
|
+
}, isInFixedBottomNavbar = () => null !== document.querySelector(".c-navbar--fixed-bottom");
|
|
13190
|
+
/**
|
|
13191
|
+
* Generate dropdown menu class based on properties
|
|
13192
|
+
* @param props - Dropdown properties
|
|
13193
|
+
* @returns Class string
|
|
13194
|
+
*/ return {
|
|
13195
|
+
defaultProps: defaultProps,
|
|
13196
|
+
generateDropdownMenuClass: props => {
|
|
13197
|
+
const {alignment: alignment = defaultProps.alignment, megaMenu: megaMenu = defaultProps.megaMenu, className: className = ""} = props, baseClass = megaMenu ? NAV.SELECTORS.MEGA_MENU.replace(".", "") : NAV.SELECTORS.DROPDOWN_MENU.replace(".", "");
|
|
13198
|
+
// Select the base class based on mega menu or regular dropdown
|
|
13199
|
+
// Add alignment class if not default 'start'
|
|
13200
|
+
let alignmentClass = "";
|
|
13201
|
+
return "center" === alignment ? alignmentClass = `${baseClass}--center` : "end" === alignment && (alignmentClass = `${baseClass}--end`),
|
|
13202
|
+
`${baseClass} ${alignmentClass} ${className}`.trim();
|
|
13203
|
+
},
|
|
13204
|
+
isInFixedBottomNavbar: isInFixedBottomNavbar,
|
|
13205
|
+
getIconName: (isMegaMenu = !1) => isInFixedBottomNavbar() ? "CaretUp" : "CaretDown"
|
|
13206
|
+
};
|
|
13237
13207
|
}
|
|
13238
13208
|
|
|
13239
13209
|
/**
|
|
13240
|
-
*
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
|
|
13246
|
-
|
|
13247
|
-
|
|
13210
|
+
* SideMenu state and functionality
|
|
13211
|
+
* @param initialProps - Initial side menu properties
|
|
13212
|
+
* @returns SideMenu state and methods
|
|
13213
|
+
*/ function useSideMenu(initialProps) {
|
|
13214
|
+
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);
|
|
13215
|
+
// Local open state for when not controlled externally
|
|
13216
|
+
// Update local state when external state changes
|
|
13217
|
+
useEffect((() => {
|
|
13218
|
+
void 0 !== isOpen ? setIsOpenState(isOpen) : void 0 !== defaultCollapsedDesktop && setIsOpenState(!defaultCollapsedDesktop);
|
|
13219
|
+
}), [ isOpen, defaultCollapsedDesktop ]),
|
|
13220
|
+
// Set initial height on mount
|
|
13221
|
+
useEffect((() => {
|
|
13222
|
+
const shouldCollapse = window.innerWidth < 768 ? collapsible : collapsibleDesktop, currentOpen = void 0 !== isOpen ? isOpen : isOpenState;
|
|
13223
|
+
if (shouldCollapse && wrapperRef.current && innerRef.current) {
|
|
13224
|
+
// Use setTimeout to ensure DOM is fully rendered
|
|
13225
|
+
const timeoutId = setTimeout((() => {
|
|
13226
|
+
wrapperRef.current && innerRef.current && (wrapperRef.current.style.height = currentOpen ? `${innerRef.current.scrollHeight}px` : "0px");
|
|
13227
|
+
}), 0);
|
|
13228
|
+
return () => clearTimeout(timeoutId);
|
|
13248
13229
|
}
|
|
13230
|
+
!shouldCollapse && wrapperRef.current && (wrapperRef.current.style.height = "auto");
|
|
13231
|
+
}), [ collapsible, collapsibleDesktop, isOpen, isOpenState ]),
|
|
13232
|
+
// Handle responsive behavior - vertical collapse for both mobile and desktop
|
|
13233
|
+
useEffect((() => {
|
|
13234
|
+
const handleResize = () => {
|
|
13235
|
+
if (window.innerWidth < 768 ? collapsible : collapsibleDesktop) {
|
|
13236
|
+
if (wrapperRef.current && innerRef.current) {
|
|
13237
|
+
// Set proper height for vertical animation (both mobile and desktop)
|
|
13238
|
+
const currentOpen = void 0 !== isOpen ? isOpen : isOpenState;
|
|
13239
|
+
// Use requestAnimationFrame to ensure DOM is ready
|
|
13240
|
+
requestAnimationFrame((() => {
|
|
13241
|
+
wrapperRef.current && innerRef.current && (wrapperRef.current.style.height = currentOpen ? `${innerRef.current.scrollHeight}px` : "0px");
|
|
13242
|
+
}));
|
|
13243
|
+
}
|
|
13244
|
+
} else
|
|
13245
|
+
// Not collapsible - always show content
|
|
13246
|
+
wrapperRef.current && (wrapperRef.current.style.height = "auto");
|
|
13247
|
+
}, timeoutId = setTimeout(handleResize, 0);
|
|
13248
|
+
// Initial call with a small delay to ensure DOM is ready
|
|
13249
|
+
return window.addEventListener("resize", handleResize), () => {
|
|
13250
|
+
clearTimeout(timeoutId), window.removeEventListener("resize", handleResize);
|
|
13251
|
+
};
|
|
13252
|
+
}), [ collapsible, collapsibleDesktop, isOpen, onToggle, isOpenState ]),
|
|
13253
|
+
// Update wrapper height when open state changes (both mobile and desktop)
|
|
13254
|
+
useEffect((() => {
|
|
13255
|
+
const shouldCollapse = window.innerWidth < 768 ? collapsible : collapsibleDesktop;
|
|
13256
|
+
if (shouldCollapse && wrapperRef.current && innerRef.current) {
|
|
13257
|
+
const currentOpen = void 0 !== isOpen ? isOpen : isOpenState;
|
|
13258
|
+
// Use requestAnimationFrame to ensure DOM is ready
|
|
13259
|
+
requestAnimationFrame((() => {
|
|
13260
|
+
wrapperRef.current && innerRef.current && (wrapperRef.current.style.height = currentOpen ? `${innerRef.current.scrollHeight}px` : "0px");
|
|
13261
|
+
}));
|
|
13262
|
+
} else !shouldCollapse && wrapperRef.current && (
|
|
13263
|
+
// Not collapsible - always show content
|
|
13264
|
+
wrapperRef.current.style.height = "auto");
|
|
13265
|
+
}), [ isOpen, isOpenState, collapsible, collapsibleDesktop ]);
|
|
13266
|
+
/**
|
|
13267
|
+
* Generate side menu class based on properties
|
|
13268
|
+
* @param props - Side menu properties
|
|
13269
|
+
* @returns Class string
|
|
13270
|
+
*/
|
|
13271
|
+
const handleToggle = () => {
|
|
13272
|
+
if (disabled) return;
|
|
13273
|
+
const newState = void 0 !== isOpen ? !isOpen : !isOpenState;
|
|
13274
|
+
"function" == typeof onToggle ?
|
|
13275
|
+
// Controlled component
|
|
13276
|
+
onToggle(newState) :
|
|
13277
|
+
// Uncontrolled component
|
|
13278
|
+
setIsOpenState(newState);
|
|
13279
|
+
}, getCurrentOpenState = () => void 0 !== isOpen ? isOpen : isOpenState;
|
|
13280
|
+
/**
|
|
13281
|
+
* Generate wrapper class
|
|
13282
|
+
* @returns Class string
|
|
13283
|
+
*/ return {
|
|
13284
|
+
isOpenState: getCurrentOpenState(),
|
|
13285
|
+
wrapperRef: wrapperRef,
|
|
13286
|
+
innerRef: innerRef,
|
|
13287
|
+
sideMenuRef: sideMenuRef,
|
|
13288
|
+
generateSideMenuClass: props => {
|
|
13289
|
+
const {className: className = "", isOpen: isOpen = !1} = props, openClass = isOpen ? SIDE_MENU.CLASSES.IS_OPEN : "";
|
|
13290
|
+
return `${SIDE_MENU.CLASSES.BASE} ${openClass} ${className}`.trim();
|
|
13291
|
+
},
|
|
13292
|
+
generateWrapperClass: () => SIDE_MENU.CLASSES.WRAPPER,
|
|
13293
|
+
handleToggle: handleToggle,
|
|
13294
|
+
handleDesktopCollapse: () => {
|
|
13295
|
+
handleToggle();
|
|
13296
|
+
},
|
|
13297
|
+
getCurrentOpenState: getCurrentOpenState
|
|
13249
13298
|
};
|
|
13250
13299
|
}
|
|
13251
13300
|
|
|
13252
13301
|
/**
|
|
13253
|
-
*
|
|
13254
|
-
|
|
13255
|
-
|
|
13256
|
-
|
|
13257
|
-
|
|
13258
|
-
|
|
13259
|
-
|
|
13260
|
-
|
|
13261
|
-
|
|
13262
|
-
|
|
13263
|
-
|
|
13264
|
-
|
|
13302
|
+
* SideMenuItem state and functionality
|
|
13303
|
+
* @param initialProps - Initial side menu item properties
|
|
13304
|
+
* @returns SideMenuItem state and methods
|
|
13305
|
+
*/ function useSideMenuItem(initialProps) {
|
|
13306
|
+
// Default side menu item properties
|
|
13307
|
+
const defaultProps = {
|
|
13308
|
+
active: !1,
|
|
13309
|
+
disabled: !1,
|
|
13310
|
+
...initialProps
|
|
13311
|
+
};
|
|
13312
|
+
/**
|
|
13313
|
+
* Generate side menu item class based on properties
|
|
13314
|
+
* @returns Class string
|
|
13315
|
+
*/ return {
|
|
13316
|
+
defaultProps: defaultProps,
|
|
13317
|
+
generateSideMenuItemClass: () => {
|
|
13318
|
+
const {active: active = defaultProps.active, disabled: disabled = defaultProps.disabled, className: className = ""} = defaultProps, activeClass = active ? SIDE_MENU.CLASSES.ACTIVE : "", disabledClass = disabled ? SIDE_MENU.CLASSES.DISABLED : "";
|
|
13319
|
+
return `${SIDE_MENU.CLASSES.LINK} ${activeClass} ${disabledClass} ${className}`.trim();
|
|
13320
|
+
},
|
|
13321
|
+
handleClick: handler => e => {
|
|
13322
|
+
defaultProps.disabled ? e.preventDefault() : handler && handler(e);
|
|
13265
13323
|
}
|
|
13266
13324
|
};
|
|
13267
13325
|
}
|
|
13268
13326
|
|
|
13269
|
-
/**
|
|
13270
|
-
* Generate a UUID v4
|
|
13271
|
-
*/ function generateUUID() {
|
|
13272
|
-
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c => {
|
|
13273
|
-
const r = 16 * Math.random() | 0;
|
|
13274
|
-
return ("x" === c ? r : 3 & r | 8).toString(16);
|
|
13275
|
-
}));
|
|
13276
|
-
}
|
|
13277
|
-
|
|
13278
|
-
/**
|
|
13279
|
-
* Check if a URL is a YouTube URL
|
|
13280
|
-
*/ function isYouTubeUrl(url) {
|
|
13281
|
-
return /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/.+/.test(url);
|
|
13282
|
-
}
|
|
13283
|
-
|
|
13284
|
-
/**
|
|
13285
|
-
* Extract YouTube video ID from URL
|
|
13286
|
-
*/ function extractYouTubeId(url) {
|
|
13287
|
-
if (!isYouTubeUrl(url)) return null;
|
|
13288
|
-
const patterns = [ /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/, /youtube\.com\/.*[?&]v=([^&\n?#]+)/ ];
|
|
13289
|
-
for (const pattern of patterns) {
|
|
13290
|
-
const match = url.match(pattern);
|
|
13291
|
-
if (match && match[1]) return match[1];
|
|
13292
|
-
}
|
|
13293
|
-
return null;
|
|
13294
|
-
}
|
|
13295
|
-
|
|
13296
13327
|
/**
|
|
13297
13328
|
* Font Preloading Utilities
|
|
13298
13329
|
*
|
|
@@ -13660,48 +13691,11 @@ const composablesImport = Object.freeze( Object.defineProperty({
|
|
|
13660
13691
|
DeviceDetector: DeviceDetector,
|
|
13661
13692
|
MOBILE_OPTIMIZED_BREAKPOINTS: MOBILE_OPTIMIZED_BREAKPOINTS,
|
|
13662
13693
|
PERFORMANCE_PRESET: PERFORMANCE_PRESET,
|
|
13663
|
-
PerformanceOverlay: function({metrics: metrics}) {
|
|
13664
|
-
return null;
|
|
13665
|
-
// Performance overlay removed - will be implemented as separate component
|
|
13666
|
-
}
|
|
13667
|
-
/**
|
|
13668
|
-
* Utility to get quality multipliers for glass parameters
|
|
13669
|
-
*/ ,
|
|
13670
13694
|
QUALITY_PRESET: QUALITY_PRESET,
|
|
13671
13695
|
createBreakpoints: createBreakpoints$1,
|
|
13672
13696
|
getDefaultBreakpoints: getDefaultBreakpoints,
|
|
13673
13697
|
getDevicePreset: getDevicePreset,
|
|
13674
13698
|
getMobileOptimizedParams: getMobileOptimizedParams,
|
|
13675
|
-
getQualityMultipliers: function(quality) {
|
|
13676
|
-
switch (quality) {
|
|
13677
|
-
case "low":
|
|
13678
|
-
return {
|
|
13679
|
-
distortionOctaves: 2,
|
|
13680
|
-
displacementScale: .6,
|
|
13681
|
-
blurAmount: .7,
|
|
13682
|
-
animationSpeed: .8,
|
|
13683
|
-
chromaticIntensity: .5
|
|
13684
|
-
};
|
|
13685
|
-
|
|
13686
|
-
case "medium":
|
|
13687
|
-
return {
|
|
13688
|
-
distortionOctaves: 4,
|
|
13689
|
-
displacementScale: .85,
|
|
13690
|
-
blurAmount: .9,
|
|
13691
|
-
animationSpeed: .95,
|
|
13692
|
-
chromaticIntensity: .75
|
|
13693
|
-
};
|
|
13694
|
-
|
|
13695
|
-
case "high":
|
|
13696
|
-
return {
|
|
13697
|
-
distortionOctaves: 5,
|
|
13698
|
-
displacementScale: 1,
|
|
13699
|
-
blurAmount: 1,
|
|
13700
|
-
animationSpeed: 1,
|
|
13701
|
-
chromaticIntensity: 1
|
|
13702
|
-
};
|
|
13703
|
-
}
|
|
13704
|
-
},
|
|
13705
13699
|
useAccordion: useAccordion,
|
|
13706
13700
|
useAtomixGlass: useAtomixGlass,
|
|
13707
13701
|
useBadge: useBadge,
|
|
@@ -14004,12 +13998,7 @@ const SelectComponentBase = ({options: options, value: value, onChange: onChange
|
|
|
14004
13998
|
});
|
|
14005
13999
|
// Handle item selection
|
|
14006
14000
|
if (glass) {
|
|
14007
|
-
|
|
14008
|
-
const defaultGlassProps = {
|
|
14009
|
-
displacementScale: 60,
|
|
14010
|
-
blurAmount: 10,
|
|
14011
|
-
mode: "shader"
|
|
14012
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
14001
|
+
const defaultGlassProps = GLASS_DEFAULTS.SELECT, glassProps = !0 === glass ? defaultGlassProps : {
|
|
14013
14002
|
...defaultGlassProps,
|
|
14014
14003
|
...glass
|
|
14015
14004
|
};
|
|
@@ -14059,15 +14048,7 @@ const Radio = memo((({label: label, checked: checked = !1, onChange: onChange,
|
|
|
14059
14048
|
}) ]
|
|
14060
14049
|
});
|
|
14061
14050
|
if (glass) {
|
|
14062
|
-
|
|
14063
|
-
const defaultGlassProps = {
|
|
14064
|
-
displacementScale: 40,
|
|
14065
|
-
blurAmount: 1,
|
|
14066
|
-
saturation: 160,
|
|
14067
|
-
aberrationIntensity: .3,
|
|
14068
|
-
borderRadius: 6,
|
|
14069
|
-
mode: "shader"
|
|
14070
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
14051
|
+
const defaultGlassProps = GLASS_DEFAULTS.RADIO, glassProps = !0 === glass ? defaultGlassProps : {
|
|
14071
14052
|
...defaultGlassProps,
|
|
14072
14053
|
...glass
|
|
14073
14054
|
};
|
|
@@ -14125,15 +14106,7 @@ const Textarea = memo( forwardRef((({value: value, defaultValue: defaultValue,
|
|
|
14125
14106
|
} : style
|
|
14126
14107
|
});
|
|
14127
14108
|
if (glass) {
|
|
14128
|
-
|
|
14129
|
-
const defaultGlassProps = {
|
|
14130
|
-
displacementScale: 60,
|
|
14131
|
-
blurAmount: 1,
|
|
14132
|
-
saturation: 180,
|
|
14133
|
-
aberrationIntensity: 1,
|
|
14134
|
-
borderRadius: 8,
|
|
14135
|
-
mode: "shader"
|
|
14136
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
14109
|
+
const defaultGlassProps = GLASS_DEFAULTS.TEXTAREA, glassProps = !0 === glass ? defaultGlassProps : {
|
|
14137
14110
|
...defaultGlassProps,
|
|
14138
14111
|
...glass
|
|
14139
14112
|
};
|
|
@@ -15249,12 +15222,7 @@ const Messages = ({messages: messages = [], otherAvatar: otherAvatar, selfAvatar
|
|
|
15249
15222
|
};
|
|
15250
15223
|
})({
|
|
15251
15224
|
onSendMessage: onSendMessage
|
|
15252
|
-
}), messagesId = id || `messages-${Math.random().toString(36).substr(2, 9)}`, inputId = `${messagesId}-input`, defaultGlassProps = {
|
|
15253
|
-
displacementScale: 150,
|
|
15254
|
-
borderRadius: 12,
|
|
15255
|
-
elasticity: 0,
|
|
15256
|
-
aberrationIntensity: 2
|
|
15257
|
-
}, messagesClasses = `${MESSAGES.CLASSES.BASE} ${glass ? "c-messages--glass" : ""} ${disabled ? "is-disabled" : ""} ${className}`, messagesContent = jsxs(Fragment, {
|
|
15225
|
+
}), messagesId = id || `messages-${Math.random().toString(36).substr(2, 9)}`, inputId = `${messagesId}-input`, defaultGlassProps = GLASS_DEFAULTS.MESSAGES, messagesClasses = `${MESSAGES.CLASSES.BASE} ${glass ? "c-messages--glass" : ""} ${disabled ? "is-disabled" : ""} ${className}`, messagesContent = jsxs(Fragment, {
|
|
15258
15226
|
children: [ jsx("div", {
|
|
15259
15227
|
className: MESSAGES.CLASSES.BODY,
|
|
15260
15228
|
style: bodyHeight ? {
|
|
@@ -15614,12 +15582,11 @@ const ModalImpl = memo((({children: children, isOpen: isOpen = !1, onOpenChange
|
|
|
15614
15582
|
children: glass ?
|
|
15615
15583
|
// Default glass settings for modals
|
|
15616
15584
|
(() => {
|
|
15585
|
+
// Default glass settings for modals
|
|
15617
15586
|
const defaultGlassProps = {
|
|
15618
|
-
|
|
15619
|
-
|
|
15620
|
-
|
|
15621
|
-
mode: "shader",
|
|
15622
|
-
shaderMode: "premiumGlass"
|
|
15587
|
+
...GLASS_DEFAULTS.MODAL,
|
|
15588
|
+
// displacementScale driven by modal content height at runtime
|
|
15589
|
+
displacementScale: document.querySelector(".c-modal---glass .c-modal__content")?.clientHeight
|
|
15623
15590
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
15624
15591
|
...defaultGlassProps,
|
|
15625
15592
|
...glass
|
|
@@ -15667,12 +15634,7 @@ const Modal = ModalWithSubcomponents, Nav = forwardRef((({children: children, a
|
|
|
15667
15634
|
}))
|
|
15668
15635
|
});
|
|
15669
15636
|
if (glass) {
|
|
15670
|
-
const defaultGlassProps = {
|
|
15671
|
-
displacementScale: 60,
|
|
15672
|
-
blurAmount: 1.5,
|
|
15673
|
-
borderRadius: 8,
|
|
15674
|
-
mode: "shader"
|
|
15675
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
15637
|
+
const defaultGlassProps = GLASS_DEFAULTS.NAV, glassProps = !0 === glass ? defaultGlassProps : {
|
|
15676
15638
|
...defaultGlassProps,
|
|
15677
15639
|
...glass
|
|
15678
15640
|
};
|
|
@@ -15698,24 +15660,7 @@ const Modal = ModalWithSubcomponents, Nav = forwardRef((({children: children, a
|
|
|
15698
15660
|
* </NavDropdown>
|
|
15699
15661
|
* </Nav>
|
|
15700
15662
|
* ```
|
|
15701
|
-
*/
|
|
15702
|
-
/**
|
|
15703
|
-
* Utility to merge multiple React refs into one
|
|
15704
|
-
*/
|
|
15705
|
-
function setRef(ref, value) {
|
|
15706
|
-
"function" == typeof ref ? ref(value) : ref && (
|
|
15707
|
-
// This is safe because we're checking that ref exists first
|
|
15708
|
-
ref.current = value);
|
|
15709
|
-
}
|
|
15710
|
-
|
|
15711
|
-
/**
|
|
15712
|
-
* Combines two React refs into a single ref function
|
|
15713
|
-
* This is used when you need to use and forward a ref at the same time
|
|
15714
|
-
*/ function useForkRef(refA, refB) {
|
|
15715
|
-
return React.useMemo((() => null == refA && null == refB ? null : refValue => {
|
|
15716
|
-
setRef(refA, refValue), setRef(refB, refValue);
|
|
15717
|
-
}), [ refA, refB ]);
|
|
15718
|
-
}
|
|
15663
|
+
*/ Nav.displayName = "Nav";
|
|
15719
15664
|
|
|
15720
15665
|
/**
|
|
15721
15666
|
* NavItem component represents a single navigation item that can be a link, dropdown trigger, or mega menu trigger.
|
|
@@ -15744,8 +15689,7 @@ function setRef(ref, value) {
|
|
|
15744
15689
|
* </MegaMenu>
|
|
15745
15690
|
* </NavItem>
|
|
15746
15691
|
* ```
|
|
15747
|
-
*/
|
|
15748
|
-
|
|
15692
|
+
*/
|
|
15749
15693
|
const NavItem = forwardRef((({children: children, dropdown: dropdown = !1, megaMenu: megaMenu = !1, active: active = !1, href: href, target: target, onClick: onClick, className: className = "", disabled: disabled = !1, "aria-expanded": ariaExpanded, linkComponent: linkComponent}, ref) => {
|
|
15750
15694
|
const {generateNavItemClass: generateNavItemClass, generateNavLinkClass: generateNavLinkClass, handleClick: handleClick} = useNavItem({
|
|
15751
15695
|
dropdown: dropdown,
|
|
@@ -15912,14 +15856,7 @@ const Navbar = forwardRef((({brand: brand, children: children, variant: variant
|
|
|
15912
15856
|
});
|
|
15913
15857
|
// Generate the container style
|
|
15914
15858
|
if (glass) {
|
|
15915
|
-
const defaultGlassProps = {
|
|
15916
|
-
displacementScale: 30,
|
|
15917
|
-
blurAmount: 2,
|
|
15918
|
-
borderRadius: 0,
|
|
15919
|
-
elasticity: 0,
|
|
15920
|
-
mode: "shader",
|
|
15921
|
-
shaderVariant: "premiumGlass"
|
|
15922
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
15859
|
+
const defaultGlassProps = GLASS_DEFAULTS.NAVBAR, glassProps = !0 === glass ? defaultGlassProps : {
|
|
15923
15860
|
...defaultGlassProps,
|
|
15924
15861
|
...glass
|
|
15925
15862
|
};
|
|
@@ -16277,12 +16214,7 @@ const SideMenu = forwardRef((({title: title, children: children, menuItems: men
|
|
|
16277
16214
|
}) ]
|
|
16278
16215
|
});
|
|
16279
16216
|
if (glass) {
|
|
16280
|
-
const defaultGlassProps = {
|
|
16281
|
-
displacementScale: 70,
|
|
16282
|
-
blurAmount: 2,
|
|
16283
|
-
borderRadius: 12,
|
|
16284
|
-
mode: "shader"
|
|
16285
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
16217
|
+
const defaultGlassProps = GLASS_DEFAULTS.SIDE_MENU, glassProps = !0 === glass ? defaultGlassProps : {
|
|
16286
16218
|
...defaultGlassProps,
|
|
16287
16219
|
...glass
|
|
16288
16220
|
};
|
|
@@ -17863,14 +17795,7 @@ const PopoverContext = createContext({
|
|
|
17863
17795
|
children: [ glass ?
|
|
17864
17796
|
// Default glass settings for popovers
|
|
17865
17797
|
(() => {
|
|
17866
|
-
const defaultGlassProps = {
|
|
17867
|
-
displacementScale: 50,
|
|
17868
|
-
blurAmount: 1,
|
|
17869
|
-
saturation: 160,
|
|
17870
|
-
aberrationIntensity: .5,
|
|
17871
|
-
borderRadius: 8,
|
|
17872
|
-
mode: "shader"
|
|
17873
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
17798
|
+
const defaultGlassProps = GLASS_DEFAULTS.POPOVER, glassProps = !0 === glass ? defaultGlassProps : {
|
|
17874
17799
|
...defaultGlassProps,
|
|
17875
17800
|
...glass
|
|
17876
17801
|
};
|
|
@@ -18095,15 +18020,7 @@ const calculateStarValue = (e, starValue, allowHalf) => {
|
|
|
18095
18020
|
});
|
|
18096
18021
|
// Generate stars
|
|
18097
18022
|
if (glass) {
|
|
18098
|
-
|
|
18099
|
-
const defaultGlassProps = {
|
|
18100
|
-
displacementScale: 60,
|
|
18101
|
-
blurAmount: 1,
|
|
18102
|
-
saturation: 160,
|
|
18103
|
-
aberrationIntensity: .5,
|
|
18104
|
-
borderRadius: 8,
|
|
18105
|
-
mode: "shader"
|
|
18106
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
18023
|
+
const defaultGlassProps = GLASS_DEFAULTS.RATING, glassProps = !0 === glass ? defaultGlassProps : {
|
|
18107
18024
|
...defaultGlassProps,
|
|
18108
18025
|
...glass
|
|
18109
18026
|
};
|
|
@@ -18259,12 +18176,7 @@ const Progress = memo( forwardRef((({value: value, variant: variant = "primary"
|
|
|
18259
18176
|
})
|
|
18260
18177
|
});
|
|
18261
18178
|
if (glass) {
|
|
18262
|
-
const defaultGlassProps = {
|
|
18263
|
-
displacementScale: 30,
|
|
18264
|
-
blurAmount: .5,
|
|
18265
|
-
borderRadius: 8,
|
|
18266
|
-
mode: "shader"
|
|
18267
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
18179
|
+
const defaultGlassProps = GLASS_DEFAULTS.PROGRESS, glassProps = !0 === glass ? defaultGlassProps : {
|
|
18268
18180
|
...defaultGlassProps,
|
|
18269
18181
|
...glass
|
|
18270
18182
|
};
|
|
@@ -18913,15 +18825,7 @@ const Steps = ({items: items, activeIndex: activeIndex = 0, vertical: vertical =
|
|
|
18913
18825
|
children: content
|
|
18914
18826
|
});
|
|
18915
18827
|
if (glass) {
|
|
18916
|
-
|
|
18917
|
-
const defaultGlassProps = {
|
|
18918
|
-
displacementScale: 60,
|
|
18919
|
-
blurAmount: 1,
|
|
18920
|
-
saturation: 160,
|
|
18921
|
-
aberrationIntensity: .5,
|
|
18922
|
-
borderRadius: 8,
|
|
18923
|
-
mode: "shader"
|
|
18924
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
18828
|
+
const defaultGlassProps = GLASS_DEFAULTS.STEPS, glassProps = !0 === glass ? defaultGlassProps : {
|
|
18925
18829
|
...defaultGlassProps,
|
|
18926
18830
|
...glass
|
|
18927
18831
|
};
|
|
@@ -19125,14 +19029,7 @@ const TabsComponentBase = ({items: items, activeIndex: activeIndex = TAB.DEFAULT
|
|
|
19125
19029
|
});
|
|
19126
19030
|
if (glass) {
|
|
19127
19031
|
// Default glass settings for tabs
|
|
19128
|
-
const defaultGlassProps = {
|
|
19129
|
-
displacementScale: 60,
|
|
19130
|
-
blurAmount: 1,
|
|
19131
|
-
saturation: 160,
|
|
19132
|
-
aberrationIntensity: .5,
|
|
19133
|
-
borderRadius: 8,
|
|
19134
|
-
mode: "shader"
|
|
19135
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
19032
|
+
const defaultGlassProps = GLASS_DEFAULTS.TABS, glassProps = !0 === glass ? defaultGlassProps : {
|
|
19136
19033
|
...defaultGlassProps,
|
|
19137
19034
|
...glass
|
|
19138
19035
|
};
|
|
@@ -19368,15 +19265,7 @@ const Toggle = ({checked: controlledChecked, defaultChecked: defaultChecked = !1
|
|
|
19368
19265
|
})
|
|
19369
19266
|
});
|
|
19370
19267
|
if (glass) {
|
|
19371
|
-
|
|
19372
|
-
const defaultGlassProps = {
|
|
19373
|
-
displacementScale: 60,
|
|
19374
|
-
blurAmount: 1,
|
|
19375
|
-
saturation: 160,
|
|
19376
|
-
aberrationIntensity: .5,
|
|
19377
|
-
borderRadius: 8,
|
|
19378
|
-
mode: "shader"
|
|
19379
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
19268
|
+
const defaultGlassProps = GLASS_DEFAULTS.TOGGLE, glassProps = !0 === glass ? defaultGlassProps : {
|
|
19380
19269
|
...defaultGlassProps,
|
|
19381
19270
|
...glass
|
|
19382
19271
|
};
|
|
@@ -19564,10 +19453,7 @@ const Tooltip = memo((({content: content, children: children, position: positio
|
|
|
19564
19453
|
}), content ]
|
|
19565
19454
|
});
|
|
19566
19455
|
if (glass) {
|
|
19567
|
-
const defaultGlassProps = {
|
|
19568
|
-
displacementScale: 100,
|
|
19569
|
-
blurAmount: 3
|
|
19570
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
19456
|
+
const defaultGlassProps = GLASS_DEFAULTS.TOOLTIP, glassProps = !0 === glass ? defaultGlassProps : {
|
|
19571
19457
|
...defaultGlassProps,
|
|
19572
19458
|
...glass
|
|
19573
19459
|
};
|
|
@@ -20741,6 +20627,8 @@ const components = Object.freeze( Object.defineProperty({
|
|
|
20741
20627
|
FOOTER: FOOTER,
|
|
20742
20628
|
FORM: FORM,
|
|
20743
20629
|
FORM_GROUP: FORM_GROUP,
|
|
20630
|
+
GLASS_BORDER_GRADIENT: GLASS_BORDER_GRADIENT,
|
|
20631
|
+
GLASS_DEFAULTS: GLASS_DEFAULTS,
|
|
20744
20632
|
HERO: HERO,
|
|
20745
20633
|
INPUT: INPUT,
|
|
20746
20634
|
LIST: LIST,
|
|
@@ -28527,5 +28415,5 @@ const atomix = {
|
|
|
28527
28415
|
types: types
|
|
28528
28416
|
};
|
|
28529
28417
|
|
|
28530
|
-
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, 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, 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, usePerformanceMonitor, usePieChart, useRadio, useResponsive, useResponsiveGlass, useRiver, useSelect, useSideMenu, useSideMenuItem, useSlot, useSpinner, useTextarea, useTheme, useThemeSwitcher, useThemeTokens, useTodo, utils, validateConfig, validateConfiguration, validateTheme };
|
|
28418
|
+
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, GLASS_BORDER_GRADIENT, GLASS_DEFAULTS, 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, 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, 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, usePerformanceMonitor, usePieChart, useRadio, useResponsive, useResponsiveGlass, useRiver, useSelect, useSideMenu, useSideMenuItem, useSlot, useSpinner, useTextarea, useTheme, useThemeSwitcher, useThemeTokens, useTodo, utils, validateConfig, validateConfiguration, validateTheme };
|
|
28531
28419
|
//# sourceMappingURL=index.esm.js.map
|