@shohojdhara/atomix 0.4.0 → 0.4.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 (66) hide show
  1. package/dist/atomix.css +9231 -9337
  2. package/dist/atomix.css.map +1 -1
  3. package/dist/atomix.min.css +2 -2
  4. package/dist/atomix.min.css.map +1 -1
  5. package/dist/charts.js +4 -5
  6. package/dist/charts.js.map +1 -1
  7. package/dist/core.d.ts +87 -10
  8. package/dist/core.js +673 -480
  9. package/dist/core.js.map +1 -1
  10. package/dist/forms.d.ts +15 -3
  11. package/dist/forms.js +530 -97
  12. package/dist/forms.js.map +1 -1
  13. package/dist/heavy.js +5 -6
  14. package/dist/heavy.js.map +1 -1
  15. package/dist/index.d.ts +495 -254
  16. package/dist/index.esm.js +1269 -723
  17. package/dist/index.esm.js.map +1 -1
  18. package/dist/index.js +1273 -723
  19. package/dist/index.js.map +1 -1
  20. package/dist/index.min.js +1 -1
  21. package/dist/index.min.js.map +1 -1
  22. package/package.json +2 -2
  23. package/scripts/atomix-cli.js +10 -1
  24. package/scripts/cli/__tests__/utils.test.js +6 -2
  25. package/scripts/cli/migration-tools.js +2 -2
  26. package/scripts/cli/theme-bridge.js +7 -9
  27. package/scripts/cli/utils.js +2 -1
  28. package/src/components/Accordion/Accordion.stories.tsx +40 -0
  29. package/src/components/Accordion/Accordion.tsx +174 -56
  30. package/src/components/Accordion/AccordionCompound.test.tsx +70 -0
  31. package/src/components/Breadcrumb/Breadcrumb.tsx +156 -50
  32. package/src/components/Breadcrumb/BreadcrumbCompound.test.tsx +84 -0
  33. package/src/components/Callout/Callout.stories.tsx +166 -1011
  34. package/src/components/Callout/Callout.tsx +196 -84
  35. package/src/components/Callout/CalloutCompound.test.tsx +72 -0
  36. package/src/components/Dropdown/Dropdown.tsx +133 -20
  37. package/src/components/Dropdown/DropdownCompound.test.tsx +64 -0
  38. package/src/components/EdgePanel/EdgePanel.tsx +164 -112
  39. package/src/components/EdgePanel/EdgePanelCompound.test.tsx +53 -0
  40. package/src/components/Form/Select.stories.tsx +23 -0
  41. package/src/components/Form/Select.test.tsx +99 -0
  42. package/src/components/Form/Select.tsx +144 -93
  43. package/src/components/Form/SelectOption.tsx +88 -0
  44. package/src/components/Hero/Hero.stories.tsx +37 -0
  45. package/src/components/Hero/Hero.test.tsx +142 -0
  46. package/src/components/Hero/Hero.tsx +142 -3
  47. package/src/components/List/List.test.tsx +62 -0
  48. package/src/components/List/List.tsx +16 -5
  49. package/src/components/List/ListItem.tsx +20 -0
  50. package/src/components/Modal/Modal.stories.tsx +65 -1
  51. package/src/components/Modal/Modal.tsx +115 -35
  52. package/src/components/Modal/ModalCompound.test.tsx +94 -0
  53. package/src/components/Steps/Steps.tsx +124 -21
  54. package/src/components/Steps/StepsCompound.test.tsx +81 -0
  55. package/src/components/Tabs/Tabs.tsx +197 -44
  56. package/src/components/Tabs/TabsCompound.test.tsx +64 -0
  57. package/src/lib/composables/index.ts +0 -4
  58. package/src/lib/composables/useAtomixGlass.ts +0 -15
  59. package/src/lib/theme/devtools/CLI.ts +2 -10
  60. package/src/lib/types/components.ts +8 -2
  61. package/src/lib/utils/__tests__/componentUtils.test.ts +57 -2
  62. package/src/lib/utils/__tests__/themeNaming.test.ts +117 -0
  63. package/src/lib/utils/themeNaming.ts +1 -1
  64. package/src/styles/02-tools/_tools.breakpoints.scss +1 -1
  65. package/src/styles/02-tools/_tools.utility-api.scss +6 -6
  66. package/src/styles/99-utilities/_utilities.text.scss +0 -1
@@ -201,7 +201,6 @@ export function useAtomixGlass({
201
201
  onClick,
202
202
  debugCornerRadius = false,
203
203
  debugOverLight = false,
204
- enablePerformanceMonitoring = false,
205
204
  children,
206
205
  }: UseAtomixGlassOptions): UseAtomixGlassReturn {
207
206
  // State
@@ -558,8 +557,6 @@ export function useAtomixGlass({
558
557
  return;
559
558
  }
560
559
 
561
- const startTime = enablePerformanceMonitoring ? performance.now() : 0;
562
-
563
560
  // Use cached rect if available, otherwise get new one
564
561
  let rect = cachedRectRef.current;
565
562
  if (!rect || rect.width === 0 || rect.height === 0) {
@@ -582,17 +579,6 @@ export function useAtomixGlass({
582
579
  // React 18 automatically batches these updates
583
580
  setInternalMouseOffset(newOffset);
584
581
  setInternalGlobalMousePosition(globalPos);
585
-
586
- if (
587
- (typeof process === 'undefined' || process.env?.NODE_ENV !== 'production') &&
588
- enablePerformanceMonitoring
589
- ) {
590
- const endTime = performance.now();
591
- // const duration = endTime - startTime;
592
- // if (duration > 5) {
593
- // console.warn(`AtomixGlass: Mouse tracking took ${duration.toFixed(2)}ms`);
594
- // }
595
- }
596
582
  },
597
583
  [
598
584
  mouseContainer,
@@ -600,7 +586,6 @@ export function useAtomixGlass({
600
586
  externalGlobalMousePosition,
601
587
  externalMouseOffset,
602
588
  effectiveDisableEffects,
603
- enablePerformanceMonitoring,
604
589
  ]
605
590
  );
606
591
 
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ts-node
1
+ #!/usr/bin/env tsx
2
2
 
3
3
  /**
4
4
  * Atomix Theme DevTools CLI
@@ -11,17 +11,9 @@ import { Command } from 'commander';
11
11
  import chalk from 'chalk';
12
12
  import * as fs from 'fs';
13
13
  import * as path from 'path';
14
- // import { ThemeValidator } from './ThemeValidator.js';
14
+ import { ThemeValidator } from './ThemeValidator';
15
15
  import boxen from 'boxen';
16
16
 
17
- // Stub validator for now to avoid ESM resolution issues in CLI
18
- // TODO: Fix ESM module resolution for ThemeValidator in CLI context
19
- class ThemeValidator {
20
- validate() {
21
- return { valid: true, errors: [], warnings: [], a11yIssues: [] };
22
- }
23
- }
24
-
25
17
  const program = new Command();
26
18
 
27
19
  program.name('atomix-theme').description('Atomix Theme DevTools').version('0.1.0');
@@ -375,7 +375,7 @@ export type StateModifier =
375
375
  */
376
376
  export type IconPosition = 'left' | 'right';
377
377
 
378
- export type listvariant = 'dash' | 'number' | 'text';
378
+ export type listvariant = 'dash' | 'number' | 'text' | 'default';
379
379
  /**;
380
380
  * List component properties
381
381
  */
@@ -1140,6 +1140,12 @@ export interface HeroProps
1140
1140
  * Granular part-based styling
1141
1141
  */
1142
1142
  parts?: HeroParts;
1143
+
1144
+ /**
1145
+ * Custom background element to render behind the content
1146
+ * @example <Hero.Background src="..." />
1147
+ */
1148
+ backgroundElement?: ReactNode;
1143
1149
  }
1144
1150
 
1145
1151
  /**
@@ -2440,7 +2446,7 @@ export interface SelectProps extends BaseComponentProps {
2440
2446
  /**
2441
2447
  * Select options
2442
2448
  */
2443
- options: SelectOption[];
2449
+ options?: SelectOption[];
2444
2450
 
2445
2451
  /**
2446
2452
  * Selected value(s)
@@ -4,6 +4,8 @@ import {
4
4
  applyPartStyles,
5
5
  createCSSVarStyle,
6
6
  mergeComponentProps,
7
+ isYouTubeUrl,
8
+ extractYouTubeId,
7
9
  } from '../componentUtils';
8
10
 
9
11
  describe('componentUtils', () => {
@@ -58,6 +60,7 @@ describe('componentUtils', () => {
58
60
  className: 'base custom',
59
61
  id: 'test',
60
62
  'data-test': 'value',
63
+ style: {},
61
64
  });
62
65
  });
63
66
  });
@@ -94,8 +97,8 @@ describe('componentUtils', () => {
94
97
  };
95
98
  const result = createCSSVarStyle(cssVars);
96
99
  expect(result).toEqual({
97
- '--atomix-button-padding-x': 16,
98
- '--atomix-button-padding-y': 8,
100
+ '--atomix-button-padding-x': '16px',
101
+ '--atomix-button-padding-y': '8px',
99
102
  });
100
103
  });
101
104
 
@@ -141,4 +144,56 @@ describe('componentUtils', () => {
141
144
  expect(result).toEqual(baseProps);
142
145
  });
143
146
  });
147
+
148
+ describe('isYouTubeUrl', () => {
149
+ it('should return true for standard YouTube URLs', () => {
150
+ expect(isYouTubeUrl('https://www.youtube.com/watch?v=dQw4w9WgXcQ')).toBe(true);
151
+ expect(isYouTubeUrl('http://www.youtube.com/watch?v=dQw4w9WgXcQ')).toBe(true);
152
+ expect(isYouTubeUrl('www.youtube.com/watch?v=dQw4w9WgXcQ')).toBe(true);
153
+ expect(isYouTubeUrl('youtube.com/watch?v=dQw4w9WgXcQ')).toBe(true);
154
+ });
155
+
156
+ it('should return true for shortened YouTube URLs', () => {
157
+ expect(isYouTubeUrl('https://youtu.be/dQw4w9WgXcQ')).toBe(true);
158
+ expect(isYouTubeUrl('http://youtu.be/dQw4w9WgXcQ')).toBe(true);
159
+ expect(isYouTubeUrl('youtu.be/dQw4w9WgXcQ')).toBe(true);
160
+ });
161
+
162
+ it('should return true for embed YouTube URLs', () => {
163
+ expect(isYouTubeUrl('https://www.youtube.com/embed/dQw4w9WgXcQ')).toBe(true);
164
+ });
165
+
166
+ it('should return false for non-YouTube URLs', () => {
167
+ expect(isYouTubeUrl('https://vimeo.com/12345')).toBe(false);
168
+ expect(isYouTubeUrl('https://google.com')).toBe(false);
169
+ expect(isYouTubeUrl('random string')).toBe(false);
170
+ expect(isYouTubeUrl('')).toBe(false);
171
+ });
172
+ });
173
+
174
+ describe('extractYouTubeId', () => {
175
+ it('should extract ID from standard YouTube URLs', () => {
176
+ expect(extractYouTubeId('https://www.youtube.com/watch?v=dQw4w9WgXcQ')).toBe('dQw4w9WgXcQ');
177
+ });
178
+
179
+ it('should extract ID from shortened YouTube URLs', () => {
180
+ expect(extractYouTubeId('https://youtu.be/dQw4w9WgXcQ')).toBe('dQw4w9WgXcQ');
181
+ });
182
+
183
+ it('should extract ID from embed YouTube URLs', () => {
184
+ expect(extractYouTubeId('https://www.youtube.com/embed/dQw4w9WgXcQ')).toBe('dQw4w9WgXcQ');
185
+ });
186
+
187
+ it('should extract ID with additional query parameters', () => {
188
+ expect(extractYouTubeId('https://www.youtube.com/watch?v=dQw4w9WgXcQ&feature=youtu.be')).toBe(
189
+ 'dQw4w9WgXcQ'
190
+ );
191
+ });
192
+
193
+ it('should return null for non-YouTube URLs', () => {
194
+ expect(extractYouTubeId('https://vimeo.com/12345')).toBe(null);
195
+ expect(extractYouTubeId('https://google.com')).toBe(null);
196
+ expect(extractYouTubeId('')).toBe(null);
197
+ });
198
+ });
144
199
  });
@@ -0,0 +1,117 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import { ThemeNaming } from '../themeNaming';
3
+
4
+ describe('ThemeNaming', () => {
5
+ afterEach(() => {
6
+ // Reset prefix to default after each test
7
+ ThemeNaming.setPrefix('atomix');
8
+ });
9
+
10
+ describe('setPrefix / getPrefix', () => {
11
+ it('should have default prefix "atomix"', () => {
12
+ expect(ThemeNaming.getPrefix()).toBe('atomix');
13
+ });
14
+
15
+ it('should update prefix', () => {
16
+ ThemeNaming.setPrefix('custom');
17
+ expect(ThemeNaming.getPrefix()).toBe('custom');
18
+ });
19
+ });
20
+
21
+ describe('camelToKebab', () => {
22
+ it('should convert camelCase to kebab-case', () => {
23
+ expect(ThemeNaming.camelToKebab('camelCase')).toBe('camel-case');
24
+ });
25
+
26
+ it('should handle PascalCase', () => {
27
+ expect(ThemeNaming.camelToKebab('PascalCase')).toBe('pascal-case');
28
+ });
29
+
30
+ it('should handle simple strings', () => {
31
+ expect(ThemeNaming.camelToKebab('simple')).toBe('simple');
32
+ });
33
+
34
+ it('should handle empty string', () => {
35
+ expect(ThemeNaming.camelToKebab('')).toBe('');
36
+ });
37
+ });
38
+
39
+ describe('kebabToCamel', () => {
40
+ it('should convert kebab-case to camelCase', () => {
41
+ expect(ThemeNaming.kebabToCamel('kebab-case')).toBe('kebabCase');
42
+ });
43
+
44
+ it('should handle simple strings', () => {
45
+ expect(ThemeNaming.kebabToCamel('simple')).toBe('simple');
46
+ });
47
+
48
+ it('should handle empty string', () => {
49
+ expect(ThemeNaming.kebabToCamel('')).toBe('');
50
+ });
51
+ });
52
+
53
+ describe('cssVar', () => {
54
+ it('should create CSS variable with default prefix', () => {
55
+ expect(ThemeNaming.cssVar('tokenName')).toBe('--atomix-token-name');
56
+ });
57
+
58
+ it('should create CSS variable with custom prefix', () => {
59
+ ThemeNaming.setPrefix('custom');
60
+ expect(ThemeNaming.cssVar('tokenName')).toBe('--custom-token-name');
61
+ });
62
+ });
63
+
64
+ describe('bemClass', () => {
65
+ it('should create block class', () => {
66
+ expect(ThemeNaming.bemClass('block')).toBe('c-block');
67
+ });
68
+
69
+ it('should create block element class', () => {
70
+ expect(ThemeNaming.bemClass('block', 'element')).toBe('c-block__element');
71
+ });
72
+
73
+ it('should create block modifier class', () => {
74
+ expect(ThemeNaming.bemClass('block', undefined, 'mod')).toBe('c-block--mod');
75
+ });
76
+
77
+ it('should create block element modifier class', () => {
78
+ expect(ThemeNaming.bemClass('block', 'element', 'mod')).toBe('c-block__element--mod');
79
+ });
80
+ });
81
+
82
+ describe('variantClass', () => {
83
+ it('should create variant class', () => {
84
+ expect(ThemeNaming.variantClass('button', 'primary')).toBe('c-button--primary');
85
+ });
86
+ });
87
+
88
+ describe('sizeClass', () => {
89
+ it('should create size class', () => {
90
+ expect(ThemeNaming.sizeClass('button', 'lg')).toBe('c-button--lg');
91
+ });
92
+ });
93
+
94
+ describe('stateClass', () => {
95
+ it('should create state class', () => {
96
+ expect(ThemeNaming.stateClass('input', 'disabled')).toBe('c-input--disabled');
97
+ });
98
+ });
99
+
100
+ describe('utilityClass', () => {
101
+ it('should create utility class', () => {
102
+ expect(ThemeNaming.utilityClass('flex')).toBe('u-flex');
103
+ });
104
+ });
105
+
106
+ describe('layoutClass', () => {
107
+ it('should create layout class', () => {
108
+ expect(ThemeNaming.layoutClass('grid')).toBe('l-grid');
109
+ });
110
+ });
111
+
112
+ describe('objectClass', () => {
113
+ it('should create object class', () => {
114
+ expect(ThemeNaming.objectClass('container')).toBe('o-container');
115
+ });
116
+ });
117
+ });
@@ -28,7 +28,7 @@ export class ThemeNaming {
28
28
  * @param str - String to convert
29
29
  */
30
30
  static camelToKebab(str: string): string {
31
- return str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2').toLowerCase();
31
+ return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
32
32
  }
33
33
 
34
34
  /**
@@ -8,7 +8,7 @@
8
8
  // Breakpoint viewport sizes and media queries.
9
9
  @mixin media-breakpoint-up($name, $breakpoints: breakpoints.$grid-breakpoints) {
10
10
  $min: map.get($breakpoints, $name);
11
- @if $min {
11
+ @if $min and $min != 0 {
12
12
  @media (min-width: $min) {
13
13
  @content;
14
14
  }
@@ -22,7 +22,7 @@ $utility-defaults: (
22
22
  class: null,
23
23
  state: null,
24
24
  local-vars: (),
25
- rtl: true,
25
+ is-important: true,
26
26
  ) !default;
27
27
 
28
28
  // Core function to generate utility classes
@@ -77,11 +77,11 @@ $utility-defaults: (
77
77
  --atomix-u-#{$css-variable-name}: #{$value};
78
78
  } @else if $properties {
79
79
  @each $property in $properties {
80
- #{$property}: $value if(map.get($utility, rtl), null, !important);
80
+ #{$property}: $value if(map.get($utility, is-important), !important, null);
81
81
  }
82
82
  } @else if $value != null {
83
83
  // Guard: only emit property declaration if value is not null
84
- #{$property-class}: $value if(map.get($utility, rtl), null, !important);
84
+ #{$property-class}: $value if(map.get($utility, is-important), !important, null);
85
85
  }
86
86
 
87
87
  // Add local CSS variables if specified
@@ -111,11 +111,11 @@ $utility-defaults: (
111
111
  --atomix-u-#{$css-variable-name}#{$modifier}: #{$value};
112
112
  } @else if $properties {
113
113
  @each $property in $properties {
114
- #{$property}: $value if(map.get($utility, rtl), null, !important);
114
+ #{$property}: $value if(map.get($utility, is-important), !important, null);
115
115
  }
116
116
  } @else if $value != null {
117
117
  // Guard: only emit property declaration if value is not null
118
- #{$base-class}: $value if(map.get($utility, rtl), null, !important);
118
+ #{$base-class}: $value if(map.get($utility, is-important), !important, null);
119
119
  }
120
120
 
121
121
  // Add local CSS variables if specified
@@ -169,7 +169,7 @@ $utility-defaults: (
169
169
  values: map.get($config, values),
170
170
  class: map.get($config, class),
171
171
  state: map.get($config, state),
172
- rtl: map.get($config, rtl),
172
+ is-important: map.get($config, is-important),
173
173
  css-var: map.get($config, css-var),
174
174
  local-vars: map.get($config, local-vars),
175
175
  responsive: map.get($config, responsive),
@@ -99,7 +99,6 @@ $utilities-text: (
99
99
  values: (
100
100
  break: break-word,
101
101
  ),
102
- rtl: false,
103
102
  ),
104
103
  'color': (
105
104
  property: color,