@shohojdhara/atomix 0.3.13 → 0.3.15
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/CHANGELOG.md +39 -0
- package/README.md +2 -0
- package/build-tools/EXAMPLES.md +372 -0
- package/build-tools/README.md +242 -0
- package/build-tools/__tests__/error-handler.test.js +230 -0
- package/build-tools/__tests__/index.test.js +141 -0
- package/build-tools/__tests__/rollup-plugin.test.js +194 -0
- package/build-tools/__tests__/utils.test.js +161 -0
- package/build-tools/__tests__/vite-plugin.test.js +129 -0
- package/build-tools/__tests__/webpack-loader.test.js +190 -0
- package/build-tools/error-handler.js +308 -0
- package/build-tools/index.d.ts +43 -0
- package/build-tools/index.js +88 -0
- package/build-tools/package.json +67 -0
- package/build-tools/rollup-plugin.js +236 -0
- package/build-tools/types.d.ts +163 -0
- package/build-tools/utils.js +203 -0
- package/build-tools/vite-plugin.js +161 -0
- package/build-tools/webpack-loader.js +123 -0
- package/dist/atomix.css +298 -167
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +3 -3
- package/dist/atomix.min.css.map +1 -1
- package/dist/build-tools/EXAMPLES.md +372 -0
- package/dist/build-tools/README.md +242 -0
- package/dist/build-tools/__tests__/error-handler.test.js +230 -0
- package/dist/build-tools/__tests__/index.test.js +141 -0
- package/dist/build-tools/__tests__/rollup-plugin.test.js +194 -0
- package/dist/build-tools/__tests__/utils.test.js +161 -0
- package/dist/build-tools/__tests__/vite-plugin.test.js +129 -0
- package/dist/build-tools/__tests__/webpack-loader.test.js +190 -0
- package/dist/build-tools/error-handler.js +308 -0
- package/dist/build-tools/index.d.ts +43 -0
- package/dist/build-tools/index.js +88 -0
- package/dist/build-tools/package.json +67 -0
- package/dist/build-tools/rollup-plugin.js +236 -0
- package/dist/build-tools/types.d.ts +163 -0
- package/dist/build-tools/utils.js +203 -0
- package/dist/build-tools/vite-plugin.js +161 -0
- package/dist/build-tools/webpack-loader.js +123 -0
- package/dist/charts.d.ts +2 -2
- package/dist/charts.js +87 -58
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +42 -12
- package/dist/core.js +175 -135
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +30 -16
- package/dist/forms.js +146 -131
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +2 -2
- package/dist/heavy.js +151 -118
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +130 -106
- package/dist/index.esm.js +1083 -465
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1102 -483
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/theme.d.ts +27 -2
- package/dist/theme.js +721 -108
- package/dist/theme.js.map +1 -1
- package/package.json +23 -8
- package/scripts/atomix-cli.js +749 -1153
- package/scripts/cli/__tests__/README.md +81 -0
- package/scripts/cli/__tests__/basic.test.js +115 -0
- package/scripts/cli/__tests__/component-generator.test.js +332 -0
- package/scripts/cli/__tests__/integration.test.js +327 -0
- package/scripts/cli/__tests__/test-setup.js +133 -0
- package/scripts/cli/__tests__/token-manager.test.js +251 -0
- package/scripts/cli/__tests__/utils.test.js +78 -118
- package/scripts/cli/component-generator.js +564 -0
- package/scripts/cli/dependency-checker.js +355 -0
- package/scripts/cli/documentation-sync.js +542 -0
- package/scripts/cli/interactive-init.js +129 -292
- package/scripts/cli/mappings.js +211 -0
- package/scripts/cli/migration-tools.js +95 -288
- package/scripts/cli/template-manager.js +105 -0
- package/scripts/cli/templates/README.md +123 -0
- package/scripts/cli/templates/common-templates.js +636 -0
- package/scripts/cli/templates/composable-templates.js +171 -0
- package/scripts/cli/templates/config-templates.js +126 -0
- package/scripts/cli/templates/index.js +102 -0
- package/scripts/cli/templates/project-templates.js +342 -0
- package/scripts/cli/templates/react-templates.js +331 -0
- package/scripts/cli/templates/scss-templates.js +155 -0
- package/scripts/cli/templates/storybook-templates.js +236 -0
- package/scripts/cli/templates/testing-templates.js +224 -0
- package/scripts/cli/templates/testing-utils.js +278 -0
- package/scripts/cli/templates/token-templates.js +447 -0
- package/scripts/cli/templates/types-templates.js +147 -0
- package/scripts/cli/templates.js +35 -0
- package/scripts/cli/theme-bridge.js +28 -16
- package/scripts/cli/token-manager.js +432 -247
- package/scripts/cli/utils.js +37 -26
- package/src/components/Accordion/Accordion.stories.tsx +369 -870
- package/src/components/Accordion/Accordion.test.tsx +57 -0
- package/src/components/Accordion/Accordion.tsx +4 -0
- package/src/components/AtomixGlass/AtomixGlass.tsx +80 -39
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +103 -81
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +8 -7
- package/src/components/AtomixGlass/glass-utils.ts +2 -2
- package/src/components/AtomixGlass/shader-utils.ts +5 -0
- package/src/components/AtomixGlass/stories/Customization.stories.tsx +131 -0
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +2965 -2861
- package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -1
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +348 -0
- package/src/components/AtomixGlass/stories/Performance.stories.tsx +103 -0
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +73 -59
- package/src/components/AtomixGlass/stories/{ShaderVariants.stories.tsx → Shaders.stories.tsx} +1 -1
- package/src/components/AtomixGlass/stories/shared-components.tsx +90 -190
- package/src/components/Avatar/Avatar.stories.tsx +239 -27
- package/src/components/Badge/Badge.stories.tsx +132 -373
- package/src/components/Badge/Badge.test.tsx +51 -0
- package/src/components/Badge/Badge.tsx +20 -1
- package/src/components/Block/Block.stories.tsx +26 -17
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +141 -23
- package/src/components/Breadcrumb/Breadcrumb.tsx +2 -2
- package/src/components/Button/Button.stories.tsx +463 -1126
- package/src/components/Button/Button.test.tsx +107 -0
- package/src/components/Button/Button.tsx +50 -54
- package/src/components/Button/ButtonGroup.stories.tsx +373 -217
- package/src/components/Button/README.md +5 -0
- package/src/components/Callout/Callout.stories.tsx +299 -644
- package/src/components/Callout/Callout.test.tsx +10 -10
- package/src/components/Callout/Callout.tsx +7 -7
- package/src/components/Callout/README.md +9 -8
- package/src/components/Card/Card.stories.tsx +248 -68
- package/src/components/Card/Card.tsx +2 -2
- package/src/components/Chart/Chart.stories.tsx +156 -14
- package/src/components/Chart/Chart.tsx +1 -1
- package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +151 -69
- package/src/components/Countdown/Countdown.stories.tsx +115 -8
- package/src/components/DataTable/DataTable.stories.tsx +346 -146
- package/src/components/DataTable/DataTable.tsx +14 -12
- package/src/components/DatePicker/DatePicker.stories.tsx +325 -1066
- package/src/components/Dropdown/Dropdown.stories.tsx +157 -37
- package/src/components/EdgePanel/EdgePanel.stories.tsx +230 -21
- package/src/components/Footer/Footer.stories.tsx +392 -328
- package/src/components/Form/Checkbox.stories.tsx +143 -9
- package/src/components/Form/Checkbox.test.tsx +63 -0
- package/src/components/Form/Checkbox.tsx +90 -52
- package/src/components/Form/Form.stories.tsx +121 -22
- package/src/components/Form/FormGroup.stories.tsx +128 -5
- package/src/components/Form/Input.stories.tsx +28 -16
- package/src/components/Form/Input.test.tsx +59 -0
- package/src/components/Form/Input.tsx +97 -95
- package/src/components/Form/Radio.stories.tsx +232 -97
- package/src/components/Form/Radio.tsx +2 -2
- package/src/components/Form/Select.stories.tsx +144 -12
- package/src/components/Form/Select.tsx +2 -2
- package/src/components/Form/Textarea.stories.tsx +171 -13
- package/src/components/Form/Textarea.test.tsx +45 -0
- package/src/components/Form/Textarea.tsx +88 -86
- package/src/components/Hero/Hero.stories.tsx +333 -32
- package/src/components/List/List.stories.tsx +143 -5
- package/src/components/Modal/Modal.stories.tsx +185 -46
- package/src/components/Navigation/Navbar/Navbar.stories.tsx +5 -5
- package/src/components/Navigation/Navbar/Navbar.tsx +1 -1
- package/src/components/Navigation/README.md +1 -1
- package/src/components/Pagination/Pagination.stories.tsx +5 -2
- package/src/components/Pagination/Pagination.tsx +1 -1
- package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -10
- package/src/components/Popover/Popover.stories.tsx +449 -99
- package/src/components/ProductReview/ProductReview.tsx +1 -1
- package/src/components/Progress/Progress.stories.tsx +167 -5
- package/src/components/Progress/Progress.tsx +46 -46
- package/src/components/Rating/Rating.stories.tsx +4 -4
- package/src/components/Rating/Rating.tsx +8 -8
- package/src/components/River/River.stories.tsx +1 -1
- package/src/components/SectionIntro/SectionIntro.stories.tsx +240 -48
- package/src/components/Slider/Slider.stories.tsx +63 -63
- package/src/components/Spinner/Spinner.stories.tsx +104 -10
- package/src/components/Spinner/Spinner.test.tsx +35 -0
- package/src/components/Spinner/Spinner.tsx +9 -2
- package/src/components/Steps/Steps.stories.tsx +172 -43
- package/src/components/Tabs/Tabs.stories.tsx +136 -10
- package/src/components/Testimonial/Testimonial.stories.tsx +121 -4
- package/src/components/Todo/Todo.stories.tsx +198 -9
- package/src/components/Toggle/Toggle.stories.tsx +153 -43
- package/src/components/Toggle/Toggle.test.tsx +91 -0
- package/src/components/Toggle/Toggle.tsx +44 -27
- package/src/components/Tooltip/Tooltip.stories.tsx +194 -104
- package/src/components/Tooltip/Tooltip.tsx +1 -1
- package/src/components/Upload/Upload.stories.tsx +113 -24
- package/src/layouts/Grid/Grid.stories.tsx +49 -49
- package/src/layouts/MasonryGrid/MasonryGrid.stories.tsx +2 -2
- package/src/lib/README.md +2 -2
- package/src/lib/__tests__/theme-tools.test.ts +193 -0
- package/src/lib/composables/index.ts +2 -2
- package/src/lib/composables/useAccordion.ts +12 -3
- package/src/lib/composables/useAtomixGlass.ts +28 -56
- package/src/lib/composables/useBreadcrumb.ts +2 -2
- package/src/lib/composables/useCallout.ts +7 -7
- package/src/lib/composables/useChartExport.ts +2 -7
- package/src/lib/composables/useDataTable.ts +46 -29
- package/src/lib/composables/useNavbar.ts +1 -1
- package/src/lib/constants/components.ts +10 -33
- package/src/lib/storybook/InteractiveDemo.tsx +113 -0
- package/src/lib/storybook/PreviewContainer.tsx +36 -0
- package/src/lib/storybook/VariantsGrid.tsx +21 -0
- package/src/lib/storybook/index.ts +3 -0
- package/src/lib/theme/core/createThemeObject.ts +9 -5
- package/src/lib/theme/devtools/CLI.ts +155 -0
- package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +213 -0
- package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +566 -0
- package/src/lib/theme/devtools/LiveEditor.tsx +2 -1
- package/src/lib/theme/devtools/index.ts +3 -0
- package/src/lib/theme/errors/errors.ts +8 -0
- package/src/lib/theme/runtime/ThemeProvider.tsx +117 -57
- package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +305 -0
- package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +588 -0
- package/src/lib/theme/utils/__tests__/themeValidation.test.ts +264 -0
- package/src/lib/theme/utils/index.ts +1 -0
- package/src/lib/theme/utils/themeValidation.ts +501 -0
- package/src/lib/theme-tools.ts +32 -3
- package/src/lib/types/components.ts +82 -27
- package/src/lib/utils/__tests__/csv.test.ts +45 -0
- package/src/lib/utils/csv.ts +17 -0
- package/src/lib/utils/dataTableExport.ts +1 -10
- package/src/lib/utils/themeNaming.ts +1 -1
- package/src/styles/01-settings/_index.scss +2 -1
- package/src/styles/01-settings/_settings.accordion.scss +28 -7
- package/src/styles/01-settings/_settings.colors.scss +11 -11
- package/src/styles/01-settings/_settings.typography.scss +5 -5
- package/src/styles/02-tools/_tools.utility-api.scss +14 -0
- package/src/styles/06-components/_components.accordion.scss +56 -14
- package/src/styles/06-components/_components.callout.scss +29 -33
- package/src/styles/06-components/_components.checkbox.scss +23 -17
- package/src/styles/06-components/_index.scss +1 -1
- package/src/styles/99-utilities/_index.scss +2 -0
- package/src/styles/99-utilities/_utilities.display.scss +14 -3
- package/src/styles/99-utilities/_utilities.flex.scss +10 -10
- package/src/styles/99-utilities/_utilities.scss +3 -1
- package/src/styles/99-utilities/_utilities.text-gradient.scss +45 -0
- package/src/styles/99-utilities/_utilities.text.scss +28 -8
- package/themes/dark-complementary/README.md +98 -0
- package/themes/dark-complementary/index.scss +158 -0
- package/themes/default-light/README.md +81 -0
- package/themes/default-light/index.scss +154 -0
- package/themes/high-contrast/README.md +105 -0
- package/themes/high-contrast/index.scss +172 -0
- package/themes/test-theme/README.md +38 -0
- package/themes/test-theme/index.scss +47 -0
- package/scripts/cli/__tests__/cli-commands.test.js +0 -204
- package/scripts/cli/__tests__/vitest.config.js +0 -26
- package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +0 -1438
- package/src/lib/composables/useButton.ts +0 -93
- package/src/lib/composables/useCheckbox.ts +0 -70
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
2
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
3
|
+
import { Accordion } from './Accordion';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
|
|
6
|
+
describe('Accordion Component', () => {
|
|
7
|
+
it('renders correctly with title', () => {
|
|
8
|
+
render(<Accordion title="Test Accordion">Content</Accordion>);
|
|
9
|
+
expect(screen.getByText('Test Accordion')).toBeInTheDocument();
|
|
10
|
+
expect(screen.getByText('Content')).toBeInTheDocument();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('toggles when clicked', () => {
|
|
14
|
+
const onOpenChange = vi.fn();
|
|
15
|
+
render(<Accordion title="Test" onOpenChange={onOpenChange}>Content</Accordion>);
|
|
16
|
+
const button = screen.getByRole('button');
|
|
17
|
+
|
|
18
|
+
fireEvent.click(button);
|
|
19
|
+
expect(onOpenChange).toHaveBeenCalledWith(true);
|
|
20
|
+
expect(button).toHaveAttribute('aria-expanded', 'true');
|
|
21
|
+
|
|
22
|
+
fireEvent.click(button);
|
|
23
|
+
expect(onOpenChange).toHaveBeenCalledWith(false);
|
|
24
|
+
expect(button).toHaveAttribute('aria-expanded', 'false');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('calls legacy onOpen/onClose handlers', () => {
|
|
28
|
+
const onOpen = vi.fn();
|
|
29
|
+
const onClose = vi.fn();
|
|
30
|
+
render(<Accordion title="Test" onOpen={onOpen} onClose={onClose}>Content</Accordion>);
|
|
31
|
+
const button = screen.getByRole('button');
|
|
32
|
+
|
|
33
|
+
fireEvent.click(button);
|
|
34
|
+
expect(onOpen).toHaveBeenCalled();
|
|
35
|
+
|
|
36
|
+
fireEvent.click(button);
|
|
37
|
+
expect(onClose).toHaveBeenCalled();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('handles controlled state', () => {
|
|
41
|
+
const onOpenChange = vi.fn();
|
|
42
|
+
const { rerender } = render(<Accordion title="Test" isOpen={false} onOpenChange={onOpenChange}>Content</Accordion>);
|
|
43
|
+
const button = screen.getByRole('button');
|
|
44
|
+
|
|
45
|
+
fireEvent.click(button);
|
|
46
|
+
expect(onOpenChange).toHaveBeenCalledWith(true);
|
|
47
|
+
expect(button).toHaveAttribute('aria-expanded', 'false'); // Should not change internally
|
|
48
|
+
|
|
49
|
+
rerender(<Accordion title="Test" isOpen={true} onOpenChange={onOpenChange}>Content</Accordion>);
|
|
50
|
+
expect(button).toHaveAttribute('aria-expanded', 'true');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('supports glass effect', () => {
|
|
54
|
+
const { container } = render(<Accordion title="Test" glass>Content</Accordion>);
|
|
55
|
+
expect(container.querySelector('.c-accordion--glass')).toBeInTheDocument();
|
|
56
|
+
});
|
|
57
|
+
});
|
|
@@ -12,6 +12,8 @@ export const Accordion: React.FC<AccordionProps> = memo(({
|
|
|
12
12
|
defaultOpen = false,
|
|
13
13
|
isOpen: controlledOpen,
|
|
14
14
|
onOpenChange,
|
|
15
|
+
onOpen,
|
|
16
|
+
onClose,
|
|
15
17
|
disabled = false,
|
|
16
18
|
iconPosition = 'right',
|
|
17
19
|
icon,
|
|
@@ -39,6 +41,8 @@ export const Accordion: React.FC<AccordionProps> = memo(({
|
|
|
39
41
|
iconPosition,
|
|
40
42
|
isOpen: controlledOpen,
|
|
41
43
|
onOpenChange,
|
|
44
|
+
onOpen,
|
|
45
|
+
onClose,
|
|
42
46
|
});
|
|
43
47
|
|
|
44
48
|
// Default icon
|
|
@@ -57,7 +57,7 @@ import { useAtomixGlass } from '../../lib/composables/useAtomixGlass';
|
|
|
57
57
|
*
|
|
58
58
|
* @example
|
|
59
59
|
* // OverLight - Object config with custom settings
|
|
60
|
-
* <AtomixGlass
|
|
60
|
+
* <AtomixGlass
|
|
61
61
|
* overLight={{
|
|
62
62
|
* threshold: 0.8,
|
|
63
63
|
* opacity: 0.6,
|
|
@@ -147,14 +147,16 @@ export function AtomixGlass({
|
|
|
147
147
|
children,
|
|
148
148
|
});
|
|
149
149
|
|
|
150
|
-
//
|
|
151
|
-
|
|
150
|
+
// Calculate isOverLight independently from overLightConfig to prevent displacement changes on hover
|
|
151
|
+
// overLightConfig recalculates with hover/active states, but displacement should remain stable
|
|
152
|
+
const isOverLight = useMemo(() => overLightConfig?.isOverLight, [overLight]);
|
|
153
|
+
|
|
152
154
|
const shouldRenderOverLightLayers = enableOverLightLayers && isOverLight;
|
|
153
155
|
|
|
154
156
|
// Calculate base style with transforms
|
|
155
157
|
const baseStyle = {
|
|
156
158
|
...style,
|
|
157
|
-
...(
|
|
159
|
+
...(!effectiveDisableEffects && {
|
|
158
160
|
transform: transformStyle,
|
|
159
161
|
}),
|
|
160
162
|
};
|
|
@@ -171,26 +173,32 @@ export function AtomixGlass({
|
|
|
171
173
|
.join(' ');
|
|
172
174
|
|
|
173
175
|
// Calculate position and size styles
|
|
174
|
-
const positionStyles =
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
176
|
+
const positionStyles = useMemo(
|
|
177
|
+
() => ({
|
|
178
|
+
position: (style.position || 'absolute') as React.CSSProperties['position'],
|
|
179
|
+
top: style.top || 0,
|
|
180
|
+
left: style.left || 0,
|
|
181
|
+
}),
|
|
182
|
+
[style.position, style.top, style.left]
|
|
183
|
+
);
|
|
179
184
|
|
|
180
|
-
const adjustedSize =
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
185
|
+
const adjustedSize = useMemo(
|
|
186
|
+
() => ({
|
|
187
|
+
width:
|
|
188
|
+
style.position !== 'fixed'
|
|
189
|
+
? '100%'
|
|
190
|
+
: style.width
|
|
191
|
+
? style.width
|
|
192
|
+
: Math.max(glassSize.width, 0),
|
|
193
|
+
height:
|
|
194
|
+
style.position !== 'fixed'
|
|
195
|
+
? '100%'
|
|
196
|
+
: style.height
|
|
197
|
+
? style.height
|
|
198
|
+
: Math.max(glassSize.height, 0),
|
|
199
|
+
}),
|
|
200
|
+
[style.position, style.width, style.height, glassSize.width, glassSize.height]
|
|
201
|
+
);
|
|
194
202
|
|
|
195
203
|
// Memoize expensive gradient calculations
|
|
196
204
|
const gradientValues = useMemo(() => {
|
|
@@ -252,15 +260,30 @@ export function AtomixGlass({
|
|
|
252
260
|
hover2: isActive ? 0.5 : 0,
|
|
253
261
|
hover3: isHovered ? 0.4 : isActive ? 0.8 : 0,
|
|
254
262
|
base: isOverLight ? overLightOpacity || BASE_OVER_LIGHT_OPACITY : 0,
|
|
255
|
-
over: isOverLight
|
|
263
|
+
over: isOverLight
|
|
264
|
+
? (overLightOpacity || BASE_OVER_LIGHT_OPACITY) * OVER_OPACITY_MULTIPLIER
|
|
265
|
+
: 0,
|
|
256
266
|
};
|
|
257
267
|
}, [isHovered, isActive, isOverLight, overLightConfig.opacity]);
|
|
258
268
|
|
|
259
269
|
// Memoize CSS variables object
|
|
260
270
|
const glassVars = useMemo(() => {
|
|
261
|
-
const whiteColor =
|
|
262
|
-
const blackColor =
|
|
263
|
-
const {
|
|
271
|
+
const whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE;
|
|
272
|
+
const blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK;
|
|
273
|
+
const {
|
|
274
|
+
borderGradientAngle,
|
|
275
|
+
borderStop1,
|
|
276
|
+
borderStop2,
|
|
277
|
+
borderOpacities,
|
|
278
|
+
hoverPositions,
|
|
279
|
+
basePosition,
|
|
280
|
+
mx,
|
|
281
|
+
my,
|
|
282
|
+
absMx,
|
|
283
|
+
absMy,
|
|
284
|
+
} = gradientValues;
|
|
285
|
+
|
|
286
|
+
const configBorderOpacity = overLightConfig?.borderOpacity ?? 1;
|
|
264
287
|
|
|
265
288
|
return {
|
|
266
289
|
'--atomix-glass-radius': `${effectiveCornerRadius}px`,
|
|
@@ -268,12 +291,14 @@ export function AtomixGlass({
|
|
|
268
291
|
'--atomix-glass-position': positionStyles.position,
|
|
269
292
|
'--atomix-glass-top': positionStyles.top !== 'fixed' ? `${positionStyles.top}px` : '0',
|
|
270
293
|
'--atomix-glass-left': positionStyles.left !== 'fixed' ? `${positionStyles.left}px` : '0',
|
|
271
|
-
'--atomix-glass-width':
|
|
272
|
-
|
|
294
|
+
'--atomix-glass-width':
|
|
295
|
+
style.position !== 'fixed' ? adjustedSize.width : `${adjustedSize.width}px`,
|
|
296
|
+
'--atomix-glass-height':
|
|
297
|
+
style.position !== 'fixed' ? adjustedSize.height : `${adjustedSize.height}px`,
|
|
273
298
|
'--atomix-glass-border-width': 'var(--atomix-spacing-0-5, 0.09375rem)',
|
|
274
299
|
'--atomix-glass-blend-mode': isOverLight ? 'multiply' : 'overlay',
|
|
275
|
-
'--atomix-glass-border-gradient-1': `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${borderOpacities[0]}) ${borderStop1}%, rgba(${whiteColor}, ${borderOpacities[1]}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
|
|
276
|
-
'--atomix-glass-border-gradient-2': `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${borderOpacities[2]}) ${borderStop1}%, rgba(${whiteColor}, ${borderOpacities[3]}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
|
|
300
|
+
'--atomix-glass-border-gradient-1': `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
|
|
301
|
+
'--atomix-glass-border-gradient-2': `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[2] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[3] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
|
|
277
302
|
'--atomix-glass-hover-1-opacity': opacityValues.hover1,
|
|
278
303
|
'--atomix-glass-hover-1-gradient': isOverLight
|
|
279
304
|
? `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_END}%)`
|
|
@@ -295,14 +320,26 @@ export function AtomixGlass({
|
|
|
295
320
|
? `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%)`
|
|
296
321
|
: `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`,
|
|
297
322
|
} as React.CSSProperties;
|
|
298
|
-
}, [
|
|
323
|
+
}, [
|
|
324
|
+
gradientValues,
|
|
325
|
+
opacityValues,
|
|
326
|
+
effectiveCornerRadius,
|
|
327
|
+
transformStyle,
|
|
328
|
+
positionStyles,
|
|
329
|
+
adjustedSize,
|
|
330
|
+
style.position,
|
|
331
|
+
isOverLight,
|
|
332
|
+
overLightConfig.borderOpacity,
|
|
333
|
+
]);
|
|
299
334
|
|
|
300
335
|
// Helper function to render background layers
|
|
301
336
|
const renderBackgroundLayer = (layerType: 'dark' | 'black') => (
|
|
302
337
|
<div
|
|
303
338
|
className={[
|
|
304
339
|
ATOMIX_GLASS.BACKGROUND_LAYER_CLASS,
|
|
305
|
-
layerType === 'dark'
|
|
340
|
+
layerType === 'dark'
|
|
341
|
+
? ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS
|
|
342
|
+
: ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS,
|
|
306
343
|
isOverLight
|
|
307
344
|
? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS
|
|
308
345
|
: ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS,
|
|
@@ -342,7 +379,7 @@ export function AtomixGlass({
|
|
|
342
379
|
? 0
|
|
343
380
|
: mode === 'shader'
|
|
344
381
|
? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT
|
|
345
|
-
:
|
|
382
|
+
: isOverLight
|
|
346
383
|
? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT
|
|
347
384
|
: displacementScale
|
|
348
385
|
}
|
|
@@ -350,7 +387,7 @@ export function AtomixGlass({
|
|
|
350
387
|
saturation={
|
|
351
388
|
effectiveHighContrast
|
|
352
389
|
? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST
|
|
353
|
-
:
|
|
390
|
+
: isOverLight
|
|
354
391
|
? saturation * overLightConfig.saturationBoost
|
|
355
392
|
: saturation
|
|
356
393
|
}
|
|
@@ -369,10 +406,15 @@ export function AtomixGlass({
|
|
|
369
406
|
onMouseLeave={handleMouseLeave}
|
|
370
407
|
onMouseDown={handleMouseDown}
|
|
371
408
|
onMouseUp={handleMouseUp}
|
|
372
|
-
active={isActive}
|
|
373
409
|
isHovered={isHovered}
|
|
374
410
|
isActive={isActive}
|
|
375
|
-
overLight={
|
|
411
|
+
overLight={isOverLight}
|
|
412
|
+
overLightConfig={{
|
|
413
|
+
contrast: overLightConfig.contrast,
|
|
414
|
+
brightness: overLightConfig.brightness,
|
|
415
|
+
shadowIntensity: overLightConfig.shadowIntensity,
|
|
416
|
+
borderOpacity: overLightConfig.borderOpacity,
|
|
417
|
+
}}
|
|
376
418
|
onClick={onClick}
|
|
377
419
|
mode={mode}
|
|
378
420
|
transform={baseStyle.transform}
|
|
@@ -407,8 +449,7 @@ export function AtomixGlass({
|
|
|
407
449
|
className={ATOMIX_GLASS.OVERLAY_HIGHLIGHT_CLASS}
|
|
408
450
|
style={{
|
|
409
451
|
opacity:
|
|
410
|
-
opacityValues.over *
|
|
411
|
-
ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
|
|
452
|
+
opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
|
|
412
453
|
background: `radial-gradient(circle at ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_X}% ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_Y}%, rgba(255, 255, 255, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.WHITE_OPACITY}) 0%, transparent ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.STOP}%)`,
|
|
413
454
|
}}
|
|
414
455
|
/>
|
|
@@ -3,13 +3,7 @@ import type { CSSProperties } from 'react';
|
|
|
3
3
|
import type { DisplacementMode, MousePosition, GlassSize } from '../../lib/types/components';
|
|
4
4
|
import type { FragmentShaderType } from './shader-utils';
|
|
5
5
|
import { GlassFilter } from './GlassFilter';
|
|
6
|
-
import {
|
|
7
|
-
calculateElementCenter,
|
|
8
|
-
calculateDistance,
|
|
9
|
-
calculateMouseInfluence,
|
|
10
|
-
clampBlur,
|
|
11
|
-
validateGlassSize,
|
|
12
|
-
} from './glass-utils';
|
|
6
|
+
import { calculateMouseInfluence, clampBlur, validateGlassSize } from './glass-utils';
|
|
13
7
|
import { ATOMIX_GLASS } from '../../lib/constants/components';
|
|
14
8
|
|
|
15
9
|
const { CONSTANTS } = ATOMIX_GLASS;
|
|
@@ -58,7 +52,9 @@ const setCachedShader = (key: string, url: string): void => {
|
|
|
58
52
|
// Development mode: log cache size
|
|
59
53
|
if (typeof process === 'undefined' || process.env?.NODE_ENV !== 'production') {
|
|
60
54
|
if (sharedShaderCache.size >= MAX_CACHE_SIZE * 0.8) {
|
|
61
|
-
console.log(
|
|
55
|
+
console.log(
|
|
56
|
+
`AtomixGlass: Shader cache size: ${String(sharedShaderCache.size).replace(/[\r\n]/g, '')}/${String(MAX_CACHE_SIZE).replace(/[\r\n]/g, '')}`
|
|
57
|
+
);
|
|
62
58
|
}
|
|
63
59
|
}
|
|
64
60
|
};
|
|
@@ -76,10 +72,15 @@ interface AtomixGlassContainerProps {
|
|
|
76
72
|
onMouseEnter?: () => void;
|
|
77
73
|
onMouseDown?: () => void;
|
|
78
74
|
onMouseUp?: () => void;
|
|
79
|
-
active?: boolean;
|
|
80
75
|
isHovered?: boolean;
|
|
81
76
|
isActive?: boolean;
|
|
82
77
|
overLight?: boolean;
|
|
78
|
+
overLightConfig?: {
|
|
79
|
+
contrast?: number;
|
|
80
|
+
brightness?: number;
|
|
81
|
+
shadowIntensity?: number;
|
|
82
|
+
borderOpacity?: number;
|
|
83
|
+
};
|
|
83
84
|
cornerRadius?: number;
|
|
84
85
|
padding?: string;
|
|
85
86
|
glassSize?: GlassSize;
|
|
@@ -115,10 +116,10 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
|
|
|
115
116
|
onMouseLeave,
|
|
116
117
|
onMouseDown,
|
|
117
118
|
onMouseUp,
|
|
118
|
-
active = false,
|
|
119
119
|
isHovered = false,
|
|
120
120
|
isActive = false,
|
|
121
121
|
overLight = false,
|
|
122
|
+
overLightConfig = {},
|
|
122
123
|
cornerRadius = 0,
|
|
123
124
|
padding = '0 0',
|
|
124
125
|
glassSize = { width: 0, height: 0 },
|
|
@@ -153,14 +154,19 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
|
|
|
153
154
|
useEffect(() => {
|
|
154
155
|
if (mode === 'shader') {
|
|
155
156
|
// Dynamic import shader utilities
|
|
156
|
-
import('./shader-utils')
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
157
|
+
import('./shader-utils')
|
|
158
|
+
.then(shaderUtils => {
|
|
159
|
+
shaderUtilsRef.current = {
|
|
160
|
+
ShaderDisplacementGenerator: shaderUtils.ShaderDisplacementGenerator,
|
|
161
|
+
fragmentShaders: shaderUtils.fragmentShaders,
|
|
162
|
+
};
|
|
163
|
+
})
|
|
164
|
+
.catch(error => {
|
|
165
|
+
console.warn(
|
|
166
|
+
'AtomixGlassContainer: Error loading shader utilities',
|
|
167
|
+
String(error).replace(/[\r\n]/g, '')
|
|
168
|
+
);
|
|
169
|
+
});
|
|
164
170
|
} else {
|
|
165
171
|
// Clear shader utils when not in shader mode to free memory
|
|
166
172
|
shaderUtilsRef.current = null;
|
|
@@ -170,7 +176,12 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
|
|
|
170
176
|
// Generate shader map with debouncing and caching
|
|
171
177
|
useEffect(() => {
|
|
172
178
|
// Enhanced validation for shader mode
|
|
173
|
-
if (
|
|
179
|
+
if (
|
|
180
|
+
mode === 'shader' &&
|
|
181
|
+
glassSize &&
|
|
182
|
+
validateGlassSize(glassSize) &&
|
|
183
|
+
shaderUtilsRef.current
|
|
184
|
+
) {
|
|
174
185
|
// Create cache key from size and variant
|
|
175
186
|
const cacheKey = `${glassSize.width}x${glassSize.height}-${shaderVariant}`;
|
|
176
187
|
|
|
@@ -262,11 +273,13 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
|
|
|
262
273
|
const EDGE_BLUR_MULTIPLIER = 1.25;
|
|
263
274
|
const CENTER_BLUR_MULTIPLIER = 1.1;
|
|
264
275
|
const FLOW_BLUR_MULTIPLIER = 1.2;
|
|
265
|
-
const MOUSE_INFLUENCE_BLUR_FACTOR = 0.
|
|
276
|
+
const MOUSE_INFLUENCE_BLUR_FACTOR = 0.15;
|
|
266
277
|
const EDGE_INTENSITY_MULTIPLIER = 1.5;
|
|
267
|
-
const EDGE_INTENSITY_MOUSE_FACTOR = 0.
|
|
278
|
+
const EDGE_INTENSITY_MOUSE_FACTOR = 0.15;
|
|
268
279
|
const CENTER_INTENSITY_DISTANCE_FACTOR = 0.3;
|
|
269
|
-
const CENTER_INTENSITY_MOUSE_FACTOR = 0.
|
|
280
|
+
const CENTER_INTENSITY_MOUSE_FACTOR = 0.1;
|
|
281
|
+
// Maximum blur multiplier relative to base — prevents runaway blur
|
|
282
|
+
const MAX_BLUR_RELATIVE = 2;
|
|
270
283
|
|
|
271
284
|
const liquidBlur = useMemo(() => {
|
|
272
285
|
const defaultBlur = {
|
|
@@ -280,60 +293,42 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
|
|
|
280
293
|
if (
|
|
281
294
|
!enableLiquidBlur ||
|
|
282
295
|
!rectCache ||
|
|
283
|
-
!
|
|
284
|
-
typeof
|
|
285
|
-
typeof
|
|
286
|
-
isNaN(
|
|
287
|
-
isNaN(
|
|
296
|
+
!mouseOffset ||
|
|
297
|
+
typeof mouseOffset.x !== 'number' ||
|
|
298
|
+
typeof mouseOffset.y !== 'number' ||
|
|
299
|
+
isNaN(mouseOffset.x) ||
|
|
300
|
+
isNaN(mouseOffset.y)
|
|
288
301
|
) {
|
|
289
302
|
return defaultBlur;
|
|
290
303
|
}
|
|
291
304
|
|
|
292
305
|
try {
|
|
293
|
-
// Cache center and distance calculations
|
|
294
|
-
const center = calculateElementCenter(rectCache);
|
|
295
|
-
const distance = calculateDistance(globalMousePosition, center);
|
|
296
|
-
const maxDistance =
|
|
297
|
-
Math.sqrt(rectCache.width * rectCache.width + rectCache.height * rectCache.height) / 2;
|
|
298
|
-
const normalizedDistance = Math.min(distance / maxDistance, 1);
|
|
299
306
|
const mouseInfluence = calculateMouseInfluence(mouseOffset);
|
|
307
|
+
const maxBlur = blurAmount * MAX_BLUR_RELATIVE;
|
|
300
308
|
|
|
301
|
-
const baseBlur =
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
const
|
|
306
|
-
const
|
|
307
|
-
const
|
|
308
|
-
const
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
const activeMultiplier = isActive ? 1.4 : 1;
|
|
314
|
-
const stateMultiplier = hoverMultiplier * activeMultiplier;
|
|
315
|
-
|
|
309
|
+
const baseBlur = Math.min(
|
|
310
|
+
maxBlur,
|
|
311
|
+
blurAmount + mouseInfluence * blurAmount * MOUSE_INFLUENCE_BLUR_FACTOR
|
|
312
|
+
);
|
|
313
|
+
const edgeIntensity = mouseInfluence * EDGE_INTENSITY_MOUSE_FACTOR;
|
|
314
|
+
const edgeBlur = Math.min(maxBlur, baseBlur * (0.8 + edgeIntensity * 0.4));
|
|
315
|
+
const centerIntensity = mouseInfluence * CENTER_INTENSITY_MOUSE_FACTOR;
|
|
316
|
+
const centerBlur = Math.min(maxBlur, baseBlur * (0.3 + centerIntensity * 0.3));
|
|
317
|
+
const flowBlur = Math.min(maxBlur, baseBlur * FLOW_BLUR_MULTIPLIER);
|
|
318
|
+
|
|
319
|
+
// NOTE: hover/active multipliers intentionally omitted here —
|
|
320
|
+
// they belong on opacity layers, not the blur filter itself.
|
|
316
321
|
return {
|
|
317
|
-
baseBlur: clampBlur(baseBlur
|
|
318
|
-
edgeBlur: clampBlur(edgeBlur
|
|
319
|
-
centerBlur: clampBlur(centerBlur
|
|
320
|
-
flowBlur: clampBlur(flowBlur
|
|
322
|
+
baseBlur: clampBlur(baseBlur),
|
|
323
|
+
edgeBlur: clampBlur(edgeBlur),
|
|
324
|
+
centerBlur: clampBlur(centerBlur),
|
|
325
|
+
flowBlur: clampBlur(flowBlur),
|
|
321
326
|
};
|
|
322
327
|
} catch (error) {
|
|
323
328
|
console.warn('AtomixGlassContainer: Error calculating liquid blur', error);
|
|
324
329
|
return defaultBlur;
|
|
325
330
|
}
|
|
326
|
-
}, [
|
|
327
|
-
enableLiquidBlur,
|
|
328
|
-
blurAmount,
|
|
329
|
-
globalMousePosition,
|
|
330
|
-
mouseOffset,
|
|
331
|
-
isHovered,
|
|
332
|
-
isActive,
|
|
333
|
-
rectCache,
|
|
334
|
-
style,
|
|
335
|
-
glassSize,
|
|
336
|
-
]);
|
|
331
|
+
}, [enableLiquidBlur, blurAmount, mouseOffset, rectCache]);
|
|
337
332
|
|
|
338
333
|
const backdropStyle = useMemo(() => {
|
|
339
334
|
try {
|
|
@@ -364,15 +359,18 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
|
|
|
364
359
|
const useMultiPass = enableLiquidBlur && !devicePrefersPerformance && !areaIsLarge;
|
|
365
360
|
|
|
366
361
|
if (useMultiPass) {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
362
|
+
// Use a single weighted-average blur instead of stacking multiple
|
|
363
|
+
// blur() calls. CSS blur() is additive — stacking 4 passes
|
|
364
|
+
// causes the perceived blur to compound far beyond any single value.
|
|
365
|
+
const weightedBlur = clampBlur(
|
|
366
|
+
validatedBaseBlur * 0.4 +
|
|
367
|
+
validatedEdgeBlur * 0.25 +
|
|
368
|
+
validatedCenterBlur * 0.15 +
|
|
369
|
+
validatedFlowBlur * 0.2
|
|
370
|
+
);
|
|
373
371
|
|
|
374
372
|
return {
|
|
375
|
-
backdropFilter:
|
|
373
|
+
backdropFilter: `blur(${weightedBlur}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1.05}) brightness(${overLightConfig?.brightness || 1.05})`,
|
|
376
374
|
};
|
|
377
375
|
}
|
|
378
376
|
|
|
@@ -387,7 +385,7 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
|
|
|
387
385
|
);
|
|
388
386
|
|
|
389
387
|
return {
|
|
390
|
-
backdropFilter: `blur(${effectiveBlur}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(1.05) brightness(1.05)`,
|
|
388
|
+
backdropFilter: `blur(${effectiveBlur}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1.05}) brightness(${overLightConfig?.brightness || 1.05})`,
|
|
391
389
|
};
|
|
392
390
|
} catch (error) {
|
|
393
391
|
console.warn('AtomixGlassContainer: Error calculating backdrop style', error);
|
|
@@ -424,11 +422,11 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
|
|
|
424
422
|
'--atomix-glass-container-backdrop': backdropStyle?.backdropFilter || 'none',
|
|
425
423
|
'--atomix-glass-container-shadow': overLight
|
|
426
424
|
? [
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
425
|
+
`inset 0 1px 0 rgba(255, 255, 255, ${(0.4 + mx * 0.002) * (overLightConfig?.shadowIntensity || 1)})`,
|
|
426
|
+
`inset 0 -1px 0 rgba(0, 0, 0, ${(0.2 + Math.abs(my) * 0.001) * (overLightConfig?.shadowIntensity || 1)})`,
|
|
427
|
+
`inset 0 0 20px rgba(0, 0, 0, ${(0.08 + Math.abs(mx + my) * 0.001) * (overLightConfig?.shadowIntensity || 1)})`,
|
|
428
|
+
`0 2px 12px rgba(0, 0, 0, ${(0.12 + Math.abs(my) * 0.002) * (overLightConfig?.shadowIntensity || 1)})`,
|
|
429
|
+
].join(', ')
|
|
432
430
|
: '0 0 20px rgba(0, 0, 0, 0.15) inset, 0 4px 8px rgba(0, 0, 0, 0.08) inset',
|
|
433
431
|
'--atomix-glass-container-shadow-opacity': effectiveDisableEffects ? 0 : 1,
|
|
434
432
|
// Background and shadow values use design token-aligned RGB values
|
|
@@ -464,10 +462,29 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
|
|
|
464
462
|
effectiveDisableEffects,
|
|
465
463
|
]);
|
|
466
464
|
|
|
465
|
+
// Helper to force no transition/animation overrides with !important
|
|
466
|
+
const setForceNoTransition = (el: HTMLElement | null) => {
|
|
467
|
+
if (el) {
|
|
468
|
+
el.style.setProperty('transition-duration', '0s', 'important');
|
|
469
|
+
el.style.setProperty('animation-duration', '0s', 'important');
|
|
470
|
+
el.style.setProperty('transition-delay', '0s', 'important');
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
|
|
467
474
|
return (
|
|
468
475
|
<div
|
|
469
|
-
ref={
|
|
470
|
-
|
|
476
|
+
ref={el => {
|
|
477
|
+
// Apply force no-transition
|
|
478
|
+
setForceNoTransition(el);
|
|
479
|
+
|
|
480
|
+
// Handle forwarded ref
|
|
481
|
+
if (typeof ref === 'function') {
|
|
482
|
+
ref(el);
|
|
483
|
+
} else if (ref) {
|
|
484
|
+
(ref as React.MutableRefObject<HTMLDivElement | null>).current = el;
|
|
485
|
+
}
|
|
486
|
+
}}
|
|
487
|
+
className={`${ATOMIX_GLASS.CONTAINER_CLASS} ${className} ${isActive ? ATOMIX_GLASS.CLASSES.ACTIVE : ''} ${overLight ? ATOMIX_GLASS.CLASSES.OVER_LIGHT : ''}`}
|
|
471
488
|
style={{ ...style, ...containerVars }}
|
|
472
489
|
onClick={onClick}
|
|
473
490
|
>
|
|
@@ -484,7 +501,10 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
|
|
|
484
501
|
onMouseDown={onMouseDown}
|
|
485
502
|
onMouseUp={onMouseUp}
|
|
486
503
|
>
|
|
487
|
-
<div
|
|
504
|
+
<div
|
|
505
|
+
className={ATOMIX_GLASS.FILTER_CLASS}
|
|
506
|
+
style={{ zIndex: 1, position: 'absolute', inset: 0 }}
|
|
507
|
+
>
|
|
488
508
|
<GlassFilter
|
|
489
509
|
blurAmount={blurAmount}
|
|
490
510
|
mode={mode}
|
|
@@ -503,6 +523,7 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
|
|
|
503
523
|
/>
|
|
504
524
|
{/* Enhanced Apple Liquid Glass Inner Shadow Layer */}
|
|
505
525
|
<div
|
|
526
|
+
ref={setForceNoTransition}
|
|
506
527
|
className={ATOMIX_GLASS.FILTER_OVERLAY_CLASS}
|
|
507
528
|
style={
|
|
508
529
|
{
|
|
@@ -532,7 +553,8 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
|
|
|
532
553
|
{
|
|
533
554
|
position: 'relative',
|
|
534
555
|
textShadow: `var(--atomix-glass-container-text-shadow)`,
|
|
535
|
-
|
|
556
|
+
// Ensure content is always above the filter layer (zIndex 1)
|
|
557
|
+
zIndex: elasticity > 0 ? 100 : 2,
|
|
536
558
|
} as CSSProperties
|
|
537
559
|
}
|
|
538
560
|
>
|
|
@@ -544,4 +566,4 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
|
|
|
544
566
|
}
|
|
545
567
|
);
|
|
546
568
|
|
|
547
|
-
AtomixGlassContainer.displayName = 'AtomixGlassContainer';
|
|
569
|
+
AtomixGlassContainer.displayName = 'AtomixGlassContainer';
|