@shohojdhara/atomix 0.3.14 → 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.
Files changed (173) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/build-tools/EXAMPLES.md +372 -0
  3. package/build-tools/README.md +242 -0
  4. package/build-tools/__tests__/error-handler.test.js +230 -0
  5. package/build-tools/__tests__/index.test.js +141 -0
  6. package/build-tools/__tests__/rollup-plugin.test.js +194 -0
  7. package/build-tools/__tests__/utils.test.js +161 -0
  8. package/build-tools/__tests__/vite-plugin.test.js +129 -0
  9. package/build-tools/__tests__/webpack-loader.test.js +190 -0
  10. package/build-tools/error-handler.js +308 -0
  11. package/build-tools/index.d.ts +43 -0
  12. package/build-tools/index.js +88 -0
  13. package/build-tools/package.json +67 -0
  14. package/build-tools/rollup-plugin.js +236 -0
  15. package/build-tools/types.d.ts +163 -0
  16. package/build-tools/utils.js +203 -0
  17. package/build-tools/vite-plugin.js +161 -0
  18. package/build-tools/webpack-loader.js +123 -0
  19. package/dist/atomix.css +203 -90
  20. package/dist/atomix.css.map +1 -1
  21. package/dist/atomix.min.css +3 -3
  22. package/dist/atomix.min.css.map +1 -1
  23. package/dist/build-tools/EXAMPLES.md +372 -0
  24. package/dist/build-tools/README.md +242 -0
  25. package/dist/build-tools/__tests__/error-handler.test.js +230 -0
  26. package/dist/build-tools/__tests__/index.test.js +141 -0
  27. package/dist/build-tools/__tests__/rollup-plugin.test.js +194 -0
  28. package/dist/build-tools/__tests__/utils.test.js +161 -0
  29. package/dist/build-tools/__tests__/vite-plugin.test.js +129 -0
  30. package/dist/build-tools/__tests__/webpack-loader.test.js +190 -0
  31. package/dist/build-tools/error-handler.js +308 -0
  32. package/dist/build-tools/index.d.ts +43 -0
  33. package/dist/build-tools/index.js +88 -0
  34. package/dist/build-tools/package.json +67 -0
  35. package/dist/build-tools/rollup-plugin.js +236 -0
  36. package/dist/build-tools/types.d.ts +163 -0
  37. package/dist/build-tools/utils.js +203 -0
  38. package/dist/build-tools/vite-plugin.js +161 -0
  39. package/dist/build-tools/webpack-loader.js +123 -0
  40. package/dist/charts.d.ts +1 -1
  41. package/dist/charts.js +86 -57
  42. package/dist/charts.js.map +1 -1
  43. package/dist/core.d.ts +1 -1
  44. package/dist/core.js +136 -112
  45. package/dist/core.js.map +1 -1
  46. package/dist/forms.d.ts +2 -5
  47. package/dist/forms.js +140 -128
  48. package/dist/forms.js.map +1 -1
  49. package/dist/heavy.d.ts +1 -1
  50. package/dist/heavy.js +136 -112
  51. package/dist/heavy.js.map +1 -1
  52. package/dist/index.d.ts +9 -61
  53. package/dist/index.esm.js +237 -286
  54. package/dist/index.esm.js.map +1 -1
  55. package/dist/index.js +250 -299
  56. package/dist/index.js.map +1 -1
  57. package/dist/index.min.js +1 -1
  58. package/dist/index.min.js.map +1 -1
  59. package/package.json +23 -8
  60. package/scripts/atomix-cli.js +170 -73
  61. package/scripts/cli/__tests__/README.md +81 -0
  62. package/scripts/cli/__tests__/basic.test.js +115 -0
  63. package/scripts/cli/__tests__/component-generator.test.js +332 -0
  64. package/scripts/cli/__tests__/integration.test.js +327 -0
  65. package/scripts/cli/__tests__/test-setup.js +133 -0
  66. package/scripts/cli/__tests__/token-manager.test.js +251 -0
  67. package/scripts/cli/__tests__/utils.test.js +161 -0
  68. package/scripts/cli/component-generator.js +253 -299
  69. package/scripts/cli/dependency-checker.js +355 -0
  70. package/scripts/cli/interactive-init.js +46 -5
  71. package/scripts/cli/template-manager.js +0 -2
  72. package/scripts/cli/templates/common-templates.js +636 -0
  73. package/scripts/cli/templates/composable-templates.js +148 -126
  74. package/scripts/cli/templates/index.js +23 -16
  75. package/scripts/cli/templates/project-templates.js +151 -23
  76. package/scripts/cli/templates/react-templates.js +280 -210
  77. package/scripts/cli/templates/scss-templates.js +90 -91
  78. package/scripts/cli/templates/testing-templates.js +206 -27
  79. package/scripts/cli/templates/testing-utils.js +278 -0
  80. package/scripts/cli/templates/types-templates.js +70 -56
  81. package/scripts/cli/theme-bridge.js +8 -2
  82. package/scripts/cli/token-manager.js +318 -206
  83. package/scripts/cli/utils.js +0 -1
  84. package/src/components/Accordion/Accordion.stories.tsx +369 -870
  85. package/src/components/AtomixGlass/AtomixGlass.tsx +80 -39
  86. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +103 -81
  87. package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +8 -7
  88. package/src/components/AtomixGlass/glass-utils.ts +2 -2
  89. package/src/components/AtomixGlass/shader-utils.ts +5 -0
  90. package/src/components/AtomixGlass/stories/Customization.stories.tsx +131 -0
  91. package/src/components/AtomixGlass/stories/Examples.stories.tsx +2957 -2853
  92. package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -1
  93. package/src/components/AtomixGlass/stories/Overview.stories.tsx +348 -0
  94. package/src/components/AtomixGlass/stories/Performance.stories.tsx +103 -0
  95. package/src/components/AtomixGlass/stories/Playground.stories.tsx +50 -35
  96. package/src/components/AtomixGlass/stories/{ShaderVariants.stories.tsx → Shaders.stories.tsx} +1 -1
  97. package/src/components/AtomixGlass/stories/shared-components.tsx +90 -190
  98. package/src/components/Avatar/Avatar.stories.tsx +213 -1
  99. package/src/components/Badge/Badge.stories.tsx +121 -362
  100. package/src/components/Block/Block.stories.tsx +21 -12
  101. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +141 -23
  102. package/src/components/Button/Button.stories.tsx +463 -1126
  103. package/src/components/Button/Button.test.tsx +107 -0
  104. package/src/components/Button/Button.tsx +46 -50
  105. package/src/components/Button/ButtonGroup.stories.tsx +373 -217
  106. package/src/components/Callout/Callout.stories.tsx +289 -634
  107. package/src/components/Card/Card.stories.tsx +248 -68
  108. package/src/components/Chart/Chart.stories.tsx +150 -8
  109. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +151 -69
  110. package/src/components/Countdown/Countdown.stories.tsx +115 -8
  111. package/src/components/DataTable/DataTable.stories.tsx +346 -146
  112. package/src/components/DatePicker/DatePicker.stories.tsx +325 -1066
  113. package/src/components/Dropdown/Dropdown.stories.tsx +153 -33
  114. package/src/components/EdgePanel/EdgePanel.stories.tsx +230 -21
  115. package/src/components/Footer/Footer.stories.tsx +392 -328
  116. package/src/components/Form/Checkbox.stories.tsx +140 -6
  117. package/src/components/Form/Checkbox.test.tsx +63 -0
  118. package/src/components/Form/Checkbox.tsx +87 -51
  119. package/src/components/Form/Form.stories.tsx +119 -20
  120. package/src/components/Form/FormGroup.stories.tsx +127 -4
  121. package/src/components/Form/Radio.stories.tsx +140 -5
  122. package/src/components/Form/Select.stories.tsx +140 -8
  123. package/src/components/Form/Textarea.stories.tsx +149 -6
  124. package/src/components/Hero/Hero.stories.tsx +333 -32
  125. package/src/components/List/List.stories.tsx +141 -3
  126. package/src/components/Modal/Modal.stories.tsx +181 -42
  127. package/src/components/Popover/Popover.stories.tsx +448 -98
  128. package/src/components/Progress/Progress.stories.tsx +167 -5
  129. package/src/components/River/River.stories.tsx +1 -1
  130. package/src/components/SectionIntro/SectionIntro.stories.tsx +240 -48
  131. package/src/components/Spinner/Spinner.stories.tsx +102 -8
  132. package/src/components/Steps/Steps.stories.tsx +172 -43
  133. package/src/components/Tabs/Tabs.stories.tsx +136 -10
  134. package/src/components/Testimonial/Testimonial.stories.tsx +120 -3
  135. package/src/components/Todo/Todo.stories.tsx +198 -9
  136. package/src/components/Toggle/Toggle.stories.tsx +126 -39
  137. package/src/components/Tooltip/Tooltip.stories.tsx +194 -104
  138. package/src/components/Upload/Upload.stories.tsx +113 -24
  139. package/src/lib/README.md +2 -2
  140. package/src/lib/__tests__/theme-tools.test.ts +193 -0
  141. package/src/lib/composables/index.ts +2 -2
  142. package/src/lib/composables/useAtomixGlass.ts +28 -56
  143. package/src/lib/composables/useChartExport.ts +2 -7
  144. package/src/lib/composables/useDataTable.ts +46 -29
  145. package/src/lib/constants/components.ts +9 -32
  146. package/src/lib/theme/devtools/CLI.ts +1 -1
  147. package/src/lib/types/components.ts +1 -1
  148. package/src/lib/utils/__tests__/csv.test.ts +45 -0
  149. package/src/lib/utils/csv.ts +17 -0
  150. package/src/lib/utils/dataTableExport.ts +1 -10
  151. package/src/styles/01-settings/_index.scss +2 -1
  152. package/src/styles/01-settings/_settings.accordion.scss +28 -7
  153. package/src/styles/01-settings/_settings.colors.scss +11 -11
  154. package/src/styles/01-settings/_settings.typography.scss +5 -5
  155. package/src/styles/02-tools/_tools.utility-api.scss +14 -0
  156. package/src/styles/06-components/_components.accordion.scss +56 -14
  157. package/src/styles/06-components/_components.checkbox.scss +23 -17
  158. package/src/styles/99-utilities/_index.scss +2 -0
  159. package/src/styles/99-utilities/_utilities.scss +3 -1
  160. package/src/styles/99-utilities/_utilities.text-gradient.scss +45 -0
  161. package/themes/dark-complementary/README.md +98 -0
  162. package/themes/dark-complementary/index.scss +158 -0
  163. package/themes/default-light/README.md +81 -0
  164. package/themes/default-light/index.scss +154 -0
  165. package/themes/high-contrast/README.md +105 -0
  166. package/themes/high-contrast/index.scss +172 -0
  167. package/themes/test-theme/README.md +38 -0
  168. package/themes/test-theme/index.scss +47 -0
  169. package/scripts/cli/templates-original-backup.js +0 -1655
  170. package/scripts/cli/templates_backup.js +0 -684
  171. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +0 -1438
  172. package/src/lib/composables/useButton.ts +0 -93
  173. package/src/lib/composables/useCheckbox.ts +0 -70
@@ -0,0 +1,107 @@
1
+ import { render, screen, fireEvent } from '@testing-library/react';
2
+ import { describe, it, expect, vi } from 'vitest';
3
+ import { axe, toHaveNoViolations } from 'jest-axe';
4
+ import { Button } from './Button';
5
+ import React from 'react';
6
+
7
+ expect.extend(toHaveNoViolations);
8
+
9
+ // Mock AtomixGlass component
10
+ vi.mock('../AtomixGlass/AtomixGlass', () => ({
11
+ AtomixGlass: ({ children, ...props }: any) => (
12
+ <div data-testid="atomix-glass" data-glass-props={JSON.stringify(props)}>
13
+ {children}
14
+ </div>
15
+ ),
16
+ }));
17
+
18
+ describe('Button Component', () => {
19
+ it('renders correctly with label', () => {
20
+ render(<Button label="Click Me" />);
21
+ expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument();
22
+ });
23
+
24
+ it('renders correctly with children', () => {
25
+ render(<Button>Click Me</Button>);
26
+ expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument();
27
+ });
28
+
29
+ it('handles onClick event', () => {
30
+ const handleClick = vi.fn();
31
+ render(<Button onClick={handleClick}>Click Me</Button>);
32
+ fireEvent.click(screen.getByRole('button'));
33
+ expect(handleClick).toHaveBeenCalledTimes(1);
34
+ });
35
+
36
+ it('does not fire onClick when disabled', () => {
37
+ const handleClick = vi.fn();
38
+ render(<Button disabled onClick={handleClick}>Click Me</Button>);
39
+ const button = screen.getByRole('button');
40
+ expect(button).toBeDisabled();
41
+ fireEvent.click(button);
42
+ expect(handleClick).not.toHaveBeenCalled();
43
+ });
44
+
45
+ it('renders loading state correctly', () => {
46
+ render(<Button loading>Submit</Button>);
47
+ const button = screen.getByRole('button');
48
+ // It should be disabled or aria-disabled
49
+ expect(button).toHaveAttribute('aria-busy', 'true');
50
+ // Check for spinner (implementation detail: spinner usually has specific class or role)
51
+ // Based on Button.tsx: <span className="...spinner...">...</span>
52
+ // Let's look for the spinner component or class if we can't find by role
53
+ // Or check if text is still there.
54
+ expect(screen.getByText('Submit')).toBeInTheDocument();
55
+ });
56
+
57
+ it('replaces text with loadingText when loading', () => {
58
+ render(<Button loading loadingText="Processing...">Submit</Button>);
59
+ expect(screen.queryByText('Submit')).not.toBeInTheDocument();
60
+ expect(screen.getByText('Processing...')).toBeInTheDocument();
61
+ });
62
+
63
+ it('renders as a link when href is provided', () => {
64
+ render(<Button href="/home">Home</Button>);
65
+ const link = screen.getByRole('link', { name: /home/i });
66
+ expect(link).toHaveAttribute('href', '/home');
67
+ });
68
+
69
+ it('renders as disabled link when disabled and href provided', () => {
70
+ // Current implementation might be buggy here, let's see
71
+ render(<Button href="/home" disabled>Home</Button>);
72
+ const link = screen.queryByRole('link');
73
+ const button = screen.queryByRole('button');
74
+
75
+ // If it renders as button when disabled (which logic suggested), then:
76
+ if (button) {
77
+ expect(button).toBeDisabled();
78
+ } else if (link) {
79
+ expect(link).toHaveAttribute('aria-disabled', 'true');
80
+ // Should not navigate
81
+ }
82
+ });
83
+
84
+ it('forwards ref', () => {
85
+ const ref = React.createRef<HTMLButtonElement>();
86
+ render(<Button ref={ref}>Ref Button</Button>);
87
+ expect(ref.current).toBeInstanceOf(HTMLButtonElement);
88
+ });
89
+
90
+ it('handles iconOnly correctly with aria-label', () => {
91
+ render(<Button iconOnly icon={<span>Icon</span>} aria-label="Icon Button" />);
92
+ expect(screen.getByLabelText('Icon Button')).toBeInTheDocument();
93
+ });
94
+
95
+ it('does not render [object Object] as aria-label when children is an element', () => {
96
+ const { container } = render(<Button iconOnly icon={<span>Icon</span>}><span>Text</span></Button>);
97
+ const button = screen.getByRole('button');
98
+ // aria-label should probably be undefined or empty, or extracted text, but definitely not "[object Object]"
99
+ expect(button.getAttribute('aria-label')).not.toBe('[object Object]');
100
+ });
101
+
102
+ it('should have no accessibility violations', async () => {
103
+ const { container } = render(<Button>Accessible Button</Button>);
104
+ const results = await axe(container);
105
+ expect(results).toHaveNoViolations();
106
+ });
107
+ });
@@ -1,5 +1,4 @@
1
1
  import React, { ElementType, forwardRef, useCallback } from 'react';
2
- import { useButton } from '../../lib/composables/useButton';
3
2
  import { ButtonProps } from '../../lib/types/components';
4
3
  import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
5
4
  import { Spinner } from '../Spinner/Spinner';
@@ -60,24 +59,14 @@ export const Button = React.memo(
60
59
  const isDisabled = disabled || loading;
61
60
 
62
61
  // Determine if we should render as a link
62
+ // If disabled, we still check href, but we might want to render as button or anchor with aria-disabled
63
+ // The previous logic was Boolean(href && !isDisabled). This meant if disabled, it renders as <button>.
64
+ // This is a safe fallback for disabled links.
63
65
  const shouldRenderAsLink = Boolean(href && !isDisabled);
64
66
 
65
67
  // Resolve icon element - support both icon (ReactNode) and iconName (string)
66
68
  const iconElement = iconName ? <Icon name={iconName as PhosphorIconsType} size={iconSize} /> : icon;
67
69
 
68
- const { generateButtonClass, handleClick } = useButton({
69
- variant,
70
- size,
71
- disabled: isDisabled,
72
- rounded,
73
- glass,
74
- loading,
75
- fullWidth,
76
- block,
77
- active,
78
- selected,
79
- });
80
-
81
70
  const buttonClass = [
82
71
  BUTTON.BASE_CLASS,
83
72
  ThemeNaming.variantClass(THEME_NAMING.BUTTON_PREFIX, variant),
@@ -144,6 +133,9 @@ export const Button = React.memo(
144
133
  // Determine spinner size based on button size
145
134
  const spinnerSize = size === 'sm' ? 'sm' : size === 'lg' ? 'md' : 'sm';
146
135
 
136
+ // Safe Aria Label
137
+ const safeAriaLabel = ariaLabel || (iconOnly ? (typeof label === 'string' ? label : (typeof children === 'string' ? children : undefined)) : undefined);
138
+
147
139
  // Button content with icon positioning
148
140
  const buttonContent = (
149
141
  <>
@@ -172,17 +164,14 @@ export const Button = React.memo(
172
164
 
173
165
  // Button props
174
166
  const buttonProps = {
175
- ref,
176
167
  className: buttonClass,
177
- type: Component === 'button' && !shouldRenderAsLink ? type : undefined,
178
168
  onClick: handleClickEvent,
179
169
  onMouseEnter: onHover ? handleMouseEnter : undefined,
180
170
  onFocus: onFocus ? handleFocusEvent : undefined,
181
171
  onBlur: onBlur ? handleBlurEvent : undefined,
182
- disabled: isDisabled && Component === 'button' && !shouldRenderAsLink,
183
172
  'aria-disabled': isDisabled,
184
173
  'aria-busy': loading,
185
- 'aria-label': ariaLabel || (iconOnly ? label || children : undefined),
174
+ 'aria-label': safeAriaLabel,
186
175
  'aria-describedby': ariaDescribedBy,
187
176
  'aria-expanded': ariaExpanded,
188
177
  'aria-controls': ariaControls,
@@ -191,60 +180,67 @@ export const Button = React.memo(
191
180
  ...props,
192
181
  };
193
182
 
194
- // Default glass props
195
- const defaultGlassProps = {
196
- displacementScale: 20,
197
- blurAmount: 0,
198
- saturation: 200,
199
- elasticity: 0,
200
- };
201
- const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
183
+ let content: React.ReactElement;
202
184
 
203
185
  // Render as anchor if href is provided
204
186
  if (shouldRenderAsLink) {
205
- const { ref: _, ...buttonPropsWithoutRef } = buttonProps;
206
- const anchorButtonProps = {
207
- ...buttonPropsWithoutRef,
208
- type: undefined,
209
- disabled: undefined,
210
- };
211
-
212
187
  // Use custom LinkComponent if provided (e.g., Next.js Link)
213
188
  if (LinkComponent) {
214
189
  const LinkComp = LinkComponent as React.ComponentType<any>;
215
190
  const linkProps = {
216
- ...anchorButtonProps,
217
- ref: ref as React.Ref<HTMLAnchorElement>,
191
+ ...buttonProps,
192
+ ref: ref as any, // LinkComponent usually forwards ref to anchor
218
193
  href,
219
194
  target,
220
195
  rel: target === '_blank' ? 'noopener noreferrer' : undefined,
221
196
  };
222
197
 
223
- const linkElement = (
198
+ content = (
224
199
  <LinkComp {...linkProps}>
225
200
  {buttonContent}
226
201
  </LinkComp>
227
202
  );
228
-
229
- return glass ? <AtomixGlass {...glassProps}>{linkElement}</AtomixGlass> : linkElement;
203
+ } else {
204
+ // Fallback to regular anchor tag
205
+ content = (
206
+ <a
207
+ {...buttonProps}
208
+ ref={ref as React.Ref<HTMLAnchorElement>}
209
+ href={href}
210
+ target={target}
211
+ rel={target === '_blank' ? 'noopener noreferrer' : undefined}
212
+ >
213
+ {buttonContent}
214
+ </a>
215
+ );
230
216
  }
231
-
232
- // Fallback to regular anchor tag
233
- const anchorElement = (
234
- <a {...anchorButtonProps} ref={ref as React.Ref<HTMLAnchorElement>} href={href} target={target} rel={target === '_blank' ? 'noopener noreferrer' : undefined}>
217
+ } else {
218
+ // Default button rendering
219
+ content = (
220
+ <Component
221
+ {...buttonProps}
222
+ ref={ref}
223
+ type={Component === 'button' ? type : undefined}
224
+ disabled={isDisabled}
225
+ >
235
226
  {buttonContent}
236
- </a>
227
+ </Component>
237
228
  );
238
-
239
- return glass ? <AtomixGlass {...glassProps}>{anchorElement}</AtomixGlass> : anchorElement;
240
229
  }
241
230
 
242
- // Default button rendering
243
- const buttonElement = (
244
- <Component {...buttonProps}>{buttonContent}</Component>
245
- );
231
+ if (glass) {
232
+ // Default glass props
233
+ const defaultGlassProps = {
234
+ displacementScale: 20,
235
+ blurAmount: 0,
236
+ saturation: 200,
237
+ elasticity: 0,
238
+ };
239
+ const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
240
+ return <AtomixGlass {...glassProps}>{content}</AtomixGlass>;
241
+ }
246
242
 
247
- return glass ? <AtomixGlass {...glassProps}>{buttonElement}</AtomixGlass> : buttonElement;
243
+ return content;
248
244
  }
249
245
  )
250
246
  );