@shohojdhara/atomix 0.5.2 → 0.5.4

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 (39) hide show
  1. package/atomix.config.ts +33 -33
  2. package/dist/config.d.ts +187 -112
  3. package/dist/config.js +7 -49
  4. package/dist/config.js.map +1 -1
  5. package/dist/index.d.ts +1958 -900
  6. package/dist/index.esm.js +2275 -383
  7. package/dist/index.esm.js.map +1 -1
  8. package/dist/index.js +2327 -417
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.min.js +1 -1
  11. package/dist/index.min.js.map +1 -1
  12. package/dist/theme.d.ts +1390 -276
  13. package/dist/theme.js +2129 -621
  14. package/dist/theme.js.map +1 -1
  15. package/package.json +1 -1
  16. package/scripts/cli/internal/config-loader.js +30 -20
  17. package/src/lib/config/index.ts +38 -362
  18. package/src/lib/config/loader.ts +419 -0
  19. package/src/lib/config/public-api.ts +43 -0
  20. package/src/lib/config/types.ts +389 -0
  21. package/src/lib/config/validator.ts +305 -0
  22. package/src/lib/theme/adapters/index.ts +1 -1
  23. package/src/lib/theme/adapters/themeAdapter.ts +358 -229
  24. package/src/lib/theme/components/ThemeToggle.tsx +276 -0
  25. package/src/lib/theme/config/configLoader.ts +351 -0
  26. package/src/lib/theme/config/loader.ts +221 -0
  27. package/src/lib/theme/core/createTheme.ts +126 -50
  28. package/src/lib/theme/core/createThemeObject.ts +7 -4
  29. package/src/lib/theme/hooks/useThemeSwitcher.ts +164 -0
  30. package/src/lib/theme/index.ts +322 -38
  31. package/src/lib/theme/runtime/ThemeProvider.tsx +44 -10
  32. package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +44 -393
  33. package/src/lib/theme/runtime/useTheme.ts +1 -0
  34. package/src/lib/theme/tokens/tokens.ts +101 -1
  35. package/src/lib/theme/types.ts +91 -0
  36. package/src/lib/theme/utils/performanceMonitor.ts +315 -0
  37. package/src/lib/theme/utils/responsive.ts +280 -0
  38. package/src/lib/theme/utils/themeUtils.ts +531 -117
  39. package/src/styles/05-objects/_objects.masonry-grid.scss +3 -3
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Responsive Utility for Atomix Theme System
3
+ *
4
+ * Provides responsive breakpoint detection and device-aware parameter scaling
5
+ * based on configuration from the advanced optimization features.
6
+ */
7
+
8
+ import React from 'react';
9
+
10
+ /**
11
+ * Breakpoint definitions
12
+ */
13
+ export interface Breakpoints {
14
+ mobile: string;
15
+ tablet: string;
16
+ desktop: string;
17
+ wide: string;
18
+ }
19
+
20
+ /**
21
+ * Device scaling factors
22
+ */
23
+ export interface DeviceScaling {
24
+ mobile: number;
25
+ tablet: number;
26
+ desktop: number;
27
+ }
28
+
29
+ /**
30
+ * Responsive configuration
31
+ */
32
+ export interface ResponsiveConfig {
33
+ breakpoints: Breakpoints;
34
+ deviceScaling: DeviceScaling;
35
+ }
36
+
37
+ /**
38
+ * Current device type
39
+ */
40
+ export type DeviceType = 'mobile' | 'tablet' | 'desktop' | 'wide';
41
+
42
+ /**
43
+ * Responsive utility class
44
+ */
45
+ export class ResponsiveUtil {
46
+ private config: ResponsiveConfig;
47
+ private currentDevice: DeviceType = 'desktop'; // Default
48
+ private resizeHandler: (() => void) | null = null;
49
+ private observer: ResizeObserver | null = null;
50
+
51
+ constructor(config: ResponsiveConfig) {
52
+ this.config = config;
53
+ this.currentDevice = this.getCurrentDeviceType();
54
+
55
+ // Set up resize listener
56
+ this.setupResizeListener();
57
+ }
58
+
59
+ /**
60
+ * Get the current device type based on viewport width
61
+ */
62
+ public getCurrentDeviceType(): DeviceType {
63
+ if (typeof window === 'undefined') return 'desktop'; // SSR fallback
64
+
65
+ const width = window.innerWidth;
66
+
67
+ // Parse breakpoint values to numbers
68
+ const mobileWidth = this.parsePxValue(this.config.breakpoints.mobile);
69
+ const tabletWidth = this.parsePxValue(this.config.breakpoints.tablet);
70
+ const desktopWidth = this.parsePxValue(this.config.breakpoints.desktop);
71
+ const wideWidth = this.parsePxValue(this.config.breakpoints.wide);
72
+
73
+ if (width < tabletWidth) {
74
+ return 'mobile';
75
+ } else if (width < desktopWidth) {
76
+ return 'tablet';
77
+ } else if (width < wideWidth) {
78
+ return 'desktop';
79
+ } else {
80
+ return 'wide';
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Get the scaling factor for the current device
86
+ */
87
+ public getCurrentScalingFactor(): number {
88
+ // 'wide' devices use the same scaling as 'desktop'
89
+ const scalingKey = this.currentDevice === 'wide' ? 'desktop' : this.currentDevice;
90
+ return this.config.deviceScaling[scalingKey] || 1.0;
91
+ }
92
+
93
+ /**
94
+ * Scale a value based on the current device's scaling factor
95
+ */
96
+ public scaleValue(value: number): number {
97
+ return value * this.getCurrentScalingFactor();
98
+ }
99
+
100
+ /**
101
+ * Check if the current device matches a specific type
102
+ */
103
+ public isDevice(device: DeviceType): boolean {
104
+ return this.currentDevice === device;
105
+ }
106
+
107
+ /**
108
+ * Check if the current device is mobile or smaller
109
+ */
110
+ public isMobileOrSmaller(): boolean {
111
+ return this.currentDevice === 'mobile';
112
+ }
113
+
114
+ /**
115
+ * Check if the current device is tablet or smaller
116
+ */
117
+ public isTabletOrSmaller(): boolean {
118
+ return this.currentDevice === 'mobile' || this.currentDevice === 'tablet';
119
+ }
120
+
121
+ /**
122
+ * Check if the current device is desktop or larger
123
+ */
124
+ public isDesktopOrLarger(): boolean {
125
+ return this.currentDevice === 'desktop' || this.currentDevice === 'wide';
126
+ }
127
+
128
+ /**
129
+ * Update the responsive configuration
130
+ */
131
+ public updateConfig(config: ResponsiveConfig): void {
132
+ this.config = config;
133
+ this.currentDevice = this.getCurrentDeviceType();
134
+ }
135
+
136
+ /**
137
+ * Destroy the responsive utility and clean up listeners
138
+ */
139
+ public destroy(): void {
140
+ if (this.resizeHandler) {
141
+ window.removeEventListener('resize', this.resizeHandler);
142
+ this.resizeHandler = null;
143
+ }
144
+
145
+ if (this.observer) {
146
+ this.observer.disconnect();
147
+ this.observer = null;
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Parse a CSS value to pixels
153
+ */
154
+ private parsePxValue(value: string): number {
155
+ if (value.endsWith('px')) {
156
+ return parseFloat(value.slice(0, -2));
157
+ }
158
+
159
+ // For other units, we'll use a rough conversion assuming 16px base
160
+ if (value.endsWith('rem')) {
161
+ return parseFloat(value.slice(0, -3)) * 16;
162
+ }
163
+
164
+ if (value.endsWith('em')) {
165
+ return parseFloat(value.slice(0, -2)) * 16;
166
+ }
167
+
168
+ // Default to parsing as a raw number
169
+ return parseFloat(value) || 0;
170
+ }
171
+
172
+ /**
173
+ * Set up the resize listener
174
+ */
175
+ private setupResizeListener(): void {
176
+ if (typeof window === 'undefined') return;
177
+
178
+ // Throttled resize handler
179
+ let resizeTimeout: number | null = null;
180
+
181
+ const handleResize = () => {
182
+ if (resizeTimeout) {
183
+ window.clearTimeout(resizeTimeout);
184
+ }
185
+
186
+ resizeTimeout = window.setTimeout(() => {
187
+ const newDeviceType = this.getCurrentDeviceType();
188
+
189
+ if (newDeviceType !== this.currentDevice) {
190
+ this.currentDevice = newDeviceType;
191
+ // Optionally trigger a callback here if needed
192
+ }
193
+ }, 150); // Throttle to 150ms
194
+ };
195
+
196
+ this.resizeHandler = handleResize;
197
+ window.addEventListener('resize', handleResize);
198
+
199
+ // Also observe the document body for size changes
200
+ if (typeof ResizeObserver !== 'undefined') {
201
+ this.observer = new ResizeObserver(handleResize);
202
+ this.observer.observe(document.body);
203
+ }
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Create a responsive utility instance
209
+ *
210
+ * @param config Responsive configuration
211
+ * @returns ResponsiveUtil instance
212
+ */
213
+ export function createResponsiveUtil(config: ResponsiveConfig): ResponsiveUtil {
214
+ return new ResponsiveUtil(config);
215
+ }
216
+
217
+ /**
218
+ * Hook for React components to use responsive features
219
+ *
220
+ * @param config Responsive configuration
221
+ * @returns Current device type and utility functions
222
+ */
223
+ export function useResponsive(config: ResponsiveConfig) {
224
+ const [util] = React.useState(() => createResponsiveUtil(config));
225
+ const [deviceType, setDeviceType] = React.useState<DeviceType>(() =>
226
+ typeof window !== 'undefined' ? util.getCurrentDeviceType() : 'desktop'
227
+ );
228
+
229
+ React.useEffect(() => {
230
+ if (typeof window === 'undefined') return;
231
+
232
+ const handleResize = () => {
233
+ const newDeviceType = util.getCurrentDeviceType();
234
+ if (newDeviceType !== deviceType) {
235
+ setDeviceType(newDeviceType);
236
+ }
237
+ };
238
+
239
+ // Update device type on mount
240
+ setDeviceType(util.getCurrentDeviceType());
241
+
242
+ // Listen for resize events
243
+ window.addEventListener('resize', handleResize);
244
+
245
+ return () => {
246
+ window.removeEventListener('resize', handleResize);
247
+ util.destroy();
248
+ };
249
+ }, [util, deviceType]);
250
+
251
+ if (typeof window === 'undefined') {
252
+ return {
253
+ deviceType: 'desktop' as DeviceType,
254
+ isMobile: false,
255
+ isTablet: false,
256
+ isDesktop: true,
257
+ isWide: false,
258
+ scaleValue: (value: number) => value,
259
+ getCurrentDeviceType: (): DeviceType => 'desktop',
260
+ getCurrentScalingFactor: (): number => 1,
261
+ isMobileOrSmaller: (): boolean => false,
262
+ isTabletOrSmaller: (): boolean => true,
263
+ isDesktopOrLarger: (): boolean => true,
264
+ };
265
+ }
266
+
267
+ return {
268
+ deviceType,
269
+ isMobile: deviceType === 'mobile',
270
+ isTablet: deviceType === 'tablet',
271
+ isDesktop: deviceType === 'desktop',
272
+ isWide: deviceType === 'wide',
273
+ scaleValue: (value: number) => util.scaleValue(value),
274
+ getCurrentDeviceType: () => util.getCurrentDeviceType(),
275
+ getCurrentScalingFactor: () => util.getCurrentScalingFactor(),
276
+ isMobileOrSmaller: () => util.isMobileOrSmaller(),
277
+ isTabletOrSmaller: () => util.isTabletOrSmaller(),
278
+ isDesktopOrLarger: () => util.isDesktopOrLarger(),
279
+ };
280
+ }