@umituz/react-native-settings 5.2.34 → 5.2.36
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.
- package/package.json +2 -4
- package/src/domains/about/presentation/screens/AboutScreenContent.tsx +87 -63
- package/src/domains/appearance/data/colorPalettes.ts +0 -23
- package/src/domains/appearance/presentation/components/CustomColorsSection.tsx +2 -4
- package/src/domains/appearance/presentation/components/ThemeOption.tsx +2 -2
- package/src/domains/dev/presentation/components/DevSettingsSection.tsx +5 -2
- package/src/domains/faqs/presentation/screens/FAQScreen.tsx +19 -25
- package/src/domains/feedback/presentation/components/FeedbackForm.tsx +160 -81
- package/src/domains/gamification/components/GamificationScreen/GamificationScreenWithConfig.tsx +11 -11
- package/src/domains/localization/infrastructure/components/LanguageSwitcher.tsx +0 -2
- package/src/domains/localization/infrastructure/storage/localizationStoreUtils.ts +1 -1
- package/src/domains/localization/presentation/screens/LanguageSelectionScreen.tsx +85 -48
- package/src/domains/localization/presentation/screens/__tests__/LanguageSelectionScreen.test.tsx +0 -15
- package/src/domains/notifications/presentation/screens/NotificationsScreen.tsx +1 -3
- package/src/domains/notifications/reminders/presentation/components/ReminderForm.constants.ts +0 -4
- package/src/domains/notifications/reminders/presentation/components/ReminderForm.tsx +69 -31
- package/src/domains/rating/presentation/components/StarRating.tsx +7 -13
- package/src/infrastructure/utils/configFactory.ts +0 -26
- package/src/infrastructure/utils/constants/textLimits.ts +0 -2
- package/src/infrastructure/utils/sanitizers.ts +1 -25
- package/src/infrastructure/utils/validation/core.ts +0 -33
- package/src/infrastructure/utils/validation/formValidators.ts +7 -1
- package/src/infrastructure/utils/validation/index.ts +2 -33
- package/src/infrastructure/utils/validators.ts +0 -6
- package/src/presentation/navigation/utils/index.ts +1 -7
- package/src/presentation/navigation/utils/navigationHelpers.ts +2 -87
- package/src/presentation/screens/components/SettingsContent.tsx +4 -19
- package/src/presentation/screens/components/sections/CustomSettingsList.tsx +3 -8
- package/src/presentation/screens/components/sections/FeatureSettingsSection.tsx +0 -4
- package/src/presentation/screens/components/sections/IdentitySettingsSection.tsx +0 -4
- package/src/presentation/screens/components/sections/SupportSettingsSection.tsx +0 -4
- package/src/presentation/utils/screenFactory.ts +0 -25
- package/src/utils/appUtils.ts +0 -18
- package/src/utils/devUtils.ts +0 -10
- package/src/utils/errorUtils.ts +0 -22
- package/src/domains/about/utils/index.ts +0 -156
- package/src/domains/faqs/domain/services/index.ts +0 -1
- package/src/domains/faqs/presentation/screens/index.ts +0 -2
- package/src/domains/gamification/components/GamificationScreen/Header.tsx +0 -30
- package/src/domains/legal/presentation/components/LegalLinks.tsx +0 -137
- package/src/domains/legal/presentation/components/index.ts +0 -5
- package/src/domains/localization/infrastructure/config/languagesData.ts +0 -26
- package/src/domains/localization/infrastructure/hooks/TranslationHook.ts +0 -37
- package/src/domains/localization/infrastructure/storage/AsyncStorageWrapper.ts +0 -34
- package/src/infrastructure/storage/storeConfig.ts +0 -114
- package/src/infrastructure/types/commonComponentTypes.ts +0 -142
- package/src/infrastructure/utils/async/core.ts +0 -110
- package/src/infrastructure/utils/async/debounceAndBatch.ts +0 -69
- package/src/infrastructure/utils/async/index.ts +0 -8
- package/src/infrastructure/utils/async/retryAndTimeout.ts +0 -65
- package/src/infrastructure/utils/dateUtils.ts +0 -61
- package/src/infrastructure/utils/errorHandlers.ts +0 -250
- package/src/infrastructure/utils/index.ts +0 -12
- package/src/infrastructure/utils/memoComparisonUtils.ts +0 -66
- package/src/infrastructure/utils/memoUtils.ts +0 -167
- package/src/infrastructure/utils/styleTokens.ts +0 -145
- package/src/infrastructure/utils/styles/componentStyles.ts +0 -90
- package/src/infrastructure/utils/styles/index.ts +0 -9
- package/src/infrastructure/utils/styles/layoutStyles.ts +0 -56
- package/src/infrastructure/utils/styles/spacingStyles.ts +0 -33
- package/src/infrastructure/utils/styles/styleHelpers.ts +0 -22
- package/src/infrastructure/utils/translationHelpers.ts +0 -81
- package/src/infrastructure/utils/validation/numericValidators.ts +0 -66
- package/src/infrastructure/utils/validation/passwordValidator.ts +0 -53
- package/src/infrastructure/utils/validation/textValidators.ts +0 -118
- package/src/presentation/components/ErrorBoundary/SettingsErrorBoundary.tsx +0 -105
- package/src/presentation/components/ErrorBoundary/index.ts +0 -12
- package/src/presentation/components/ErrorBoundary/withErrorBoundary.tsx +0 -45
- package/src/utils/hooks/index.ts +0 -6
- package/src/utils/index.ts +0 -3
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Error Handling Utilities
|
|
3
|
-
* Centralized error handling and error message generation
|
|
4
|
-
* FIXED: Added safety checks for showToast and proper error handling
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { isDev } from '../../utils/devUtils';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Error types for better error classification
|
|
11
|
-
*/
|
|
12
|
-
export enum ErrorType {
|
|
13
|
-
NETWORK = "NETWORK",
|
|
14
|
-
VALIDATION = "VALIDATION",
|
|
15
|
-
AUTHENTICATION = "AUTHENTICATION",
|
|
16
|
-
AUTHORIZATION = "AUTHORIZATION",
|
|
17
|
-
NOT_FOUND = "NOT_FOUND",
|
|
18
|
-
SERVER = "SERVER",
|
|
19
|
-
UNKNOWN = "UNKNOWN",
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Custom error class with error type
|
|
24
|
-
*/
|
|
25
|
-
export class AppError extends Error {
|
|
26
|
-
constructor(
|
|
27
|
-
message: string,
|
|
28
|
-
public type: ErrorType = ErrorType.UNKNOWN,
|
|
29
|
-
public code?: string,
|
|
30
|
-
public statusCode?: number
|
|
31
|
-
) {
|
|
32
|
-
super(message);
|
|
33
|
-
this.name = "AppError";
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Error handler result
|
|
39
|
-
*/
|
|
40
|
-
export interface ErrorHandlerResult {
|
|
41
|
-
message: string;
|
|
42
|
-
type: ErrorType;
|
|
43
|
-
shouldShowToUser: boolean;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Classify error based on error properties
|
|
48
|
-
*/
|
|
49
|
-
export const classifyError = (error: unknown): ErrorType => {
|
|
50
|
-
if (error instanceof AppError) {
|
|
51
|
-
return error.type;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (!(error instanceof Error)) {
|
|
55
|
-
return ErrorType.UNKNOWN;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const errorMessage = error.message.toLowerCase();
|
|
59
|
-
|
|
60
|
-
// Network errors
|
|
61
|
-
if (
|
|
62
|
-
errorMessage.includes("network") ||
|
|
63
|
-
errorMessage.includes("fetch") ||
|
|
64
|
-
errorMessage.includes("connection")
|
|
65
|
-
) {
|
|
66
|
-
return ErrorType.NETWORK;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Authentication errors
|
|
70
|
-
if (
|
|
71
|
-
errorMessage.includes("unauthorized") ||
|
|
72
|
-
errorMessage.includes("unauthenticated") ||
|
|
73
|
-
errorMessage.includes("token") ||
|
|
74
|
-
errorMessage.includes("401")
|
|
75
|
-
) {
|
|
76
|
-
return ErrorType.AUTHENTICATION;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Authorization errors
|
|
80
|
-
if (
|
|
81
|
-
errorMessage.includes("forbidden") ||
|
|
82
|
-
errorMessage.includes("permission") ||
|
|
83
|
-
errorMessage.includes("403")
|
|
84
|
-
) {
|
|
85
|
-
return ErrorType.AUTHORIZATION;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Not found errors
|
|
89
|
-
if (
|
|
90
|
-
errorMessage.includes("not found") ||
|
|
91
|
-
errorMessage.includes("404")
|
|
92
|
-
) {
|
|
93
|
-
return ErrorType.NOT_FOUND;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Server errors
|
|
97
|
-
if (
|
|
98
|
-
errorMessage.includes("500") ||
|
|
99
|
-
errorMessage.includes("502") ||
|
|
100
|
-
errorMessage.includes("503")
|
|
101
|
-
) {
|
|
102
|
-
return ErrorType.SERVER;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return ErrorType.UNKNOWN;
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Get user-friendly error message
|
|
110
|
-
*/
|
|
111
|
-
export const getUserFriendlyErrorMessage = (
|
|
112
|
-
error: unknown,
|
|
113
|
-
context?: {
|
|
114
|
-
operation?: string;
|
|
115
|
-
entity?: string;
|
|
116
|
-
}
|
|
117
|
-
): ErrorHandlerResult => {
|
|
118
|
-
const errorType = classifyError(error);
|
|
119
|
-
|
|
120
|
-
let message = "An unexpected error occurred";
|
|
121
|
-
let shouldShowToUser = true;
|
|
122
|
-
|
|
123
|
-
switch (errorType) {
|
|
124
|
-
case ErrorType.NETWORK:
|
|
125
|
-
message = "Unable to connect. Please check your internet connection and try again.";
|
|
126
|
-
break;
|
|
127
|
-
|
|
128
|
-
case ErrorType.AUTHENTICATION:
|
|
129
|
-
message = "Your session has expired. Please sign in again.";
|
|
130
|
-
break;
|
|
131
|
-
|
|
132
|
-
case ErrorType.AUTHORIZATION:
|
|
133
|
-
message = "You don't have permission to perform this action.";
|
|
134
|
-
break;
|
|
135
|
-
|
|
136
|
-
case ErrorType.NOT_FOUND:
|
|
137
|
-
if (context?.entity) {
|
|
138
|
-
// FIXED: Sanitize entity name to prevent injection
|
|
139
|
-
const sanitizedEntity = String(context.entity).replace(/[<>]/g, "");
|
|
140
|
-
message = `${sanitizedEntity} not found`;
|
|
141
|
-
} else {
|
|
142
|
-
message = "The requested resource was not found.";
|
|
143
|
-
}
|
|
144
|
-
break;
|
|
145
|
-
|
|
146
|
-
case ErrorType.SERVER:
|
|
147
|
-
message = "Server error. Please try again later.";
|
|
148
|
-
shouldShowToUser = false;
|
|
149
|
-
break;
|
|
150
|
-
|
|
151
|
-
case ErrorType.VALIDATION:
|
|
152
|
-
message = error instanceof Error ? error.message : "Invalid input";
|
|
153
|
-
break;
|
|
154
|
-
|
|
155
|
-
default:
|
|
156
|
-
if (error instanceof Error) {
|
|
157
|
-
message = error.message;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return { message, type: errorType, shouldShowToUser };
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Log error appropriately based on type
|
|
166
|
-
*/
|
|
167
|
-
export const logError = (
|
|
168
|
-
error: unknown,
|
|
169
|
-
context?: {
|
|
170
|
-
operation?: string;
|
|
171
|
-
userId?: string;
|
|
172
|
-
additionalInfo?: Record<string, unknown>;
|
|
173
|
-
}
|
|
174
|
-
): void => {
|
|
175
|
-
const errorType = classifyError(error);
|
|
176
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
177
|
-
|
|
178
|
-
const logData = {
|
|
179
|
-
type: errorType,
|
|
180
|
-
message: errorMessage,
|
|
181
|
-
operation: context?.operation,
|
|
182
|
-
userId: context?.userId,
|
|
183
|
-
...context?.additionalInfo,
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
// Log errors in development mode
|
|
187
|
-
if (isDev()) {
|
|
188
|
-
console.error("[Error]", logData);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Note: Apps can integrate error tracking services (e.g., Sentry) by wrapping this function
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Handle error with logging and user message
|
|
196
|
-
*/
|
|
197
|
-
export const handleError = (
|
|
198
|
-
error: unknown,
|
|
199
|
-
context?: {
|
|
200
|
-
operation?: string;
|
|
201
|
-
entity?: string;
|
|
202
|
-
userId?: string;
|
|
203
|
-
showToast?: (message: string) => void;
|
|
204
|
-
}
|
|
205
|
-
): ErrorHandlerResult => {
|
|
206
|
-
// Log the error
|
|
207
|
-
logError(error, context);
|
|
208
|
-
|
|
209
|
-
// Get user-friendly message
|
|
210
|
-
const result = getUserFriendlyErrorMessage(error, context);
|
|
211
|
-
|
|
212
|
-
// Show toast if provided and safe to do so
|
|
213
|
-
// FIXED: Added safety check and try-catch for showToast
|
|
214
|
-
if (context?.showToast && result.shouldShowToUser) {
|
|
215
|
-
try {
|
|
216
|
-
if (typeof context.showToast === "function") {
|
|
217
|
-
context.showToast(result.message);
|
|
218
|
-
}
|
|
219
|
-
} catch (toastError) {
|
|
220
|
-
// Log toast error but don't crash error handling
|
|
221
|
-
if (isDev()) {
|
|
222
|
-
console.error("[ErrorHandlers] showToast failed:", toastError);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
return result;
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Wrap an async function with error handling
|
|
232
|
-
*/
|
|
233
|
-
export const withErrorHandling = async <T>(
|
|
234
|
-
operation: () => Promise<T>,
|
|
235
|
-
options: {
|
|
236
|
-
operation?: string;
|
|
237
|
-
entity?: string;
|
|
238
|
-
showToast?: (message: string) => void;
|
|
239
|
-
onError?: (result: ErrorHandlerResult) => void;
|
|
240
|
-
}
|
|
241
|
-
): Promise<{ success: true; data: T } | { success: false; error: ErrorHandlerResult }> => {
|
|
242
|
-
try {
|
|
243
|
-
const data = await operation();
|
|
244
|
-
return { success: true, data };
|
|
245
|
-
} catch (error) {
|
|
246
|
-
const errorResult = handleError(error, options);
|
|
247
|
-
options?.onError?.(errorResult);
|
|
248
|
-
return { success: false, error: errorResult };
|
|
249
|
-
}
|
|
250
|
-
};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Infrastructure Utilities
|
|
3
|
-
* Centralized utility functions for common operations
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export * from './styles';
|
|
7
|
-
export * from './memoUtils';
|
|
8
|
-
export * from './styleTokens';
|
|
9
|
-
export * from './configFactory';
|
|
10
|
-
export * from './validation';
|
|
11
|
-
export * from './async';
|
|
12
|
-
export * from './errorHandlers';
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Memo Comparison Utilities
|
|
3
|
-
*
|
|
4
|
-
* Provides reusable comparison functions for React.memo to reduce code duplication.
|
|
5
|
-
* These functions follow best practices for shallow comparison in React components.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Standard comparison for components with config and translation props
|
|
10
|
-
* @param prevProps Previous props
|
|
11
|
-
* @param nextProps Next props
|
|
12
|
-
* @returns true if props are equal (should not re-render)
|
|
13
|
-
*/
|
|
14
|
-
export function compareConfigAndTranslate(
|
|
15
|
-
prevProps: Record<string, unknown>,
|
|
16
|
-
nextProps: Record<string, unknown>
|
|
17
|
-
): boolean {
|
|
18
|
-
return (
|
|
19
|
-
prevProps.config === nextProps.config &&
|
|
20
|
-
prevProps.t === nextProps.t
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Standard comparison for components with normalized config and features
|
|
26
|
-
* @param prevProps Previous props
|
|
27
|
-
* @param nextProps Next props
|
|
28
|
-
* @returns true if props are equal (should not re-render)
|
|
29
|
-
*/
|
|
30
|
-
export function compareConfigAndFeatures(
|
|
31
|
-
prevProps: Record<string, unknown>,
|
|
32
|
-
nextProps: Record<string, unknown>
|
|
33
|
-
): boolean {
|
|
34
|
-
return (
|
|
35
|
-
prevProps.normalizedConfig === nextProps.normalizedConfig &&
|
|
36
|
-
prevProps.features === nextProps.features
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Standard comparison for components with single prop
|
|
42
|
-
* @param propKey Property key to compare
|
|
43
|
-
* @returns Comparison function
|
|
44
|
-
*/
|
|
45
|
-
export function createSinglePropComparator<K extends string>(
|
|
46
|
-
propKey: K
|
|
47
|
-
): (prevProps: Record<string, unknown>, nextProps: Record<string, unknown>) => boolean {
|
|
48
|
-
return (prevProps, nextProps) => prevProps[propKey] === nextProps[propKey];
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Standard comparison for components with gamification config
|
|
53
|
-
* @param prevProps Previous props
|
|
54
|
-
* @param nextProps Next props
|
|
55
|
-
* @returns true if props are equal (should not re-render)
|
|
56
|
-
*/
|
|
57
|
-
export function compareGamificationProps(
|
|
58
|
-
prevProps: Record<string, unknown>,
|
|
59
|
-
nextProps: Record<string, unknown>
|
|
60
|
-
): boolean {
|
|
61
|
-
return (
|
|
62
|
-
prevProps.config === nextProps.config &&
|
|
63
|
-
prevProps.gamificationConfig === nextProps.gamificationConfig &&
|
|
64
|
-
prevProps.t === nextProps.t
|
|
65
|
-
);
|
|
66
|
-
}
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Memo Utilities
|
|
3
|
-
* Centralized memoization helpers to reduce code duplication
|
|
4
|
-
*/
|
|
5
|
-
import { useMemo, useCallback, useRef, useEffect, DependencyList } from 'react';
|
|
6
|
-
import type { DesignTokens } from '@umituz/react-native-design-system';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Custom hook to create memoized styles from a style factory function
|
|
10
|
-
* @param styleFactory Function that creates styles
|
|
11
|
-
* @param tokens Design tokens
|
|
12
|
-
* @param deps Dependencies for memoization
|
|
13
|
-
* @returns Memoized styles object
|
|
14
|
-
*/
|
|
15
|
-
export function useMemoizedStyles<T>(
|
|
16
|
-
styleFactory: (tokens: DesignTokens) => T,
|
|
17
|
-
tokens: DesignTokens,
|
|
18
|
-
deps: DependencyList = []
|
|
19
|
-
): T {
|
|
20
|
-
return useMemo(() => styleFactory(tokens), [tokens, ...deps]);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Custom hook to create a memoized callback with proper type inference
|
|
25
|
-
* @param callback Function to memoize
|
|
26
|
-
* @param deps Dependencies for memoization
|
|
27
|
-
* @returns Memoized callback
|
|
28
|
-
*/
|
|
29
|
-
export function useMemoizedCallback<T extends (...args: never[]) => unknown>(
|
|
30
|
-
callback: T,
|
|
31
|
-
deps: DependencyList
|
|
32
|
-
): T {
|
|
33
|
-
return useCallback(callback, deps) as T;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Custom hook to create a memoized value with proper type inference
|
|
38
|
-
* @param factory Function that creates the value
|
|
39
|
-
* @param deps Dependencies for memoization
|
|
40
|
-
* @returns Memoized value
|
|
41
|
-
*/
|
|
42
|
-
export function useMemoizedValue<T>(
|
|
43
|
-
factory: () => T,
|
|
44
|
-
deps: DependencyList
|
|
45
|
-
): T {
|
|
46
|
-
return useMemo(factory, deps);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Creates a memoized style object with proper caching
|
|
51
|
-
* @param styleCreator Function that creates styles
|
|
52
|
-
* @param deps Dependencies for memoization
|
|
53
|
-
* @returns Memoized styles
|
|
54
|
-
*/
|
|
55
|
-
export function useStyledMemo<T extends Record<string, unknown>>(
|
|
56
|
-
styleCreator: () => T,
|
|
57
|
-
deps: DependencyList = []
|
|
58
|
-
): T {
|
|
59
|
-
return useMemo(styleCreator, deps);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Memoizes a value with a custom equality check (non-hook version)
|
|
64
|
-
* @param value Value to memoize
|
|
65
|
-
* @param _isEqual Custom equality function
|
|
66
|
-
* @returns Memoized value
|
|
67
|
-
*/
|
|
68
|
-
export function memoWithEquality<T>(
|
|
69
|
-
value: T,
|
|
70
|
-
_isEqual: (prev: T, next: T) => boolean
|
|
71
|
-
): T {
|
|
72
|
-
// This is a utility function, not a hook
|
|
73
|
-
// It cannot use hooks internally
|
|
74
|
-
return value;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Creates a cache key for style memoization
|
|
79
|
-
* @param tokens Design tokens
|
|
80
|
-
* @param prefix Optional prefix for the key
|
|
81
|
-
* @returns Cache key string
|
|
82
|
-
*/
|
|
83
|
-
export function createStyleCacheKey(
|
|
84
|
-
tokens: DesignTokens,
|
|
85
|
-
prefix: string = ''
|
|
86
|
-
): string {
|
|
87
|
-
const { colors, spacing, typography } = tokens;
|
|
88
|
-
|
|
89
|
-
return `${prefix}-${JSON.stringify({
|
|
90
|
-
colors: { primary: colors.primary, background: colors.backgroundPrimary },
|
|
91
|
-
spacing: { md: spacing.md, lg: spacing.lg },
|
|
92
|
-
typography: { body: typography.bodyMedium.responsiveFontSize },
|
|
93
|
-
})}`;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Memoizes a value with a custom equality check
|
|
98
|
-
* @param value Value to memoize
|
|
99
|
-
* @param _isEqual Custom equality function
|
|
100
|
-
* @returns Memoized value
|
|
101
|
-
*/
|
|
102
|
-
export function useMemoWithEquality<T>(
|
|
103
|
-
value: T,
|
|
104
|
-
_isEqual: (prev: T, next: T) => boolean
|
|
105
|
-
): T {
|
|
106
|
-
const ref = useRef<T>(value);
|
|
107
|
-
|
|
108
|
-
return useMemo(() => {
|
|
109
|
-
if (!_isEqual(ref.current, value)) {
|
|
110
|
-
ref.current = value;
|
|
111
|
-
}
|
|
112
|
-
return ref.current;
|
|
113
|
-
}, [value, _isEqual]);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Custom hook that creates a debounced callback with proper cleanup
|
|
118
|
-
* @param callback Function to debounce
|
|
119
|
-
* @param delay Delay in milliseconds
|
|
120
|
-
* @returns Debounced callback
|
|
121
|
-
*/
|
|
122
|
-
export function useDebouncedCallback<T extends (...args: never[]) => unknown>(
|
|
123
|
-
callback: T,
|
|
124
|
-
delay: number
|
|
125
|
-
): T {
|
|
126
|
-
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
127
|
-
|
|
128
|
-
useEffect(() => {
|
|
129
|
-
return () => {
|
|
130
|
-
if (timeoutRef.current) {
|
|
131
|
-
clearTimeout(timeoutRef.current);
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
}, []);
|
|
135
|
-
|
|
136
|
-
return useCallback((...args: Parameters<T>) => {
|
|
137
|
-
if (timeoutRef.current) {
|
|
138
|
-
clearTimeout(timeoutRef.current);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
timeoutRef.current = setTimeout(() => {
|
|
142
|
-
callback(...args);
|
|
143
|
-
}, delay);
|
|
144
|
-
}, [callback, delay]) as T;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Custom hook that creates a throttled callback
|
|
149
|
-
* @param callback Function to throttle
|
|
150
|
-
* @param delay Delay in milliseconds
|
|
151
|
-
* @returns Throttled callback
|
|
152
|
-
*/
|
|
153
|
-
export function useThrottledCallback<T extends (...args: never[]) => unknown>(
|
|
154
|
-
callback: T,
|
|
155
|
-
delay: number
|
|
156
|
-
): T {
|
|
157
|
-
const lastRunRef = useRef<number>(0);
|
|
158
|
-
|
|
159
|
-
return useCallback((...args: Parameters<T>) => {
|
|
160
|
-
const now = Date.now();
|
|
161
|
-
|
|
162
|
-
if (now - lastRunRef.current >= delay) {
|
|
163
|
-
callback(...args);
|
|
164
|
-
lastRunRef.current = now;
|
|
165
|
-
}
|
|
166
|
-
}, [callback, delay]) as T;
|
|
167
|
-
}
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Style Tokens
|
|
3
|
-
* Centralized design tokens to replace magic numbers across the codebase
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Spacing tokens - replaces magic numbers for padding, margins, gaps
|
|
8
|
-
*/
|
|
9
|
-
export const SPACING = {
|
|
10
|
-
xs: 4,
|
|
11
|
-
sm: 8,
|
|
12
|
-
md: 12,
|
|
13
|
-
lg: 16,
|
|
14
|
-
xl: 20,
|
|
15
|
-
xxl: 24,
|
|
16
|
-
xxxl: 32,
|
|
17
|
-
} as const;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Font size tokens - replaces magic numbers for font sizes
|
|
21
|
-
*/
|
|
22
|
-
export const FONT_SIZE = {
|
|
23
|
-
xs: 10,
|
|
24
|
-
sm: 12,
|
|
25
|
-
md: 14,
|
|
26
|
-
base: 16,
|
|
27
|
-
lg: 18,
|
|
28
|
-
xl: 20,
|
|
29
|
-
xxl: 24,
|
|
30
|
-
xxxl: 28,
|
|
31
|
-
display: 32,
|
|
32
|
-
} as const;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Border radius tokens - replaces magic numbers for border radius
|
|
36
|
-
*/
|
|
37
|
-
export const BORDER_RADIUS = {
|
|
38
|
-
none: 0,
|
|
39
|
-
sm: 4,
|
|
40
|
-
md: 8,
|
|
41
|
-
lg: 12,
|
|
42
|
-
xl: 16,
|
|
43
|
-
full: 9999,
|
|
44
|
-
} as const;
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Opacity tokens - replaces magic numbers for opacity values
|
|
48
|
-
*/
|
|
49
|
-
export const OPACITY = {
|
|
50
|
-
disabled: 0.3,
|
|
51
|
-
hover: 0.7,
|
|
52
|
-
focus: 0.8,
|
|
53
|
-
pressed: 0.9,
|
|
54
|
-
overlay: 0.5,
|
|
55
|
-
icon: 0.6,
|
|
56
|
-
} as const;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Alpha/Transparency values for withAlpha() usage
|
|
60
|
-
* Used with design system's withAlpha(color, alpha) function
|
|
61
|
-
*/
|
|
62
|
-
export const ALPHA_VALUES = {
|
|
63
|
-
subtle: 0.1, // Very subtle tint
|
|
64
|
-
light: 0.15, // Light background tint
|
|
65
|
-
medium: 0.2, // Medium background
|
|
66
|
-
strong: 0.3, // Strong background
|
|
67
|
-
visible: 0.5, // Clearly visible
|
|
68
|
-
prominent: 0.8, // Almost opaque
|
|
69
|
-
} as const;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Icon size tokens
|
|
73
|
-
*/
|
|
74
|
-
export const ICON_SIZE = {
|
|
75
|
-
xs: 16,
|
|
76
|
-
sm: 20,
|
|
77
|
-
md: 24,
|
|
78
|
-
lg: 32,
|
|
79
|
-
xl: 40,
|
|
80
|
-
xxl: 48,
|
|
81
|
-
} as const;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Layout dimension tokens
|
|
85
|
-
*/
|
|
86
|
-
export const DIMENSION = {
|
|
87
|
-
touchTarget: {
|
|
88
|
-
minHeight: 44,
|
|
89
|
-
minWidth: 44,
|
|
90
|
-
},
|
|
91
|
-
card: {
|
|
92
|
-
minHeight: 72,
|
|
93
|
-
},
|
|
94
|
-
input: {
|
|
95
|
-
minHeight: 48,
|
|
96
|
-
},
|
|
97
|
-
button: {
|
|
98
|
-
minHeight: 44,
|
|
99
|
-
height: 48,
|
|
100
|
-
},
|
|
101
|
-
avatar: {
|
|
102
|
-
xs: 24,
|
|
103
|
-
sm: 32,
|
|
104
|
-
md: 40,
|
|
105
|
-
lg: 48,
|
|
106
|
-
xl: 64,
|
|
107
|
-
xxl: 96,
|
|
108
|
-
},
|
|
109
|
-
} as const;
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Z-index tokens for layering
|
|
113
|
-
*/
|
|
114
|
-
export const Z_INDEX = {
|
|
115
|
-
base: 0,
|
|
116
|
-
overlay: 10,
|
|
117
|
-
dropdown: 100,
|
|
118
|
-
sticky: 200,
|
|
119
|
-
fixed: 300,
|
|
120
|
-
modalBackdrop: 400,
|
|
121
|
-
modal: 500,
|
|
122
|
-
popover: 600,
|
|
123
|
-
toast: 700,
|
|
124
|
-
} as const;
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Animation duration tokens (in ms)
|
|
128
|
-
*/
|
|
129
|
-
export const DURATION = {
|
|
130
|
-
fast: 150,
|
|
131
|
-
normal: 250,
|
|
132
|
-
slow: 350,
|
|
133
|
-
extraSlow: 500,
|
|
134
|
-
} as const;
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Type exports for token values
|
|
138
|
-
*/
|
|
139
|
-
export type SpacingToken = typeof SPACING[keyof typeof SPACING];
|
|
140
|
-
export type FontSizeToken = typeof FONT_SIZE[keyof typeof FONT_SIZE];
|
|
141
|
-
export type BorderRadiusToken = typeof BORDER_RADIUS[keyof typeof BORDER_RADIUS];
|
|
142
|
-
export type OpacityToken = typeof OPACITY[keyof typeof OPACITY];
|
|
143
|
-
export type IconSizeToken = typeof ICON_SIZE[keyof typeof ICON_SIZE];
|
|
144
|
-
export type ZIndexToken = typeof Z_INDEX[keyof typeof Z_INDEX];
|
|
145
|
-
export type DurationToken = typeof DURATION[keyof typeof DURATION];
|