@shohojdhara/atomix 0.4.7 → 0.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/atomix.config.ts +58 -1
- package/dist/atomix.css +172 -157
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +4 -4
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.d.ts +33 -0
- package/dist/charts.js +1274 -164
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +33 -10
- package/dist/core.js +1099 -83
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +33 -0
- package/dist/forms.js +2106 -1050
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +42 -1
- package/dist/heavy.js +1663 -638
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +442 -270
- package/dist/index.esm.js +1947 -680
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1982 -712
- 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 +6 -3
- package/scripts/atomix-cli.js +136 -1827
- package/scripts/cli/__tests__/basic.test.js +3 -2
- package/scripts/cli/__tests__/clean.test.js +278 -0
- package/scripts/cli/__tests__/component-validator.test.js +433 -0
- package/scripts/cli/__tests__/generator.test.js +613 -0
- package/scripts/cli/__tests__/glass-motion.test.js +256 -0
- package/scripts/cli/__tests__/integration.test.js +719 -108
- package/scripts/cli/__tests__/migrate.test.js +74 -0
- package/scripts/cli/__tests__/security.test.js +206 -0
- package/scripts/cli/__tests__/test-setup.js +3 -1
- package/scripts/cli/__tests__/theme-bridge.test.js +507 -0
- package/scripts/cli/__tests__/token-provider.test.js +361 -0
- package/scripts/cli/__tests__/utils.test.js +5 -5
- package/scripts/cli/commands/benchmark.js +105 -0
- package/scripts/cli/commands/build-theme.js +115 -0
- package/scripts/cli/commands/clean.js +109 -0
- package/scripts/cli/commands/doctor.js +88 -0
- package/scripts/cli/commands/generate.js +218 -0
- package/scripts/cli/commands/init.js +73 -0
- package/scripts/cli/commands/migrate.js +106 -0
- package/scripts/cli/commands/sync-tokens.js +206 -0
- package/scripts/cli/commands/theme-bridge.js +248 -0
- package/scripts/cli/commands/tokens.js +157 -0
- package/scripts/cli/commands/validate.js +194 -0
- package/scripts/cli/internal/ai-engine.js +156 -0
- package/scripts/cli/internal/compiler.js +114 -0
- package/scripts/cli/internal/component-validator.js +443 -0
- package/scripts/cli/internal/config-loader.js +162 -0
- package/scripts/cli/internal/filesystem.js +158 -0
- package/scripts/cli/internal/generator.js +430 -0
- package/scripts/cli/internal/glass-generator.js +398 -0
- package/scripts/cli/internal/hook-generator.js +369 -0
- package/scripts/cli/internal/hooks.js +61 -0
- package/scripts/cli/internal/itcss-generator.js +565 -0
- package/scripts/cli/internal/motion-generator.js +679 -0
- package/scripts/cli/internal/template-engine.js +301 -0
- package/scripts/cli/internal/theme-bridge.js +664 -0
- package/scripts/cli/internal/tokens/engine.js +122 -0
- package/scripts/cli/internal/tokens/provider.js +34 -0
- package/scripts/cli/internal/tokens/providers/figma.js +50 -0
- package/scripts/cli/internal/tokens/providers/style-dictionary.js +48 -0
- package/scripts/cli/internal/tokens/providers/w3c.js +48 -0
- package/scripts/cli/internal/tokens/token-provider.js +443 -0
- package/scripts/cli/internal/tokens/token-validator.js +513 -0
- package/scripts/cli/internal/validator.js +276 -0
- package/scripts/cli/internal/wizard.js +115 -0
- package/scripts/cli/mappings.js +23 -0
- package/scripts/cli/migration-tools.js +164 -94
- package/scripts/cli/plugins/style-dictionary.js +46 -0
- package/scripts/cli/templates/README.md +525 -95
- package/scripts/cli/templates/common-templates.js +40 -14
- package/scripts/cli/templates/components/react-component.ts +282 -0
- package/scripts/cli/templates/config/project-config.ts +112 -0
- package/scripts/cli/templates/hooks/use-component.ts +477 -0
- package/scripts/cli/templates/index.js +19 -4
- package/scripts/cli/templates/index.ts +171 -0
- package/scripts/cli/templates/next-templates.js +72 -0
- package/scripts/cli/templates/react-templates.js +70 -126
- package/scripts/cli/templates/scss-templates.js +35 -35
- package/scripts/cli/templates/stories/storybook-story.ts +241 -0
- package/scripts/cli/templates/styles/scss-component.ts +255 -0
- package/scripts/cli/templates/tests/vitest-test.ts +229 -0
- package/scripts/cli/templates/token-templates.js +337 -1
- package/scripts/cli/templates/tokens/token-generators.ts +1088 -0
- package/scripts/cli/templates/types/component-types.ts +145 -0
- package/scripts/cli/templates/utils/testing-utils.ts +144 -0
- package/scripts/cli/templates/vanilla-templates.js +39 -0
- package/scripts/cli/token-manager.js +8 -2
- package/scripts/cli/utils/cache-manager.js +240 -0
- package/scripts/cli/utils/detector.js +46 -0
- package/scripts/cli/utils/diagnostics.js +289 -0
- package/scripts/cli/utils/error.js +89 -0
- package/scripts/cli/utils/helpers.js +67 -0
- package/scripts/cli/utils/logger.js +75 -0
- package/scripts/cli/utils/security.js +302 -0
- package/scripts/cli/utils/telemetry.js +115 -0
- package/scripts/cli/utils/validation.js +37 -0
- package/scripts/cli/utils.js +28 -341
- package/src/components/Accordion/Accordion.stories.tsx +0 -18
- package/src/components/Accordion/Accordion.test.tsx +0 -17
- package/src/components/Accordion/Accordion.tsx +0 -4
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +37 -3
- package/src/components/AtomixGlass/AtomixGlass.tsx +143 -31
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +129 -31
- package/src/components/AtomixGlass/PerformanceDashboard.tsx +219 -0
- package/src/components/AtomixGlass/README.md +25 -10
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +216 -0
- package/src/components/AtomixGlass/animation-system.ts +578 -0
- package/src/components/AtomixGlass/shader-utils.ts +4 -1
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +157 -6
- package/src/components/AtomixGlass/stories/Phase1-Animation.stories.tsx +653 -0
- package/src/components/AtomixGlass/stories/Phase1-Test.stories.tsx +95 -0
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +51 -51
- package/src/components/AtomixGlass/stories/shared-components.tsx +6 -0
- package/src/components/Avatar/Avatar.tsx +1 -1
- package/src/components/Button/Button.stories.disabled-link.tsx +10 -0
- package/src/components/Button/Button.stories.tsx +10 -0
- package/src/components/Button/Button.test.tsx +16 -11
- package/src/components/Button/Button.tsx +4 -4
- package/src/components/Card/Card.tsx +1 -1
- package/src/components/Dropdown/Dropdown.tsx +12 -12
- package/src/components/Form/Select.tsx +62 -3
- package/src/components/Modal/Modal.tsx +14 -3
- package/src/components/Navigation/Navbar/Navbar.tsx +44 -0
- package/src/components/Slider/Slider.stories.tsx +3 -3
- package/src/components/Slider/Slider.tsx +38 -0
- package/src/components/Steps/Steps.tsx +3 -3
- package/src/components/Tabs/Tabs.tsx +77 -8
- package/src/components/Testimonial/Testimonial.tsx +1 -1
- package/src/components/TypedButton/TypedButton.stories.tsx +59 -0
- package/src/components/TypedButton/TypedButton.tsx +39 -0
- package/src/components/TypedButton/index.ts +2 -0
- package/src/components/VideoPlayer/VideoPlayer.tsx +11 -4
- package/src/lib/composables/index.ts +4 -7
- package/src/lib/composables/types.ts +45 -0
- package/src/lib/composables/useAccordion.ts +0 -7
- package/src/lib/composables/useAtomixGlass.ts +148 -6
- package/src/lib/composables/useAtomixGlassStyles.ts +9 -7
- package/src/lib/composables/useChartExport.ts +3 -13
- package/src/lib/composables/useDropdown.ts +66 -0
- package/src/lib/composables/useFocusTrap.ts +80 -0
- package/src/lib/composables/usePerformanceMonitor.ts +448 -0
- package/src/lib/composables/useResponsiveGlass.presets.ts +192 -0
- package/src/lib/composables/useResponsiveGlass.ts +441 -0
- package/src/lib/composables/useTooltip.ts +16 -0
- package/src/lib/composables/useTypedButton.ts +66 -0
- package/src/lib/config/index.ts +62 -5
- package/src/lib/constants/components.ts +62 -7
- package/src/lib/theme/devtools/__tests__/useHistory.test.tsx +150 -0
- package/src/lib/theme/tokens/centralized-tokens.ts +120 -0
- package/src/lib/theme/utils/__tests__/domUtils.test.ts +101 -0
- package/src/lib/types/components.ts +37 -11
- package/src/lib/types/glass.ts +35 -0
- package/src/lib/types/index.ts +1 -0
- package/src/lib/utils/displacement-generator.ts +1 -1
- package/src/styles/01-settings/_settings.testtypecheck.scss +53 -0
- package/src/styles/01-settings/_settings.typedbutton.scss +53 -0
- package/src/styles/06-components/_components.atomix-glass.scss +17 -21
- package/src/styles/06-components/_components.edge-panel.scss +1 -5
- package/src/styles/06-components/_components.modal.scss +1 -4
- package/src/styles/06-components/_components.navbar.scss +1 -1
- package/src/styles/06-components/_components.testbutton.scss +212 -0
- package/src/styles/06-components/_components.testtypecheck.scss +212 -0
- package/src/styles/06-components/_components.tooltip.scss +9 -5
- package/src/styles/06-components/_components.typedbutton.scss +212 -0
- package/src/styles/99-utilities/_index.scss +1 -0
- package/src/styles/99-utilities/_utilities.text.scss +1 -1
- package/src/styles/99-utilities/_utilities.touch-target.scss +36 -0
- package/scripts/cli/component-generator.js +0 -564
- package/scripts/cli/interactive-init.js +0 -357
- package/src/styles/06-components/old.chart.styles.scss +0 -2788
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { renderHook, act } from '@testing-library/react';
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import { useHistory } from '../useHistory';
|
|
4
|
+
|
|
5
|
+
describe('useHistory', () => {
|
|
6
|
+
it('initializes with default values', () => {
|
|
7
|
+
const { result } = renderHook(() => useHistory({ initialState: 'initial' }));
|
|
8
|
+
|
|
9
|
+
expect(result.current.state).toBe('initial');
|
|
10
|
+
expect(result.current.canUndo).toBe(false);
|
|
11
|
+
expect(result.current.canRedo).toBe(false);
|
|
12
|
+
expect(result.current.getHistoryStats()).toEqual({ currentIndex: 0, totalEntries: 1 });
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('updates state and history on setState', () => {
|
|
16
|
+
const { result } = renderHook(() => useHistory({ initialState: 'initial' }));
|
|
17
|
+
|
|
18
|
+
act(() => {
|
|
19
|
+
result.current.setState('step 1');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
expect(result.current.state).toBe('step 1');
|
|
23
|
+
expect(result.current.canUndo).toBe(true);
|
|
24
|
+
expect(result.current.canRedo).toBe(false);
|
|
25
|
+
expect(result.current.getHistoryStats()).toEqual({ currentIndex: 1, totalEntries: 2 });
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('handles undo correctly', () => {
|
|
29
|
+
const { result } = renderHook(() => useHistory({ initialState: 'initial' }));
|
|
30
|
+
|
|
31
|
+
act(() => {
|
|
32
|
+
result.current.setState('step 1');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
act(() => {
|
|
36
|
+
result.current.undo();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
expect(result.current.state).toBe('initial');
|
|
40
|
+
expect(result.current.canUndo).toBe(false);
|
|
41
|
+
expect(result.current.canRedo).toBe(true);
|
|
42
|
+
expect(result.current.getHistoryStats()).toEqual({ currentIndex: 0, totalEntries: 2 });
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('handles redo correctly', () => {
|
|
46
|
+
const { result } = renderHook(() => useHistory({ initialState: 'initial' }));
|
|
47
|
+
|
|
48
|
+
act(() => {
|
|
49
|
+
result.current.setState('step 1');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
act(() => {
|
|
53
|
+
result.current.undo();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
act(() => {
|
|
57
|
+
result.current.redo();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
expect(result.current.state).toBe('step 1');
|
|
61
|
+
expect(result.current.canUndo).toBe(true);
|
|
62
|
+
expect(result.current.canRedo).toBe(false);
|
|
63
|
+
expect(result.current.getHistoryStats()).toEqual({ currentIndex: 1, totalEntries: 2 });
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('truncates future history when setState is called after undo', () => {
|
|
67
|
+
const { result } = renderHook(() => useHistory({ initialState: 'initial' }));
|
|
68
|
+
|
|
69
|
+
act(() => {
|
|
70
|
+
result.current.setState('step 1');
|
|
71
|
+
});
|
|
72
|
+
act(() => {
|
|
73
|
+
result.current.setState('step 2');
|
|
74
|
+
});
|
|
75
|
+
act(() => {
|
|
76
|
+
result.current.undo();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
expect(result.current.state).toBe('step 1');
|
|
80
|
+
|
|
81
|
+
act(() => {
|
|
82
|
+
result.current.setState('step 1.5');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
expect(result.current.state).toBe('step 1.5');
|
|
86
|
+
expect(result.current.canUndo).toBe(true);
|
|
87
|
+
expect(result.current.canRedo).toBe(false);
|
|
88
|
+
expect(result.current.getHistoryStats()).toEqual({ currentIndex: 2, totalEntries: 3 });
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('respects maxHistorySize limit', () => {
|
|
92
|
+
const { result } = renderHook(() => useHistory({ initialState: '0', maxHistorySize: 3 }));
|
|
93
|
+
|
|
94
|
+
act(() => { result.current.setState('1'); });
|
|
95
|
+
act(() => { result.current.setState('2'); });
|
|
96
|
+
act(() => { result.current.setState('3'); });
|
|
97
|
+
act(() => { result.current.setState('4'); });
|
|
98
|
+
|
|
99
|
+
// If maxHistorySize is 3, then total entries should be 3.
|
|
100
|
+
expect(result.current.state).toBe('4');
|
|
101
|
+
expect(result.current.getHistoryStats().totalEntries).toBe(3);
|
|
102
|
+
expect(result.current.getHistoryStats().currentIndex).toBe(2);
|
|
103
|
+
|
|
104
|
+
// Test that the oldest state has been removed by attempting to undo completely
|
|
105
|
+
act(() => { result.current.undo(); }); // state: 3
|
|
106
|
+
act(() => { result.current.undo(); }); // state: 2
|
|
107
|
+
expect(result.current.state).toBe('2');
|
|
108
|
+
expect(result.current.canUndo).toBe(false);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('handles clearHistory', () => {
|
|
112
|
+
const { result } = renderHook(() => useHistory({ initialState: 'initial' }));
|
|
113
|
+
|
|
114
|
+
act(() => { result.current.setState('step 1'); });
|
|
115
|
+
act(() => { result.current.setState('step 2'); });
|
|
116
|
+
|
|
117
|
+
act(() => {
|
|
118
|
+
result.current.clearHistory();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
expect(result.current.state).toBe('step 2');
|
|
122
|
+
expect(result.current.canUndo).toBe(false);
|
|
123
|
+
expect(result.current.canRedo).toBe(false);
|
|
124
|
+
expect(result.current.getHistoryStats()).toEqual({ currentIndex: 0, totalEntries: 1 });
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('does nothing when undoing at beginning of history', () => {
|
|
128
|
+
const { result } = renderHook(() => useHistory({ initialState: 'initial' }));
|
|
129
|
+
|
|
130
|
+
act(() => {
|
|
131
|
+
result.current.undo();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
expect(result.current.state).toBe('initial');
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('does nothing when redoing at end of history', () => {
|
|
138
|
+
const { result } = renderHook(() => useHistory({ initialState: 'initial' }));
|
|
139
|
+
|
|
140
|
+
act(() => {
|
|
141
|
+
result.current.setState('step 1');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
act(() => {
|
|
145
|
+
result.current.redo();
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
expect(result.current.state).toBe('step 1');
|
|
149
|
+
});
|
|
150
|
+
});
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized Design Token Library
|
|
3
|
+
*
|
|
4
|
+
* This file serves as the single source of truth for all design tokens
|
|
5
|
+
* in the Atomix Design System. It consolidates colors, typography,
|
|
6
|
+
* spacing, shadows, and animations.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { DesignTokens } from './tokens';
|
|
10
|
+
|
|
11
|
+
export const COLORS = {
|
|
12
|
+
primary: '#7c3aed',
|
|
13
|
+
secondary: '#64748b',
|
|
14
|
+
success: '#22c55e',
|
|
15
|
+
info: '#3b82f6',
|
|
16
|
+
warning: '#eab308',
|
|
17
|
+
error: '#ef4444',
|
|
18
|
+
light: '#f8fafc',
|
|
19
|
+
dark: '#0f172a',
|
|
20
|
+
gray: {
|
|
21
|
+
1: '#f8fafc',
|
|
22
|
+
2: '#f1f5f9',
|
|
23
|
+
3: '#e2e8f0',
|
|
24
|
+
4: '#cbd5e1',
|
|
25
|
+
5: '#94a3b8',
|
|
26
|
+
6: '#64748b',
|
|
27
|
+
7: '#475569',
|
|
28
|
+
8: '#334155',
|
|
29
|
+
9: '#1e293b',
|
|
30
|
+
10: '#0f172a',
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const TYPOGRAPHY = {
|
|
35
|
+
fontFamily: {
|
|
36
|
+
base: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
|
|
37
|
+
heading: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
|
|
38
|
+
mono: "'Fira Code', 'JetBrains Mono', monospace",
|
|
39
|
+
},
|
|
40
|
+
fontSize: {
|
|
41
|
+
xs: '0.75rem',
|
|
42
|
+
sm: '0.875rem',
|
|
43
|
+
base: '1rem',
|
|
44
|
+
lg: '1.125rem',
|
|
45
|
+
xl: '1.25rem',
|
|
46
|
+
'2xl': '1.5rem',
|
|
47
|
+
'3xl': '1.875rem',
|
|
48
|
+
'4xl': '2.25rem',
|
|
49
|
+
},
|
|
50
|
+
fontWeight: {
|
|
51
|
+
light: 300,
|
|
52
|
+
normal: 400,
|
|
53
|
+
medium: 500,
|
|
54
|
+
semibold: 600,
|
|
55
|
+
bold: 700,
|
|
56
|
+
},
|
|
57
|
+
lineHeight: {
|
|
58
|
+
none: 1,
|
|
59
|
+
tight: 1.25,
|
|
60
|
+
snug: 1.375,
|
|
61
|
+
normal: 1.5,
|
|
62
|
+
relaxed: 1.625,
|
|
63
|
+
loose: 2,
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const SPACING = {
|
|
68
|
+
0: '0',
|
|
69
|
+
1: '0.25rem',
|
|
70
|
+
2: '0.5rem',
|
|
71
|
+
3: '0.75rem',
|
|
72
|
+
4: '1rem',
|
|
73
|
+
5: '1.25rem',
|
|
74
|
+
6: '1.5rem',
|
|
75
|
+
8: '2rem',
|
|
76
|
+
10: '2.5rem',
|
|
77
|
+
12: '3rem',
|
|
78
|
+
16: '4rem',
|
|
79
|
+
20: '5rem',
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export const SHADOWS = {
|
|
83
|
+
xs: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
|
|
84
|
+
sm: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
|
|
85
|
+
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
|
|
86
|
+
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
|
|
87
|
+
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const ANIMATIONS = {
|
|
91
|
+
duration: {
|
|
92
|
+
fast: '150ms',
|
|
93
|
+
normal: '300ms',
|
|
94
|
+
slow: '500ms',
|
|
95
|
+
},
|
|
96
|
+
easing: {
|
|
97
|
+
linear: 'linear',
|
|
98
|
+
in: 'cubic-bezier(0.4, 0, 1, 1)',
|
|
99
|
+
out: 'cubic-bezier(0, 0, 0.2, 1)',
|
|
100
|
+
inOut: 'cubic-bezier(0.4, 0, 0.2, 1)',
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Helper to convert centralized tokens to the DesignTokens interface format
|
|
106
|
+
*/
|
|
107
|
+
export function getDesignTokens(): Partial<DesignTokens> {
|
|
108
|
+
// This would map the nested structure to the flat structure expected by the system
|
|
109
|
+
return {
|
|
110
|
+
primary: COLORS.primary,
|
|
111
|
+
secondary: COLORS.secondary,
|
|
112
|
+
success: COLORS.success,
|
|
113
|
+
info: COLORS.info,
|
|
114
|
+
warning: COLORS.warning,
|
|
115
|
+
error: COLORS.error,
|
|
116
|
+
'body-font-family': TYPOGRAPHY.fontFamily.base,
|
|
117
|
+
'body-font-size': TYPOGRAPHY.fontSize.base,
|
|
118
|
+
// ... more mappings
|
|
119
|
+
};
|
|
120
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vitest-environment happy-dom
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
5
|
+
import {
|
|
6
|
+
isBrowser,
|
|
7
|
+
isServer,
|
|
8
|
+
getThemeLinkId,
|
|
9
|
+
removeThemeCSS,
|
|
10
|
+
} from '../domUtils';
|
|
11
|
+
import { THEME_LINK_ID_PREFIX } from '../../constants/constants';
|
|
12
|
+
|
|
13
|
+
describe('DOM Utils', () => {
|
|
14
|
+
describe('isBrowser', () => {
|
|
15
|
+
it('should return true in a browser environment', () => {
|
|
16
|
+
// With happy-dom environment, window and document are defined
|
|
17
|
+
expect(isBrowser()).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('isServer', () => {
|
|
22
|
+
it('should return false in a browser environment', () => {
|
|
23
|
+
expect(isServer()).toBe(false);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('getThemeLinkId', () => {
|
|
28
|
+
it('should correctly format theme link ID', () => {
|
|
29
|
+
const themeName = 'dark-theme';
|
|
30
|
+
expect(getThemeLinkId(themeName)).toBe(`${THEME_LINK_ID_PREFIX}${themeName}`);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe('removeThemeCSS', () => {
|
|
35
|
+
beforeEach(() => {
|
|
36
|
+
// Clear document body before each test
|
|
37
|
+
document.body.innerHTML = '';
|
|
38
|
+
document.head.innerHTML = '';
|
|
39
|
+
vi.restoreAllMocks();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
vi.restoreAllMocks();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should do nothing if on server', () => {
|
|
47
|
+
// Mock window to be undefined to simulate server
|
|
48
|
+
const originalWindow = global.window;
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
delete (global as any).window;
|
|
51
|
+
|
|
52
|
+
const getElementByIdSpy = vi.spyOn(document, 'getElementById');
|
|
53
|
+
removeThemeCSS('test-theme');
|
|
54
|
+
|
|
55
|
+
expect(getElementByIdSpy).not.toHaveBeenCalled();
|
|
56
|
+
|
|
57
|
+
// Restore window
|
|
58
|
+
global.window = originalWindow;
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should remove element found by direct ID', () => {
|
|
62
|
+
const linkId = 'my-custom-theme-link';
|
|
63
|
+
const link = document.createElement('link');
|
|
64
|
+
link.id = linkId;
|
|
65
|
+
document.head.appendChild(link);
|
|
66
|
+
|
|
67
|
+
const removeSpy = vi.spyOn(link, 'remove');
|
|
68
|
+
|
|
69
|
+
removeThemeCSS(linkId);
|
|
70
|
+
|
|
71
|
+
expect(removeSpy).toHaveBeenCalled();
|
|
72
|
+
expect(document.getElementById(linkId)).toBeNull();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should remove element found by generated theme link ID', () => {
|
|
76
|
+
const themeName = 'dark';
|
|
77
|
+
const expectedLinkId = getThemeLinkId(themeName);
|
|
78
|
+
|
|
79
|
+
const link = document.createElement('link');
|
|
80
|
+
link.id = expectedLinkId;
|
|
81
|
+
document.head.appendChild(link);
|
|
82
|
+
|
|
83
|
+
const removeSpy = vi.spyOn(link, 'remove');
|
|
84
|
+
|
|
85
|
+
// Pass the theme name, not the link ID directly
|
|
86
|
+
removeThemeCSS(themeName);
|
|
87
|
+
|
|
88
|
+
expect(removeSpy).toHaveBeenCalled();
|
|
89
|
+
expect(document.getElementById(expectedLinkId)).toBeNull();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should do nothing if element is not found', () => {
|
|
93
|
+
// No element added to DOM
|
|
94
|
+
const getElementByIdSpy = vi.spyOn(document, 'getElementById');
|
|
95
|
+
|
|
96
|
+
removeThemeCSS('non-existent-theme');
|
|
97
|
+
|
|
98
|
+
expect(getElementByIdSpy).toHaveBeenCalledTimes(2); // Once for direct ID, once for generated ID
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
});
|
|
@@ -245,6 +245,17 @@ export interface AtomixGlassProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
245
245
|
| 'waves'
|
|
246
246
|
| 'noise';
|
|
247
247
|
|
|
248
|
+
/**
|
|
249
|
+
* Phase 1: Animation System props
|
|
250
|
+
*/
|
|
251
|
+
withTimeAnimation?: boolean;
|
|
252
|
+
animationSpeed?: number;
|
|
253
|
+
withMultiLayerDistortion?: boolean;
|
|
254
|
+
distortionOctaves?: number;
|
|
255
|
+
distortionLacunarity?: number;
|
|
256
|
+
distortionGain?: number;
|
|
257
|
+
distortionQuality?: 'low' | 'medium' | 'high' | 'ultra';
|
|
258
|
+
|
|
248
259
|
/**
|
|
249
260
|
* Performance and accessibility options
|
|
250
261
|
*/
|
|
@@ -283,6 +294,32 @@ export interface AtomixGlassProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
283
294
|
* </AtomixGlass>
|
|
284
295
|
*/
|
|
285
296
|
debugOverLight?: boolean;
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Phase 3: Responsive & Performance Optimization props
|
|
300
|
+
*/
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Device preset for responsive optimization
|
|
304
|
+
*
|
|
305
|
+
* Pre-configured presets that adjust glass parameters based on device capabilities
|
|
306
|
+
* - 'performance': Optimized for low-end devices (reduced octaves, lower quality)
|
|
307
|
+
* - 'balanced': Balanced quality and performance (default)
|
|
308
|
+
* - 'quality': Maximum visual quality (high octaves, ultra quality)
|
|
309
|
+
*
|
|
310
|
+
* @default 'balanced'
|
|
311
|
+
*/
|
|
312
|
+
devicePreset?: 'performance' | 'balanced' | 'quality';
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Disable responsive breakpoint system
|
|
316
|
+
*
|
|
317
|
+
* When true, disables automatic parameter adjustment based on viewport size
|
|
318
|
+
* Use this when you want full manual control over all parameters
|
|
319
|
+
*
|
|
320
|
+
* @default false
|
|
321
|
+
*/
|
|
322
|
+
disableResponsiveBreakpoints?: boolean;
|
|
286
323
|
}
|
|
287
324
|
|
|
288
325
|
/**
|
|
@@ -812,17 +849,6 @@ export interface AccordionProps extends BaseComponentProps {
|
|
|
812
849
|
*/
|
|
813
850
|
onOpenChange?: (open: boolean) => void;
|
|
814
851
|
|
|
815
|
-
/**
|
|
816
|
-
* @deprecated Use onOpenChange instead
|
|
817
|
-
* Optional open handler
|
|
818
|
-
*/
|
|
819
|
-
onOpen?: () => void;
|
|
820
|
-
|
|
821
|
-
/**
|
|
822
|
-
* @deprecated Use onOpenChange instead
|
|
823
|
-
* Optional close handler
|
|
824
|
-
*/
|
|
825
|
-
onClose?: () => void;
|
|
826
852
|
/**
|
|
827
853
|
* Glass morphism effect for the accordion
|
|
828
854
|
* Can be a boolean to enable with default settings, or an object with AtomixGlassProps to customize the effect
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Glass effect parameters for responsive breakpoints
|
|
3
|
+
*/
|
|
4
|
+
export interface GlassParams {
|
|
5
|
+
distortionOctaves?: number;
|
|
6
|
+
displacementScale?: number;
|
|
7
|
+
blurAmount?: number;
|
|
8
|
+
saturation?: number;
|
|
9
|
+
aberrationIntensity?: number;
|
|
10
|
+
animationSpeed?: number;
|
|
11
|
+
chromaticIntensity?: number;
|
|
12
|
+
distortionLacunarity?: number;
|
|
13
|
+
distortionGain?: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Responsive breakpoint configuration
|
|
18
|
+
*/
|
|
19
|
+
export interface ResponsiveBreakpoint {
|
|
20
|
+
maxWidth?: number;
|
|
21
|
+
minWidth?: number;
|
|
22
|
+
params: GlassParams;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Design system theme tokens for glass component
|
|
27
|
+
*/
|
|
28
|
+
export interface GlassThemeTokens {
|
|
29
|
+
glassOpacity?: string;
|
|
30
|
+
glassBlur?: string;
|
|
31
|
+
glassBorderRadius?: string;
|
|
32
|
+
glassBorderColor?: string;
|
|
33
|
+
glassShadow?: string;
|
|
34
|
+
glassSaturation?: string;
|
|
35
|
+
}
|
package/src/lib/types/index.ts
CHANGED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// TestTypeCheck Component Settings
|
|
2
|
+
// Generated by Atomix CLI
|
|
3
|
+
// =============================================================================
|
|
4
|
+
|
|
5
|
+
@use 'sass:color';
|
|
6
|
+
@use '../../lib/functions' as *;
|
|
7
|
+
@use '../../lib/mixins' as *;
|
|
8
|
+
|
|
9
|
+
// Component-specific CSS Custom Properties
|
|
10
|
+
// These override or extend global design tokens
|
|
11
|
+
|
|
12
|
+
:root {
|
|
13
|
+
// Brand Colors
|
|
14
|
+
--testtypecheck-primary: var(--atomix-color-primary);
|
|
15
|
+
--testtypecheck-primary-hover: color.adjust(var(--atomix-color-primary), $lightness: -10%);
|
|
16
|
+
--testtypecheck-primary-active: color.adjust(var(--atomix-color-primary), $lightness: -20%);
|
|
17
|
+
|
|
18
|
+
// Spacing
|
|
19
|
+
--testtypecheck-padding-x: var(--atomix-spacing-4);
|
|
20
|
+
--testtypecheck-padding-y: calc(var(--atomix-spacing-4) * 0.5);
|
|
21
|
+
--testtypecheck-gap: var(--atomix-spacing-4);
|
|
22
|
+
|
|
23
|
+
// Border Radius
|
|
24
|
+
--testtypecheck-radius: var(--atomix-radius-md);
|
|
25
|
+
|
|
26
|
+
// Typography
|
|
27
|
+
--testtypecheck-font-size: var(--atomix-font-size-base);
|
|
28
|
+
--testtypecheck-font-weight: var(--atomix-font-weight-medium);
|
|
29
|
+
--testtypecheck-line-height: var(--atomix-line-height-tight);
|
|
30
|
+
|
|
31
|
+
// States
|
|
32
|
+
--testtypecheck-disabled-opacity: 0.5;
|
|
33
|
+
--testtypecheck-focus-ring: 0 0 0 2px var(--atomix-color-primary-200);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Dark mode overrides
|
|
37
|
+
.dark {
|
|
38
|
+
:root {
|
|
39
|
+
--testtypecheck-focus-ring: 0 0 0 2px var(--atomix-color-primary-800);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Component configuration map
|
|
44
|
+
$testtypecheck-config: (
|
|
45
|
+
'primary': var(--testtypecheck-primary),
|
|
46
|
+
'padding-x': var(--testtypecheck-padding-x),
|
|
47
|
+
'padding-y': var(--testtypecheck-padding-y),
|
|
48
|
+
'gap': var(--testtypecheck-gap),
|
|
49
|
+
'radius': var(--testtypecheck-radius),
|
|
50
|
+
'font-size': var(--testtypecheck-font-size),
|
|
51
|
+
'font-weight': var(--testtypecheck-font-weight),
|
|
52
|
+
'line-height': var(--testtypecheck-line-height),
|
|
53
|
+
) !default;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// TypedButton Component Settings
|
|
2
|
+
// Generated by Atomix CLI
|
|
3
|
+
// =============================================================================
|
|
4
|
+
|
|
5
|
+
@use 'sass:color';
|
|
6
|
+
@use '../../lib/functions' as *;
|
|
7
|
+
@use '../../lib/mixins' as *;
|
|
8
|
+
|
|
9
|
+
// Component-specific CSS Custom Properties
|
|
10
|
+
// These override or extend global design tokens
|
|
11
|
+
|
|
12
|
+
:root {
|
|
13
|
+
// Brand Colors
|
|
14
|
+
--typedbutton-primary: var(--atomix-color-primary);
|
|
15
|
+
--typedbutton-primary-hover: color.adjust(var(--atomix-color-primary), $lightness: -10%);
|
|
16
|
+
--typedbutton-primary-active: color.adjust(var(--atomix-color-primary), $lightness: -20%);
|
|
17
|
+
|
|
18
|
+
// Spacing
|
|
19
|
+
--typedbutton-padding-x: var(--atomix-spacing-4);
|
|
20
|
+
--typedbutton-padding-y: calc(var(--atomix-spacing-4) * 0.5);
|
|
21
|
+
--typedbutton-gap: var(--atomix-spacing-4);
|
|
22
|
+
|
|
23
|
+
// Border Radius
|
|
24
|
+
--typedbutton-radius: var(--atomix-radius-md);
|
|
25
|
+
|
|
26
|
+
// Typography
|
|
27
|
+
--typedbutton-font-size: var(--atomix-font-size-base);
|
|
28
|
+
--typedbutton-font-weight: var(--atomix-font-weight-medium);
|
|
29
|
+
--typedbutton-line-height: var(--atomix-line-height-tight);
|
|
30
|
+
|
|
31
|
+
// States
|
|
32
|
+
--typedbutton-disabled-opacity: 0.5;
|
|
33
|
+
--typedbutton-focus-ring: 0 0 0 2px var(--atomix-color-primary-200);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Dark mode overrides
|
|
37
|
+
.dark {
|
|
38
|
+
:root {
|
|
39
|
+
--typedbutton-focus-ring: 0 0 0 2px var(--atomix-color-primary-800);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Component configuration map
|
|
44
|
+
$typedbutton-config: (
|
|
45
|
+
'primary': var(--typedbutton-primary),
|
|
46
|
+
'padding-x': var(--typedbutton-padding-x),
|
|
47
|
+
'padding-y': var(--typedbutton-padding-y),
|
|
48
|
+
'gap': var(--typedbutton-gap),
|
|
49
|
+
'radius': var(--typedbutton-radius),
|
|
50
|
+
'font-size': var(--typedbutton-font-size),
|
|
51
|
+
'font-weight': var(--typedbutton-font-weight),
|
|
52
|
+
'line-height': var(--typedbutton-line-height),
|
|
53
|
+
) !default;
|
|
@@ -7,13 +7,8 @@
|
|
|
7
7
|
position: relative;
|
|
8
8
|
|
|
9
9
|
// CSS custom property defaults
|
|
10
|
-
--atomix-glass-
|
|
11
|
-
--atomix-glass-transform: none;
|
|
12
|
-
--atomix-glass-transition: transform var(--atomix-transition-duration, 0.45s)
|
|
13
|
-
cubic-bezier(0.22, 1, 0.36, 1);
|
|
10
|
+
--atomix-glass-transition: all 0.15s ease;
|
|
14
11
|
--atomix-glass-position: absolute;
|
|
15
|
-
--atomix-glass-container-width: 100%;
|
|
16
|
-
--atomix-glass-container-height: 100%;
|
|
17
12
|
--atomix-glass-border-width: var(--atomix-spacing-0-5, 0.09375rem);
|
|
18
13
|
|
|
19
14
|
// =========================================================================
|
|
@@ -42,13 +37,15 @@
|
|
|
42
37
|
--_glass-z-border-1: calc(var(--atomix-glass-base-z-index) + 5);
|
|
43
38
|
--_glass-z-border-2: calc(var(--atomix-glass-base-z-index) + 6);
|
|
44
39
|
--_glass-z-content: calc(var(--atomix-glass-base-z-index) + 7);
|
|
40
|
+
position: relative;
|
|
45
41
|
|
|
46
42
|
// Base layer styles for all effect layers (hover, border, overlay)
|
|
47
43
|
&__hover-1,
|
|
48
44
|
&__hover-2,
|
|
49
45
|
&__hover-3 {
|
|
50
|
-
position:
|
|
51
|
-
|
|
46
|
+
position: var(--atomix-glass-position);
|
|
47
|
+
top: var(--atomix-glass-top);
|
|
48
|
+
left: var(--atomix-glass-left);
|
|
52
49
|
pointer-events: none;
|
|
53
50
|
border-radius: var(--atomix-glass-radius);
|
|
54
51
|
transform: var(--atomix-glass-transform);
|
|
@@ -58,8 +55,6 @@
|
|
|
58
55
|
|
|
59
56
|
&__base,
|
|
60
57
|
&__overlay {
|
|
61
|
-
position: absolute;
|
|
62
|
-
inset: 0;
|
|
63
58
|
pointer-events: none;
|
|
64
59
|
border-radius: var(--atomix-glass-radius);
|
|
65
60
|
transform: var(--atomix-glass-transform);
|
|
@@ -167,9 +162,9 @@
|
|
|
167
162
|
background: var(--atomix-glass-border-gradient-1, none);
|
|
168
163
|
box-shadow: var(
|
|
169
164
|
--atomix-glass-border-shadow,
|
|
170
|
-
0 0 0 0.
|
|
171
|
-
0
|
|
172
|
-
0
|
|
165
|
+
0 0 0 0.5px rgba(255, 255, 255, 0.5) inset,
|
|
166
|
+
0 1px 3px rgba(255, 255, 255, 0.25) inset,
|
|
167
|
+
0 1px 4px rgba(0, 0, 0, 0.35)
|
|
173
168
|
);
|
|
174
169
|
}
|
|
175
170
|
|
|
@@ -179,25 +174,26 @@
|
|
|
179
174
|
background: var(--atomix-glass-border-gradient-2, none);
|
|
180
175
|
box-shadow: var(
|
|
181
176
|
--atomix-glass-border-shadow,
|
|
182
|
-
0 0 0 0.
|
|
183
|
-
0
|
|
184
|
-
0
|
|
177
|
+
0 0 0 0.5px rgba(255, 255, 255, 0.5) inset,
|
|
178
|
+
0 1px 3px rgba(255, 255, 255, 0.25) inset,
|
|
179
|
+
0 1px 4px rgba(0, 0, 0, 0.35)
|
|
185
180
|
);
|
|
186
181
|
}
|
|
187
182
|
|
|
188
183
|
// Container styles
|
|
189
184
|
&__container {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
185
|
+
position: var(--atomix-glass-position);
|
|
186
|
+
top: var(--atomix-glass-top);
|
|
187
|
+
left: var(--atomix-glass-left);
|
|
193
188
|
border-radius: var(--atomix-glass-radius);
|
|
194
189
|
transition: var(--atomix-glass-transition);
|
|
190
|
+
transform: var(--atomix-glass-transform);
|
|
195
191
|
z-index: var(--_glass-z-container);
|
|
196
192
|
}
|
|
197
193
|
|
|
198
194
|
&__inner {
|
|
199
|
-
width:
|
|
200
|
-
height:
|
|
195
|
+
width: 100%;
|
|
196
|
+
height: 100%;
|
|
201
197
|
position: relative;
|
|
202
198
|
border-radius: var(--atomix-glass-radius);
|
|
203
199
|
padding: var(--atomix-glass-container-padding);
|