@umituz/react-native-design-system 4.23.53 → 4.23.55
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 +1 -1
- package/src/atoms/AtomicInput.tsx +2 -2
- package/src/atoms/index.ts +1 -1
- package/src/atoms/input/components/InputIcon.tsx +2 -2
- package/src/exports/molecules/navigation.ts +0 -2
- package/src/global.d.ts +4 -0
- package/src/image/infrastructure/services/ImageEditorService.ts +1 -1
- package/src/image/infrastructure/utils/FilterProcessor.ts +16 -14
- package/src/image/infrastructure/utils/LayerManager.ts +7 -4
- package/src/image/infrastructure/utils/validation/mime-type-validator.ts +1 -1
- package/src/image/presentation/components/ImageGallery.tsx +2 -2
- package/src/image/presentation/components/editor/TextEditorSheet.tsx +3 -3
- package/src/image/presentation/hooks/useImageBatch.ts +1 -1
- package/src/infinite-scroll/domain/types/infinite-scroll-config.ts +1 -1
- package/src/init/createAppInitializer.ts +1 -2
- package/src/init/env/createEnvConfig.ts +2 -3
- package/src/media/domain/entities/CardMultimedia.types.ts +17 -2
- package/src/media/domain/entities/MultimediaFlashcardTypes.ts +17 -2
- package/src/media/infrastructure/services/CardMediaUploadService.ts +2 -3
- package/src/media/infrastructure/services/CardMediaValidationService.ts +2 -2
- package/src/media/infrastructure/services/CardMultimediaService.ts +3 -2
- package/src/media/infrastructure/services/MediaUploadService.ts +2 -1
- package/src/media/infrastructure/services/MediaValidationService.ts +2 -2
- package/src/media/infrastructure/services/MultimediaFlashcardService.ts +3 -2
- package/src/media/presentation/hooks/card-multimedia.types.ts +5 -3
- package/src/media/presentation/hooks/multimedia.types.ts +5 -3
- package/src/media/presentation/hooks/useCardMediaUpload.ts +2 -1
- package/src/media/presentation/hooks/useCardMediaValidation.ts +2 -2
- package/src/media/presentation/hooks/useCardMultimediaFlashcard.ts +3 -2
- package/src/media/presentation/hooks/useMediaUpload.ts +2 -1
- package/src/media/presentation/hooks/useMediaValidation.ts +2 -2
- package/src/media/presentation/hooks/useMultimediaFlashcard.ts +3 -2
- package/src/molecules/BaseModal.tsx +2 -3
- package/src/molecules/bottom-sheet/components/BottomSheetModal.tsx +0 -1
- package/src/molecules/bottom-sheet/components/filter/FilterBottomSheet.tsx +15 -6
- package/src/molecules/bottom-sheet/components/filter/FilterSheetComponents/FilterSheetOption.tsx +1 -1
- package/src/molecules/calendar/infrastructure/storage/CalendarStore.ts +2 -3
- package/src/molecules/calendar/presentation/hooks/useCalendar.ts +3 -3
- package/src/molecules/circular-menu/CircularMenuItem.tsx +1 -1
- package/src/molecules/countdown/components/CountdownHeader.tsx +1 -1
- package/src/molecules/emoji/domain/entities/Emoji.ts +17 -6
- package/src/molecules/emoji/presentation/components/EmojiPicker.tsx +2 -2
- package/src/molecules/filter-group/FilterGroup.tsx +1 -1
- package/src/molecules/filter-group/types.ts +4 -3
- package/src/molecules/navigation/StackNavigator.tsx +3 -3
- package/src/molecules/navigation/TabsNavigator.tsx +6 -6
- package/src/molecules/navigation/components/TabLabel.tsx +1 -1
- package/src/molecules/navigation/index.ts +0 -2
- package/src/molecules/navigation/types.ts +2 -2
- package/src/molecules/navigation/utils/NavigationTheme.ts +1 -1
- package/src/molecules/navigation/utils/ScreenFactory.ts +2 -2
- package/src/molecules/splash/components/SplashScreen.tsx +0 -1
- package/src/molecules/splash/hooks/useSplashFlow.ts +2 -3
- package/src/onboarding/domain/entities/OnboardingQuestion.ts +8 -3
- package/src/onboarding/domain/entities/OnboardingSlide.ts +8 -6
- package/src/onboarding/domain/entities/OnboardingUserData.ts +5 -3
- package/src/onboarding/infrastructure/hooks/useOnboardingAnswers.ts +4 -3
- package/src/onboarding/infrastructure/services/ValidationManager.ts +5 -5
- package/src/onboarding/infrastructure/storage/OnboardingStoreSelectors.ts +2 -1
- package/src/onboarding/infrastructure/storage/actions/answerActions.ts +2 -1
- package/src/onboarding/presentation/components/BackgroundVideo.tsx +3 -2
- package/src/onboarding/presentation/components/OnboardingSlide.tsx +1 -1
- package/src/onboarding/presentation/components/QuestionRenderer.tsx +11 -11
- package/src/onboarding/presentation/components/QuestionSlide.tsx +3 -2
- package/src/onboarding/presentation/components/QuestionSlideHeader.tsx +1 -1
- package/src/onboarding/presentation/components/questions/QuestionOptionItem.tsx +1 -1
- package/src/onboarding/presentation/components/questions/SingleChoiceQuestion.tsx +1 -1
- package/src/onboarding/presentation/hooks/useOnboardingContainerStyle.ts +2 -1
- package/src/onboarding/presentation/hooks/useOnboardingScreenState.ts +5 -3
- package/src/onboarding/presentation/types/OnboardingProps.ts +5 -3
- package/src/storage/cache/domain/Cache.ts +4 -4
- package/src/storage/cache/infrastructure/TTLCache.ts +7 -7
- package/src/storage/domain/factories/StoreFactory.ts +6 -6
- package/src/storage/domain/utils/devUtils.ts +8 -8
- package/src/tanstack/infrastructure/monitoring/DevMonitorLogger.ts +6 -6
- package/src/tanstack/infrastructure/providers/TanstackProvider.tsx +1 -1
- package/src/tanstack/presentation/hooks/useOptimisticUpdate.ts +1 -1
- package/src/theme/core/TokenFactory.ts +40 -33
- package/src/theme/core/colors/DarkColors.ts +1 -1
- package/src/theme/core/colors/LightColors.ts +1 -1
- package/src/theme/infrastructure/globalThemeStore.ts +0 -1
- package/src/atoms/AtomicChip.tsx +0 -7
- package/src/image/infrastructure/utils/ImageFilterUtils.ts +0 -20
- package/src/molecules/navigation/createStackNavigator.ts +0 -20
- package/src/molecules/navigation/createTabNavigator.ts +0 -20
- package/src/safe-area/utils/performance.ts +0 -10
- package/src/storage/cache/types.d.ts +0 -3
- package/src/tanstack/types/global.d.ts +0 -1
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Follows Single Responsibility Principle
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { OnboardingQuestion } from "../../domain/entities/OnboardingQuestion";
|
|
8
|
+
import type { OnboardingQuestion, OnboardingAnswerValue } from "../../domain/entities/OnboardingQuestion";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* ValidationManager
|
|
@@ -19,7 +19,7 @@ export class ValidationManager {
|
|
|
19
19
|
*/
|
|
20
20
|
static validateAnswer(
|
|
21
21
|
question: OnboardingQuestion,
|
|
22
|
-
answer:
|
|
22
|
+
answer: OnboardingAnswerValue,
|
|
23
23
|
): boolean {
|
|
24
24
|
const { validation } = question;
|
|
25
25
|
if (!validation) {
|
|
@@ -56,7 +56,7 @@ export class ValidationManager {
|
|
|
56
56
|
* Validate multiple choice answer
|
|
57
57
|
*/
|
|
58
58
|
private static validateMultipleChoice(
|
|
59
|
-
answer:
|
|
59
|
+
answer: OnboardingAnswerValue,
|
|
60
60
|
validation: OnboardingQuestion["validation"],
|
|
61
61
|
): boolean {
|
|
62
62
|
if (!validation) return true;
|
|
@@ -80,7 +80,7 @@ export class ValidationManager {
|
|
|
80
80
|
* Validate text input answer
|
|
81
81
|
*/
|
|
82
82
|
private static validateTextInput(
|
|
83
|
-
answer:
|
|
83
|
+
answer: OnboardingAnswerValue,
|
|
84
84
|
validation: OnboardingQuestion["validation"],
|
|
85
85
|
): boolean {
|
|
86
86
|
if (!validation) return true;
|
|
@@ -104,7 +104,7 @@ export class ValidationManager {
|
|
|
104
104
|
* Validate numeric answer (rating)
|
|
105
105
|
*/
|
|
106
106
|
private static validateNumeric(
|
|
107
|
-
answer:
|
|
107
|
+
answer: OnboardingAnswerValue,
|
|
108
108
|
validation: OnboardingQuestion["validation"],
|
|
109
109
|
): boolean {
|
|
110
110
|
if (!validation) return true;
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
* Single Responsibility: Store state selectors
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import type { OnboardingAnswerValue } from "../../domain/entities/OnboardingQuestion";
|
|
6
7
|
import type { OnboardingStoreState } from "./OnboardingStoreState";
|
|
7
8
|
|
|
8
9
|
export interface OnboardingStoreSelectors {
|
|
9
|
-
getAnswer: (questionId: string) =>
|
|
10
|
+
getAnswer: (questionId: string) => OnboardingAnswerValue;
|
|
10
11
|
getUserData: () => OnboardingStoreState['userData'];
|
|
11
12
|
}
|
|
12
13
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { storageRepository } from "../../../../storage";
|
|
7
|
+
import type { OnboardingAnswerValue } from "../../../domain/entities/OnboardingQuestion";
|
|
7
8
|
import type { OnboardingUserData } from "../../../domain/entities/OnboardingUserData";
|
|
8
9
|
import type { OnboardingStoreState } from "../OnboardingStoreState";
|
|
9
10
|
import { USER_DATA_STORAGE_KEY, handleError, logSuccess } from "./storageHelpers";
|
|
@@ -19,7 +20,7 @@ export async function saveAnswerAction(
|
|
|
19
20
|
...get().userData,
|
|
20
21
|
answers: {
|
|
21
22
|
...get().userData.answers,
|
|
22
|
-
[questionId]: answer,
|
|
23
|
+
[questionId]: answer as OnboardingAnswerValue,
|
|
23
24
|
},
|
|
24
25
|
};
|
|
25
26
|
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { StyleSheet, View } from 'react-native';
|
|
3
3
|
import { useVideoPlayer, VideoView } from 'expo-video';
|
|
4
|
+
import type { VideoSource, VideoPlayer } from 'expo-video';
|
|
4
5
|
|
|
5
6
|
interface BackgroundVideoProps {
|
|
6
|
-
source:
|
|
7
|
+
source: VideoSource;
|
|
7
8
|
overlayOpacity?: number;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
export const BackgroundVideo = ({ source, overlayOpacity = 0.5 }: BackgroundVideoProps) => {
|
|
11
|
-
const player = useVideoPlayer(source, (p:
|
|
12
|
+
const player = useVideoPlayer(source, (p: VideoPlayer) => {
|
|
12
13
|
p.loop = true;
|
|
13
14
|
p.play();
|
|
14
15
|
p.muted = true;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import React from "react";
|
|
7
|
-
import type { OnboardingQuestion } from "../../domain/entities/OnboardingQuestion";
|
|
7
|
+
import type { OnboardingQuestion, OnboardingAnswerValue } from "../../domain/entities/OnboardingQuestion";
|
|
8
8
|
import { SingleChoiceQuestion } from "./questions/SingleChoiceQuestion";
|
|
9
9
|
import { MultipleChoiceQuestion } from "./questions/MultipleChoiceQuestion";
|
|
10
10
|
import { TextInputQuestion } from "./questions/TextInputQuestion";
|
|
@@ -12,8 +12,8 @@ import { RatingQuestion } from "./questions/RatingQuestion";
|
|
|
12
12
|
|
|
13
13
|
export interface QuestionRendererProps {
|
|
14
14
|
question: OnboardingQuestion;
|
|
15
|
-
value:
|
|
16
|
-
onChange: (value:
|
|
15
|
+
value: OnboardingAnswerValue;
|
|
16
|
+
onChange: (value: OnboardingAnswerValue) => void;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export const QuestionRenderer = ({
|
|
@@ -26,32 +26,32 @@ export const QuestionRenderer = ({
|
|
|
26
26
|
return (
|
|
27
27
|
<SingleChoiceQuestion
|
|
28
28
|
question={question}
|
|
29
|
-
value={value}
|
|
30
|
-
onChange={onChange}
|
|
29
|
+
value={value as string | undefined}
|
|
30
|
+
onChange={onChange as (value: string) => void}
|
|
31
31
|
/>
|
|
32
32
|
);
|
|
33
33
|
case "multiple_choice":
|
|
34
34
|
return (
|
|
35
35
|
<MultipleChoiceQuestion
|
|
36
36
|
question={question}
|
|
37
|
-
value={value}
|
|
38
|
-
onChange={onChange}
|
|
37
|
+
value={value as string[] | undefined}
|
|
38
|
+
onChange={onChange as (value: string[]) => void}
|
|
39
39
|
/>
|
|
40
40
|
);
|
|
41
41
|
case "text_input":
|
|
42
42
|
return (
|
|
43
43
|
<TextInputQuestion
|
|
44
44
|
question={question}
|
|
45
|
-
value={value}
|
|
46
|
-
onChange={onChange}
|
|
45
|
+
value={value as string | undefined}
|
|
46
|
+
onChange={onChange as (value: string) => void}
|
|
47
47
|
/>
|
|
48
48
|
);
|
|
49
49
|
case "rating":
|
|
50
50
|
return (
|
|
51
51
|
<RatingQuestion
|
|
52
52
|
question={question}
|
|
53
|
-
value={value}
|
|
54
|
-
onChange={onChange}
|
|
53
|
+
value={value as number | undefined}
|
|
54
|
+
onChange={onChange as (value: number) => void}
|
|
55
55
|
/>
|
|
56
56
|
);
|
|
57
57
|
default:
|
|
@@ -2,6 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { View, StyleSheet } from "react-native";
|
|
3
3
|
import { AtomicText } from "../../../atoms/AtomicText";
|
|
4
4
|
import type { OnboardingSlide } from "../../domain/entities/OnboardingSlide";
|
|
5
|
+
import type { OnboardingAnswerValue } from "../../domain/entities/OnboardingQuestion";
|
|
5
6
|
import { QuestionSlideHeader } from "./QuestionSlideHeader";
|
|
6
7
|
import { QuestionRenderer } from "./QuestionRenderer";
|
|
7
8
|
import { BaseSlide } from "./BaseSlide";
|
|
@@ -9,8 +10,8 @@ import { useOnboardingProvider } from "../providers/OnboardingProvider";
|
|
|
9
10
|
|
|
10
11
|
export interface QuestionSlideProps {
|
|
11
12
|
slide: OnboardingSlide;
|
|
12
|
-
value:
|
|
13
|
-
onChange: (value:
|
|
13
|
+
value: OnboardingAnswerValue;
|
|
14
|
+
onChange: (value: OnboardingAnswerValue) => void;
|
|
14
15
|
variant?: "default" | "card" | "minimal" | "fullscreen";
|
|
15
16
|
fieldRequiredText?: string;
|
|
16
17
|
}
|
|
@@ -26,7 +26,7 @@ export const QuestionSlideHeader = ({ slide }: QuestionSlideHeaderProps) => {
|
|
|
26
26
|
{isEmoji ? (
|
|
27
27
|
<AtomicText style={{ fontSize: 48 }}>{slide.icon}</AtomicText>
|
|
28
28
|
) : (
|
|
29
|
-
<AtomicIcon name={slide.icon
|
|
29
|
+
<AtomicIcon name={slide.icon} customSize={48} customColor={colors.textColor} />
|
|
30
30
|
)}
|
|
31
31
|
</View>
|
|
32
32
|
|
|
@@ -46,7 +46,7 @@ export const QuestionOptionItem = ({
|
|
|
46
46
|
<AtomicText style={{ fontSize: 24 }}>{option.icon}</AtomicText>
|
|
47
47
|
) : (
|
|
48
48
|
<AtomicIcon
|
|
49
|
-
name={option.icon
|
|
49
|
+
name={option.icon}
|
|
50
50
|
customSize={20}
|
|
51
51
|
customColor={isSelected ? colors.buttonTextColor : colors.subTextColor}
|
|
52
52
|
/>
|
|
@@ -46,7 +46,7 @@ export const SingleChoiceQuestion = ({
|
|
|
46
46
|
<AtomicText style={{ fontSize: 24 }}>{option.icon}</AtomicText>
|
|
47
47
|
) : (
|
|
48
48
|
<AtomicIcon
|
|
49
|
-
name={option.icon
|
|
49
|
+
name={option.icon}
|
|
50
50
|
customSize={20}
|
|
51
51
|
customColor={isSelected ? colors.buttonTextColor : colors.subTextColor}
|
|
52
52
|
/>
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { useMemo } from "react";
|
|
7
|
+
import type { StyleProp, ViewStyle } from "react-native";
|
|
7
8
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
8
9
|
import { useAppDesignTokens } from "../../../theme/hooks/useAppDesignTokens";
|
|
9
10
|
|
|
@@ -12,7 +13,7 @@ export interface UseOnboardingContainerStyleProps {
|
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export interface UseOnboardingContainerStyleReturn {
|
|
15
|
-
containerStyle:
|
|
16
|
+
containerStyle: StyleProp<ViewStyle>;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export function useOnboardingContainerStyle({
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { useMemo, useEffect } from "react";
|
|
7
|
+
import type { StyleProp, ViewStyle } from "react-native";
|
|
7
8
|
import type { OnboardingSlide } from "../../domain/entities/OnboardingSlide";
|
|
9
|
+
import type { OnboardingAnswerValue } from "../../domain/entities/OnboardingQuestion";
|
|
8
10
|
import { useOnboarding } from "../../infrastructure/storage/OnboardingStore";
|
|
9
11
|
import { useOnboardingNavigation } from "../../infrastructure/hooks/useOnboardingNavigation";
|
|
10
12
|
import { useOnboardingAnswers } from "../../infrastructure/hooks/useOnboardingAnswers";
|
|
@@ -28,14 +30,14 @@ export interface UseOnboardingScreenStateReturn {
|
|
|
28
30
|
currentIndex: number;
|
|
29
31
|
isFirstSlide: boolean;
|
|
30
32
|
isLastSlide: boolean;
|
|
31
|
-
currentAnswer:
|
|
33
|
+
currentAnswer: OnboardingAnswerValue;
|
|
32
34
|
isAnswerValid: boolean;
|
|
33
35
|
useCustomBackground: boolean;
|
|
34
|
-
containerStyle:
|
|
36
|
+
containerStyle: StyleProp<ViewStyle>;
|
|
35
37
|
handleNext: () => Promise<void>;
|
|
36
38
|
handlePrevious: () => void;
|
|
37
39
|
handleSkip: () => Promise<void>;
|
|
38
|
-
setCurrentAnswer: (value:
|
|
40
|
+
setCurrentAnswer: (value: OnboardingAnswerValue) => void;
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
export function useOnboardingScreenState({
|
|
@@ -2,17 +2,19 @@
|
|
|
2
2
|
* Onboarding Screen Content Props
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import type { StyleProp, ViewStyle } from "react-native";
|
|
5
6
|
import type { OnboardingSlide } from "../../domain/entities/OnboardingSlide";
|
|
7
|
+
import type { OnboardingAnswerValue } from "../../domain/entities/OnboardingQuestion";
|
|
6
8
|
|
|
7
9
|
export interface OnboardingScreenContentProps {
|
|
8
|
-
containerStyle?:
|
|
10
|
+
containerStyle?: StyleProp<ViewStyle>;
|
|
9
11
|
useCustomBackground: boolean;
|
|
10
12
|
currentSlide: OnboardingSlide | undefined;
|
|
11
13
|
isFirstSlide: boolean;
|
|
12
14
|
isLastSlide: boolean;
|
|
13
15
|
currentIndex: number;
|
|
14
16
|
totalSlides: number;
|
|
15
|
-
currentAnswer:
|
|
17
|
+
currentAnswer: OnboardingAnswerValue;
|
|
16
18
|
isAnswerValid: boolean;
|
|
17
19
|
showBackButton: boolean;
|
|
18
20
|
showSkipButton: boolean;
|
|
@@ -25,7 +27,7 @@ export interface OnboardingScreenContentProps {
|
|
|
25
27
|
onBack: () => void;
|
|
26
28
|
onSkip: () => void;
|
|
27
29
|
onNext: () => void;
|
|
28
|
-
onAnswerChange: (value:
|
|
30
|
+
onAnswerChange: (value: OnboardingAnswerValue) => void;
|
|
29
31
|
renderHeader?: (props: {
|
|
30
32
|
isFirstSlide: boolean;
|
|
31
33
|
onBack: () => void;
|
|
@@ -11,9 +11,9 @@ import { FIFOStrategy } from './strategies/FIFOStrategy';
|
|
|
11
11
|
import { TTLStrategy } from './strategies/TTLStrategy';
|
|
12
12
|
|
|
13
13
|
export class Cache<T = unknown> {
|
|
14
|
-
|
|
14
|
+
protected store = new Map<string, CacheEntry<T>>();
|
|
15
15
|
private config: Required<CacheConfig>;
|
|
16
|
-
|
|
16
|
+
protected statsTracker = new CacheStatsTracker();
|
|
17
17
|
private strategies = {
|
|
18
18
|
lru: new LRUStrategy<T>(),
|
|
19
19
|
lfu: new LFUStrategy<T>(),
|
|
@@ -46,7 +46,7 @@ export class Cache<T = unknown> {
|
|
|
46
46
|
this.store.set(key, entry);
|
|
47
47
|
this.statsTracker.updateSize(this.store.size);
|
|
48
48
|
|
|
49
|
-
if (
|
|
49
|
+
if (__DEV__) {
|
|
50
50
|
console.log(`Cache: Set key "${key}" with TTL ${entry.ttl}ms`);
|
|
51
51
|
}
|
|
52
52
|
}
|
|
@@ -134,7 +134,7 @@ export class Cache<T = unknown> {
|
|
|
134
134
|
this.statsTracker.recordEviction();
|
|
135
135
|
this.statsTracker.updateSize(this.store.size);
|
|
136
136
|
|
|
137
|
-
if (
|
|
137
|
+
if (__DEV__) {
|
|
138
138
|
console.log(`Cache: Evicted key "${keyToEvict}" using ${strategy} strategy`);
|
|
139
139
|
}
|
|
140
140
|
|
|
@@ -36,18 +36,18 @@ export class TTLCache<T = unknown> extends Cache<T> {
|
|
|
36
36
|
const now = Date.now();
|
|
37
37
|
|
|
38
38
|
for (const key of keys) {
|
|
39
|
-
const entry =
|
|
39
|
+
const entry = this.store.get(key);
|
|
40
40
|
if (entry && (now - entry.timestamp) > entry.ttl) {
|
|
41
|
-
|
|
41
|
+
this.store.delete(key);
|
|
42
42
|
cleanedCount++;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
if (cleanedCount > 0) {
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
this.statsTracker.updateSize(this.store.size);
|
|
48
|
+
this.statsTracker.recordExpiration();
|
|
49
49
|
|
|
50
|
-
if (
|
|
50
|
+
if (__DEV__) {
|
|
51
51
|
console.log(`TTLCache: Cleaned up ${cleanedCount} expired entries`);
|
|
52
52
|
}
|
|
53
53
|
}
|
|
@@ -68,7 +68,7 @@ export class TTLCache<T = unknown> extends Cache<T> {
|
|
|
68
68
|
|
|
69
69
|
override set(key: string, value: T, ttl?: number): void {
|
|
70
70
|
if (this.isDestroyed) {
|
|
71
|
-
if (
|
|
71
|
+
if (__DEV__) {
|
|
72
72
|
console.warn('TTLCache: Attempted to set value on destroyed cache');
|
|
73
73
|
}
|
|
74
74
|
return;
|
|
@@ -78,7 +78,7 @@ export class TTLCache<T = unknown> extends Cache<T> {
|
|
|
78
78
|
|
|
79
79
|
override get(key: string): T | undefined {
|
|
80
80
|
if (this.isDestroyed) {
|
|
81
|
-
if (
|
|
81
|
+
if (__DEV__) {
|
|
82
82
|
console.warn('TTLCache: Attempted to get value from destroyed cache');
|
|
83
83
|
}
|
|
84
84
|
return undefined;
|
|
@@ -37,8 +37,8 @@ export function createStore<
|
|
|
37
37
|
name: config.name,
|
|
38
38
|
storage: createJSONStorage(() => storageService),
|
|
39
39
|
version: config.version || 1,
|
|
40
|
-
partialize: config.partialize
|
|
41
|
-
? (state: Store) => config.partialize!(state
|
|
40
|
+
partialize: (config.partialize
|
|
41
|
+
? (state: Store) => config.partialize!(state)
|
|
42
42
|
: (state: Store) => {
|
|
43
43
|
const persisted: Record<string, unknown> = {};
|
|
44
44
|
for (const key of Object.keys(state)) {
|
|
@@ -46,14 +46,14 @@ export function createStore<
|
|
|
46
46
|
persisted[key] = state[key as keyof Store];
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
return persisted
|
|
50
|
-
},
|
|
49
|
+
return persisted;
|
|
50
|
+
}) as (state: Store) => Store,
|
|
51
51
|
onRehydrateStorage: () => (state: Store | undefined) => {
|
|
52
52
|
if (state && config.onRehydrate) {
|
|
53
|
-
config.onRehydrate(state
|
|
53
|
+
config.onRehydrate(state);
|
|
54
54
|
}
|
|
55
55
|
},
|
|
56
|
-
migrate: config.migrate as
|
|
56
|
+
migrate: config.migrate as ((persistedState: unknown, version: number) => Store | Promise<Store>),
|
|
57
57
|
})
|
|
58
58
|
);
|
|
59
59
|
}
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
* Check if running in development mode
|
|
7
7
|
*/
|
|
8
8
|
export const isDev = (): boolean => {
|
|
9
|
-
return
|
|
9
|
+
return __DEV__;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Log warning in development mode only
|
|
14
14
|
*/
|
|
15
|
-
export const devWarn = (message: string, ...args:
|
|
16
|
-
if (
|
|
15
|
+
export const devWarn = (message: string, ...args: unknown[]): void => {
|
|
16
|
+
if (__DEV__) {
|
|
17
17
|
console.warn(message, ...args);
|
|
18
18
|
}
|
|
19
19
|
};
|
|
@@ -21,8 +21,8 @@ export const devWarn = (message: string, ...args: any[]): void => {
|
|
|
21
21
|
/**
|
|
22
22
|
* Log error in development mode only
|
|
23
23
|
*/
|
|
24
|
-
export const devError = (message: string, ...args:
|
|
25
|
-
if (
|
|
24
|
+
export const devError = (message: string, ...args: unknown[]): void => {
|
|
25
|
+
if (__DEV__) {
|
|
26
26
|
console.error(message, ...args);
|
|
27
27
|
}
|
|
28
28
|
};
|
|
@@ -30,8 +30,8 @@ export const devError = (message: string, ...args: any[]): void => {
|
|
|
30
30
|
/**
|
|
31
31
|
* Log info in development mode only
|
|
32
32
|
*/
|
|
33
|
-
export const devLog = (message: string, ...args:
|
|
34
|
-
if (
|
|
33
|
+
export const devLog = (message: string, ...args: unknown[]): void => {
|
|
34
|
+
if (__DEV__) {
|
|
35
35
|
console.log(message, ...args);
|
|
36
36
|
}
|
|
37
|
-
};
|
|
37
|
+
};
|
|
@@ -7,13 +7,13 @@ import type { QueryMetrics, CacheStats } from './DevMonitor.types';
|
|
|
7
7
|
|
|
8
8
|
export class DevMonitorLogger {
|
|
9
9
|
static logInit(): void {
|
|
10
|
-
if (
|
|
10
|
+
if (__DEV__) {
|
|
11
11
|
console.log('[TanStack DevMonitor] Monitoring initialized');
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
static logSlowQuery(queryKeyString: string, fetchTime: number): void {
|
|
16
|
-
if (
|
|
16
|
+
if (__DEV__) {
|
|
17
17
|
console.warn(
|
|
18
18
|
`[TanStack DevMonitor] Slow query detected: ${queryKeyString} (${fetchTime}ms)`,
|
|
19
19
|
);
|
|
@@ -21,25 +21,25 @@ export class DevMonitorLogger {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
static logAttached(): void {
|
|
24
|
-
if (
|
|
24
|
+
if (__DEV__) {
|
|
25
25
|
console.log('[TanStack DevMonitor] Attached to QueryClient');
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
static logMethodsCleared(): void {
|
|
30
|
-
if (
|
|
30
|
+
if (__DEV__) {
|
|
31
31
|
console.log('[TanStack DevMonitor] Metrics cleared');
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
static logReset(): void {
|
|
36
|
-
if (
|
|
36
|
+
if (__DEV__) {
|
|
37
37
|
console.log('[TanStack DevMonitor] Reset');
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
static logReport(stats: CacheStats | null, slowQueries: QueryMetrics[]): void {
|
|
42
|
-
if (
|
|
42
|
+
if (__DEV__) {
|
|
43
43
|
console.group('[TanStack DevMonitor] Performance Report');
|
|
44
44
|
|
|
45
45
|
if (stats) {
|
|
@@ -82,7 +82,7 @@ export function TanstackProvider({
|
|
|
82
82
|
const client = providedQueryClient ?? createQueryClient(queryClientOptions);
|
|
83
83
|
setGlobalQueryClient(client);
|
|
84
84
|
|
|
85
|
-
if (enableDevTools &&
|
|
85
|
+
if (enableDevTools && __DEV__) {
|
|
86
86
|
DevMonitor.attach(client);
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -47,7 +47,7 @@ export function useOptimisticUpdate<TData = unknown, TVariables = unknown, TErro
|
|
|
47
47
|
},
|
|
48
48
|
onError: (error: TError, variables: TVariables, context: unknown) => {
|
|
49
49
|
|
|
50
|
-
const ctx = context as
|
|
50
|
+
const ctx = context as { previousData?: TData } | undefined;
|
|
51
51
|
if (ctx?.previousData !== undefined) {
|
|
52
52
|
queryClient.setQueryData(queryKey, ctx.previousData);
|
|
53
53
|
|
|
@@ -6,9 +6,6 @@ import { type DesignTokens, type ResponsiveTypography } from '../types/ThemeType
|
|
|
6
6
|
/**
|
|
7
7
|
* Create complete design tokens for a specific theme mode
|
|
8
8
|
*
|
|
9
|
-
* ✅ Responsive by default
|
|
10
|
-
* ✅ SINGLE SOURCE OF TRUTH
|
|
11
|
-
*
|
|
12
9
|
* @param mode - Theme mode ('light' or 'dark')
|
|
13
10
|
* @param customColors - Optional custom colors to override default colors
|
|
14
11
|
* @param multiplier - Device-based spacing multiplier
|
|
@@ -25,48 +22,59 @@ export const createDesignTokens = (
|
|
|
25
22
|
const colors = applyCustomColors(baseColors, customColors);
|
|
26
23
|
|
|
27
24
|
// Responsive Spacing
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
type SpacingKeys = keyof typeof BASE_TOKENS.spacing;
|
|
26
|
+
const spacing: Record<string, number | string> = {};
|
|
27
|
+
for (const key of Object.keys(BASE_TOKENS.spacing) as SpacingKeys[]) {
|
|
28
|
+
const value = BASE_TOKENS.spacing[key];
|
|
29
|
+
spacing[key] = typeof value === 'number' ? value * multiplier : value;
|
|
30
|
+
}
|
|
33
31
|
|
|
34
32
|
// Responsive Typography
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
type TypographyKeys = keyof typeof BASE_TOKENS.typography;
|
|
34
|
+
const typography: Record<string, unknown> = {};
|
|
35
|
+
for (const key of Object.keys(BASE_TOKENS.typography) as TypographyKeys[]) {
|
|
36
|
+
const style = BASE_TOKENS.typography[key];
|
|
37
|
+
if (typeof style === 'object' && 'fontSize' in style) {
|
|
38
|
+
typography[key] = {
|
|
39
|
+
...style,
|
|
40
40
|
responsiveFontSize: getFontSize(style.fontSize as number),
|
|
41
41
|
};
|
|
42
42
|
} else {
|
|
43
|
-
|
|
43
|
+
typography[key] = style;
|
|
44
44
|
}
|
|
45
|
-
|
|
46
|
-
}, {} as any) as ResponsiveTypography;
|
|
45
|
+
}
|
|
47
46
|
|
|
48
47
|
// Responsive Borders
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
type RadiusKeys = keyof typeof BASE_TOKENS.borders.radius;
|
|
49
|
+
const borderRadius = (Object.keys(BASE_TOKENS.borders.radius) as RadiusKeys[]).reduce<Record<RadiusKeys, number>>((acc, key) => {
|
|
50
|
+
const value = BASE_TOKENS.borders.radius[key];
|
|
51
|
+
acc[key] = value === 0 || key === 'full' ? value : Math.round(value * multiplier);
|
|
52
|
+
return acc;
|
|
53
|
+
}, {} as Record<RadiusKeys, number>);
|
|
54
|
+
|
|
55
|
+
// Responsive Icon Sizes
|
|
56
|
+
type IconKeys = keyof typeof BASE_TOKENS.iconSizes;
|
|
57
|
+
const iconSizes = (Object.keys(BASE_TOKENS.iconSizes) as IconKeys[]).reduce<Record<IconKeys, number>>((acc, key) => {
|
|
58
|
+
acc[key] = BASE_TOKENS.iconSizes[key] * multiplier;
|
|
59
|
+
return acc;
|
|
60
|
+
}, {} as Record<IconKeys, number>);
|
|
61
|
+
|
|
62
|
+
// Responsive Avatar Sizes
|
|
63
|
+
type AvatarKeys = keyof typeof BASE_TOKENS.avatarSizes;
|
|
64
|
+
const avatarSizes = (Object.keys(BASE_TOKENS.avatarSizes) as AvatarKeys[]).reduce<Record<AvatarKeys, number>>((acc, key) => {
|
|
65
|
+
acc[key] = BASE_TOKENS.avatarSizes[key] * multiplier;
|
|
52
66
|
return acc;
|
|
53
|
-
}, {} as
|
|
67
|
+
}, {} as Record<AvatarKeys, number>);
|
|
54
68
|
|
|
55
69
|
return {
|
|
56
70
|
colors,
|
|
57
|
-
spacing,
|
|
58
|
-
typography,
|
|
59
|
-
iconSizes:
|
|
60
|
-
acc[key as keyof typeof BASE_TOKENS.iconSizes] = BASE_TOKENS.iconSizes[key as keyof typeof BASE_TOKENS.iconSizes] * multiplier;
|
|
61
|
-
return acc;
|
|
62
|
-
}, {} as any),
|
|
71
|
+
spacing: spacing as DesignTokens['spacing'],
|
|
72
|
+
typography: typography as ResponsiveTypography,
|
|
73
|
+
iconSizes: iconSizes as DesignTokens['iconSizes'],
|
|
63
74
|
opacity: BASE_TOKENS.opacity,
|
|
64
|
-
avatarSizes:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}, {} as any),
|
|
68
|
-
radius: borderRadius,
|
|
69
|
-
borderRadius: borderRadius,
|
|
75
|
+
avatarSizes: avatarSizes as DesignTokens['avatarSizes'],
|
|
76
|
+
radius: borderRadius as DesignTokens['radius'],
|
|
77
|
+
borderRadius: borderRadius as DesignTokens['borderRadius'],
|
|
70
78
|
borders: {
|
|
71
79
|
...BASE_TOKENS.borders,
|
|
72
80
|
radius: borderRadius,
|
|
@@ -88,4 +96,3 @@ export const createDesignTokens = (
|
|
|
88
96
|
|
|
89
97
|
export { withAlpha };
|
|
90
98
|
export type { ThemeMode, ColorPalette };
|
|
91
|
-
|
|
@@ -112,7 +112,7 @@ export const darkColors = {
|
|
|
112
112
|
|
|
113
113
|
cardBackground: '#1E293B', // Dark card background
|
|
114
114
|
|
|
115
|
-
// COLOR ALIASES
|
|
115
|
+
// COLOR ALIASES
|
|
116
116
|
text: '#F1F5F9', // Alias for textPrimary
|
|
117
117
|
background: '#0F172A', // Alias for backgroundPrimary
|
|
118
118
|
card: '#1E293B', // Alias for cardBackground
|
|
@@ -112,7 +112,7 @@ export const lightColors = {
|
|
|
112
112
|
|
|
113
113
|
cardBackground: '#FFFFFF',
|
|
114
114
|
|
|
115
|
-
// COLOR ALIASES
|
|
115
|
+
// COLOR ALIASES
|
|
116
116
|
text: '#1E293B', // Alias for textPrimary
|
|
117
117
|
background: '#FFFFFF', // Alias for backgroundPrimary
|
|
118
118
|
card: '#FFFFFF', // Alias for cardBackground
|