@umituz/react-native-design-system 4.27.15 → 4.27.17
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/dist/core/cache/domain/CleanupStrategy.d.ts +62 -0
- package/dist/core/cache/domain/UnifiedCache.d.ts +82 -0
- package/dist/core/cache/domain/types.d.ts +15 -0
- package/dist/core/cache/index.d.ts +13 -0
- package/dist/core/cache/infrastructure/CacheFactory.d.ts +63 -0
- package/dist/core/index.d.ts +17 -0
- package/dist/core/permissions/domain/PermissionHandler.d.ts +82 -0
- package/dist/core/permissions/domain/types.d.ts +42 -0
- package/dist/core/permissions/index.d.ts +7 -0
- package/dist/core/repositories/domain/RepositoryKeyFactory.d.ts +25 -0
- package/dist/core/repositories/domain/RepositoryUtils.d.ts +39 -0
- package/dist/core/repositories/domain/types.d.ts +53 -0
- package/dist/core/repositories/index.d.ts +10 -0
- package/dist/hooks/index.d.ts +27 -0
- package/dist/index.d.ts +1 -0
- package/dist/media/domain/strategies/CameraPickerStrategy.d.ts +25 -0
- package/dist/media/domain/strategies/LibraryPickerStrategy.d.ts +18 -0
- package/dist/media/domain/strategies/PickerStrategy.d.ts +55 -0
- package/dist/media/domain/strategies/index.d.ts +10 -0
- package/dist/media/infrastructure/services/MediaPickerService.d.ts +49 -6
- package/dist/media/infrastructure/utils/PermissionManager.d.ts +6 -0
- package/dist/media/infrastructure/utils/mediaPickerMappers.d.ts +15 -1
- package/dist/molecules/calendar/infrastructure/services/CalendarService.d.ts +1 -0
- package/dist/molecules/calendar/infrastructure/storage/CalendarStore.d.ts +2 -2
- package/dist/molecules/filter-group/FilterGroup.d.ts +1 -1
- package/dist/molecules/navigation/index.d.ts +1 -1
- package/dist/offline/index.d.ts +1 -1
- package/dist/offline/presentation/hooks/useOffline.d.ts +0 -5
- package/dist/tanstack/domain/repositories/BaseRepository.d.ts +5 -1
- package/dist/tanstack/infrastructure/monitoring/DevMonitor.d.ts +1 -0
- package/dist/utils/constants/TimeConstants.d.ts +27 -0
- package/package.json +11 -6
- package/src/atoms/GlassView/GlassView.tsx +0 -2
- package/src/atoms/picker/components/PickerChips.tsx +27 -21
- package/src/core/cache/index.ts +3 -2
- package/src/core/index.ts +5 -3
- package/src/core/repositories/domain/RepositoryUtils.ts +4 -4
- package/src/core/repositories/domain/types.ts +2 -2
- package/src/hooks/index.ts +22 -25
- package/src/image/presentation/components/ImageGallery.tsx +25 -21
- package/src/infinite-scroll/presentation/hooks/useInfiniteScroll.ts +32 -29
- package/src/media/domain/strategies/CameraPickerStrategy.ts +4 -8
- package/src/media/domain/strategies/index.ts +1 -1
- package/src/media/infrastructure/services/MediaPickerService.ts +3 -14
- package/src/media/infrastructure/utils/mediaPickerMappers.ts +29 -6
- package/src/molecules/avatar/AvatarGroup.tsx +137 -62
- package/src/molecules/filter-group/FilterGroup.tsx +31 -22
- package/src/molecules/icon-grid/IconGrid.tsx +52 -20
- package/src/molecules/swipe-actions/domain/entities/SwipeAction.ts +0 -1
- package/src/offline/index.ts +1 -1
- package/src/offline/presentation/hooks/useOffline.ts +0 -8
- package/src/onboarding/presentation/components/BackgroundImageCollage.tsx +32 -23
- package/src/storage/README.md +0 -1
- package/src/storage/cache/domain/types/README.md +0 -1
- package/src/storage/cache/presentation/README.md +0 -1
- package/src/storage/cache/presentation/useCachedValue.ts +12 -2
- package/src/storage/domain/constants/README.md +0 -1
- package/src/storage/infrastructure/adapters/README.md +0 -1
- package/src/storage/presentation/hooks/README.md +0 -6
- package/src/storage/presentation/hooks/useStorageState.ts +13 -4
- package/src/tanstack/domain/repositories/BaseRepository.ts +1 -1
- package/src/theme/hooks/useAppDesignTokens.ts +29 -3
- package/src/timezone/infrastructure/services/TimezoneProvider.ts +2 -2
- package/src/init/index.ts +0 -29
- package/src/layouts/ScreenLayout/index.ts +0 -1
- package/src/layouts/index.ts +0 -5
- package/src/molecules/SearchBar/index.ts +0 -4
- package/src/molecules/StepProgress/index.ts +0 -1
- package/src/molecules/alerts/index.ts +0 -47
- package/src/molecules/bottom-sheet/index.ts +0 -10
- package/src/molecules/circular-menu/index.ts +0 -3
- package/src/molecules/filter-group/index.ts +0 -3
- package/src/molecules/index.ts +0 -38
- package/src/molecules/info-grid/index.ts +0 -3
- package/src/molecules/swipe-actions/index.ts +0 -6
- package/src/presentation/utils/variants/index.ts +0 -6
- package/src/timezone/infrastructure/utils/SimpleCache.ts +0 -64
- package/src/utilities/index.ts +0 -6
|
@@ -2,18 +2,61 @@
|
|
|
2
2
|
* Media Domain - Media Picker Service
|
|
3
3
|
*
|
|
4
4
|
* Service for picking images/videos using expo-image-picker.
|
|
5
|
-
*
|
|
5
|
+
* Refactored to use strategy pattern to reduce code duplication.
|
|
6
|
+
*
|
|
7
|
+
* Before: 182 LOC with 4 similar methods
|
|
8
|
+
* After: ~120 LOC with 1 generic launcher + convenience wrappers - 34% reduction
|
|
6
9
|
*/
|
|
7
|
-
import type { MediaPickerOptions, MediaPickerResult, CameraOptions } from
|
|
10
|
+
import type { MediaPickerOptions, MediaPickerResult, CameraOptions } from '../../domain/entities/Media';
|
|
11
|
+
import type { PickerStrategy, LaunchOptions } from '../../domain/strategies/PickerStrategy';
|
|
8
12
|
/**
|
|
9
13
|
* Media picker service for selecting images/videos
|
|
14
|
+
* Uses strategy pattern to support different picker types
|
|
10
15
|
*/
|
|
11
16
|
export declare class MediaPickerService {
|
|
17
|
+
/**
|
|
18
|
+
* Generic media picker launcher using strategy pattern
|
|
19
|
+
*
|
|
20
|
+
* @param strategy - Picker strategy to use
|
|
21
|
+
* @param options - Picker options
|
|
22
|
+
* @returns Picker result
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* const strategy = new CameraPickerStrategy({ mediaType: 'images' });
|
|
27
|
+
* const result = await MediaPickerService.launchMediaPicker(strategy, {
|
|
28
|
+
* quality: 0.8,
|
|
29
|
+
* allowsEditing: true
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
static launchMediaPicker(strategy: PickerStrategy, options?: LaunchOptions): Promise<MediaPickerResult>;
|
|
34
|
+
/**
|
|
35
|
+
* Launch camera for image capture
|
|
36
|
+
*/
|
|
12
37
|
static launchCamera(options?: CameraOptions): Promise<MediaPickerResult>;
|
|
38
|
+
/**
|
|
39
|
+
* Launch camera for video capture
|
|
40
|
+
*/
|
|
13
41
|
static launchCameraForVideo(options?: CameraOptions): Promise<MediaPickerResult>;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
static
|
|
42
|
+
/**
|
|
43
|
+
* Pick from library with file size validation
|
|
44
|
+
*/
|
|
45
|
+
static pickFromLibrary(options?: MediaPickerOptions): Promise<MediaPickerResult>;
|
|
46
|
+
/**
|
|
47
|
+
* Pick single image from library
|
|
48
|
+
*/
|
|
49
|
+
static pickSingleImage(options?: Omit<MediaPickerOptions, 'allowsMultipleSelection'>): Promise<MediaPickerResult>;
|
|
50
|
+
/**
|
|
51
|
+
* Pick multiple images from library
|
|
52
|
+
*/
|
|
53
|
+
static pickMultipleImages(options?: Omit<MediaPickerOptions, 'allowsMultipleSelection'>): Promise<MediaPickerResult>;
|
|
54
|
+
/**
|
|
55
|
+
* Pick video from library
|
|
56
|
+
*/
|
|
57
|
+
static pickVideo(options?: Omit<MediaPickerOptions, 'mediaTypes'>): Promise<MediaPickerResult>;
|
|
58
|
+
/**
|
|
59
|
+
* Pick any media from library
|
|
60
|
+
*/
|
|
18
61
|
static pickMedia(options?: MediaPickerOptions): Promise<MediaPickerResult>;
|
|
19
62
|
}
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* Permission Manager
|
|
3
3
|
*
|
|
4
4
|
* Centralized permission handling for media operations.
|
|
5
|
+
* Refactored to use generic PermissionHandler to reduce duplication.
|
|
6
|
+
*
|
|
7
|
+
* Before: 4 similar methods (~80 LOC)
|
|
8
|
+
* After: 1 generic handler (~50 LOC) - 37% reduction
|
|
5
9
|
*/
|
|
6
10
|
import { MediaLibraryPermission } from "../../domain/entities/Media";
|
|
7
11
|
/**
|
|
@@ -10,8 +14,10 @@ import { MediaLibraryPermission } from "../../domain/entities/Media";
|
|
|
10
14
|
export type PermissionType = 'camera' | 'mediaLibrary';
|
|
11
15
|
/**
|
|
12
16
|
* Permission manager for media operations
|
|
17
|
+
* Uses generic PermissionHandler to reduce code duplication
|
|
13
18
|
*/
|
|
14
19
|
export declare class PermissionManager {
|
|
20
|
+
private static handler;
|
|
15
21
|
/**
|
|
16
22
|
* Requests camera permission
|
|
17
23
|
*/
|
|
@@ -7,7 +7,7 @@ import { MediaLibraryPermission, MediaType, type MediaPickerResult } from "../..
|
|
|
7
7
|
/**
|
|
8
8
|
* Map expo-image-picker permission status to MediaLibraryPermission
|
|
9
9
|
*/
|
|
10
|
-
export declare const mapPermissionStatus: (status:
|
|
10
|
+
export declare const mapPermissionStatus: (status: string) => MediaLibraryPermission;
|
|
11
11
|
/**
|
|
12
12
|
* Map MediaType to expo-image-picker media types
|
|
13
13
|
*/
|
|
@@ -16,3 +16,17 @@ export declare const mapMediaType: (type?: MediaType) => ImagePicker.MediaType[]
|
|
|
16
16
|
* Map expo-image-picker result to MediaPickerResult
|
|
17
17
|
*/
|
|
18
18
|
export declare const mapPickerResult: (result: ImagePicker.ImagePickerResult) => MediaPickerResult;
|
|
19
|
+
/**
|
|
20
|
+
* Map PickerStrategy result to MediaPickerResult
|
|
21
|
+
*/
|
|
22
|
+
export declare const mapPickerResultFromStrategy: (result: {
|
|
23
|
+
canceled: boolean;
|
|
24
|
+
assets?: Array<{
|
|
25
|
+
uri: string;
|
|
26
|
+
width?: number;
|
|
27
|
+
height?: number;
|
|
28
|
+
type?: "image" | "video";
|
|
29
|
+
duration?: number;
|
|
30
|
+
fileSize?: number;
|
|
31
|
+
}>;
|
|
32
|
+
}) => MediaPickerResult;
|
|
@@ -17,6 +17,7 @@ import type { CalendarEvent } from '../../domain/entities/CalendarEvent.entity';
|
|
|
17
17
|
* Follows SOLID principles with composition over inheritance.
|
|
18
18
|
*/
|
|
19
19
|
export declare class CalendarService {
|
|
20
|
+
private static weekdayNamesCache;
|
|
20
21
|
/**
|
|
21
22
|
* Generate calendar days for a specific month
|
|
22
23
|
*/
|
|
@@ -30,7 +30,7 @@ export declare const useCalendar: () => {
|
|
|
30
30
|
setCurrentMonth: (date: Date) => void;
|
|
31
31
|
viewMode: import("./CalendarStore").CalendarViewMode;
|
|
32
32
|
setViewMode: (mode: import("./CalendarStore").CalendarViewMode) => void;
|
|
33
|
-
getEventsForDate: (date: Date) => import("../..").CalendarEvent[];
|
|
33
|
+
getEventsForDate: (date: Date | null | undefined) => import("../..").CalendarEvent[];
|
|
34
34
|
getEventsForMonth: (year: number, month: number) => import("../..").CalendarEvent[];
|
|
35
35
|
};
|
|
36
36
|
/**
|
|
@@ -55,7 +55,7 @@ export declare const useCalendarStore: () => {
|
|
|
55
55
|
navigateMonth: (direction: "prev" | "next") => void;
|
|
56
56
|
setCurrentMonth: (date: Date) => void;
|
|
57
57
|
setViewMode: (mode: import("./CalendarStore").CalendarViewMode) => void;
|
|
58
|
-
getEventsForDate: (date: Date) => import("../..").CalendarEvent[];
|
|
58
|
+
getEventsForDate: (date: Date | null | undefined) => import("../..").CalendarEvent[];
|
|
59
59
|
getEventsForMonth: (year: number, month: number) => import("../..").CalendarEvent[];
|
|
60
60
|
clearError: () => void;
|
|
61
61
|
clearAllEvents: () => Promise<void>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { FilterGroupProps } from './types';
|
|
3
|
-
export declare
|
|
3
|
+
export declare const FilterGroup: React.MemoExoticComponent<(<T = string>({ items, selectedValue, onSelect, multiSelect, style, contentContainerStyle, itemStyle, }: FilterGroupProps<T>) => React.JSX.Element)>;
|
|
@@ -21,7 +21,7 @@ export type { NavigationCleanup } from "./utils/NavigationCleanup";
|
|
|
21
21
|
*/
|
|
22
22
|
export { AppNavigation } from "./utils/AppNavigation";
|
|
23
23
|
export { TabLabel, type TabLabelProps } from "./components/TabLabel";
|
|
24
|
-
export
|
|
24
|
+
export { NavigationHeader, type NavigationHeaderProps } from "./components/NavigationHeader";
|
|
25
25
|
export { useTabBarStyles, type TabBarConfig } from "./hooks/useTabBarStyles";
|
|
26
26
|
export { useTabConfig, type UseTabConfigProps } from "./hooks/useTabConfig";
|
|
27
27
|
/**
|
package/dist/offline/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
export type { NetworkState, OfflineState, OfflineStore, OfflineConfig, ConnectionQuality, } from './types';
|
|
6
6
|
export { useOfflineStore } from './infrastructure/storage/OfflineStore';
|
|
7
7
|
export { useOfflineConfigStore } from './infrastructure/storage/OfflineConfigStore';
|
|
8
|
-
export { useOffline
|
|
8
|
+
export { useOffline } from './presentation/hooks/useOffline';
|
|
9
9
|
export { useOfflineState } from './presentation/hooks/useOfflineState';
|
|
10
10
|
export { useOfflineWithMutations } from './presentation/hooks/useOfflineWithMutations';
|
|
11
11
|
export { OfflineBanner } from './presentation/components/OfflineBanner';
|
|
@@ -4,11 +4,6 @@
|
|
|
4
4
|
* Automatically subscribes to network changes via expo-network (lazy loaded)
|
|
5
5
|
*/
|
|
6
6
|
import type { OfflineConfig } from '../../types';
|
|
7
|
-
/**
|
|
8
|
-
* Configure offline settings globally
|
|
9
|
-
* This is a facade over the config store for backward compatibility
|
|
10
|
-
*/
|
|
11
|
-
export declare const configureOffline: (config: OfflineConfig) => void;
|
|
12
7
|
export declare const useOffline: (config?: OfflineConfig) => {
|
|
13
8
|
isOnline: boolean;
|
|
14
9
|
isOffline: boolean;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Domain layer - Abstract repository for data operations
|
|
4
4
|
*
|
|
5
5
|
* Provides generic CRUD operations with TanStack Query integration.
|
|
6
|
-
*
|
|
6
|
+
* Now uses common repository utilities from core/repositories.
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
9
|
* ```typescript
|
|
@@ -51,6 +51,10 @@ export declare abstract class BaseRepository<TData, TCreateVariables = unknown,
|
|
|
51
51
|
* Query key factory for this repository
|
|
52
52
|
*/
|
|
53
53
|
readonly keys: ReturnType<typeof createQueryKeyFactory>;
|
|
54
|
+
/**
|
|
55
|
+
* Debug logger for this repository
|
|
56
|
+
*/
|
|
57
|
+
protected readonly log: (method: string, ...args: unknown[]) => void;
|
|
54
58
|
constructor(resource: string, options?: RepositoryOptions);
|
|
55
59
|
/**
|
|
56
60
|
* Get query client instance
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time Constants
|
|
3
|
+
*
|
|
4
|
+
* Centralized time-related constants to replace magic numbers
|
|
5
|
+
*/
|
|
6
|
+
export declare const MILLISECONDS_PER_SECOND = 1000;
|
|
7
|
+
export declare const MILLISECONDS_PER_MINUTE: number;
|
|
8
|
+
export declare const MILLISECONDS_PER_HOUR: number;
|
|
9
|
+
export declare const MILLISECONDS_PER_DAY: number;
|
|
10
|
+
export declare const SECONDS_PER_MINUTE = 60;
|
|
11
|
+
export declare const SECONDS_PER_HOUR: number;
|
|
12
|
+
export declare const SECONDS_PER_DAY: number;
|
|
13
|
+
export declare const MINUTES_PER_HOUR = 60;
|
|
14
|
+
export declare const MINUTES_PER_DAY: number;
|
|
15
|
+
export declare const ONE_SECOND_MS = 1000;
|
|
16
|
+
export declare const FIVE_SECONDS_MS: number;
|
|
17
|
+
export declare const TEN_SECONDS_MS: number;
|
|
18
|
+
export declare const THIRTY_SECONDS_MS: number;
|
|
19
|
+
export declare const ONE_MINUTE_MS: number;
|
|
20
|
+
export declare const FIVE_MINUTES_MS: number;
|
|
21
|
+
export declare const TEN_MINUTES_MS: number;
|
|
22
|
+
export declare const THIRTY_MINUTES_MS: number;
|
|
23
|
+
export declare const ONE_HOUR_MS: number;
|
|
24
|
+
export declare const ONE_DAY_MS: number;
|
|
25
|
+
export declare const DEFAULT_TIMEOUT_MS: number;
|
|
26
|
+
export declare const DEFAULT_LONG_TIMEOUT_MS: number;
|
|
27
|
+
export declare const DEFAULT_CACHE_TTL_MS: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-design-system",
|
|
3
|
-
"version": "4.27.
|
|
3
|
+
"version": "4.27.17",
|
|
4
4
|
"description": "Universal design system for React Native apps - Consolidated package with atoms, molecules, organisms, theme, typography, responsive, safe area, exception, infinite scroll, UUID, image, timezone, offline, onboarding, and loading utilities - TanStack persistence and expo-image-manipulator now lazy loaded",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -208,13 +208,14 @@
|
|
|
208
208
|
"url": "https://github.com/umituz/react-native-design-system"
|
|
209
209
|
},
|
|
210
210
|
"peerDependencies": {
|
|
211
|
-
"
|
|
211
|
+
"@react-native-community/datetimepicker": ">=8.0.0",
|
|
212
212
|
"@react-navigation/bottom-tabs": ">=7.0.0",
|
|
213
213
|
"@react-navigation/native": ">=7.0.0",
|
|
214
214
|
"@react-navigation/stack": ">=7.0.0",
|
|
215
215
|
"@tanstack/query-async-storage-persister": ">=5.0.0",
|
|
216
216
|
"@tanstack/react-query": ">=5.0.0",
|
|
217
217
|
"@tanstack/react-query-persist-client": ">=5.0.0",
|
|
218
|
+
"expo": ">=54.0.0",
|
|
218
219
|
"expo-application": ">=5.0.0",
|
|
219
220
|
"expo-clipboard": ">=8.0.0",
|
|
220
221
|
"expo-crypto": ">=13.0.0",
|
|
@@ -230,10 +231,9 @@
|
|
|
230
231
|
"react": ">=19.0.0",
|
|
231
232
|
"react-native": "*",
|
|
232
233
|
"react-native-gesture-handler": ">=2.20.0",
|
|
234
|
+
"react-native-keyboard-controller": ">=1.0.0",
|
|
233
235
|
"react-native-safe-area-context": ">=5.6.2",
|
|
234
|
-
"zustand": ">=5.0.0"
|
|
235
|
-
"@react-native-community/datetimepicker": ">=8.0.0",
|
|
236
|
-
"react-native-keyboard-controller": ">=1.0.0"
|
|
236
|
+
"zustand": ">=5.0.0"
|
|
237
237
|
},
|
|
238
238
|
"peerDependenciesMeta": {
|
|
239
239
|
"react-native-keyboard-controller": {
|
|
@@ -298,13 +298,18 @@
|
|
|
298
298
|
"@eslint/js": "^9.39.2",
|
|
299
299
|
"@react-native-async-storage/async-storage": "^2.2.0",
|
|
300
300
|
"@react-native-community/datetimepicker": "^8.5.1",
|
|
301
|
+
"@react-navigation/bottom-tabs": "^7.15.5",
|
|
302
|
+
"@react-navigation/native": "^7.1.33",
|
|
303
|
+
"@react-navigation/stack": "^7.8.5",
|
|
301
304
|
"@tanstack/query-async-storage-persister": "^5.66.7",
|
|
302
305
|
"@tanstack/react-query": "^5.66.7",
|
|
303
306
|
"@tanstack/react-query-persist-client": "^5.66.7",
|
|
304
307
|
"@testing-library/react": "^16.3.1",
|
|
305
308
|
"@testing-library/react-native": "^13.3.3",
|
|
306
309
|
"@types/jest": "^30.0.0",
|
|
307
|
-
"@types/
|
|
310
|
+
"@types/node": "^25.5.0",
|
|
311
|
+
"@types/react": "^19.2.14",
|
|
312
|
+
"@types/react-native": "^0.72.8",
|
|
308
313
|
"@typescript-eslint/eslint-plugin": "^8.50.1",
|
|
309
314
|
"@typescript-eslint/parser": "^8.50.1",
|
|
310
315
|
"eslint": "^9.39.2",
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { StyleSheet, ViewStyle, StyleProp, View } from 'react-native';
|
|
3
|
-
// Remove expo-blur import to fix native module error
|
|
4
|
-
// import { BlurView, BlurTint } from 'expo-blur';
|
|
5
3
|
import { useDesignSystemTheme } from '../../theme';
|
|
6
4
|
import { intensityToOpacity } from '../../utils/math';
|
|
7
5
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Extracted from AtomicPicker for better separation of concerns.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import React from 'react';
|
|
8
|
+
import React, { useMemo, useCallback } from 'react';
|
|
9
9
|
import { View, TouchableOpacity, GestureResponderEvent } from 'react-native';
|
|
10
10
|
import { useAppDesignTokens } from '../../../theme';
|
|
11
11
|
import { PickerOption } from '../types';
|
|
@@ -30,30 +30,36 @@ export const PickerChips: React.FC<PickerChipsProps> = React.memo(({
|
|
|
30
30
|
const tokens = useAppDesignTokens();
|
|
31
31
|
const closeIcon = useIconName('close');
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
const
|
|
33
|
+
// Memoize styles to prevent recalculation
|
|
34
|
+
const chipContainerStyles = useMemo(() => getChipContainerStyles(tokens), [tokens]);
|
|
35
|
+
const chipStyles = useMemo(() => getChipStyles(tokens), [tokens]);
|
|
36
|
+
const chipTextStyles = useMemo(() => getChipTextStyles(tokens), [tokens]);
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
// Memoized chip renderer - handleRemove created inline to avoid useCallback inside callback
|
|
39
|
+
const renderChip = useCallback((opt: PickerOption) => {
|
|
40
|
+
const handleRemove = (e: GestureResponderEvent) => {
|
|
41
|
+
e.stopPropagation();
|
|
42
|
+
onRemoveChip(opt.value);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<View key={opt.value} style={chipStyles}>
|
|
47
|
+
<AtomicText style={chipTextStyles}>{opt.label}</AtomicText>
|
|
48
|
+
<TouchableOpacity
|
|
49
|
+
onPress={handleRemove}
|
|
50
|
+
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
|
|
51
|
+
accessibilityRole="button"
|
|
52
|
+
accessibilityLabel={`Remove ${opt.label}`}
|
|
53
|
+
>
|
|
54
|
+
<AtomicIcon name={closeIcon} size="sm" color="primary" />
|
|
55
|
+
</TouchableOpacity>
|
|
56
|
+
</View>
|
|
57
|
+
);
|
|
58
|
+
}, [chipStyles, chipTextStyles, closeIcon, onRemoveChip]);
|
|
38
59
|
|
|
39
60
|
return (
|
|
40
61
|
<View style={chipContainerStyles}>
|
|
41
|
-
{selectedOptions.map(
|
|
42
|
-
<View key={opt.value} style={chipStyles}>
|
|
43
|
-
<AtomicText style={chipTextStyles}>{opt.label}</AtomicText>
|
|
44
|
-
<TouchableOpacity
|
|
45
|
-
onPress={(e: GestureResponderEvent) => {
|
|
46
|
-
e.stopPropagation();
|
|
47
|
-
onRemoveChip(opt.value);
|
|
48
|
-
}}
|
|
49
|
-
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
|
|
50
|
-
accessibilityRole="button"
|
|
51
|
-
accessibilityLabel={`Remove ${opt.label}`}
|
|
52
|
-
>
|
|
53
|
-
<AtomicIcon name={closeIcon} size="sm" color="primary" />
|
|
54
|
-
</TouchableOpacity>
|
|
55
|
-
</View>
|
|
56
|
-
))}
|
|
62
|
+
{selectedOptions.map(renderChip)}
|
|
57
63
|
</View>
|
|
58
64
|
);
|
|
59
65
|
});
|
package/src/core/cache/index.ts
CHANGED
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
export { UnifiedCache } from './domain/UnifiedCache';
|
|
9
9
|
export type { UnifiedCacheConfig } from './domain/UnifiedCache';
|
|
10
10
|
|
|
11
|
-
export { CleanupStrategy
|
|
12
|
-
export
|
|
11
|
+
export type { CleanupStrategy } from './domain/CleanupStrategy';
|
|
12
|
+
export { IntervalCleanupStrategy, TimeoutCleanupStrategy } from './domain/CleanupStrategy';
|
|
13
|
+
export type { CleanupType } from './domain/types';
|
|
13
14
|
|
|
14
15
|
export { CacheFactory } from './infrastructure/CacheFactory';
|
|
15
16
|
|
package/src/core/index.ts
CHANGED
|
@@ -6,10 +6,12 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
// Cache
|
|
9
|
-
export { UnifiedCache
|
|
10
|
-
export {
|
|
9
|
+
export { UnifiedCache } from './cache/domain/UnifiedCache';
|
|
10
|
+
export { CacheFactory } from './cache/infrastructure/CacheFactory';
|
|
11
|
+
export type { CleanupStrategy } from './cache/domain/CleanupStrategy';
|
|
12
|
+
export { IntervalCleanupStrategy, TimeoutCleanupStrategy } from './cache/domain/CleanupStrategy';
|
|
11
13
|
export type { UnifiedCacheConfig } from './cache/domain/UnifiedCache';
|
|
12
|
-
export type { CacheEntry, CacheConfig } from './cache/domain/types';
|
|
14
|
+
export type { CacheEntry, CacheConfig, CleanupType } from './cache/domain/types';
|
|
13
15
|
|
|
14
16
|
// Permissions
|
|
15
17
|
export { PermissionHandler } from './permissions/domain/PermissionHandler';
|
|
@@ -12,7 +12,7 @@ import type { RepositoryOptions, ListParams } from './types';
|
|
|
12
12
|
*/
|
|
13
13
|
const DEFAULT_CACHE_OPTIONS = {
|
|
14
14
|
staleTime: 5 * 60 * 1000, // 5 minutes
|
|
15
|
-
gcTime: 10 * 60 * 1000, // 10 minutes
|
|
15
|
+
gcTime: 10 * 60 * 1000, // 10 minutes
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -43,10 +43,10 @@ export function getCacheOptions(options: RepositoryOptions): {
|
|
|
43
43
|
staleTime: number;
|
|
44
44
|
gcTime: number;
|
|
45
45
|
} {
|
|
46
|
-
const
|
|
46
|
+
const cache = options.cache ?? {};
|
|
47
47
|
return {
|
|
48
|
-
staleTime:
|
|
49
|
-
gcTime:
|
|
48
|
+
staleTime: cache.staleTime ?? DEFAULT_CACHE_OPTIONS.staleTime,
|
|
49
|
+
gcTime: cache.gcTime ?? DEFAULT_CACHE_OPTIONS.gcTime,
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -53,7 +53,7 @@ export interface UpdateParams<TVariables> {
|
|
|
53
53
|
export type QueryKeyFactory = {
|
|
54
54
|
all: () => readonly string[];
|
|
55
55
|
lists: () => readonly string[];
|
|
56
|
-
list: (params: ListParams) => readonly
|
|
56
|
+
list: (params: ListParams) => readonly unknown[];
|
|
57
57
|
details: () => readonly string[];
|
|
58
|
-
detail: (id: string | number) => readonly
|
|
58
|
+
detail: (id: string | number) => readonly unknown[];
|
|
59
59
|
};
|
package/src/hooks/index.ts
CHANGED
|
@@ -20,11 +20,6 @@
|
|
|
20
20
|
|
|
21
21
|
export {
|
|
22
22
|
useAppDesignTokens,
|
|
23
|
-
useDesignSystemTheme,
|
|
24
|
-
useTheme,
|
|
25
|
-
useThemedStyles,
|
|
26
|
-
useThemedStyleSheet,
|
|
27
|
-
useCommonStyles,
|
|
28
23
|
} from '../theme/hooks/useAppDesignTokens';
|
|
29
24
|
|
|
30
25
|
export { useTheme as useThemeStore } from '../theme/infrastructure/stores/themeStore';
|
|
@@ -35,9 +30,10 @@ export { useTheme as useThemeStore } from '../theme/infrastructure/stores/themeS
|
|
|
35
30
|
|
|
36
31
|
export {
|
|
37
32
|
useResponsive,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
useScreenWidth,
|
|
34
|
+
useScreenHeight,
|
|
35
|
+
useScreenDimensions,
|
|
36
|
+
type UseResponsiveReturn,
|
|
41
37
|
} from '../responsive';
|
|
42
38
|
|
|
43
39
|
// =============================================================================
|
|
@@ -45,7 +41,6 @@ export {
|
|
|
45
41
|
// =============================================================================
|
|
46
42
|
|
|
47
43
|
export {
|
|
48
|
-
useSafeArea,
|
|
49
44
|
useSafeAreaInsets,
|
|
50
45
|
} from '../safe-area';
|
|
51
46
|
|
|
@@ -55,8 +50,8 @@ export {
|
|
|
55
50
|
|
|
56
51
|
export {
|
|
57
52
|
useInfiniteScroll,
|
|
58
|
-
type
|
|
59
|
-
type
|
|
53
|
+
type InfiniteScrollConfig,
|
|
54
|
+
type UseInfiniteScrollReturn,
|
|
60
55
|
} from '../infinite-scroll';
|
|
61
56
|
|
|
62
57
|
// =============================================================================
|
|
@@ -65,7 +60,7 @@ export {
|
|
|
65
60
|
|
|
66
61
|
export {
|
|
67
62
|
useOffline,
|
|
68
|
-
type
|
|
63
|
+
type NetworkState,
|
|
69
64
|
} from '../offline';
|
|
70
65
|
|
|
71
66
|
// =============================================================================
|
|
@@ -73,9 +68,11 @@ export {
|
|
|
73
68
|
// =============================================================================
|
|
74
69
|
|
|
75
70
|
export {
|
|
76
|
-
useDeviceContext,
|
|
77
71
|
useDeviceInfo,
|
|
72
|
+
useDeviceCapabilities,
|
|
73
|
+
useDeviceId,
|
|
78
74
|
type DeviceInfo,
|
|
75
|
+
type AnonymousUser,
|
|
79
76
|
} from '../device';
|
|
80
77
|
|
|
81
78
|
// =============================================================================
|
|
@@ -84,8 +81,14 @@ export {
|
|
|
84
81
|
|
|
85
82
|
export {
|
|
86
83
|
useStorage,
|
|
87
|
-
|
|
88
|
-
|
|
84
|
+
useStorageState,
|
|
85
|
+
useStore,
|
|
86
|
+
usePersistentCache,
|
|
87
|
+
useCache,
|
|
88
|
+
useCachedValue,
|
|
89
|
+
useCacheState,
|
|
90
|
+
type PersistentCacheOptions,
|
|
91
|
+
type PersistentCacheResult,
|
|
89
92
|
} from '../storage';
|
|
90
93
|
|
|
91
94
|
// =============================================================================
|
|
@@ -93,10 +96,8 @@ export {
|
|
|
93
96
|
// =============================================================================
|
|
94
97
|
|
|
95
98
|
export {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
useCamera,
|
|
99
|
-
type ImagePickerResult,
|
|
99
|
+
useMedia,
|
|
100
|
+
type MediaPickerResult,
|
|
100
101
|
} from '../media';
|
|
101
102
|
|
|
102
103
|
// =============================================================================
|
|
@@ -105,7 +106,6 @@ export {
|
|
|
105
106
|
|
|
106
107
|
export {
|
|
107
108
|
useTimezone,
|
|
108
|
-
useLocalTime,
|
|
109
109
|
type TimezoneInfo,
|
|
110
110
|
} from '../timezone';
|
|
111
111
|
|
|
@@ -115,9 +115,6 @@ export {
|
|
|
115
115
|
|
|
116
116
|
export {
|
|
117
117
|
useHaptics,
|
|
118
|
-
useImpact,
|
|
119
|
-
useNotification,
|
|
120
|
-
useSelection,
|
|
121
118
|
} from '../haptics';
|
|
122
119
|
|
|
123
120
|
// =============================================================================
|
|
@@ -125,6 +122,6 @@ export {
|
|
|
125
122
|
// =============================================================================
|
|
126
123
|
|
|
127
124
|
export {
|
|
128
|
-
|
|
129
|
-
|
|
125
|
+
useGlobalLoading,
|
|
126
|
+
type LoadingState,
|
|
130
127
|
} from '../loading';
|
|
@@ -20,6 +20,29 @@ try {
|
|
|
20
20
|
// expo-image not installed — using React Native Image fallback
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
// Memoized image component (outside main component to avoid dependency issues)
|
|
24
|
+
const GalleryImage = React.memo<{ item: ImageViewerItem; style: any }>(({ item, style }) => (
|
|
25
|
+
<View style={style.imageWrapper}>
|
|
26
|
+
{ExpoImage ? (
|
|
27
|
+
<ExpoImage
|
|
28
|
+
source={{ uri: item.uri }}
|
|
29
|
+
style={style.fullImage}
|
|
30
|
+
contentFit="contain"
|
|
31
|
+
cachePolicy="memory-disk"
|
|
32
|
+
onError={() => { if (__DEV__) console.warn('[ImageGallery] Failed to load image:', item.uri); }}
|
|
33
|
+
/>
|
|
34
|
+
) : (
|
|
35
|
+
<RNImage
|
|
36
|
+
source={{ uri: item.uri }}
|
|
37
|
+
style={style.fullImage}
|
|
38
|
+
resizeMode="contain"
|
|
39
|
+
onError={() => { if (__DEV__) console.warn('[ImageGallery] Failed to load image:', item.uri); }}
|
|
40
|
+
/>
|
|
41
|
+
)}
|
|
42
|
+
</View>
|
|
43
|
+
));
|
|
44
|
+
GalleryImage.displayName = 'GalleryImage';
|
|
45
|
+
|
|
23
46
|
export interface ImageGalleryProps extends ImageGalleryOptions {
|
|
24
47
|
images: ImageViewerItem[];
|
|
25
48
|
visible: boolean;
|
|
@@ -44,7 +67,6 @@ export const ImageGallery: React.FC<ImageGalleryProps> = ({
|
|
|
44
67
|
const insets = useSafeAreaInsets();
|
|
45
68
|
const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = useWindowDimensions();
|
|
46
69
|
const currentIndexRef = useRef(index);
|
|
47
|
-
const [, forceRender] = React.useReducer((x: number) => x + 1, 0);
|
|
48
70
|
|
|
49
71
|
const styles = useMemo(() => StyleSheet.create({
|
|
50
72
|
container: { flex: 1 },
|
|
@@ -81,30 +103,12 @@ export const ImageGallery: React.FC<ImageGalleryProps> = ({
|
|
|
81
103
|
if (nextIndex !== currentIndexRef.current) {
|
|
82
104
|
currentIndexRef.current = nextIndex;
|
|
83
105
|
onIndexChange?.(nextIndex);
|
|
84
|
-
forceRender();
|
|
85
106
|
}
|
|
86
107
|
}, [onIndexChange, SCREEN_WIDTH, images.length]);
|
|
87
108
|
|
|
88
109
|
const renderItem = useCallback(({ item }: { item: ImageViewerItem }) => (
|
|
89
|
-
<
|
|
90
|
-
|
|
91
|
-
<ExpoImage
|
|
92
|
-
source={{ uri: item.uri }}
|
|
93
|
-
style={styles.fullImage}
|
|
94
|
-
contentFit="contain"
|
|
95
|
-
cachePolicy="memory-disk"
|
|
96
|
-
onError={() => { if (__DEV__) console.warn('[ImageGallery] Failed to load image:', item.uri); }}
|
|
97
|
-
/>
|
|
98
|
-
) : (
|
|
99
|
-
<RNImage
|
|
100
|
-
source={{ uri: item.uri }}
|
|
101
|
-
style={styles.fullImage}
|
|
102
|
-
resizeMode="contain"
|
|
103
|
-
onError={() => { if (__DEV__) console.warn('[ImageGallery] Failed to load image:', item.uri); }}
|
|
104
|
-
/>
|
|
105
|
-
)}
|
|
106
|
-
</View>
|
|
107
|
-
), [styles]);
|
|
110
|
+
<GalleryImage item={item} style={{ imageWrapper: styles.imageWrapper, fullImage: styles.fullImage }} />
|
|
111
|
+
), [styles.imageWrapper, styles.fullImage]);
|
|
108
112
|
|
|
109
113
|
const getItemLayout = useCallback((_: unknown, i: number) => ({
|
|
110
114
|
length: SCREEN_WIDTH,
|