@shohojdhara/atomix 0.6.1 → 0.6.3

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 (67) hide show
  1. package/README.md +510 -106
  2. package/dist/atomix.css +30 -24
  3. package/dist/atomix.css.map +1 -1
  4. package/dist/atomix.min.css +6 -6
  5. package/dist/atomix.min.css.map +1 -1
  6. package/dist/atomix.umd.js +1 -1
  7. package/dist/atomix.umd.js.map +1 -1
  8. package/dist/atomix.umd.min.js +1 -1
  9. package/dist/charts.d.ts +11 -2
  10. package/dist/charts.js +294 -139
  11. package/dist/charts.js.map +1 -1
  12. package/dist/core.d.ts +14 -39
  13. package/dist/core.js +297 -145
  14. package/dist/core.js.map +1 -1
  15. package/dist/forms.d.ts +11 -1
  16. package/dist/forms.js +385 -185
  17. package/dist/forms.js.map +1 -1
  18. package/dist/heavy.d.ts +9 -0
  19. package/dist/heavy.js +297 -143
  20. package/dist/heavy.js.map +1 -1
  21. package/dist/index.d.ts +156 -164
  22. package/dist/index.esm.js +391 -203
  23. package/dist/index.esm.js.map +1 -1
  24. package/dist/index.js +391 -203
  25. package/dist/index.js.map +1 -1
  26. package/dist/index.min.js +1 -1
  27. package/dist/index.min.js.map +1 -1
  28. package/dist/theme.d.ts +14 -6
  29. package/dist/theme.js +2 -9
  30. package/dist/theme.js.map +1 -1
  31. package/package.json +26 -26
  32. package/src/components/AtomixGlass/AtomixGlass.tsx +1 -1
  33. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +8 -1
  34. package/src/components/AtomixGlass/deprecated/AtomixGlass.deprecated.tsx +390 -0
  35. package/src/components/AtomixGlass/glass-utils.ts +29 -0
  36. package/src/components/AtomixGlass/stories/Playground.stories.tsx +32 -1
  37. package/src/components/Button/Button.stories.tsx +1 -1
  38. package/src/components/Button/Button.tsx +6 -5
  39. package/src/components/Card/Card.tsx +2 -2
  40. package/src/components/Dropdown/Dropdown.tsx +1 -0
  41. package/src/components/EdgePanel/EdgePanel.tsx +1 -3
  42. package/src/components/Form/Select.test.tsx +75 -0
  43. package/src/components/Form/Select.tsx +348 -252
  44. package/src/components/Form/SelectOption.tsx +16 -10
  45. package/src/components/index.ts +1 -1
  46. package/src/layouts/CssGrid/index.ts +1 -0
  47. package/src/lib/composables/shared-mouse-tracker.ts +62 -6
  48. package/src/lib/composables/useAtomixGlass.ts +241 -139
  49. package/src/lib/composables/useAtomixGlassStyles.ts +201 -149
  50. package/src/lib/constants/components.ts +54 -35
  51. package/src/lib/theme/config/configLoader.ts +1 -1
  52. package/src/lib/theme/test/testTheme.ts +2 -2
  53. package/src/lib/theme/utils/themeUtils.ts +98 -110
  54. package/src/lib/types/components.ts +29 -65
  55. package/src/styles/01-settings/_settings.spacing.scss +6 -1
  56. package/src/styles/03-generic/_generic.reset.scss +1 -1
  57. package/src/styles/06-components/_components.atomix-glass.scss +20 -29
  58. package/src/styles/06-components/_components.data-table.scss +5 -4
  59. package/src/styles/06-components/_components.dynamic-background.scss +9 -8
  60. package/src/styles/06-components/_components.footer.scss +8 -7
  61. package/src/styles/06-components/_components.hero.scss +2 -2
  62. package/src/styles/06-components/_components.messages.scss +16 -16
  63. package/src/styles/06-components/_components.navbar.scss +2 -0
  64. package/src/styles/06-components/_components.select.scss +15 -2
  65. package/src/styles/06-components/_components.upload.scss +3 -3
  66. package/CHANGELOG.md +0 -165
  67. package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +0 -215
@@ -219,7 +219,7 @@ export async function loadThemeFromConfig(options?: { configPath?: string; requi
219
219
  const req = typeof require !== 'undefined' ? require : undefined;
220
220
  if (!req) throw new Error('require is not available');
221
221
  const { loadAtomixConfig: loader } = req('../../config/loader');
222
- loadAtomixConfig = loader;
222
+ const loadAtomixConfig: any = loader;
223
223
  config = loadAtomixConfig({ configPath: options?.configPath, required: options?.required !== false });
224
224
  } catch (error) {
225
225
  // If loadAtomixConfig is not available (e.g., in browser bundle), provide helpful error
@@ -9,7 +9,7 @@ import type { DesignTokens } from '../tokens/tokens';
9
9
  import type { Theme, ThemeOptions } from '../types';
10
10
  import { createTheme } from '../core/createTheme';
11
11
  import { createThemeObject } from '../core/createThemeObject';
12
- import { themeToDesignTokens, createDesignTokensFromTheme } from '../adapters/themeAdapter';
12
+ import { themeToDesignTokens } from '../adapters/themeAdapter';
13
13
 
14
14
  // ============================================================================
15
15
  // Test Theme 1: Using DesignTokens (Recommended - Flat Structure)
@@ -311,7 +311,7 @@ export function testThemeAdapter(): {
311
311
  } {
312
312
  const theme = createTestThemeObject();
313
313
  const tokens = themeToDesignTokens(theme);
314
- const fullTokens = createDesignTokensFromTheme(theme);
314
+ const fullTokens = themeToDesignTokens(theme);
315
315
 
316
316
  return {
317
317
  theme,
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Theme Utilities
3
- *
3
+ *
4
4
  * Helper functions for common theme operations including:
5
5
  * - Theme switching (dark/light mode)
6
6
  * - Theme persistence (localStorage)
@@ -13,6 +13,8 @@ import type { DesignTokens } from '../tokens';
13
13
  import type { SpacingFunction, SpacingOptions } from '../types';
14
14
  import { injectCSS, removeCSS } from '../utils/injectCSS';
15
15
  import { deepMerge } from '../core/composeTheme';
16
+ import { getSystemTheme } from './domUtils';
17
+ export { getSystemTheme };
16
18
 
17
19
  // ============================================================================
18
20
  // Type Definitions
@@ -44,28 +46,25 @@ export interface ThemePersistenceOptions {
44
46
 
45
47
  /**
46
48
  * Switch between light and dark themes
47
- *
49
+ *
48
50
  * Automatically toggles a class on the root element and persists the choice.
49
- *
51
+ *
50
52
  * @param mode - Theme mode ('light', 'dark', or 'system')
51
53
  * @param options - Configuration options
52
- *
54
+ *
53
55
  * @example
54
56
  * ```typescript
55
57
  * import { switchTheme } from '@shohojdhara/atomix/theme/utils';
56
- *
58
+ *
57
59
  * // Switch to dark mode
58
60
  * switchTheme('dark');
59
- *
61
+ *
60
62
  * // Toggle between light/dark
61
63
  * const current = getCurrentTheme();
62
64
  * switchTheme(current === 'dark' ? 'light' : 'dark');
63
65
  * ```
64
66
  */
65
- export function switchTheme(
66
- mode: ThemeMode,
67
- options: ThemeSwitcherOptions = {}
68
- ): void {
67
+ export function switchTheme(mode: ThemeMode, options: ThemeSwitcherOptions = {}): void {
69
68
  const {
70
69
  selector = ':root',
71
70
  storageKey = 'atomix-theme',
@@ -84,7 +83,7 @@ export function switchTheme(
84
83
  if (enableTransition) {
85
84
  const htmlRoot = root as HTMLElement;
86
85
  htmlRoot.style.transition = `all ${transitionDuration}ms ease-in-out`;
87
-
86
+
88
87
  // Remove transition after it completes
89
88
  setTimeout(() => {
90
89
  htmlRoot.style.transition = '';
@@ -102,17 +101,19 @@ export function switchTheme(
102
101
  persistTheme(resolvedMode, { storageKey });
103
102
 
104
103
  // Dispatch custom event for listeners
105
- window.dispatchEvent(new CustomEvent('atomix-theme-change', {
106
- detail: { mode: resolvedMode }
107
- }));
104
+ window.dispatchEvent(
105
+ new CustomEvent('atomix-theme-change', {
106
+ detail: { mode: resolvedMode },
107
+ })
108
+ );
108
109
  }
109
110
 
110
111
  /**
111
112
  * Toggle between light and dark themes
112
- *
113
+ *
113
114
  * @param options - Configuration options
114
115
  * @returns The new theme mode
115
- *
116
+ *
116
117
  * @example
117
118
  * ```typescript
118
119
  * const newMode = toggleTheme();
@@ -128,56 +129,44 @@ export function toggleTheme(options: ThemeSwitcherOptions = {}): ThemeMode {
128
129
 
129
130
  /**
130
131
  * Get current theme mode
131
- *
132
+ *
132
133
  * @param storageKey - Storage key (default: 'atomix-theme')
133
134
  * @returns Current theme mode or 'light' if not set
134
135
  */
135
136
  export function getCurrentTheme(storageKey: string = 'atomix-theme'): ThemeMode {
136
137
  if (typeof window === 'undefined') return 'light';
137
-
138
+
138
139
  const stored = localStorage.getItem(storageKey);
139
140
  return (stored as ThemeMode) || 'light';
140
141
  }
141
142
 
142
- /**
143
- * Get system theme preference
144
- *
145
- * @returns 'dark' if system prefers dark mode, 'light' otherwise
146
- */
147
- export function getSystemTheme(): ThemeMode {
148
- if (typeof window === 'undefined') return 'light';
149
-
150
- const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
151
- return prefersDark ? 'dark' : 'light';
152
- }
153
-
154
143
  /**
155
144
  * Initialize theme based on saved preference or system preference
156
- *
145
+ *
157
146
  * Call this once at app startup.
158
- *
147
+ *
159
148
  * @param options - Configuration options
160
149
  * @returns The initialized theme mode
161
- *
150
+ *
162
151
  * @example
163
152
  * ```typescript
164
153
  * // In your app entry point
165
154
  * import { initializeTheme } from '@shohojdhara/atomix/theme/utils';
166
- *
155
+ *
167
156
  * const theme = initializeTheme();
168
157
  * console.log('Theme initialized:', theme);
169
158
  * ```
170
159
  */
171
160
  export function initializeTheme(options: ThemeSwitcherOptions = {}): ThemeMode {
172
161
  const saved = getCurrentTheme(options.storageKey);
173
-
162
+
174
163
  // If no saved preference, use system preference
175
164
  if (!saved || saved === 'system') {
176
165
  const system = getSystemTheme();
177
166
  switchTheme(system, options);
178
167
  return system;
179
168
  }
180
-
169
+
181
170
  // Use saved preference
182
171
  switchTheme(saved, options);
183
172
  return saved;
@@ -185,36 +174,36 @@ export function initializeTheme(options: ThemeSwitcherOptions = {}): ThemeMode {
185
174
 
186
175
  /**
187
176
  * Listen for system theme changes
188
- *
177
+ *
189
178
  * @param callback - Function to call when system theme changes
190
179
  * @returns Cleanup function to stop listening
191
- *
180
+ *
192
181
  * @example
193
182
  * ```typescript
194
183
  * const cleanup = listenToSystemTheme((mode) => {
195
184
  * console.log('System theme changed to:', mode);
196
185
  * switchTheme(mode);
197
186
  * });
198
- *
187
+ *
199
188
  * // Later, when component unmounts
200
189
  * cleanup();
201
190
  * ```
202
191
  */
203
192
  export function listenToSystemTheme(callback: (mode: ThemeMode) => void): () => void {
204
193
  if (typeof window === 'undefined') return () => {};
205
-
194
+
206
195
  const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
207
-
196
+
208
197
  const handler = (e: MediaQueryListEvent) => {
209
198
  callback(e.matches ? 'dark' : 'light');
210
199
  };
211
-
200
+
212
201
  // Modern browsers
213
202
  if (mediaQuery.addEventListener) {
214
203
  mediaQuery.addEventListener('change', handler);
215
204
  return () => mediaQuery.removeEventListener('change', handler);
216
205
  }
217
-
206
+
218
207
  // Fallback for older browsers
219
208
  mediaQuery.addListener(handler);
220
209
  return () => mediaQuery.removeListener(handler);
@@ -226,38 +215,29 @@ export function listenToSystemTheme(callback: (mode: ThemeMode) => void): () =>
226
215
 
227
216
  /**
228
217
  * Save theme preference to storage
229
- *
218
+ *
230
219
  * @param mode - Theme mode to save
231
220
  * @param options - Persistence options
232
221
  */
233
- export function persistTheme(
234
- mode: ThemeMode,
235
- options: ThemePersistenceOptions = {}
236
- ): void {
222
+ export function persistTheme(mode: ThemeMode, options: ThemePersistenceOptions = {}): void {
237
223
  if (typeof window === 'undefined') return;
238
-
239
- const {
240
- storageKey = 'atomix-theme',
241
- storageType = 'localStorage',
242
- } = options;
243
-
224
+
225
+ const { storageKey = 'atomix-theme', storageType = 'localStorage' } = options;
226
+
244
227
  const storage = storageType === 'localStorage' ? localStorage : sessionStorage;
245
228
  storage.setItem(storageKey, mode);
246
229
  }
247
230
 
248
231
  /**
249
232
  * Clear saved theme preference
250
- *
233
+ *
251
234
  * @param options - Persistence options
252
235
  */
253
236
  export function clearThemePreference(options: ThemePersistenceOptions = {}): void {
254
237
  if (typeof window === 'undefined') return;
255
-
256
- const {
257
- storageKey = 'atomix-theme',
258
- storageType = 'localStorage',
259
- } = options;
260
-
238
+
239
+ const { storageKey = 'atomix-theme', storageType = 'localStorage' } = options;
240
+
261
241
  const storage = storageType === 'localStorage' ? localStorage : sessionStorage;
262
242
  storage.removeItem(storageKey);
263
243
  }
@@ -268,12 +248,12 @@ export function clearThemePreference(options: ThemePersistenceOptions = {}): voi
268
248
 
269
249
  /**
270
250
  * Merge multiple token sets
271
- *
251
+ *
272
252
  * Deep merges token objects, with later tokens overriding earlier ones.
273
- *
253
+ *
274
254
  * @param tokens - Token objects to merge
275
255
  * @returns Merged tokens
276
- *
256
+ *
277
257
  * @example
278
258
  * ```typescript
279
259
  * const merged = mergeTokens(
@@ -290,13 +270,13 @@ export function mergeTokens(...tokens: Array<Partial<DesignTokens>>): Partial<De
290
270
 
291
271
  /**
292
272
  * Override specific tokens
293
- *
273
+ *
294
274
  * Creates a new token object with specific overrides.
295
- *
275
+ *
296
276
  * @param base - Base tokens
297
277
  * @param overrides - Tokens to override
298
278
  * @returns New tokens with overrides applied
299
- *
279
+ *
300
280
  * @example
301
281
  * ```typescript
302
282
  * const customized = overrideTokens(defaultTokens, {
@@ -315,13 +295,13 @@ export function overrideTokens(
315
295
 
316
296
  /**
317
297
  * Pick specific token categories
318
- *
298
+ *
319
299
  * Extracts only the specified categories from tokens.
320
- *
300
+ *
321
301
  * @param tokens - Source tokens
322
302
  * @param categories - Categories to pick
323
303
  * @returns Tokens with only selected categories
324
- *
304
+ *
325
305
  * @example
326
306
  * ```typescript
327
307
  * const colorTokens = pickTokens(allTokens, ['colors']);
@@ -332,25 +312,25 @@ export function pickTokens(
332
312
  categories: Array<keyof DesignTokens>
333
313
  ): Partial<DesignTokens> {
334
314
  const result: Partial<DesignTokens> = {};
335
-
315
+
336
316
  categories.forEach(category => {
337
317
  if (tokens[category]) {
338
318
  result[category] = tokens[category];
339
319
  }
340
320
  });
341
-
321
+
342
322
  return result;
343
323
  }
344
324
 
345
325
  /**
346
326
  * Omit specific token categories
347
- *
327
+ *
348
328
  * Removes specified categories from tokens.
349
- *
329
+ *
350
330
  * @param tokens - Source tokens
351
331
  * @param categories - Categories to omit
352
332
  * @returns Tokens without omitted categories
353
- *
333
+ *
354
334
  * @example
355
335
  * ```typescript
356
336
  * const withoutColors = omitTokens(allTokens, ['colors']);
@@ -361,11 +341,11 @@ export function omitTokens(
361
341
  categories: Array<keyof DesignTokens>
362
342
  ): Partial<DesignTokens> {
363
343
  const result = { ...tokens };
364
-
344
+
365
345
  categories.forEach(category => {
366
346
  delete result[category];
367
347
  });
368
-
348
+
369
349
  return result;
370
350
  }
371
351
 
@@ -375,22 +355,25 @@ export function omitTokens(
375
355
 
376
356
  /**
377
357
  * Convert hex color to RGB
378
- *
358
+ *
379
359
  * @param hex - Hex color (with or without #)
380
360
  * @returns RGB object { r, g, b }
381
361
  */
382
362
  export function hexToRgb(hex: string): { r: number; g: number; b: number } | null {
383
363
  // Remove # if present
384
364
  hex = hex.replace(/^#/, '');
385
-
365
+
386
366
  // Handle shorthand hex
387
367
  if (hex.length === 3) {
388
- hex = hex.split('').map(c => c + c).join('');
368
+ hex = hex
369
+ .split('')
370
+ .map(c => c + c)
371
+ .join('');
389
372
  }
390
-
373
+
391
374
  // Validate
392
375
  if (hex.length !== 6) return null;
393
-
376
+
394
377
  const num = parseInt(hex, 16);
395
378
  return {
396
379
  r: (num >> 16) & 255,
@@ -401,42 +384,47 @@ export function hexToRgb(hex: string): { r: number; g: number; b: number } | nul
401
384
 
402
385
  /**
403
386
  * Convert RGB to hex
404
- *
387
+ *
405
388
  * @param r - Red (0-255)
406
389
  * @param g - Green (0-255)
407
390
  * @param b - Blue (0-255)
408
391
  * @returns Hex color with #
409
392
  */
410
393
  export function rgbToHex(r: number, g: number, b: number): string {
411
- return '#' + [r, g, b].map(x => {
412
- const hex = x.toString(16);
413
- return hex.length === 1 ? '0' + hex : hex;
414
- }).join('');
394
+ return (
395
+ '#' +
396
+ [r, g, b]
397
+ .map(x => {
398
+ const hex = x.toString(16);
399
+ return hex.length === 1 ? '0' + hex : hex;
400
+ })
401
+ .join('')
402
+ );
415
403
  }
416
404
 
417
405
  /**
418
406
  * Calculate luminance of a color
419
- *
407
+ *
420
408
  * Used for determining contrast ratios.
421
- *
409
+ *
422
410
  * @param hex - Hex color
423
411
  * @returns Luminance value (0-1)
424
412
  */
425
413
  export function getLuminance(hex: string): number {
426
414
  const rgb = hexToRgb(hex);
427
415
  if (!rgb) return 0;
428
-
416
+
429
417
  const [r, g, b] = [rgb.r, rgb.g, rgb.b].map(v => {
430
418
  v /= 255;
431
419
  return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
432
420
  });
433
-
421
+
434
422
  return 0.2126 * (r ?? 0) + 0.7152 * (g ?? 0) + 0.0722 * (b ?? 0);
435
423
  }
436
424
 
437
425
  /**
438
426
  * Calculate contrast ratio between two colors
439
- *
427
+ *
440
428
  * @param hex1 - First hex color
441
429
  * @param hex2 - Second hex color
442
430
  * @returns Contrast ratio (1-21)
@@ -444,16 +432,16 @@ export function getLuminance(hex: string): number {
444
432
  export function getContrastRatio(hex1: string, hex2: string): number {
445
433
  const lum1 = getLuminance(hex1);
446
434
  const lum2 = getLuminance(hex2);
447
-
435
+
448
436
  const brightest = Math.max(lum1, lum2);
449
437
  const darkest = Math.min(lum1, lum2);
450
-
438
+
451
439
  return (brightest + 0.05) / (darkest + 0.05);
452
440
  }
453
441
 
454
442
  /**
455
443
  * Check if text color passes WCAG AA standard
456
- *
444
+ *
457
445
  * @param textColor - Text color hex
458
446
  * @param backgroundColor - Background color hex
459
447
  * @param size - Font size ('small' or 'large')
@@ -465,16 +453,16 @@ export function isAccessible(
465
453
  size: 'small' | 'large' = 'small'
466
454
  ): boolean {
467
455
  const ratio = getContrastRatio(textColor, backgroundColor);
468
-
456
+
469
457
  // WCAG AA requires 4.5:1 for normal text, 3:1 for large text
470
458
  const minimumRatio = size === 'large' ? 3 : 4.5;
471
-
459
+
472
460
  return ratio >= minimumRatio;
473
461
  }
474
462
 
475
463
  /**
476
464
  * Get appropriate text color (black or white) for a background
477
- *
465
+ *
478
466
  * @param backgroundColor - Background hex color
479
467
  * @param threshold - Contrast threshold (default: 3)
480
468
  * @returns '#000000' or '#FFFFFF'
@@ -489,7 +477,7 @@ export function getContrastText(backgroundColor: string, threshold: number = 3):
489
477
 
490
478
  /**
491
479
  * Lighten a color
492
- *
480
+ *
493
481
  * @param hex - Base hex color
494
482
  * @param amount - Amount to lighten (0-1)
495
483
  * @returns Lightened hex color
@@ -497,20 +485,20 @@ export function getContrastText(backgroundColor: string, threshold: number = 3):
497
485
  export function lighten(hex: string, amount: number = 0): string {
498
486
  const rgb = hexToRgb(hex);
499
487
  if (!rgb) return hex;
500
-
488
+
501
489
  // Use amount directly as factor (0-1)
502
490
  const factor = Math.max(0, Math.min(1, amount));
503
-
491
+
504
492
  const r = Math.round(rgb.r + (255 - rgb.r) * factor);
505
493
  const g = Math.round(rgb.g + (255 - rgb.g) * factor);
506
494
  const b = Math.round(rgb.b + (255 - rgb.b) * factor);
507
-
495
+
508
496
  return rgbToHex(Math.min(255, r), Math.min(255, g), Math.min(255, b));
509
497
  }
510
498
 
511
499
  /**
512
500
  * Darken a color
513
- *
501
+ *
514
502
  * @param hex - Base hex color
515
503
  * @param amount - Amount to darken (0-1)
516
504
  * @returns Darkened hex color
@@ -518,20 +506,20 @@ export function lighten(hex: string, amount: number = 0): string {
518
506
  export function darken(hex: string, amount: number = 0): string {
519
507
  const rgb = hexToRgb(hex);
520
508
  if (!rgb) return hex;
521
-
509
+
522
510
  // Use amount directly as factor (0-1)
523
511
  const factor = Math.max(0, Math.min(1, amount));
524
-
512
+
525
513
  const r = Math.round(rgb.r * (1 - factor));
526
514
  const g = Math.round(rgb.g * (1 - factor));
527
515
  const b = Math.round(rgb.b * (1 - factor));
528
-
516
+
529
517
  return rgbToHex(Math.max(0, r), Math.max(0, g), Math.max(0, b));
530
518
  }
531
519
 
532
520
  /**
533
521
  * Add alpha to a color
534
- *
522
+ *
535
523
  * @param hex - Hex color
536
524
  * @param opacity - Opacity value (0-1)
537
525
  * @returns RGBA color string
@@ -539,14 +527,14 @@ export function darken(hex: string, amount: number = 0): string {
539
527
  export function alpha(hex: string, opacity: number): string {
540
528
  const rgb = hexToRgb(hex);
541
529
  if (!rgb) return hex;
542
-
530
+
543
531
  const validOpacity = Math.max(0, Math.min(1, opacity));
544
532
  return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${validOpacity})`;
545
533
  }
546
534
 
547
535
  /**
548
536
  * Emphasize a color (lighten if dark, darken if light)
549
- *
537
+ *
550
538
  * @param hex - Hex color
551
539
  * @param amount - Amount to emphasize (0-1)
552
540
  * @returns Emphasized hex color
@@ -558,7 +546,7 @@ export function emphasize(hex: string, amount: number = 0.15): string {
558
546
 
559
547
  /**
560
548
  * Create a spacing utility
561
- *
549
+ *
562
550
  * @param spacingInput - Spacing configuration
563
551
  * @returns Spacing function
564
552
  */