@umituz/react-native-loading 1.0.0

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/lib/index.js ADDED
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Loading Domain - Barrel Export
3
+ *
4
+ * Public API for the loading domain.
5
+ * Provides consistent loading states and animations across all apps.
6
+ *
7
+ * Features:
8
+ * - Breathing animation loading state (meditation-inspired)
9
+ * - Skeleton loaders with shimmer effect
10
+ * - Loading state management hooks
11
+ * - App-specific emoji presets
12
+ * - Configurable sizes and patterns
13
+ *
14
+ * Usage:
15
+ * ```tsx
16
+ * import {
17
+ * LoadingState,
18
+ * SkeletonLoader,
19
+ * useLoading,
20
+ * LOADING_EMOJIS,
21
+ * } from '@umituz/react-native-loading';
22
+ *
23
+ * // Basic loading state
24
+ * const MyScreen = () => {
25
+ * const { isLoading, startLoading, stopLoading } = useLoading();
26
+ *
27
+ * return (
28
+ * <View>
29
+ * {isLoading ? (
30
+ * <LoadingState message="Loading..." />
31
+ * ) : (
32
+ * <Content />
33
+ * )}
34
+ * </View>
35
+ * );
36
+ * };
37
+ *
38
+ * // Skeleton loader for lists
39
+ * const ListScreen = () => {
40
+ * const [data, setData] = useState([]);
41
+ * const { isLoading } = useLoading();
42
+ *
43
+ * return (
44
+ * <View>
45
+ * {isLoading ? (
46
+ * <SkeletonLoader pattern="list" count={5} />
47
+ * ) : (
48
+ * <FlatList data={data} ... />
49
+ * )}
50
+ * </View>
51
+ * );
52
+ * };
53
+ *
54
+ * // With async wrapper
55
+ * const DataScreen = () => {
56
+ * const { isLoading, loadingMessage, withLoading } = useLoading();
57
+ *
58
+ * const loadData = () => withLoading(
59
+ * fetchData(),
60
+ * 'Loading data...'
61
+ * );
62
+ *
63
+ * return (
64
+ * <View>
65
+ * {isLoading && <LoadingState message={loadingMessage} />}
66
+ * <Button onPress={loadData}>Load</Button>
67
+ * </View>
68
+ * );
69
+ * };
70
+ *
71
+ * // Custom emoji per app
72
+ * const FitnessLoadingScreen = () => (
73
+ * <LoadingState
74
+ * emoji={LOADING_EMOJIS.fitness}
75
+ * message="Loading workouts..."
76
+ * />
77
+ * );
78
+ * ```
79
+ */
80
+ export { SIZE_CONFIGS, LOADING_EMOJIS, ANIMATION_CONFIGS, SKELETON_PATTERNS, LoadingUtils, LOADING_CONSTANTS, } from './domain/entities/Loading';
81
+ // Presentation Components
82
+ export { LoadingState, } from './presentation/components/LoadingState';
83
+ export { SkeletonLoader, } from './presentation/components/SkeletonLoader';
84
+ // Presentation Hooks
85
+ export { useLoading, useSimpleLoading, } from './presentation/hooks/useLoading';
86
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8EG;AAaH,OAAO,EACL,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AAEnC,0BAA0B;AAC1B,OAAO,EACL,YAAY,GAEb,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EACL,cAAc,GAEf,MAAM,0CAA0C,CAAC;AAElD,qBAAqB;AACrB,OAAO,EACL,UAAU,EACV,gBAAgB,GAEjB,MAAM,iCAAiC,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Loading Domain - LoadingState Component
3
+ *
4
+ * Universal loading component with breathing animation.
5
+ * Provides consistent, calm loading UX across all apps.
6
+ *
7
+ * Adapted from meditation_timer app's LoadingState component.
8
+ *
9
+ * @domain loading
10
+ * @layer presentation/components
11
+ */
12
+ import React from 'react';
13
+ import { type StyleProp, type ViewStyle, type TextStyle } from 'react-native';
14
+ import type { LoadingSize } from '../../domain/entities/Loading';
15
+ /**
16
+ * LoadingState component props
17
+ */
18
+ export interface LoadingStateProps {
19
+ /** Loading emoji - default: ⌛ (customizable per app) */
20
+ emoji?: string;
21
+ /** Loading message (optional) */
22
+ message?: string;
23
+ /** Size: small (inline), medium (section), large (full screen) */
24
+ size?: LoadingSize;
25
+ /** Full screen layout vs inline */
26
+ fullScreen?: boolean;
27
+ /** Custom container style */
28
+ style?: StyleProp<ViewStyle>;
29
+ /** Custom message style */
30
+ messageStyle?: StyleProp<TextStyle>;
31
+ }
32
+ /**
33
+ * LoadingState Component
34
+ *
35
+ * Universal loading indicator with breathing animation.
36
+ * Creates a calm, mindful loading experience.
37
+ *
38
+ * USAGE:
39
+ * ```typescript
40
+ * // Basic usage
41
+ * <LoadingState />
42
+ *
43
+ * // With message
44
+ * <LoadingState message="Loading data..." size="medium" />
45
+ *
46
+ * // Full screen
47
+ * <LoadingState fullScreen message="Please wait..." />
48
+ *
49
+ * // Custom emoji (per app theme)
50
+ * <LoadingState emoji="🧘" message="Loading meditations..." />
51
+ *
52
+ * // Inline loading
53
+ * <LoadingState size="small" />
54
+ * ```
55
+ */
56
+ export declare const LoadingState: React.FC<LoadingStateProps>;
57
+ //# sourceMappingURL=LoadingState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingState.d.ts","sourceRoot":"","sources":["../../../src/presentation/components/LoadingState.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAA4B,MAAM,OAAO,CAAC;AACjD,OAAO,EAAsC,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAElH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAOjE;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,mCAAmC;IACnC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,2BAA2B;IAC3B,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CACrC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA4EpD,CAAC"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Loading Domain - LoadingState Component
3
+ *
4
+ * Universal loading component with breathing animation.
5
+ * Provides consistent, calm loading UX across all apps.
6
+ *
7
+ * Adapted from meditation_timer app's LoadingState component.
8
+ *
9
+ * @domain loading
10
+ * @layer presentation/components
11
+ */
12
+ import React, { useEffect, useRef } from 'react';
13
+ import { View, StyleSheet, Animated, Easing } from 'react-native';
14
+ import { useAppDesignTokens, AtomicText } from '@umituz/react-native-design-system';
15
+ import { SIZE_CONFIGS, LOADING_EMOJIS, } from '../../domain/entities/Loading';
16
+ /**
17
+ * LoadingState Component
18
+ *
19
+ * Universal loading indicator with breathing animation.
20
+ * Creates a calm, mindful loading experience.
21
+ *
22
+ * USAGE:
23
+ * ```typescript
24
+ * // Basic usage
25
+ * <LoadingState />
26
+ *
27
+ * // With message
28
+ * <LoadingState message="Loading data..." size="medium" />
29
+ *
30
+ * // Full screen
31
+ * <LoadingState fullScreen message="Please wait..." />
32
+ *
33
+ * // Custom emoji (per app theme)
34
+ * <LoadingState emoji="🧘" message="Loading meditations..." />
35
+ *
36
+ * // Inline loading
37
+ * <LoadingState size="small" />
38
+ * ```
39
+ */
40
+ export const LoadingState = ({ emoji = LOADING_EMOJIS.default, message, size = 'large', fullScreen = false, style, messageStyle, }) => {
41
+ const tokens = useAppDesignTokens();
42
+ const config = SIZE_CONFIGS[size];
43
+ // Animated value for emoji pulse (breathing effect)
44
+ const scaleAnim = useRef(new Animated.Value(1)).current;
45
+ useEffect(() => {
46
+ // Meditation breathing animation: 2 second cycle (inhale/exhale)
47
+ const breathingAnimation = Animated.loop(Animated.sequence([
48
+ // Inhale - expand
49
+ Animated.timing(scaleAnim, {
50
+ toValue: 1.15,
51
+ duration: 1000,
52
+ easing: Easing.inOut(Easing.ease),
53
+ useNativeDriver: true,
54
+ }),
55
+ // Exhale - contract
56
+ Animated.timing(scaleAnim, {
57
+ toValue: 1,
58
+ duration: 1000,
59
+ easing: Easing.inOut(Easing.ease),
60
+ useNativeDriver: true,
61
+ }),
62
+ ]));
63
+ breathingAnimation.start();
64
+ return () => {
65
+ breathingAnimation.stop();
66
+ };
67
+ }, [scaleAnim]);
68
+ return (<View style={[
69
+ styles.container,
70
+ fullScreen && styles.fullScreen,
71
+ { gap: config.spacing },
72
+ style,
73
+ ]}>
74
+ {/* Animated Emoji with breathing pulse */}
75
+ <Animated.Text style={[
76
+ styles.emoji,
77
+ {
78
+ fontSize: config.emojiSize,
79
+ transform: [{ scale: scaleAnim }],
80
+ },
81
+ ]}>
82
+ {emoji}
83
+ </Animated.Text>
84
+
85
+ {/* Optional Loading Message */}
86
+ {config.showMessage && message && (<AtomicText type="bodySmall" color="secondary" style={[styles.message, messageStyle]}>
87
+ {message}
88
+ </AtomicText>)}
89
+ </View>);
90
+ };
91
+ const styles = StyleSheet.create({
92
+ container: {
93
+ justifyContent: 'center',
94
+ alignItems: 'center',
95
+ paddingVertical: 20,
96
+ },
97
+ fullScreen: {
98
+ flex: 1,
99
+ paddingVertical: 60,
100
+ },
101
+ emoji: {
102
+ fontFamily: 'System', // Emoji font
103
+ },
104
+ message: {
105
+ textAlign: 'center',
106
+ opacity: 0.7,
107
+ paddingHorizontal: 32,
108
+ },
109
+ });
110
+ //# sourceMappingURL=LoadingState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingState.js","sourceRoot":"","sources":["../../../src/presentation/components/LoadingState.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Loading Domain - SkeletonLoader Component
3
+ *
4
+ * Skeleton placeholder loader with shimmer animation.
5
+ * Provides visual feedback during content loading.
6
+ *
7
+ * @domain loading
8
+ * @layer presentation/components
9
+ */
10
+ import React from 'react';
11
+ import { type StyleProp, type ViewStyle } from 'react-native';
12
+ import type { SkeletonPattern, SkeletonConfig } from '../../domain/entities/Loading';
13
+ /**
14
+ * SkeletonLoader component props
15
+ */
16
+ export interface SkeletonLoaderProps {
17
+ /** Skeleton pattern preset */
18
+ pattern?: SkeletonPattern;
19
+ /** Custom skeleton configurations */
20
+ custom?: SkeletonConfig[];
21
+ /** Number of skeleton items to render */
22
+ count?: number;
23
+ /** Custom container style */
24
+ style?: StyleProp<ViewStyle>;
25
+ /** Disable shimmer animation */
26
+ disableAnimation?: boolean;
27
+ }
28
+ /**
29
+ * SkeletonLoader Component
30
+ *
31
+ * Renders skeleton placeholders with shimmer animation.
32
+ * Provides visual feedback while content is loading.
33
+ *
34
+ * USAGE:
35
+ * ```typescript
36
+ * // List skeleton (default)
37
+ * <SkeletonLoader pattern="list" count={5} />
38
+ *
39
+ * // Card skeleton
40
+ * <SkeletonLoader pattern="card" count={3} />
41
+ *
42
+ * // Profile skeleton
43
+ * <SkeletonLoader pattern="profile" />
44
+ *
45
+ * // Text skeleton
46
+ * <SkeletonLoader pattern="text" count={3} />
47
+ *
48
+ * // Custom skeleton
49
+ * <SkeletonLoader
50
+ * pattern="custom"
51
+ * custom={[
52
+ * { width: 100, height: 100, borderRadius: 50 },
53
+ * { width: '80%', height: 20, borderRadius: 4 },
54
+ * ]}
55
+ * />
56
+ * ```
57
+ */
58
+ export declare const SkeletonLoader: React.FC<SkeletonLoaderProps>;
59
+ //# sourceMappingURL=SkeletonLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkeletonLoader.d.ts","sourceRoot":"","sources":["../../../src/presentation/components/SkeletonLoader.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAA4B,MAAM,OAAO,CAAC;AACjD,OAAO,EAA8B,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAE1F,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAMrF;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,8BAA8B;IAC9B,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,qCAAqC;IACrC,MAAM,CAAC,EAAE,cAAc,EAAE,CAAC;IAC1B,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,gCAAgC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAiFxD,CAAC"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Loading Domain - SkeletonLoader Component
3
+ *
4
+ * Skeleton placeholder loader with shimmer animation.
5
+ * Provides visual feedback during content loading.
6
+ *
7
+ * @domain loading
8
+ * @layer presentation/components
9
+ */
10
+ import React, { useEffect, useRef } from 'react';
11
+ import { View, StyleSheet, Animated } from 'react-native';
12
+ import { useAppDesignTokens } from '@umituz/react-native-design-system';
13
+ import { SKELETON_PATTERNS, LOADING_CONSTANTS, } from '../../domain/entities/Loading';
14
+ /**
15
+ * SkeletonLoader Component
16
+ *
17
+ * Renders skeleton placeholders with shimmer animation.
18
+ * Provides visual feedback while content is loading.
19
+ *
20
+ * USAGE:
21
+ * ```typescript
22
+ * // List skeleton (default)
23
+ * <SkeletonLoader pattern="list" count={5} />
24
+ *
25
+ * // Card skeleton
26
+ * <SkeletonLoader pattern="card" count={3} />
27
+ *
28
+ * // Profile skeleton
29
+ * <SkeletonLoader pattern="profile" />
30
+ *
31
+ * // Text skeleton
32
+ * <SkeletonLoader pattern="text" count={3} />
33
+ *
34
+ * // Custom skeleton
35
+ * <SkeletonLoader
36
+ * pattern="custom"
37
+ * custom={[
38
+ * { width: 100, height: 100, borderRadius: 50 },
39
+ * { width: '80%', height: 20, borderRadius: 4 },
40
+ * ]}
41
+ * />
42
+ * ```
43
+ */
44
+ export const SkeletonLoader = ({ pattern = 'list', custom, count = 1, style, disableAnimation = false, }) => {
45
+ const tokens = useAppDesignTokens();
46
+ // Get skeleton config
47
+ const skeletonConfigs = pattern === 'custom' && custom
48
+ ? custom
49
+ : SKELETON_PATTERNS[pattern];
50
+ // Animated value for shimmer effect
51
+ const shimmerAnim = useRef(new Animated.Value(0)).current;
52
+ useEffect(() => {
53
+ if (disableAnimation)
54
+ return;
55
+ // Shimmer animation: 1.2 second cycle
56
+ const shimmerAnimation = Animated.loop(Animated.sequence([
57
+ Animated.timing(shimmerAnim, {
58
+ toValue: 1,
59
+ duration: LOADING_CONSTANTS.SKELETON_SHIMMER_DURATION,
60
+ useNativeDriver: false, // backgroundColor animation requires false
61
+ }),
62
+ Animated.timing(shimmerAnim, {
63
+ toValue: 0,
64
+ duration: 0,
65
+ useNativeDriver: false,
66
+ }),
67
+ ]));
68
+ shimmerAnimation.start();
69
+ return () => {
70
+ shimmerAnimation.stop();
71
+ };
72
+ }, [shimmerAnim, disableAnimation]);
73
+ // Interpolate shimmer animation to background color
74
+ const backgroundColor = shimmerAnim.interpolate({
75
+ inputRange: [0, 0.5, 1],
76
+ outputRange: [
77
+ tokens.colors.surfaceSecondary,
78
+ tokens.colors.border,
79
+ tokens.colors.surfaceSecondary,
80
+ ],
81
+ });
82
+ // Render skeleton items
83
+ const renderSkeletonItem = (index) => (<View key={`skeleton-group-${index}`} style={styles.skeletonGroup}>
84
+ {skeletonConfigs.map((config, configIndex) => (<Animated.View key={`skeleton-${index}-${configIndex}`} style={[
85
+ styles.skeleton,
86
+ {
87
+ width: config.width,
88
+ height: config.height,
89
+ borderRadius: config.borderRadius,
90
+ marginBottom: config.marginBottom,
91
+ backgroundColor: disableAnimation
92
+ ? tokens.colors.surfaceSecondary
93
+ : backgroundColor,
94
+ },
95
+ ]}/>))}
96
+ </View>);
97
+ return (<View style={[styles.container, style]}>
98
+ {Array.from({ length: count }).map((_, index) => renderSkeletonItem(index))}
99
+ </View>);
100
+ };
101
+ const styles = StyleSheet.create({
102
+ container: {
103
+ width: '100%',
104
+ },
105
+ skeletonGroup: {
106
+ width: '100%',
107
+ },
108
+ skeleton: {
109
+ overflow: 'hidden',
110
+ },
111
+ });
112
+ //# sourceMappingURL=SkeletonLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkeletonLoader.js","sourceRoot":"","sources":["../../../src/presentation/components/SkeletonLoader.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Loading Domain - useLoading Hook
3
+ *
4
+ * React hook for managing loading states.
5
+ * Provides consistent loading state management across components.
6
+ *
7
+ * @domain loading
8
+ * @layer presentation/hooks
9
+ */
10
+ import type { LoadingType } from '../../domain/entities/Loading';
11
+ /**
12
+ * useLoading hook return type
13
+ */
14
+ export interface UseLoadingReturn {
15
+ isLoading: boolean;
16
+ loadingMessage: string | null;
17
+ loadingType: LoadingType;
18
+ startLoading: (message?: string, type?: LoadingType) => void;
19
+ stopLoading: () => void;
20
+ setLoadingMessage: (message: string | null) => void;
21
+ setLoadingType: (type: LoadingType) => void;
22
+ withLoading: <T>(asyncFn: Promise<T>, message?: string, type?: LoadingType) => Promise<T>;
23
+ }
24
+ /**
25
+ * useLoading hook for loading state management
26
+ *
27
+ * USAGE:
28
+ * ```typescript
29
+ * const {
30
+ * isLoading,
31
+ * loadingMessage,
32
+ * startLoading,
33
+ * stopLoading,
34
+ * withLoading,
35
+ * } = useLoading();
36
+ *
37
+ * // Manual control
38
+ * const handleSave = async () => {
39
+ * startLoading('Saving data...');
40
+ * try {
41
+ * await saveData();
42
+ * } finally {
43
+ * stopLoading();
44
+ * }
45
+ * };
46
+ *
47
+ * // Automatic wrapper
48
+ * const handleLoad = () => withLoading(
49
+ * loadData(),
50
+ * 'Loading data...'
51
+ * );
52
+ *
53
+ * // In render
54
+ * {isLoading && <LoadingState message={loadingMessage} />}
55
+ * ```
56
+ */
57
+ export declare const useLoading: () => UseLoadingReturn;
58
+ /**
59
+ * Convenience hook for simple loading state (no message)
60
+ */
61
+ export declare const useSimpleLoading: () => {
62
+ isLoading: boolean;
63
+ startLoading: () => void;
64
+ stopLoading: () => void;
65
+ withLoading: <T>(asyncFn: Promise<T>) => Promise<T>;
66
+ };
67
+ //# sourceMappingURL=useLoading.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLoading.d.ts","sourceRoot":"","sources":["../../../src/presentation/hooks/useLoading.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAE/B,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,WAAW,CAAC;IAGzB,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7D,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACpD,cAAc,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IAG5C,WAAW,EAAE,CAAC,CAAC,EACb,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,OAAO,CAAC,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,WAAW,KACf,OAAO,CAAC,CAAC,CAAC,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,UAAU,QAAO,gBAwE7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;kBAIlB,CAAC,WAAY,OAAO,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,CAAC;CAmB9C,CAAC"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Loading Domain - useLoading Hook
3
+ *
4
+ * React hook for managing loading states.
5
+ * Provides consistent loading state management across components.
6
+ *
7
+ * @domain loading
8
+ * @layer presentation/hooks
9
+ */
10
+ import { useState, useCallback } from 'react';
11
+ /**
12
+ * useLoading hook for loading state management
13
+ *
14
+ * USAGE:
15
+ * ```typescript
16
+ * const {
17
+ * isLoading,
18
+ * loadingMessage,
19
+ * startLoading,
20
+ * stopLoading,
21
+ * withLoading,
22
+ * } = useLoading();
23
+ *
24
+ * // Manual control
25
+ * const handleSave = async () => {
26
+ * startLoading('Saving data...');
27
+ * try {
28
+ * await saveData();
29
+ * } finally {
30
+ * stopLoading();
31
+ * }
32
+ * };
33
+ *
34
+ * // Automatic wrapper
35
+ * const handleLoad = () => withLoading(
36
+ * loadData(),
37
+ * 'Loading data...'
38
+ * );
39
+ *
40
+ * // In render
41
+ * {isLoading && <LoadingState message={loadingMessage} />}
42
+ * ```
43
+ */
44
+ export const useLoading = () => {
45
+ const [isLoading, setIsLoading] = useState(false);
46
+ const [loadingMessage, setLoadingMessage] = useState(null);
47
+ const [loadingType, setLoadingType] = useState('pulse');
48
+ /**
49
+ * Start loading state
50
+ */
51
+ const startLoading = useCallback((message, type = 'pulse') => {
52
+ setIsLoading(true);
53
+ setLoadingMessage(message || null);
54
+ setLoadingType(type);
55
+ }, []);
56
+ /**
57
+ * Stop loading state
58
+ */
59
+ const stopLoading = useCallback(() => {
60
+ setIsLoading(false);
61
+ setLoadingMessage(null);
62
+ }, []);
63
+ /**
64
+ * Update loading message
65
+ */
66
+ const updateLoadingMessage = useCallback((message) => {
67
+ setLoadingMessage(message);
68
+ }, []);
69
+ /**
70
+ * Update loading type
71
+ */
72
+ const updateLoadingType = useCallback((type) => {
73
+ setLoadingType(type);
74
+ }, []);
75
+ /**
76
+ * Async wrapper that automatically manages loading state
77
+ */
78
+ const withLoading = useCallback(async (asyncFn, message, type = 'pulse') => {
79
+ startLoading(message, type);
80
+ try {
81
+ const result = await asyncFn;
82
+ return result;
83
+ }
84
+ finally {
85
+ stopLoading();
86
+ }
87
+ }, [startLoading, stopLoading]);
88
+ return {
89
+ // Loading state
90
+ isLoading,
91
+ loadingMessage,
92
+ loadingType,
93
+ // Actions
94
+ startLoading,
95
+ stopLoading,
96
+ setLoadingMessage: updateLoadingMessage,
97
+ setLoadingType: updateLoadingType,
98
+ // Async wrapper
99
+ withLoading,
100
+ };
101
+ };
102
+ /**
103
+ * Convenience hook for simple loading state (no message)
104
+ */
105
+ export const useSimpleLoading = () => {
106
+ const [isLoading, setIsLoading] = useState(false);
107
+ const withLoading = useCallback(async (asyncFn) => {
108
+ setIsLoading(true);
109
+ try {
110
+ const result = await asyncFn;
111
+ return result;
112
+ }
113
+ finally {
114
+ setIsLoading(false);
115
+ }
116
+ }, []);
117
+ return {
118
+ isLoading,
119
+ startLoading: useCallback(() => setIsLoading(true), []),
120
+ stopLoading: useCallback(() => setIsLoading(false), []),
121
+ withLoading,
122
+ };
123
+ };
124
+ //# sourceMappingURL=useLoading.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLoading.js","sourceRoot":"","sources":["../../../src/presentation/hooks/useLoading.ts"],"names":[],"mappings":"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"}