@shohojdhara/atomix 0.3.6 → 0.3.8

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 (74) hide show
  1. package/README.md +3 -3
  2. package/dist/atomix.css +77 -0
  3. package/dist/atomix.css.map +1 -1
  4. package/dist/atomix.min.css +77 -0
  5. package/dist/atomix.min.css.map +1 -1
  6. package/dist/charts.js +50 -142
  7. package/dist/charts.js.map +1 -1
  8. package/dist/core.d.ts +2 -2
  9. package/dist/core.js +179 -274
  10. package/dist/core.js.map +1 -1
  11. package/dist/forms.js +50 -142
  12. package/dist/forms.js.map +1 -1
  13. package/dist/heavy.js +179 -274
  14. package/dist/heavy.js.map +1 -1
  15. package/dist/index.d.ts +1255 -1226
  16. package/dist/index.esm.js +2806 -2958
  17. package/dist/index.esm.js.map +1 -1
  18. package/dist/index.js +3113 -3269
  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/dist/theme.d.ts +313 -667
  23. package/dist/theme.js +1818 -2589
  24. package/dist/theme.js.map +1 -1
  25. package/package.json +1 -1
  26. package/src/components/AtomixGlass/AtomixGlass.tsx +128 -356
  27. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +1 -1
  28. package/src/components/Button/Button.tsx +85 -167
  29. package/src/components/DataTable/DataTable.stories.tsx +238 -0
  30. package/src/components/DataTable/DataTable.test.tsx +450 -0
  31. package/src/components/DataTable/DataTable.tsx +384 -61
  32. package/src/components/DatePicker/DatePicker.tsx +29 -38
  33. package/src/components/Upload/Upload.tsx +539 -40
  34. package/src/lib/composables/useAtomixGlass.ts +7 -7
  35. package/src/lib/composables/useDataTable.ts +355 -15
  36. package/src/lib/composables/useDatePicker.ts +19 -0
  37. package/src/lib/config/loader.ts +2 -3
  38. package/src/lib/constants/components.ts +17 -0
  39. package/src/lib/hooks/usePerformanceMonitor.ts +1 -1
  40. package/src/lib/theme/adapters/cssVariableMapper.ts +29 -14
  41. package/src/lib/theme/adapters/index.ts +1 -4
  42. package/src/lib/theme/config/configLoader.ts +82 -223
  43. package/src/lib/theme/config/loader.ts +15 -21
  44. package/src/lib/theme/constants/constants.ts +1 -1
  45. package/src/lib/theme/core/ThemeRegistry.ts +75 -279
  46. package/src/lib/theme/core/composeTheme.ts +30 -88
  47. package/src/lib/theme/core/createTheme.ts +88 -51
  48. package/src/lib/theme/core/createThemeObject.ts +2 -2
  49. package/src/lib/theme/core/index.ts +15 -2
  50. package/src/lib/theme/errors/errors.ts +1 -1
  51. package/src/lib/theme/generators/generateCSSNested.ts +131 -0
  52. package/src/lib/theme/generators/generateCSSVariables.ts +24 -16
  53. package/src/lib/theme/generators/index.ts +6 -0
  54. package/src/lib/theme/index.ts +45 -27
  55. package/src/lib/theme/runtime/ThemeApplicator.ts +6 -109
  56. package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +1 -1
  57. package/src/lib/theme/runtime/ThemeProvider.tsx +393 -544
  58. package/src/lib/theme/runtime/index.ts +1 -0
  59. package/src/lib/theme/runtime/useTheme.ts +1 -1
  60. package/src/lib/theme/runtime/useThemeTokens.ts +122 -0
  61. package/src/lib/theme/test/testTheme.ts +2 -1
  62. package/src/lib/theme/types.ts +14 -14
  63. package/src/lib/theme/utils/componentTheming.ts +140 -0
  64. package/src/lib/theme/utils/domUtils.ts +57 -15
  65. package/src/lib/theme/utils/injectCSS.ts +0 -1
  66. package/src/lib/theme/utils/naming.ts +100 -0
  67. package/src/lib/theme/utils/themeHelpers.ts +1 -39
  68. package/src/lib/theme/utils/themeUtils.ts +1 -170
  69. package/src/lib/types/components.ts +145 -0
  70. package/src/lib/utils/componentUtils.ts +1 -1
  71. package/src/lib/utils/dataTableExport.ts +143 -0
  72. package/src/lib/utils/memoryMonitor.ts +3 -3
  73. package/src/lib/utils/themeNaming.ts +135 -0
  74. package/src/styles/06-components/_components.data-table.scss +95 -0
@@ -5,7 +5,7 @@
5
5
  * spacing helpers, and theme value accessors.
6
6
  */
7
7
 
8
- import type { Theme, SpacingFunction, SpacingOptions } from '../types';
8
+ import type { SpacingFunction, SpacingOptions } from '../types';
9
9
 
10
10
  // ============================================================================
11
11
  // Color Manipulation Utilities
@@ -184,172 +184,3 @@ export function createSpacing(spacingInput: SpacingOptions = 4): SpacingFunction
184
184
  };
185
185
  }
186
186
 
187
- /**
188
- * Get spacing value from theme
189
- *
190
- * @param theme - Theme object
191
- * @param values - Spacing multipliers
192
- * @returns Spacing string
193
- */
194
- export function spacing(theme: Theme, ...values: number[]): string {
195
- return theme.spacing(...values);
196
- }
197
-
198
- // ============================================================================
199
- // Theme Value Accessors
200
- // ============================================================================
201
-
202
- /**
203
- * Safely get a nested value from theme using dot notation
204
- *
205
- * @param theme - Theme object
206
- * @param path - Dot-notation path (e.g., 'palette.primary.main')
207
- * @param fallback - Fallback value if path not found
208
- * @returns Theme value or fallback
209
- */
210
- export function getThemeValue<T = any>(theme: Theme, path: string, fallback?: T): T {
211
- const keys = path.split('.');
212
- let value: any = theme;
213
-
214
- for (const key of keys) {
215
- if (value && typeof value === 'object' && key in value) {
216
- value = value[key];
217
- } else {
218
- return fallback as T;
219
- }
220
- }
221
-
222
- return value as T;
223
- }
224
-
225
- /**
226
- * Check if a theme is a JS theme (created with createTheme)
227
- */
228
- export function isJSTheme(theme: any): theme is Theme {
229
- return theme && typeof theme === 'object' && theme.__isJSTheme === true;
230
- }
231
-
232
- // ============================================================================
233
- // Responsive Utilities
234
- // ============================================================================
235
-
236
- /**
237
- * Get media query for breakpoint up
238
- */
239
- export function breakpointUp(theme: Theme, key: keyof Theme['breakpoints']['values'] | number): string {
240
- return theme.breakpoints.up(key);
241
- }
242
-
243
- /**
244
- * Get media query for breakpoint down
245
- */
246
- export function breakpointDown(theme: Theme, key: keyof Theme['breakpoints']['values'] | number): string {
247
- return theme.breakpoints.down(key);
248
- }
249
-
250
- /**
251
- * Get media query for breakpoint between
252
- */
253
- export function breakpointBetween(
254
- theme: Theme,
255
- start: keyof Theme['breakpoints']['values'] | number,
256
- end: keyof Theme['breakpoints']['values'] | number
257
- ): string {
258
- return theme.breakpoints.between(start, end);
259
- }
260
-
261
- // ============================================================================
262
- // Typography Utilities
263
- // ============================================================================
264
-
265
- /**
266
- * Get typography variant styles
267
- */
268
- export function getTypography(theme: Theme, variant: keyof Theme['typography']): any {
269
- return theme.typography[variant] ?? {};
270
- }
271
-
272
- /**
273
- * Convert rem to px based on theme font size
274
- */
275
- export function remToPx(theme: Theme, rem: number): number {
276
- return rem * theme.typography.fontSize;
277
- }
278
-
279
- /**
280
- * Convert px to rem based on theme font size
281
- */
282
- export function pxToRem(theme: Theme, px: number): string {
283
- return `${px / theme.typography.fontSize}rem`;
284
- }
285
-
286
- // ============================================================================
287
- // Shadow Utilities
288
- // ============================================================================
289
-
290
- /**
291
- * Get shadow value from theme
292
- */
293
- export function getShadow(theme: Theme, level: keyof Theme['shadows']): string {
294
- return theme.shadows[level] || 'none';
295
- }
296
-
297
- // ============================================================================
298
- // Transition Utilities
299
- // ============================================================================
300
-
301
- /**
302
- * Create a transition string
303
- */
304
- export function createTransition(
305
- theme: Theme,
306
- props: string | string[],
307
- options?: {
308
- duration?: keyof Theme['transitions']['duration'] | number;
309
- easing?: keyof Theme['transitions']['easing'] | string;
310
- delay?: number;
311
- }
312
- ): string {
313
- const properties = Array.isArray(props) ? props : [props];
314
- const duration =
315
- typeof options?.duration === 'number'
316
- ? options.duration
317
- : theme.transitions.duration[options?.duration || 'standard'];
318
- const easing =
319
- typeof options?.easing === 'string' && !options.easing.includes('(')
320
- ? theme.transitions.easing[options.easing as keyof Theme['transitions']['easing']]
321
- : options?.easing || theme.transitions.easing.easeInOut;
322
- const delay = options?.delay || 0;
323
-
324
- return properties
325
- .map((prop) => `${prop} ${duration}ms ${easing}${delay ? ` ${delay}ms` : ''}`)
326
- .join(', ');
327
- }
328
-
329
- /**
330
- * Get transition duration
331
- */
332
- export function getTransitionDuration(
333
- theme: Theme,
334
- key: keyof Theme['transitions']['duration']
335
- ): number {
336
- return theme.transitions.duration[key] ?? 300;
337
- }
338
-
339
- /**
340
- * Get transition easing
341
- */
342
- export function getTransitionEasing(theme: Theme, key: keyof Theme['transitions']['easing']): string {
343
- return theme.transitions.easing[key] ?? 'cubic-bezier(0.4, 0, 0.2, 1)';
344
- }
345
-
346
- // ============================================================================
347
- // Z-Index Utilities
348
- // ============================================================================
349
-
350
- /**
351
- * Get z-index value from theme
352
- */
353
- export function getZIndex(theme: Theme, key: keyof Theme['zIndex']): number {
354
- return theme.zIndex[key] ?? 0;
355
- }
@@ -1644,6 +1644,46 @@ export interface DataTableColumn {
1644
1644
  * Width of the column (CSS value)
1645
1645
  */
1646
1646
  width?: string;
1647
+
1648
+ /**
1649
+ * Minimum width for resizable columns (CSS value)
1650
+ */
1651
+ minWidth?: string;
1652
+
1653
+ /**
1654
+ * Maximum width for resizable columns (CSS value)
1655
+ */
1656
+ maxWidth?: string;
1657
+
1658
+ /**
1659
+ * Whether the column is resizable
1660
+ */
1661
+ resizable?: boolean;
1662
+
1663
+ /**
1664
+ * Whether the column is visible by default
1665
+ */
1666
+ visible?: boolean;
1667
+
1668
+ /**
1669
+ * Whether the column can be reordered
1670
+ */
1671
+ reorderable?: boolean;
1672
+
1673
+ /**
1674
+ * Custom filter function for column-specific filtering
1675
+ */
1676
+ filterFunction?: (value: any, filterValue: string) => boolean;
1677
+
1678
+ /**
1679
+ * Filter type for column-specific filtering
1680
+ */
1681
+ filterType?: 'text' | 'select' | 'date' | 'number' | 'custom';
1682
+
1683
+ /**
1684
+ * Options for select-type filters
1685
+ */
1686
+ filterOptions?: Array<{ label: string; value: any }>;
1647
1687
  }
1648
1688
 
1649
1689
  /**
@@ -1661,6 +1701,16 @@ export interface SortConfig {
1661
1701
  direction: 'asc' | 'desc';
1662
1702
  }
1663
1703
 
1704
+ /**
1705
+ * Row selection mode
1706
+ */
1707
+ export type SelectionMode = 'single' | 'multiple' | 'none';
1708
+
1709
+ /**
1710
+ * Export format
1711
+ */
1712
+ export type ExportFormat = 'csv' | 'excel' | 'json';
1713
+
1664
1714
  /**
1665
1715
  * DataTable component properties
1666
1716
  */
@@ -1735,6 +1785,101 @@ export interface DataTableProps extends BaseComponentProps {
1735
1785
  * Can be a boolean to enable with default settings, or an object with AtomixGlassProps to customize the effect
1736
1786
  */
1737
1787
  glass?: AtomixGlassProps | boolean;
1788
+
1789
+ /**
1790
+ * Row selection mode ('single', 'multiple', or 'none')
1791
+ */
1792
+ selectionMode?: SelectionMode;
1793
+
1794
+ /**
1795
+ * Selected row IDs (for controlled selection)
1796
+ */
1797
+ selectedRowIds?: (string | number)[];
1798
+
1799
+ /**
1800
+ * Callback when selection changes
1801
+ */
1802
+ onSelectionChange?: (selectedRows: any[], selectedIds: (string | number)[]) => void;
1803
+
1804
+ /**
1805
+ * Key to use as unique identifier for rows (defaults to 'id')
1806
+ */
1807
+ rowKey?: string | ((row: any) => string | number);
1808
+
1809
+ /**
1810
+ * Whether columns are resizable
1811
+ */
1812
+ resizable?: boolean;
1813
+
1814
+ /**
1815
+ * Whether columns can be reordered
1816
+ */
1817
+ reorderable?: boolean;
1818
+
1819
+ /**
1820
+ * Callback when column order changes
1821
+ */
1822
+ onColumnReorder?: (columnKeys: string[]) => void;
1823
+
1824
+ /**
1825
+ * Whether to show column visibility toggle
1826
+ */
1827
+ showColumnVisibility?: boolean;
1828
+
1829
+ /**
1830
+ * Callback when column visibility changes
1831
+ */
1832
+ onColumnVisibilityChange?: (visibleColumns: string[]) => void;
1833
+
1834
+ /**
1835
+ * Whether to enable sticky headers
1836
+ */
1837
+ stickyHeader?: boolean;
1838
+
1839
+ /**
1840
+ * Offset from top for sticky headers (CSS value)
1841
+ */
1842
+ stickyHeaderOffset?: string;
1843
+
1844
+ /**
1845
+ * Whether to enable virtual scrolling for large datasets
1846
+ */
1847
+ virtualScrolling?: boolean;
1848
+
1849
+ /**
1850
+ * Estimated row height for virtual scrolling (in pixels)
1851
+ */
1852
+ estimatedRowHeight?: number;
1853
+
1854
+ /**
1855
+ * Number of rows to render outside visible area (overscan)
1856
+ */
1857
+ overscan?: number;
1858
+
1859
+ /**
1860
+ * Whether to enable export functionality
1861
+ */
1862
+ exportable?: boolean;
1863
+
1864
+ /**
1865
+ * Export formats available
1866
+ */
1867
+ exportFormats?: ExportFormat[];
1868
+
1869
+ /**
1870
+ * Custom export filename
1871
+ */
1872
+ exportFilename?: string;
1873
+
1874
+ /**
1875
+ * Callback for custom export logic
1876
+ */
1877
+ onExport?: (format: ExportFormat, data: any[]) => void;
1878
+
1879
+ /**
1880
+ * Whether to show column-specific filters
1881
+ */
1882
+ columnFilters?: boolean;
1738
1883
  }
1739
1884
 
1740
1885
  /**
@@ -114,7 +114,7 @@ export function hasCustomization(props: {
114
114
  * Create data attributes for debugging
115
115
  */
116
116
  export function createDebugAttrs(componentName: string, variant?: string): Record<string, string> {
117
- if (process.env.NODE_ENV !== 'development') return {};
117
+ if (typeof process === 'undefined' || process.env?.NODE_ENV !== 'development') return {};
118
118
 
119
119
  return {
120
120
  'data-component': componentName,
@@ -0,0 +1,143 @@
1
+ import { DataTableColumn, ExportFormat } from '../types/components';
2
+
3
+ /**
4
+ * Sanitize cell content to prevent CSV injection
5
+ */
6
+ function sanitizeCSVCell(cell: any): string {
7
+ const sanitized = String(cell ?? '').replace(/[\r\n\t]/g, ' ').replace(/"/g, '""');
8
+ // Prevent formula injection by prefixing dangerous characters
9
+ const dangerous = /^[=+\-@]/;
10
+ return dangerous.test(sanitized) ? `'${sanitized}` : sanitized;
11
+ }
12
+
13
+ /**
14
+ * Export data as CSV
15
+ */
16
+ export function exportToCSV(
17
+ data: any[],
18
+ columns: DataTableColumn[],
19
+ filename: string = 'data-table.csv'
20
+ ): void {
21
+ if (!data.length || !columns.length) return;
22
+
23
+ // Create headers
24
+ const headers = columns.map(col => col.title || col.key);
25
+
26
+ // Create rows
27
+ const rows = data.map(row => {
28
+ return columns.map(col => {
29
+ const value = row[col.key];
30
+ if (col.render) {
31
+ // For rendered cells, try to extract text content
32
+ // This is a simplified approach - in production you might want to handle React elements differently
33
+ return value ?? '';
34
+ }
35
+ return value ?? '';
36
+ });
37
+ });
38
+
39
+ // Convert to CSV string
40
+ const csvContent = [
41
+ headers.map(h => `"${sanitizeCSVCell(h)}"`).join(','),
42
+ ...rows.map(row => row.map(cell => `"${sanitizeCSVCell(cell)}"`).join(',')),
43
+ ].join('\n');
44
+
45
+ // Download
46
+ const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
47
+ const url = URL.createObjectURL(blob);
48
+ const link = document.createElement('a');
49
+ link.download = filename.endsWith('.csv') ? filename : `${filename}.csv`;
50
+ link.href = url;
51
+ link.click();
52
+ URL.revokeObjectURL(url);
53
+ }
54
+
55
+ /**
56
+ * Export data as JSON
57
+ */
58
+ export function exportToJSON(
59
+ data: any[],
60
+ filename: string = 'data-table.json'
61
+ ): void {
62
+ if (!data.length) return;
63
+
64
+ const jsonContent = JSON.stringify(data, null, 2);
65
+ const blob = new Blob([jsonContent], { type: 'application/json;charset=utf-8;' });
66
+ const url = URL.createObjectURL(blob);
67
+ const link = document.createElement('a');
68
+ link.download = filename.endsWith('.json') ? filename : `${filename}.json`;
69
+ link.href = url;
70
+ link.click();
71
+ URL.revokeObjectURL(url);
72
+ }
73
+
74
+ /**
75
+ * Export data as Excel (XLSX) - simplified version using CSV with .xlsx extension
76
+ * Note: For true Excel format, you would need a library like xlsx or exceljs
77
+ */
78
+ export function exportToExcel(
79
+ data: any[],
80
+ columns: DataTableColumn[],
81
+ filename: string = 'data-table.xlsx'
82
+ ): void {
83
+ // For now, we'll export as CSV but with .xlsx extension
84
+ // In a production environment, you'd want to use a library like 'xlsx' or 'exceljs'
85
+ // to create a proper Excel file
86
+ if (!data.length || !columns.length) return;
87
+
88
+ // Create headers
89
+ const headers = columns.map(col => col.title || col.key);
90
+
91
+ // Create rows
92
+ const rows = data.map(row => {
93
+ return columns.map(col => {
94
+ const value = row[col.key];
95
+ return value ?? '';
96
+ });
97
+ });
98
+
99
+ // Convert to CSV format (Excel can open CSV files)
100
+ const csvContent = [
101
+ headers.map(h => `"${sanitizeCSVCell(h)}"`).join(','),
102
+ ...rows.map(row => row.map(cell => `"${sanitizeCSVCell(cell)}"`).join(',')),
103
+ ].join('\n');
104
+
105
+ // Download with .xlsx extension (though it's actually CSV)
106
+ // In production, use a proper Excel library
107
+ const blob = new Blob([csvContent], {
108
+ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
109
+ });
110
+ const url = URL.createObjectURL(blob);
111
+ const link = document.createElement('a');
112
+ link.download = filename.endsWith('.xlsx') ? filename : `${filename}.xlsx`;
113
+ link.href = url;
114
+ link.click();
115
+ URL.revokeObjectURL(url);
116
+ }
117
+
118
+ /**
119
+ * Export data in the specified format
120
+ */
121
+ export function exportData(
122
+ format: ExportFormat,
123
+ data: any[],
124
+ columns: DataTableColumn[],
125
+ filename?: string
126
+ ): void {
127
+ const defaultFilename = filename || 'data-table';
128
+
129
+ switch (format) {
130
+ case 'csv':
131
+ exportToCSV(data, columns, defaultFilename);
132
+ break;
133
+ case 'excel':
134
+ exportToExcel(data, columns, defaultFilename);
135
+ break;
136
+ case 'json':
137
+ exportToJSON(data, defaultFilename);
138
+ break;
139
+ default:
140
+ console.warn(`Unsupported export format: ${format}`);
141
+ }
142
+ }
143
+
@@ -34,7 +34,7 @@ export function isMemoryMonitoringAvailable(): boolean {
34
34
  return (
35
35
  typeof performance !== 'undefined' &&
36
36
  'memory' in performance &&
37
- process.env.NODE_ENV === 'development'
37
+ (typeof process === 'undefined' || process.env?.NODE_ENV === 'development')
38
38
  );
39
39
  }
40
40
 
@@ -133,7 +133,7 @@ export function monitorMemoryUsage(
133
133
  if (snapshot) {
134
134
  if (callback) {
135
135
  callback(snapshot);
136
- } else if (process.env.NODE_ENV === 'development') {
136
+ } else if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'development') {
137
137
  console.log('[Memory Monitor]', {
138
138
  used: formatBytes(snapshot.usedJSHeapSize),
139
139
  total: formatBytes(snapshot.totalJSHeapSize),
@@ -175,7 +175,7 @@ export function trackComponentMemory(componentName: string) {
175
175
  const after = getMemorySnapshot();
176
176
  if (before && after) {
177
177
  const leakInfo = detectMemoryLeak(before, after);
178
- if (leakInfo.hasLeak && process.env.NODE_ENV === 'development') {
178
+ if (leakInfo.hasLeak && (typeof process === 'undefined' || process.env?.NODE_ENV === 'development')) {
179
179
  console.warn(
180
180
  `[Memory Monitor] Potential memory leak detected in ${componentName}:`,
181
181
  leakInfo
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Theme Naming Utility
3
+ *
4
+ * Provides consistent naming conventions for CSS classes, CSS variables,
5
+ * and JavaScript properties throughout the theme system.
6
+ */
7
+
8
+ export class ThemeNaming {
9
+ private static prefix = 'atomix';
10
+
11
+ /**
12
+ * Set the global prefix for all theme tokens
13
+ * @param newPrefix - New prefix to use
14
+ */
15
+ static setPrefix(newPrefix: string): void {
16
+ this.prefix = newPrefix;
17
+ }
18
+
19
+ /**
20
+ * Get the current prefix
21
+ */
22
+ static getPrefix(): string {
23
+ return this.prefix;
24
+ }
25
+
26
+ /**
27
+ * Convert camelCase to kebab-case for CSS variables
28
+ * @param str - String to convert
29
+ */
30
+ static camelToKebab(str: string): string {
31
+ return str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2').toLowerCase();
32
+ }
33
+
34
+ /**
35
+ * Convert kebab-case to camelCase for JavaScript properties
36
+ * @param str - String to convert
37
+ */
38
+ static kebabToCamel(str: string): string {
39
+ return str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
40
+ }
41
+
42
+ /**
43
+ * Create a CSS variable name
44
+ * @param token - Token name in camelCase
45
+ */
46
+ static cssVar(token: string): string {
47
+ return `--${this.prefix}-${this.camelToKebab(token)}`;
48
+ }
49
+
50
+ /**
51
+ * Create a BEM CSS class name
52
+ * @param block - Block name
53
+ * @param element - Element name (optional)
54
+ * @param modifier - Modifier name (optional)
55
+ */
56
+ static bemClass(block: string, element?: string, modifier?: string): string {
57
+ let className = `c-${block}`;
58
+
59
+ if (element) {
60
+ className += `__${element}`;
61
+ }
62
+
63
+ if (modifier) {
64
+ className += `--${modifier}`;
65
+ }
66
+
67
+ return className;
68
+ }
69
+
70
+ /**
71
+ * Create a variant class name
72
+ * @param component - Component name
73
+ * @param variant - Variant name
74
+ */
75
+ static variantClass(component: string, variant: string): string {
76
+ return `c-${component}--${variant}`;
77
+ }
78
+
79
+ /**
80
+ * Create a size class name
81
+ * @param component - Component name
82
+ * @param size - Size name
83
+ */
84
+ static sizeClass(component: string, size: string): string {
85
+ return `c-${component}--${size}`;
86
+ }
87
+
88
+ /**
89
+ * Create a state class name
90
+ * @param component - Component name
91
+ * @param state - State name
92
+ */
93
+ static stateClass(component: string, state: string): string {
94
+ return `c-${component}--${state}`;
95
+ }
96
+
97
+ /**
98
+ * Create a utility class name
99
+ * @param utility - Utility name
100
+ */
101
+ static utilityClass(utility: string): string {
102
+ return `u-${utility}`;
103
+ }
104
+
105
+ /**
106
+ * Create a layout class name
107
+ * @param layout - Layout name
108
+ */
109
+ static layoutClass(layout: string): string {
110
+ return `l-${layout}`;
111
+ }
112
+
113
+ /**
114
+ * Create an object class name
115
+ * @param object - Object name
116
+ */
117
+ static objectClass(object: string): string {
118
+ return `o-${object}`;
119
+ }
120
+ }
121
+
122
+ // Export constants for common naming patterns
123
+ export const THEME_NAMING = {
124
+ PREFIX: 'atomix',
125
+ CSS_VAR: ThemeNaming.cssVar,
126
+ BEM_CLASS: ThemeNaming.bemClass,
127
+ VARIANT_CLASS: ThemeNaming.variantClass,
128
+ SIZE_CLASS: ThemeNaming.sizeClass,
129
+ STATE_CLASS: ThemeNaming.stateClass,
130
+ UTILITY_CLASS: ThemeNaming.utilityClass,
131
+ LAYOUT_CLASS: ThemeNaming.layoutClass,
132
+ OBJECT_CLASS: ThemeNaming.objectClass,
133
+ CAMEL_TO_KEBAB: ThemeNaming.camelToKebab,
134
+ KEBAB_TO_CAMEL: ThemeNaming.kebabToCamel,
135
+ };