@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.
Files changed (176) hide show
  1. package/atomix.config.ts +58 -1
  2. package/dist/atomix.css +172 -157
  3. package/dist/atomix.css.map +1 -1
  4. package/dist/atomix.min.css +4 -4
  5. package/dist/atomix.min.css.map +1 -1
  6. package/dist/charts.d.ts +33 -0
  7. package/dist/charts.js +1274 -164
  8. package/dist/charts.js.map +1 -1
  9. package/dist/core.d.ts +33 -10
  10. package/dist/core.js +1099 -83
  11. package/dist/core.js.map +1 -1
  12. package/dist/forms.d.ts +33 -0
  13. package/dist/forms.js +2106 -1050
  14. package/dist/forms.js.map +1 -1
  15. package/dist/heavy.d.ts +42 -1
  16. package/dist/heavy.js +1663 -638
  17. package/dist/heavy.js.map +1 -1
  18. package/dist/index.d.ts +442 -270
  19. package/dist/index.esm.js +1947 -680
  20. package/dist/index.esm.js.map +1 -1
  21. package/dist/index.js +1982 -712
  22. package/dist/index.js.map +1 -1
  23. package/dist/index.min.js +1 -1
  24. package/dist/index.min.js.map +1 -1
  25. package/package.json +6 -3
  26. package/scripts/atomix-cli.js +136 -1827
  27. package/scripts/cli/__tests__/basic.test.js +3 -2
  28. package/scripts/cli/__tests__/clean.test.js +278 -0
  29. package/scripts/cli/__tests__/component-validator.test.js +433 -0
  30. package/scripts/cli/__tests__/generator.test.js +613 -0
  31. package/scripts/cli/__tests__/glass-motion.test.js +256 -0
  32. package/scripts/cli/__tests__/integration.test.js +719 -108
  33. package/scripts/cli/__tests__/migrate.test.js +74 -0
  34. package/scripts/cli/__tests__/security.test.js +206 -0
  35. package/scripts/cli/__tests__/test-setup.js +3 -1
  36. package/scripts/cli/__tests__/theme-bridge.test.js +507 -0
  37. package/scripts/cli/__tests__/token-provider.test.js +361 -0
  38. package/scripts/cli/__tests__/utils.test.js +5 -5
  39. package/scripts/cli/commands/benchmark.js +105 -0
  40. package/scripts/cli/commands/build-theme.js +115 -0
  41. package/scripts/cli/commands/clean.js +109 -0
  42. package/scripts/cli/commands/doctor.js +88 -0
  43. package/scripts/cli/commands/generate.js +218 -0
  44. package/scripts/cli/commands/init.js +73 -0
  45. package/scripts/cli/commands/migrate.js +106 -0
  46. package/scripts/cli/commands/sync-tokens.js +206 -0
  47. package/scripts/cli/commands/theme-bridge.js +248 -0
  48. package/scripts/cli/commands/tokens.js +157 -0
  49. package/scripts/cli/commands/validate.js +194 -0
  50. package/scripts/cli/internal/ai-engine.js +156 -0
  51. package/scripts/cli/internal/compiler.js +114 -0
  52. package/scripts/cli/internal/component-validator.js +443 -0
  53. package/scripts/cli/internal/config-loader.js +162 -0
  54. package/scripts/cli/internal/filesystem.js +158 -0
  55. package/scripts/cli/internal/generator.js +430 -0
  56. package/scripts/cli/internal/glass-generator.js +398 -0
  57. package/scripts/cli/internal/hook-generator.js +369 -0
  58. package/scripts/cli/internal/hooks.js +61 -0
  59. package/scripts/cli/internal/itcss-generator.js +565 -0
  60. package/scripts/cli/internal/motion-generator.js +679 -0
  61. package/scripts/cli/internal/template-engine.js +301 -0
  62. package/scripts/cli/internal/theme-bridge.js +664 -0
  63. package/scripts/cli/internal/tokens/engine.js +122 -0
  64. package/scripts/cli/internal/tokens/provider.js +34 -0
  65. package/scripts/cli/internal/tokens/providers/figma.js +50 -0
  66. package/scripts/cli/internal/tokens/providers/style-dictionary.js +48 -0
  67. package/scripts/cli/internal/tokens/providers/w3c.js +48 -0
  68. package/scripts/cli/internal/tokens/token-provider.js +443 -0
  69. package/scripts/cli/internal/tokens/token-validator.js +513 -0
  70. package/scripts/cli/internal/validator.js +276 -0
  71. package/scripts/cli/internal/wizard.js +115 -0
  72. package/scripts/cli/mappings.js +23 -0
  73. package/scripts/cli/migration-tools.js +164 -94
  74. package/scripts/cli/plugins/style-dictionary.js +46 -0
  75. package/scripts/cli/templates/README.md +525 -95
  76. package/scripts/cli/templates/common-templates.js +40 -14
  77. package/scripts/cli/templates/components/react-component.ts +282 -0
  78. package/scripts/cli/templates/config/project-config.ts +112 -0
  79. package/scripts/cli/templates/hooks/use-component.ts +477 -0
  80. package/scripts/cli/templates/index.js +19 -4
  81. package/scripts/cli/templates/index.ts +171 -0
  82. package/scripts/cli/templates/next-templates.js +72 -0
  83. package/scripts/cli/templates/react-templates.js +70 -126
  84. package/scripts/cli/templates/scss-templates.js +35 -35
  85. package/scripts/cli/templates/stories/storybook-story.ts +241 -0
  86. package/scripts/cli/templates/styles/scss-component.ts +255 -0
  87. package/scripts/cli/templates/tests/vitest-test.ts +229 -0
  88. package/scripts/cli/templates/token-templates.js +337 -1
  89. package/scripts/cli/templates/tokens/token-generators.ts +1088 -0
  90. package/scripts/cli/templates/types/component-types.ts +145 -0
  91. package/scripts/cli/templates/utils/testing-utils.ts +144 -0
  92. package/scripts/cli/templates/vanilla-templates.js +39 -0
  93. package/scripts/cli/token-manager.js +8 -2
  94. package/scripts/cli/utils/cache-manager.js +240 -0
  95. package/scripts/cli/utils/detector.js +46 -0
  96. package/scripts/cli/utils/diagnostics.js +289 -0
  97. package/scripts/cli/utils/error.js +89 -0
  98. package/scripts/cli/utils/helpers.js +67 -0
  99. package/scripts/cli/utils/logger.js +75 -0
  100. package/scripts/cli/utils/security.js +302 -0
  101. package/scripts/cli/utils/telemetry.js +115 -0
  102. package/scripts/cli/utils/validation.js +37 -0
  103. package/scripts/cli/utils.js +28 -341
  104. package/src/components/Accordion/Accordion.stories.tsx +0 -18
  105. package/src/components/Accordion/Accordion.test.tsx +0 -17
  106. package/src/components/Accordion/Accordion.tsx +0 -4
  107. package/src/components/AtomixGlass/AtomixGlass.test.tsx +37 -3
  108. package/src/components/AtomixGlass/AtomixGlass.tsx +143 -31
  109. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +129 -31
  110. package/src/components/AtomixGlass/PerformanceDashboard.tsx +219 -0
  111. package/src/components/AtomixGlass/README.md +25 -10
  112. package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +216 -0
  113. package/src/components/AtomixGlass/animation-system.ts +578 -0
  114. package/src/components/AtomixGlass/shader-utils.ts +4 -1
  115. package/src/components/AtomixGlass/stories/Overview.stories.tsx +157 -6
  116. package/src/components/AtomixGlass/stories/Phase1-Animation.stories.tsx +653 -0
  117. package/src/components/AtomixGlass/stories/Phase1-Test.stories.tsx +95 -0
  118. package/src/components/AtomixGlass/stories/Playground.stories.tsx +51 -51
  119. package/src/components/AtomixGlass/stories/shared-components.tsx +6 -0
  120. package/src/components/Avatar/Avatar.tsx +1 -1
  121. package/src/components/Button/Button.stories.disabled-link.tsx +10 -0
  122. package/src/components/Button/Button.stories.tsx +10 -0
  123. package/src/components/Button/Button.test.tsx +16 -11
  124. package/src/components/Button/Button.tsx +4 -4
  125. package/src/components/Card/Card.tsx +1 -1
  126. package/src/components/Dropdown/Dropdown.tsx +12 -12
  127. package/src/components/Form/Select.tsx +62 -3
  128. package/src/components/Modal/Modal.tsx +14 -3
  129. package/src/components/Navigation/Navbar/Navbar.tsx +44 -0
  130. package/src/components/Slider/Slider.stories.tsx +3 -3
  131. package/src/components/Slider/Slider.tsx +38 -0
  132. package/src/components/Steps/Steps.tsx +3 -3
  133. package/src/components/Tabs/Tabs.tsx +77 -8
  134. package/src/components/Testimonial/Testimonial.tsx +1 -1
  135. package/src/components/TypedButton/TypedButton.stories.tsx +59 -0
  136. package/src/components/TypedButton/TypedButton.tsx +39 -0
  137. package/src/components/TypedButton/index.ts +2 -0
  138. package/src/components/VideoPlayer/VideoPlayer.tsx +11 -4
  139. package/src/lib/composables/index.ts +4 -7
  140. package/src/lib/composables/types.ts +45 -0
  141. package/src/lib/composables/useAccordion.ts +0 -7
  142. package/src/lib/composables/useAtomixGlass.ts +148 -6
  143. package/src/lib/composables/useAtomixGlassStyles.ts +9 -7
  144. package/src/lib/composables/useChartExport.ts +3 -13
  145. package/src/lib/composables/useDropdown.ts +66 -0
  146. package/src/lib/composables/useFocusTrap.ts +80 -0
  147. package/src/lib/composables/usePerformanceMonitor.ts +448 -0
  148. package/src/lib/composables/useResponsiveGlass.presets.ts +192 -0
  149. package/src/lib/composables/useResponsiveGlass.ts +441 -0
  150. package/src/lib/composables/useTooltip.ts +16 -0
  151. package/src/lib/composables/useTypedButton.ts +66 -0
  152. package/src/lib/config/index.ts +62 -5
  153. package/src/lib/constants/components.ts +62 -7
  154. package/src/lib/theme/devtools/__tests__/useHistory.test.tsx +150 -0
  155. package/src/lib/theme/tokens/centralized-tokens.ts +120 -0
  156. package/src/lib/theme/utils/__tests__/domUtils.test.ts +101 -0
  157. package/src/lib/types/components.ts +37 -11
  158. package/src/lib/types/glass.ts +35 -0
  159. package/src/lib/types/index.ts +1 -0
  160. package/src/lib/utils/displacement-generator.ts +1 -1
  161. package/src/styles/01-settings/_settings.testtypecheck.scss +53 -0
  162. package/src/styles/01-settings/_settings.typedbutton.scss +53 -0
  163. package/src/styles/06-components/_components.atomix-glass.scss +17 -21
  164. package/src/styles/06-components/_components.edge-panel.scss +1 -5
  165. package/src/styles/06-components/_components.modal.scss +1 -4
  166. package/src/styles/06-components/_components.navbar.scss +1 -1
  167. package/src/styles/06-components/_components.testbutton.scss +212 -0
  168. package/src/styles/06-components/_components.testtypecheck.scss +212 -0
  169. package/src/styles/06-components/_components.tooltip.scss +9 -5
  170. package/src/styles/06-components/_components.typedbutton.scss +212 -0
  171. package/src/styles/99-utilities/_index.scss +1 -0
  172. package/src/styles/99-utilities/_utilities.text.scss +1 -1
  173. package/src/styles/99-utilities/_utilities.touch-target.scss +36 -0
  174. package/scripts/cli/component-generator.js +0 -564
  175. package/scripts/cli/interactive-init.js +0 -357
  176. 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
+ }
@@ -1,2 +1,3 @@
1
1
  // Export all component types
2
2
  export * from './components.js';
3
+ export * from './glass.js';
@@ -10,7 +10,7 @@ export interface ShaderOptions {
10
10
  }
11
11
 
12
12
  function smoothStep(a: number, b: number, t: number): number {
13
- t = Math.max(0, Math.min(1, (t - a) / (b - a)));
13
+ t = Math.max(0, Math.min(1, (t - a) / (b - a));
14
14
  return t * t * (3 - 2 * t);
15
15
  }
16
16
 
@@ -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-radius: var(--atomix-radius-md, 16px);
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: absolute;
51
- inset: 0;
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.03125rem rgba(255, 255, 255, 0.5) inset,
171
- 0 0.25rem 0.75rem rgba(255, 255, 255, 0.25) inset,
172
- 0 0.25rem 1rem rgba(0, 0, 0, 0.35)
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.03125rem rgba(255, 255, 255, 0.5) inset,
183
- 0 0.25rem 0.75rem rgba(255, 255, 255, 0.25) inset,
184
- 0 0.25rem 1rem rgba(0, 0, 0, 0.35)
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
- width: var(--atomix-glass-container-width);
191
- height: var(--atomix-glass-container-height);
192
- position: relative;
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: var(--atomix-glass-container-width);
200
- height: var(--atomix-glass-container-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);