@shohojdhara/atomix 0.3.4 → 0.3.5

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 (114) hide show
  1. package/dist/atomix.css +9 -10
  2. package/dist/atomix.css.map +1 -0
  3. package/dist/atomix.min.css +15108 -11
  4. package/dist/atomix.min.css.map +1 -0
  5. package/dist/charts.d.ts +1929 -0
  6. package/dist/charts.js +6482 -0
  7. package/dist/charts.js.map +1 -0
  8. package/dist/core.d.ts +1289 -0
  9. package/dist/core.js +3357 -0
  10. package/dist/core.js.map +1 -0
  11. package/dist/forms.d.ts +1085 -0
  12. package/dist/forms.js +2450 -0
  13. package/dist/forms.js.map +1 -0
  14. package/dist/heavy.d.ts +636 -0
  15. package/dist/heavy.js +4550 -0
  16. package/dist/heavy.js.map +1 -0
  17. package/dist/index.d.ts +5161 -4990
  18. package/dist/index.esm.js +1457 -784
  19. package/dist/index.esm.js.map +1 -1
  20. package/dist/index.js +1473 -790
  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/dist/layout.d.ts +300 -0
  25. package/dist/layout.js +336 -0
  26. package/dist/layout.js.map +1 -0
  27. package/dist/theme.d.ts +1992 -0
  28. package/dist/theme.js +5348 -0
  29. package/dist/theme.js.map +1 -0
  30. package/package.json +66 -20
  31. package/scripts/atomix-cli.js +544 -16
  32. package/scripts/cli/__tests__/cli-commands.test.js +204 -0
  33. package/scripts/cli/__tests__/utils.test.js +201 -0
  34. package/scripts/cli/__tests__/vitest.config.js +26 -0
  35. package/scripts/cli/interactive-init.js +1 -1
  36. package/scripts/cli/token-manager.js +32 -7
  37. package/scripts/cli/utils.js +347 -0
  38. package/src/components/Accordion/Accordion.tsx +5 -54
  39. package/src/components/Accordion/index.ts +1 -1
  40. package/src/components/Avatar/Avatar.tsx +3 -3
  41. package/src/components/Badge/Badge.tsx +3 -3
  42. package/src/components/Breadcrumb/Breadcrumb.tsx +3 -3
  43. package/src/components/Card/ElevationCard.tsx +1 -1
  44. package/src/components/Chart/AnimatedChart.tsx +19 -17
  45. package/src/components/Chart/AreaChart.tsx +5 -1
  46. package/src/components/Chart/BarChart.tsx +1 -0
  47. package/src/components/Chart/BubbleChart.tsx +6 -5
  48. package/src/components/Chart/ChartToolbar.tsx +1 -0
  49. package/src/components/Chart/FunnelChart.tsx +1 -1
  50. package/src/components/Chart/RadarChart.tsx +19 -12
  51. package/src/components/Chart/ScatterChart.tsx +3 -3
  52. package/src/components/Chart/TreemapChart.tsx +2 -1
  53. package/src/components/Chart/WaterfallChart.tsx +0 -1
  54. package/src/components/Chart/types.ts +12 -2
  55. package/src/components/Chart/utils.ts +4 -3
  56. package/src/components/DataTable/DataTable.tsx +3 -3
  57. package/src/components/Dropdown/Dropdown.tsx +12 -9
  58. package/src/components/Footer/FooterSection.tsx +3 -3
  59. package/src/components/Form/Checkbox.tsx +3 -3
  60. package/src/components/Form/Input.tsx +4 -2
  61. package/src/components/Form/Radio.tsx +3 -3
  62. package/src/components/Form/Select.tsx +3 -3
  63. package/src/components/Form/Textarea.tsx +4 -2
  64. package/src/components/List/List.stories.tsx +3 -3
  65. package/src/components/List/List.tsx +3 -3
  66. package/src/components/List/ListGroup.tsx +3 -1
  67. package/src/components/Modal/Modal.tsx +3 -3
  68. package/src/components/Navigation/Menu/MegaMenu.tsx +9 -3
  69. package/src/components/Navigation/Menu/Menu.tsx +9 -3
  70. package/src/components/Pagination/Pagination.tsx +6 -5
  71. package/src/components/PhotoViewer/PhotoViewerImage.tsx +2 -2
  72. package/src/components/Popover/Popover.tsx +4 -4
  73. package/src/components/Progress/Progress.tsx +6 -2
  74. package/src/components/Rating/Rating.tsx +5 -2
  75. package/src/components/Slider/Slider.tsx +10 -9
  76. package/src/components/Spinner/Spinner.tsx +3 -3
  77. package/src/components/Tabs/Tabs.tsx +3 -3
  78. package/src/components/Tooltip/Tooltip.tsx +3 -3
  79. package/src/components/index.ts +5 -2
  80. package/src/layouts/MasonryGrid/MasonryGrid.tsx +2 -2
  81. package/src/lib/composables/useChartPerformance.ts +102 -78
  82. package/src/lib/composables/useChartScale.ts +10 -0
  83. package/src/lib/composables/useHero.ts +9 -2
  84. package/src/lib/composables/useHeroBackgroundSlider.ts +5 -3
  85. package/src/lib/composables/useSideMenu.ts +1 -0
  86. package/src/lib/composables/useVideoPlayer.ts +3 -2
  87. package/src/lib/config/loader.ts +55 -13
  88. package/src/lib/hooks/index.ts +0 -1
  89. package/src/lib/hooks/useComponentCustomization.ts +10 -14
  90. package/src/lib/hooks/usePerformanceMonitor.ts +149 -0
  91. package/src/lib/patterns/index.ts +2 -2
  92. package/src/lib/patterns/slots.tsx +2 -2
  93. package/src/lib/theme/composeTheme.ts +1 -1
  94. package/src/lib/theme/core/ThemeEngine.ts +8 -0
  95. package/src/lib/theme/core/ThemeValidator.ts +5 -2
  96. package/src/lib/theme/devtools/Inspector.tsx +1 -1
  97. package/src/lib/theme/devtools/LiveEditor.tsx +11 -5
  98. package/src/lib/theme/generateCSSVariables.ts +1 -1
  99. package/src/lib/theme/i18n/rtl.ts +2 -1
  100. package/src/lib/theme/runtime/ThemeApplicator.ts +28 -11
  101. package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +3 -3
  102. package/src/lib/theme/runtime/ThemeManager.ts +4 -0
  103. package/src/lib/theme-tools.ts +1 -1
  104. package/src/lib/types/components.ts +183 -34
  105. package/src/lib/types/partProps.ts +0 -16
  106. package/src/lib/utils/fontPreloader.ts +148 -0
  107. package/src/lib/utils/index.ts +11 -0
  108. package/src/lib/utils/memoryMonitor.ts +189 -0
  109. package/src/styles/01-settings/_settings.fonts.scss +2 -5
  110. package/src/styles/03-generic/_generated-root.css +22 -1
  111. package/src/styles/06-components/_components.navbar.scss +0 -6
  112. package/src/themes/themes.config.js +37 -4
  113. package/scripts/build-themes.js +0 -208
  114. package/src/components/AtomixGlass/atomixGLass.old.tsx +0 -1263
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Performance Monitoring Hook
3
+ *
4
+ * Tracks component render times and re-render counts
5
+ * for performance analysis and optimization
6
+ */
7
+
8
+ import { useEffect, useRef } from 'react';
9
+
10
+ export interface PerformanceMetrics {
11
+ /**
12
+ * Component name
13
+ */
14
+ componentName: string;
15
+ /**
16
+ * Number of renders
17
+ */
18
+ renderCount: number;
19
+ /**
20
+ * Average render time in milliseconds
21
+ */
22
+ averageRenderTime: number;
23
+ /**
24
+ * Total render time in milliseconds
25
+ */
26
+ totalRenderTime: number;
27
+ /**
28
+ * Maximum render time in milliseconds
29
+ */
30
+ maxRenderTime: number;
31
+ /**
32
+ * Minimum render time in milliseconds
33
+ */
34
+ minRenderTime: number;
35
+ }
36
+
37
+ /**
38
+ * Options for performance monitoring
39
+ */
40
+ export interface UsePerformanceMonitorOptions {
41
+ /**
42
+ * Component name to track
43
+ */
44
+ componentName: string;
45
+ /**
46
+ * Whether to log metrics to console (development only)
47
+ */
48
+ logToConsole?: boolean;
49
+ /**
50
+ * Threshold in milliseconds to warn about slow renders
51
+ */
52
+ warnThreshold?: number;
53
+ /**
54
+ * Callback to report metrics (e.g., to analytics)
55
+ */
56
+ onMetrics?: (metrics: PerformanceMetrics) => void;
57
+ }
58
+
59
+ /**
60
+ * Hook to monitor component performance
61
+ *
62
+ * @param options - Performance monitoring options
63
+ * @returns Performance metrics
64
+ *
65
+ * @example
66
+ * ```tsx
67
+ * function MyComponent() {
68
+ * usePerformanceMonitor({
69
+ * componentName: 'MyComponent',
70
+ * warnThreshold: 16, // Warn if render takes > 16ms (1 frame)
71
+ * });
72
+ *
73
+ * return <div>Content</div>;
74
+ * }
75
+ * ```
76
+ */
77
+ export function usePerformanceMonitor(options: UsePerformanceMonitorOptions) {
78
+ const {
79
+ componentName,
80
+ logToConsole = process.env.NODE_ENV === 'development',
81
+ warnThreshold = 16,
82
+ onMetrics,
83
+ } = options;
84
+
85
+ const metricsRef = useRef<PerformanceMetrics>({
86
+ componentName,
87
+ renderCount: 0,
88
+ averageRenderTime: 0,
89
+ totalRenderTime: 0,
90
+ maxRenderTime: 0,
91
+ minRenderTime: Infinity,
92
+ });
93
+
94
+ const renderStartRef = useRef<number>(0);
95
+
96
+ useEffect(() => {
97
+ // Start timing the render
98
+ renderStartRef.current = performance.now();
99
+ });
100
+
101
+ useEffect(() => {
102
+ // Calculate render time
103
+ const renderTime = performance.now() - renderStartRef.current;
104
+ const metrics = metricsRef.current;
105
+
106
+ // Update metrics
107
+ metrics.renderCount += 1;
108
+ metrics.totalRenderTime += renderTime;
109
+ metrics.averageRenderTime = metrics.totalRenderTime / metrics.renderCount;
110
+ metrics.maxRenderTime = Math.max(metrics.maxRenderTime, renderTime);
111
+ metrics.minRenderTime = Math.min(metrics.minRenderTime, renderTime);
112
+
113
+ // Warn if render is slow
114
+ if (renderTime > warnThreshold && logToConsole) {
115
+ console.warn(
116
+ `[Performance] ${componentName} render took ${renderTime.toFixed(2)}ms ` +
117
+ `(threshold: ${warnThreshold}ms)`
118
+ );
119
+ }
120
+
121
+ // Log metrics in development
122
+ if (logToConsole && metrics.renderCount % 10 === 0) {
123
+ console.log(`[Performance] ${componentName} metrics:`, {
124
+ renderCount: metrics.renderCount,
125
+ averageRenderTime: metrics.averageRenderTime.toFixed(2) + 'ms',
126
+ maxRenderTime: metrics.maxRenderTime.toFixed(2) + 'ms',
127
+ minRenderTime: metrics.minRenderTime.toFixed(2) + 'ms',
128
+ });
129
+ }
130
+
131
+ // Report metrics via callback
132
+ if (onMetrics) {
133
+ onMetrics({ ...metrics });
134
+ }
135
+ });
136
+
137
+ return metricsRef.current;
138
+ }
139
+
140
+ /**
141
+ * Get all performance metrics for all monitored components
142
+ * (useful for debugging and analytics)
143
+ */
144
+ export function getPerformanceMetrics(): PerformanceMetrics[] {
145
+ // This would need to be implemented with a global store
146
+ // For now, this is a placeholder
147
+ return [];
148
+ }
149
+
@@ -11,7 +11,7 @@ export {
11
11
  createSlotComponent,
12
12
  useSlot,
13
13
  createSlotProps,
14
- } from './slots.tsx';
14
+ } from './slots';
15
15
 
16
16
  export type {
17
17
  SlotProps,
@@ -32,4 +32,4 @@ export type {
32
32
  DropdownRootSlotProps,
33
33
  DropdownToggleSlotProps,
34
34
  DropdownMenuSlotProps,
35
- } from './slots.tsx';
35
+ } from './slots';
@@ -59,7 +59,7 @@ export function renderSlot<T>(
59
59
  // Priority 2: component
60
60
  if (slotObj.component) {
61
61
  const Component = slotObj.component;
62
- return <Component {...props} />;
62
+ return <Component {...(props as any)} />;
63
63
  }
64
64
 
65
65
  // Priority 3: children
@@ -133,7 +133,7 @@ export function createSlotComponent<T>(
133
133
  return <Element {...(props as any)}>{children}</Element>;
134
134
  }
135
135
 
136
- const Component = defaultElement;
136
+ const Component = defaultElement as React.ComponentType<any>;
137
137
  return <Component {...slotProps}>{children}</Component>;
138
138
  };
139
139
  }
@@ -33,7 +33,7 @@ export function deepMerge<T extends Record<string, any>>(...objects: Partial<T>[
33
33
  if (!source) continue;
34
34
 
35
35
  for (const key in source) {
36
- if (!source.hasOwnProperty(key)) continue;
36
+ if (!Object.prototype.hasOwnProperty.call(source, key)) continue;
37
37
 
38
38
  const targetValue = result[key];
39
39
  const sourceValue = source[key];
@@ -538,9 +538,13 @@ export class ThemeEngine {
538
538
  /**
539
539
  * Add change listener
540
540
  */
541
+ // @ts-ignore - TypeScript overloads are valid, ESLint doesn't understand them
541
542
  on(event: 'change', listener: ThemeChangeListener): void;
543
+ // @ts-ignore
542
544
  on(event: 'load', listener: ThemeLoadListener): void;
545
+ // @ts-ignore
543
546
  on(event: 'error', listener: ThemeErrorListener): void;
547
+ // @ts-ignore
544
548
  on(event: 'revert', listener: ThemeRevertListener): void;
545
549
  on(
546
550
  event: 'change' | 'load' | 'error' | 'revert',
@@ -560,9 +564,13 @@ export class ThemeEngine {
560
564
  /**
561
565
  * Remove listener
562
566
  */
567
+ // @ts-ignore - TypeScript overloads are valid, ESLint doesn't understand them
563
568
  off(event: 'change', listener: ThemeChangeListener): void;
569
+ // @ts-ignore
564
570
  off(event: 'load', listener: ThemeLoadListener): void;
571
+ // @ts-ignore
565
572
  off(event: 'error', listener: ThemeErrorListener): void;
573
+ // @ts-ignore
566
574
  off(event: 'revert', listener: ThemeRevertListener): void;
567
575
  off(
568
576
  event: 'change' | 'load' | 'error' | 'revert',
@@ -392,8 +392,11 @@ export class ThemeValidator {
392
392
 
393
393
  for (let i = 0; i < numericEntries.length; i++) {
394
394
  for (let j = i + 1; j < numericEntries.length; j++) {
395
- const [keyA, valueA] = numericEntries[i];
396
- const [keyB, valueB] = numericEntries[j];
395
+ const entryA = numericEntries[i];
396
+ const entryB = numericEntries[j];
397
+ if (!entryA || !entryB) continue;
398
+ const [keyA, valueA] = entryA;
399
+ const [keyB, valueB] = entryB;
397
400
  const diff = Math.abs(valueA - valueB);
398
401
  if (diff < 10 && diff > 0) {
399
402
  warnings.push(
@@ -90,7 +90,7 @@ export const ThemeInspector: React.FC<ThemeInspectorProps> = ({
90
90
  }
91
91
 
92
92
  if (typeof value === 'string') {
93
- return <span className="value-string">"{value}"</span>;
93
+ return <span className="value-string">&quot;{value}&quot;</span>;
94
94
  }
95
95
 
96
96
  if (typeof value === 'number') {
@@ -59,19 +59,25 @@ export const ThemeLiveEditor: React.FC<ThemeLiveEditorProps> = ({
59
59
  }
60
60
  }, [onChange]);
61
61
 
62
- const handleColorChange = useCallback((path: string, value: string) => {
62
+ const handleColorChange = useCallback((path: string, value: string | number) => {
63
63
  const newTheme = { ...theme };
64
64
  const keys = path.split('.');
65
65
  let current: any = newTheme;
66
66
 
67
67
  for (let i = 0; i < keys.length - 1; i++) {
68
- if (!current[keys[i]]) {
69
- current[keys[i]] = {};
68
+ const key = keys[i];
69
+ if (key && !current[key]) {
70
+ current[key] = {};
71
+ }
72
+ if (key) {
73
+ current = current[key];
70
74
  }
71
- current = current[keys[i]];
72
75
  }
73
76
 
74
- current[keys[keys.length - 1]] = value;
77
+ const lastKey = keys[keys.length - 1];
78
+ if (lastKey) {
79
+ current[lastKey] = value;
80
+ }
75
81
  updateTheme(createTheme(newTheme));
76
82
  }, [theme, updateTheme]);
77
83
 
@@ -47,7 +47,7 @@ function flattenObject(
47
47
  result: Record<string, string> = {}
48
48
  ): Record<string, string> {
49
49
  for (const key in obj) {
50
- if (!obj.hasOwnProperty(key)) continue;
50
+ if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
51
51
 
52
52
  const value = obj[key];
53
53
  const newKey = prefix ? `${prefix}-${key}` : key;
@@ -93,7 +93,8 @@ export class RTLManager {
93
93
 
94
94
  // Try navigator.language first
95
95
  const lang: string = navigator.language || (navigator.languages && navigator.languages[0]) || 'en';
96
- return String(lang).split('-')[0].toLowerCase();
96
+ const langParts = String(lang).split('-');
97
+ return langParts[0] ? langParts[0].toLowerCase() : 'en';
97
98
  }
98
99
 
99
100
  /**
@@ -47,8 +47,8 @@ export class ThemeApplicator {
47
47
  }
48
48
 
49
49
  // Apply component overrides
50
- if (theme.components) {
51
- this.applyComponentOverrides(theme.components);
50
+ if ((theme as any).components) {
51
+ this.applyComponentOverrides((theme as any).components);
52
52
  }
53
53
  }
54
54
 
@@ -76,19 +76,25 @@ export class ThemeApplicator {
76
76
 
77
77
  if (typography.fontSize) {
78
78
  Object.entries(typography.fontSize).forEach(([key, value]) => {
79
- vars[`--atomix-font-size-${key}`] = value;
79
+ if (typeof value === 'string' || typeof value === 'number') {
80
+ vars[`--atomix-font-size-${key}`] = value;
81
+ }
80
82
  });
81
83
  }
82
84
 
83
85
  if (typography.fontWeight) {
84
86
  Object.entries(typography.fontWeight).forEach(([key, value]) => {
85
- vars[`--atomix-font-weight-${key}`] = value;
87
+ if (typeof value === 'string' || typeof value === 'number') {
88
+ vars[`--atomix-font-weight-${key}`] = value;
89
+ }
86
90
  });
87
91
  }
88
92
 
89
93
  if (typography.lineHeight) {
90
94
  Object.entries(typography.lineHeight).forEach(([key, value]) => {
91
- vars[`--atomix-line-height-${key}`] = value;
95
+ if (typeof value === 'string' || typeof value === 'number') {
96
+ vars[`--atomix-line-height-${key}`] = value;
97
+ }
92
98
  });
93
99
  }
94
100
 
@@ -98,12 +104,23 @@ export class ThemeApplicator {
98
104
  /**
99
105
  * Apply spacing system
100
106
  */
101
- private applySpacing(spacing: Record<string, string | number>): void {
107
+ private applySpacing(spacing: any): void {
102
108
  const vars: Record<string, string | number> = {};
103
109
 
104
- Object.entries(spacing).forEach(([key, value]) => {
105
- vars[`--atomix-space-${key}`] = value;
106
- });
110
+ // Handle spacing function or object
111
+ if (typeof spacing === 'function') {
112
+ // If spacing is a function, we can't iterate it directly
113
+ // Just skip for now as it's a special case
114
+ return;
115
+ }
116
+
117
+ if (typeof spacing === 'object' && spacing !== null) {
118
+ Object.entries(spacing).forEach(([key, value]) => {
119
+ if (typeof value === 'string' || typeof value === 'number') {
120
+ vars[`--atomix-space-${key}`] = value;
121
+ }
122
+ });
123
+ }
107
124
 
108
125
  this.applyGlobalCSSVars(vars);
109
126
  }
@@ -117,9 +134,9 @@ export class ThemeApplicator {
117
134
  const vars: Record<string, string | number> = {};
118
135
 
119
136
  Object.entries(palette).forEach(([colorName, colorScale]) => {
120
- if (colorScale) {
137
+ if (colorScale && typeof colorScale === 'object') {
121
138
  Object.entries(colorScale).forEach(([shade, value]) => {
122
- if (value) {
139
+ if (value && (typeof value === 'string' || typeof value === 'number')) {
123
140
  vars[`--atomix-color-${colorName}-${shade}`] = value;
124
141
  }
125
142
  });
@@ -148,7 +148,7 @@ export class ThemeErrorBoundary extends Component<
148
148
  };
149
149
  }
150
150
 
151
- componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
151
+ override componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
152
152
  // Log error
153
153
  const themeError = error instanceof ThemeError
154
154
  ? error
@@ -187,7 +187,7 @@ export class ThemeErrorBoundary extends Component<
187
187
  }
188
188
  }
189
189
 
190
- componentDidUpdate(prevProps: ThemeErrorBoundaryProps): void {
190
+ override componentDidUpdate(prevProps: ThemeErrorBoundaryProps): void {
191
191
  // Reset error if resetOnPropsChange is true and children changed
192
192
  if (
193
193
  this.props.resetOnPropsChange &&
@@ -202,7 +202,7 @@ export class ThemeErrorBoundary extends Component<
202
202
  }
203
203
  }
204
204
 
205
- render(): ReactNode {
205
+ override render(): ReactNode {
206
206
  if (this.state.hasError && this.state.error && this.state.errorInfo) {
207
207
  // Use custom fallback if provided
208
208
  if (this.props.fallback) {
@@ -289,9 +289,11 @@ export class ThemeManager {
289
289
  /**
290
290
  * Add event listener
291
291
  */
292
+ /* eslint-disable no-dupe-class-members */
292
293
  on(event: 'themeChange', callback: ThemeChangeCallback): void;
293
294
  on(event: 'themeLoad', callback: ThemeLoadCallback): void;
294
295
  on(event: 'themeError', callback: ThemeErrorCallback): void;
296
+ /* eslint-enable no-dupe-class-members */
295
297
  on(event: ThemeManagerEvent, callback: ThemeChangeCallback | ThemeLoadCallback | ThemeErrorCallback): void {
296
298
  if (event === 'themeChange') {
297
299
  this.eventListeners.themeChange.push(callback as ThemeChangeCallback);
@@ -305,9 +307,11 @@ export class ThemeManager {
305
307
  /**
306
308
  * Remove event listener
307
309
  */
310
+ /* eslint-disable no-dupe-class-members */
308
311
  off(event: 'themeChange', callback: ThemeChangeCallback): void;
309
312
  off(event: 'themeLoad', callback: ThemeLoadCallback): void;
310
313
  off(event: 'themeError', callback: ThemeErrorCallback): void;
314
+ /* eslint-enable no-dupe-class-members */
311
315
  off(event: ThemeManagerEvent, callback: ThemeChangeCallback | ThemeLoadCallback | ThemeErrorCallback): void {
312
316
  if (event === 'themeChange') {
313
317
  this.eventListeners.themeChange = this.eventListeners.themeChange.filter(cb => cb !== callback);
@@ -32,7 +32,7 @@ export function createDarkVariant(lightTheme: Theme): Theme {
32
32
  mode: 'dark',
33
33
  background: {
34
34
  default: '#121212',
35
- paper: '#1e1e1e',
35
+ subtle: '#1e1e1e',
36
36
  },
37
37
  text: {
38
38
  primary: '#ffffff',