@shohojdhara/atomix 0.5.0 → 0.5.1

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 (76) hide show
  1. package/dist/atomix.css +95 -69
  2. package/dist/atomix.css.map +1 -1
  3. package/dist/atomix.min.css +1 -1
  4. package/dist/atomix.min.css.map +1 -1
  5. package/dist/charts.d.ts +1 -0
  6. package/dist/charts.js +231 -332
  7. package/dist/charts.js.map +1 -1
  8. package/dist/core.d.ts +1 -0
  9. package/dist/core.js +232 -333
  10. package/dist/core.js.map +1 -1
  11. package/dist/forms.d.ts +1 -0
  12. package/dist/forms.js +231 -332
  13. package/dist/forms.js.map +1 -1
  14. package/dist/heavy.d.ts +11 -2
  15. package/dist/heavy.js +233 -334
  16. package/dist/heavy.js.map +1 -1
  17. package/dist/index.d.ts +13 -2
  18. package/dist/index.esm.js +228 -327
  19. package/dist/index.esm.js.map +1 -1
  20. package/dist/index.js +227 -326
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.min.js +1 -1
  23. package/dist/index.min.js.map +1 -1
  24. package/package.json +11 -1
  25. package/src/components/AtomixGlass/AtomixGlass.tsx +188 -128
  26. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +62 -90
  27. package/src/components/AtomixGlass/PerformanceDashboard.tsx +153 -201
  28. package/src/components/AtomixGlass/glass-utils.ts +50 -0
  29. package/src/components/AtomixGlass/stories/AnimationFeatures.stories.tsx +52 -46
  30. package/src/components/AtomixGlass/stories/Examples.stories.tsx +573 -236
  31. package/src/components/AtomixGlass/stories/Playground.stories.tsx +88 -41
  32. package/src/components/AtomixGlass/stories/argTypes.ts +19 -19
  33. package/src/components/AtomixGlass/stories/shared-components.tsx +7 -12
  34. package/src/components/AtomixGlass/stories/types.ts +3 -3
  35. package/src/lib/composables/useAtomixGlass.ts +108 -71
  36. package/src/lib/composables/useAtomixGlassStyles.ts +0 -2
  37. package/src/lib/constants/components.ts +1 -0
  38. package/src/lib/types/components.ts +1 -0
  39. package/src/lib/utils/displacement-generator.ts +1 -1
  40. package/src/styles/06-components/_components.atomix-glass.scss +158 -97
  41. package/scripts/cli/__tests__/README.md +0 -81
  42. package/scripts/cli/__tests__/basic.test.js +0 -116
  43. package/scripts/cli/__tests__/clean.test.js +0 -278
  44. package/scripts/cli/__tests__/component-generator.test.js +0 -332
  45. package/scripts/cli/__tests__/component-validator.test.js +0 -433
  46. package/scripts/cli/__tests__/generator.test.js +0 -613
  47. package/scripts/cli/__tests__/glass-motion.test.js +0 -256
  48. package/scripts/cli/__tests__/integration.test.js +0 -938
  49. package/scripts/cli/__tests__/migrate.test.js +0 -74
  50. package/scripts/cli/__tests__/security.test.js +0 -206
  51. package/scripts/cli/__tests__/test-setup.js +0 -135
  52. package/scripts/cli/__tests__/theme-bridge.test.js +0 -507
  53. package/scripts/cli/__tests__/token-manager.test.js +0 -251
  54. package/scripts/cli/__tests__/token-provider.test.js +0 -361
  55. package/scripts/cli/__tests__/utils.test.js +0 -165
  56. package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +0 -216
  57. package/src/components/AtomixGlass/stories/AnimationTests.stories.tsx +0 -95
  58. package/src/components/AtomixGlass/stories/CardExamples.stories.tsx +0 -212
  59. package/src/components/AtomixGlass/stories/Customization.stories.tsx +0 -131
  60. package/src/components/AtomixGlass/stories/DashboardExamples.stories.tsx +0 -348
  61. package/src/components/AtomixGlass/stories/EcommerceExamples.stories.tsx +0 -410
  62. package/src/components/AtomixGlass/stories/FormExamples.stories.tsx +0 -436
  63. package/src/components/AtomixGlass/stories/HeroExamples.stories.tsx +0 -264
  64. package/src/components/AtomixGlass/stories/InteractivePlayground.stories.tsx +0 -247
  65. package/src/components/AtomixGlass/stories/MobileUIExamples.stories.tsx +0 -418
  66. package/src/components/AtomixGlass/stories/ModalExamples.stories.tsx +0 -402
  67. package/src/components/AtomixGlass/stories/Modes.stories.tsx +0 -1082
  68. package/src/components/AtomixGlass/stories/Overview.stories.tsx +0 -497
  69. package/src/components/AtomixGlass/stories/Performance.stories.tsx +0 -103
  70. package/src/components/AtomixGlass/stories/PresetGallery.stories.tsx +0 -335
  71. package/src/components/AtomixGlass/stories/Shaders.stories.tsx +0 -395
  72. package/src/components/AtomixGlass/stories/WidgetExamples.stories.tsx +0 -441
  73. package/src/components/TypedButton/TypedButton.stories.tsx +0 -59
  74. package/src/components/TypedButton/TypedButton.tsx +0 -39
  75. package/src/components/TypedButton/index.ts +0 -2
  76. package/src/lib/composables/useTypedButton.ts +0 -66
@@ -1,74 +0,0 @@
1
- /**
2
- * Migrate Command Unit Tests
3
- * Tests ensureSourceIsDirectory behavior and migrate error paths
4
- */
5
-
6
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
7
- import { mkdtemp, rm, writeFile } from 'fs/promises';
8
- import { join } from 'path';
9
- import { tmpdir } from 'os';
10
- import { migrateAction } from '../commands/migrate.js';
11
- import { AtomixCLIError, ErrorCategory } from '../utils/error.js';
12
-
13
- describe('Migrate Command', () => {
14
- let tempDir;
15
- let originalCwd;
16
-
17
- beforeEach(async () => {
18
- tempDir = await mkdtemp(join(tmpdir(), 'atomix-migrate-test-'));
19
- originalCwd = process.cwd();
20
- process.chdir(tempDir);
21
- });
22
-
23
- afterEach(async () => {
24
- process.chdir(originalCwd);
25
- await rm(tempDir, { recursive: true, force: true });
26
- vi.restoreAllMocks();
27
- });
28
-
29
- describe('ensureSourceIsDirectory (via migrateAction)', () => {
30
- it('should throw INVALID_PATH when source does not exist', async () => {
31
- await expect(
32
- migrateAction('tailwind', './nonexistent-dir-xyz-123')
33
- ).rejects.toThrow(AtomixCLIError);
34
-
35
- try {
36
- await migrateAction('tailwind', './nonexistent-dir-xyz-123');
37
- } catch (err) {
38
- expect(err.code).toBe(ErrorCategory.INVALID_PATH);
39
- expect(err.message).toContain('Source not found');
40
- }
41
- });
42
-
43
- it('should throw INVALID_PATH when source is a file not a directory', async () => {
44
- const filePath = join(tempDir, 'package.json');
45
- await writeFile(filePath, '{}');
46
- const relativeFile = 'package.json';
47
-
48
- await expect(
49
- migrateAction('tailwind', relativeFile)
50
- ).rejects.toThrow(AtomixCLIError);
51
-
52
- try {
53
- await migrateAction('tailwind', relativeFile);
54
- } catch (err) {
55
- expect(err.code).toBe(ErrorCategory.INVALID_PATH);
56
- expect(err.message).toContain('not a directory');
57
- }
58
- });
59
-
60
- it('should throw when migration type is unsupported', async () => {
61
- let threw = false;
62
- try {
63
- await migrateAction('unknown-framework', '.');
64
- } catch (err) {
65
- threw = true;
66
- if (err instanceof AtomixCLIError) {
67
- expect(err.code).toBe(ErrorCategory.VALIDATION);
68
- expect(err.message).toContain('Unsupported migration type');
69
- }
70
- }
71
- expect(threw).toBe(true);
72
- });
73
- });
74
- });
@@ -1,206 +0,0 @@
1
- /**
2
- * Security-focused tests for Atomix CLI
3
- * Tests path traversal prevention, input sanitization, and security features
4
- */
5
-
6
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
7
- import {
8
- sanitizeInput,
9
- validateSecurePath,
10
- validateComponentNameSecure,
11
- SecurityError,
12
- RateLimiter
13
- } from '../utils/security.js';
14
- import { filesystem } from '../internal/filesystem.js';
15
-
16
- // Mock filesystem operations to avoid actual file I/O
17
- vi.mock('../internal/filesystem.js', () => ({
18
- filesystem: {
19
- writeFile: vi.fn(),
20
- exists: vi.fn()
21
- }
22
- }));
23
-
24
- describe('Security Utilities', () => {
25
- describe('sanitizeInput', () => {
26
- it('should sanitize filename inputs', () => {
27
- const malicious = '../../etc/passwd';
28
- const sanitized = sanitizeInput(malicious, 'filename');
29
- expect(sanitized).not.toContain('..');
30
- expect(sanitized).not.toContain('/');
31
- });
32
-
33
- it('should sanitize component names', () => {
34
- const malicious = 'Button<script>alert(1)</script>';
35
- const sanitized = sanitizeInput(malicious, 'componentName');
36
- expect(sanitized).toMatch(/^[A-Z][a-zA-Z0-9]*$/);
37
- expect(sanitized).not.toContain('<');
38
- expect(sanitized).not.toContain('>');
39
- });
40
-
41
- it('should sanitize AI prompts', () => {
42
- const malicious = 'Create a component that executes <script>malicious()</script>';
43
- const sanitized = sanitizeInput(malicious, 'prompt');
44
- expect(sanitized).not.toContain('<script>');
45
- expect(sanitized).not.toContain('</script>');
46
- });
47
-
48
- it('should handle empty inputs', () => {
49
- expect(() => sanitizeInput('', 'filename')).toThrow();
50
- });
51
- });
52
-
53
- describe('validateSecurePath', () => {
54
- it('should prevent path traversal attacks', () => {
55
- const result = validateSecurePath('../../etc/passwd', '/safe/dir');
56
- expect(result.isValid).toBe(false);
57
- expect(result.error).toContain('Path traversal');
58
- });
59
-
60
- it('should prevent access to system directories', () => {
61
- const result = validateSecurePath('/etc/passwd', '/safe/dir');
62
- expect(result.isValid).toBe(false);
63
- expect(result.error).toMatch(/Path traversal|system directories/);
64
- });
65
-
66
- it('should allow valid relative paths', () => {
67
- const result = validateSecurePath('./src/components', process.cwd());
68
- expect(result.isValid).toBe(true);
69
- });
70
-
71
- it('should allow valid absolute paths within project', () => {
72
- const result = validateSecurePath(process.cwd() + '/src/components', process.cwd());
73
- expect(result.isValid).toBe(true);
74
- });
75
- });
76
-
77
- describe('validateComponentNameSecure', () => {
78
- it('should reject malicious or reserved component names', () => {
79
- const maliciousNames = [
80
- 'eval',
81
- 'script',
82
- 'javascript',
83
- 'onload',
84
- 'onerror',
85
- 'Button<script>'
86
- ];
87
-
88
- maliciousNames.forEach(name => {
89
- const result = validateComponentNameSecure(name);
90
- expect(result.isValid).toBe(false);
91
- expect(result.error).toBeTruthy();
92
- });
93
- });
94
-
95
- it('should accept valid component names', () => {
96
- const validNames = [
97
- 'Button',
98
- 'CardHeader',
99
- 'ModalDialog',
100
- 'AccordionItem'
101
- ];
102
-
103
- validNames.forEach(name => {
104
- const result = validateComponentNameSecure(name);
105
- expect(result.isValid).toBe(true);
106
- });
107
- });
108
-
109
- it('should reject reserved words', () => {
110
- const reservedNames = ['Component', 'React', 'Fragment', 'Window'];
111
- reservedNames.forEach(name => {
112
- const result = validateComponentNameSecure(name);
113
- expect(result.isValid).toBe(false);
114
- });
115
- });
116
- });
117
-
118
- describe('RateLimiter', () => {
119
- let rateLimiter;
120
-
121
- beforeEach(() => {
122
- rateLimiter = new RateLimiter(2, 1000); // 2 requests per second
123
- });
124
-
125
- it('should enforce rate limits', () => {
126
- expect(rateLimiter.checkLimit('user1')).toBe(true);
127
- expect(rateLimiter.checkLimit('user1')).toBe(true);
128
- expect(rateLimiter.checkLimit('user1')).toBe(false); // Third request should be blocked
129
- });
130
-
131
- it('should track different users separately', () => {
132
- expect(rateLimiter.checkLimit('user1')).toBe(true);
133
- expect(rateLimiter.checkLimit('user2')).toBe(true);
134
- expect(rateLimiter.checkLimit('user1')).toBe(true);
135
- expect(rateLimiter.checkLimit('user2')).toBe(true);
136
- expect(rateLimiter.checkLimit('user1')).toBe(false);
137
- expect(rateLimiter.checkLimit('user2')).toBe(false);
138
- });
139
-
140
- it('should reset after time window', async () => {
141
- expect(rateLimiter.checkLimit('user1')).toBe(true);
142
- expect(rateLimiter.checkLimit('user1')).toBe(true);
143
- expect(rateLimiter.checkLimit('user1')).toBe(false);
144
-
145
- await new Promise(resolve => setTimeout(resolve, 1100)); // Wait longer than time window
146
-
147
- expect(rateLimiter.checkLimit('user1')).toBe(true); // Should work again
148
- });
149
- });
150
-
151
- describe('Filesystem Security', () => {
152
- it('should reject path traversal via validateSecurePath', () => {
153
- const result = validateSecurePath('../../etc/passwd', process.cwd());
154
- expect(result.isValid).toBe(false);
155
- expect(result.error).toBeTruthy();
156
- });
157
- });
158
- });
159
-
160
- describe('Path Traversal Prevention', () => {
161
- const testCases = [
162
- { input: '../../etc/passwd', expected: false },
163
- { input: '/etc/passwd', expected: false },
164
- { input: '..\\Windows\\System32', expected: false },
165
- { input: 'normal/path', expected: true },
166
- { input: './src/components', expected: true },
167
- { input: 'src/components/Button', expected: true },
168
- { input: '../' + process.cwd() + '/src', expected: false }, // Relative traversal
169
- { input: process.cwd() + '/../../etc', expected: false }, // Absolute traversal
170
- ];
171
-
172
- testCases.forEach(({ input, expected }) => {
173
- it(`should ${expected ? 'allow' : 'block'} path: ${input}`, () => {
174
- const result = validateSecurePath(input, process.cwd());
175
- expect(result.isValid).toBe(expected);
176
-
177
- if (!expected) {
178
- expect(result.error).toBeDefined();
179
- }
180
- });
181
- });
182
- });
183
-
184
- describe('Input Sanitization Edge Cases', () => {
185
- const edgeCases = [
186
- { input: null, type: 'filename', shouldThrow: true },
187
- { input: undefined, type: 'filename', shouldThrow: true },
188
- { input: '', type: 'filename', shouldThrow: true },
189
- { input: ' ', type: 'filename', shouldThrow: true },
190
- { input: 'normal', type: 'filename', expected: 'normal' },
191
- { input: 'file\x00name', type: 'filename', expected: 'filename' },
192
- { input: 'file\nname', type: 'filename', expected: 'filename' },
193
- { input: 'file<script>', type: 'filename', expected: 'filescript' },
194
- ];
195
-
196
- edgeCases.forEach(({ input, type, expected, shouldThrow }) => {
197
- it(`should handle ${JSON.stringify(input)} for ${type}`, () => {
198
- if (shouldThrow) {
199
- expect(() => sanitizeInput(input, type)).toThrow();
200
- } else {
201
- const result = sanitizeInput(input, type);
202
- expect(result).toBe(expected);
203
- }
204
- });
205
- });
206
- });
@@ -1,135 +0,0 @@
1
- /**
2
- * Test Setup for CLI Tests
3
- */
4
-
5
- import { vi } from 'vitest';
6
-
7
- // Mock external dependencies
8
- vi.mock('ora', () => ({
9
- default: vi.fn(() => ({
10
- start: vi.fn(() => ({
11
- succeed: vi.fn(),
12
- fail: vi.fn(),
13
- stop: vi.fn(),
14
- text: ''
15
- }))
16
- }))
17
- }));
18
-
19
- vi.mock('inquirer', () => ({
20
- prompt: vi.fn()
21
- }));
22
-
23
- vi.mock('chalk', () => ({
24
- default: {
25
- green: vi.fn((text) => text),
26
- red: vi.fn((text) => text),
27
- yellow: vi.fn((text) => text),
28
- cyan: vi.fn((text) => text),
29
- gray: vi.fn((text) => text),
30
- blue: vi.fn((text) => text),
31
- bold: {
32
- green: vi.fn((text) => text),
33
- red: vi.fn((text) => text),
34
- yellow: vi.fn((text) => text),
35
- cyan: vi.fn((text) => text),
36
- blue: vi.fn((text) => text)
37
- }
38
- }
39
- }));
40
-
41
- vi.mock('boxen', () => ({
42
- default: vi.fn((text) => text)
43
- }));
44
-
45
- vi.mock('chokidar', () => ({
46
- default: vi.fn(() => ({
47
- on: vi.fn(),
48
- close: vi.fn()
49
- }))
50
- }));
51
-
52
- // Mock file system operations
53
- vi.mock('fs/promises', async () => {
54
- const actual = await vi.importActual('fs/promises');
55
- return {
56
- ...actual,
57
- writeFile: vi.fn(actual.writeFile),
58
- readFile: vi.fn(actual.readFile),
59
- mkdir: vi.fn(actual.mkdir),
60
- access: vi.fn(actual.access),
61
- stat: vi.fn(actual.stat),
62
- rm: vi.fn(actual.rm)
63
- };
64
- });
65
-
66
- // Mock process.cwd for consistent test environment
67
- const originalCwd = process.cwd;
68
-
69
- beforeEach(() => {
70
- // Reset all mocks before each test
71
- vi.clearAllMocks();
72
- });
73
-
74
- afterEach(() => {
75
- // Restore original process.cwd
76
- process.cwd = originalCwd;
77
- });
78
-
79
- // Global test utilities
80
- global.createMockTempDir = () => '/tmp/atomix-test-' + Math.random().toString(36).substr(2, 9);
81
-
82
- global.mockComponentStructure = (componentName, content = '') => ({
83
- [`${componentName}.tsx`]: content || `
84
- import React, { forwardRef } from 'react';
85
-
86
- export const ${componentName} = forwardRef<HTMLDivElement, ${componentName}Props>(
87
- ({ children, className = '', ...props }, ref) => {
88
- return (
89
- <div ref={ref} className={className} {...props}>
90
- {children}
91
- </div>
92
- );
93
- }
94
- );
95
-
96
- interface ${componentName}Props {
97
- children?: React.ReactNode;
98
- className?: string;
99
- }
100
- `,
101
- 'index.ts': `export { ${componentName} } from './${componentName}';`,
102
- [`${componentName}.stories.tsx`]: `
103
- import type { Meta, StoryObj } from '@storybook/react';
104
- import { ${componentName} } from './${componentName}';
105
-
106
- const meta: Meta<typeof ${componentName}> = {
107
- title: 'Components/${componentName}',
108
- component: ${componentName},
109
- parameters: {
110
- layout: 'centered',
111
- },
112
- tags: ['autodocs'],
113
- };
114
-
115
- export default meta;
116
- type Story = StoryObj<typeof meta>;
117
-
118
- export const Default: Story = {
119
- args: {
120
- children: 'Test ${componentName}',
121
- },
122
- };
123
- `,
124
- [`${componentName}.test.tsx`]: `
125
- import { render, screen } from '@testing-library/react';
126
- import { ${componentName} } from './${componentName}';
127
-
128
- describe('${componentName}', () => {
129
- it('renders correctly', () => {
130
- render(<${componentName}>Test</${componentName}>);
131
- expect(screen.getByText('Test')).toBeInTheDocument();
132
- });
133
- });
134
- `
135
- });