@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/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@umituz/react-native-loading",
3
+ "version": "1.0.0",
4
+ "description": "Loading states and animations for React Native apps with breathing animations, skeleton loaders, and state management hooks",
5
+ "main": "./lib/index.js",
6
+ "types": "./lib/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "typecheck": "tsc --noEmit",
10
+ "lint": "tsc --noEmit",
11
+ "clean": "rm -rf lib",
12
+ "prebuild": "npm run clean",
13
+ "prepublishOnly": "npm run build",
14
+ "version:patch": "npm version patch -m 'chore: release v%s'",
15
+ "version:minor": "npm version minor -m 'chore: release v%s'",
16
+ "version:major": "npm version major -m 'chore: release v%s'"
17
+ },
18
+ "keywords": [
19
+ "react-native",
20
+ "loading",
21
+ "skeleton",
22
+ "loader",
23
+ "animation",
24
+ "spinner"
25
+ ],
26
+ "author": "รœmit UZ <umit@umituz.com>",
27
+ "license": "MIT",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/umituz/react-native-loading"
31
+ },
32
+ "peerDependencies": {
33
+ "@umituz/react-native-design-system": ">=1.5.0",
34
+ "react": ">=18.2.0",
35
+ "react-native": ">=0.74.0"
36
+ },
37
+ "devDependencies": {
38
+ "@types/react": "^18.2.45",
39
+ "@types/react-native": "^0.73.0",
40
+ "@umituz/react-native-design-system": "^1.5.0",
41
+ "react": "^18.2.0",
42
+ "react-native": "^0.74.0",
43
+ "typescript": "^5.3.3"
44
+ },
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "files": [
49
+ "lib",
50
+ "src",
51
+ "README.md",
52
+ "LICENSE"
53
+ ]
54
+ }
55
+
@@ -0,0 +1,429 @@
1
+ # Loading Domain - Usage Examples
2
+
3
+ This file provides comprehensive examples for using the loading domain across all generated apps.
4
+
5
+ ## ๐Ÿ“‹ Table of Contents
6
+
7
+ 1. [Basic Loading State](#basic-loading-state)
8
+ 2. [Skeleton Loaders](#skeleton-loaders)
9
+ 3. [Loading State Hook](#loading-state-hook)
10
+ 4. [Full Screen Loading](#full-screen-loading)
11
+ 5. [List Screens with Skeleton](#list-screens-with-skeleton)
12
+ 6. [Custom Emoji per App](#custom-emoji-per-app)
13
+
14
+ ---
15
+
16
+ ## Basic Loading State
17
+
18
+ ### Simple Loading Indicator
19
+
20
+ ```typescript
21
+ import { LoadingState } from '@domains/loading';
22
+
23
+ const MyScreen = () => {
24
+ const [isLoading, setIsLoading] = useState(true);
25
+
26
+ return (
27
+ <View>
28
+ {isLoading ? (
29
+ <LoadingState message="Loading data..." />
30
+ ) : (
31
+ <Content />
32
+ )}
33
+ </View>
34
+ );
35
+ };
36
+ ```
37
+
38
+ ### Inline Loading (Small Size)
39
+
40
+ ```typescript
41
+ <LoadingState size="small" />
42
+ ```
43
+
44
+ ### Section Loading (Medium Size)
45
+
46
+ ```typescript
47
+ <LoadingState size="medium" message="Fetching settings..." />
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Skeleton Loaders
53
+
54
+ ### List Skeleton
55
+
56
+ ```typescript
57
+ import { SkeletonLoader } from '@domains/loading';
58
+
59
+ const ListScreen = () => {
60
+ const [data, setData] = useState([]);
61
+ const [isLoading, setIsLoading] = useState(true);
62
+
63
+ return (
64
+ <View>
65
+ {isLoading ? (
66
+ <SkeletonLoader pattern="list" count={5} />
67
+ ) : (
68
+ <FlatList data={data} ... />
69
+ )}
70
+ </View>
71
+ );
72
+ };
73
+ ```
74
+
75
+ ### Card Skeleton
76
+
77
+ ```typescript
78
+ <SkeletonLoader pattern="card" count={3} />
79
+ ```
80
+
81
+ ### Profile Skeleton
82
+
83
+ ```typescript
84
+ <SkeletonLoader pattern="profile" />
85
+ ```
86
+
87
+ ### Text Skeleton
88
+
89
+ ```typescript
90
+ <SkeletonLoader pattern="text" count={3} />
91
+ ```
92
+
93
+ ### Custom Skeleton
94
+
95
+ ```typescript
96
+ <SkeletonLoader
97
+ pattern="custom"
98
+ custom={[
99
+ { width: 100, height: 100, borderRadius: 50 },
100
+ { width: '80%', height: 20, borderRadius: 4, marginBottom: 8 },
101
+ { width: '60%', height: 16, borderRadius: 4 },
102
+ ]}
103
+ />
104
+ ```
105
+
106
+ ---
107
+
108
+ ## Loading State Hook
109
+
110
+ ### Manual Control
111
+
112
+ ```typescript
113
+ import { useLoading } from '@domains/loading';
114
+
115
+ const DataScreen = () => {
116
+ const { isLoading, loadingMessage, startLoading, stopLoading } = useLoading();
117
+
118
+ const handleSave = async () => {
119
+ startLoading('Saving changes...');
120
+ try {
121
+ await saveData();
122
+ } finally {
123
+ stopLoading();
124
+ }
125
+ };
126
+
127
+ return (
128
+ <View>
129
+ {isLoading && <LoadingState message={loadingMessage} />}
130
+ <Button onPress={handleSave}>Save</Button>
131
+ </View>
132
+ );
133
+ };
134
+ ```
135
+
136
+ ### Async Wrapper (Automatic)
137
+
138
+ ```typescript
139
+ const DataScreen = () => {
140
+ const { isLoading, loadingMessage, withLoading } = useLoading();
141
+
142
+ const loadData = () => withLoading(
143
+ fetchData(),
144
+ 'Loading data...'
145
+ );
146
+
147
+ useEffect(() => {
148
+ loadData();
149
+ }, []);
150
+
151
+ return (
152
+ <View>
153
+ {isLoading ? (
154
+ <LoadingState message={loadingMessage} />
155
+ ) : (
156
+ <Content />
157
+ )}
158
+ </View>
159
+ );
160
+ };
161
+ ```
162
+
163
+ ### Simple Loading Hook
164
+
165
+ ```typescript
166
+ import { useSimpleLoading } from '@domains/loading';
167
+
168
+ const SimpleScreen = () => {
169
+ const { isLoading, withLoading } = useSimpleLoading();
170
+
171
+ const handleAction = () => withLoading(performAction());
172
+
173
+ return (
174
+ <View>
175
+ {isLoading && <LoadingState />}
176
+ <Button onPress={handleAction}>Do Action</Button>
177
+ </View>
178
+ );
179
+ };
180
+ ```
181
+
182
+ ---
183
+
184
+ ## Full Screen Loading
185
+
186
+ ### With Message
187
+
188
+ ```typescript
189
+ <LoadingState
190
+ fullScreen
191
+ message="Please wait..."
192
+ size="large"
193
+ />
194
+ ```
195
+
196
+ ### Initial App Load
197
+
198
+ ```typescript
199
+ const App = () => {
200
+ const [isReady, setIsReady] = useState(false);
201
+
202
+ useEffect(() => {
203
+ const prepare = async () => {
204
+ await loadAssets();
205
+ await loadData();
206
+ setIsReady(true);
207
+ };
208
+ prepare();
209
+ }, []);
210
+
211
+ if (!isReady) {
212
+ return <LoadingState fullScreen message="Initializing app..." />;
213
+ }
214
+
215
+ return <MainApp />;
216
+ };
217
+ ```
218
+
219
+ ---
220
+
221
+ ## List Screens with Skeleton
222
+
223
+ ### Complete Example
224
+
225
+ ```typescript
226
+ import { SkeletonLoader, useLoading } from '@domains/loading';
227
+
228
+ const WorkoutsScreen = () => {
229
+ const [workouts, setWorkouts] = useState([]);
230
+ const { isLoading, withLoading } = useLoading();
231
+
232
+ const loadWorkouts = () => withLoading(
233
+ fetchWorkouts(),
234
+ 'Loading workouts...'
235
+ );
236
+
237
+ useEffect(() => {
238
+ loadWorkouts();
239
+ }, []);
240
+
241
+ return (
242
+ <ScreenLayout>
243
+ <ScreenHeader title="Workouts" />
244
+
245
+ {isLoading ? (
246
+ <SkeletonLoader pattern="list" count={8} />
247
+ ) : workouts.length === 0 ? (
248
+ <EmptyState message="No workouts found" />
249
+ ) : (
250
+ <FlatList
251
+ data={workouts}
252
+ renderItem={({ item }) => <WorkoutCard workout={item} />}
253
+ />
254
+ )}
255
+ </ScreenLayout>
256
+ );
257
+ };
258
+ ```
259
+
260
+ ---
261
+
262
+ ## Custom Emoji per App
263
+
264
+ ### Meditation App
265
+
266
+ ```typescript
267
+ import { LoadingState, LOADING_EMOJIS } from '@domains/loading';
268
+
269
+ <LoadingState
270
+ emoji={LOADING_EMOJIS.meditation}
271
+ message="Loading meditations..."
272
+ />
273
+ ```
274
+
275
+ ### Fitness App
276
+
277
+ ```typescript
278
+ <LoadingState
279
+ emoji={LOADING_EMOJIS.fitness}
280
+ message="Loading workouts..."
281
+ />
282
+ ```
283
+
284
+ ### Productivity App
285
+
286
+ ```typescript
287
+ <LoadingState
288
+ emoji={LOADING_EMOJIS.productivity}
289
+ message="Loading tasks..."
290
+ />
291
+ ```
292
+
293
+ ### Available Emojis
294
+
295
+ ```typescript
296
+ LOADING_EMOJIS = {
297
+ meditation: '๐Ÿง˜',
298
+ fitness: '๐Ÿ’ช',
299
+ workout: '๐Ÿ‹๏ธ',
300
+ running: '๐Ÿƒ',
301
+ cycling: '๐Ÿšด',
302
+ yoga: '๐Ÿง˜โ€โ™€๏ธ',
303
+ health: '๐Ÿฅ',
304
+ nutrition: '๐Ÿฅ—',
305
+ productivity: 'โณ',
306
+ education: '๐Ÿ“š',
307
+ reading: '๐Ÿ“–',
308
+ music: '๐ŸŽต',
309
+ art: '๐ŸŽจ',
310
+ travel: 'โœˆ๏ธ',
311
+ finance: '๐Ÿ’ฐ',
312
+ shopping: '๐Ÿ›๏ธ',
313
+ cooking: '๐Ÿ‘จโ€๐Ÿณ',
314
+ gaming: '๐ŸŽฎ',
315
+ default: 'โŒ›',
316
+ }
317
+ ```
318
+
319
+ ---
320
+
321
+ ## Settings Screen Example
322
+
323
+ ```typescript
324
+ import { LoadingState, useLoading } from '@domains/loading';
325
+
326
+ const SettingsScreen = () => {
327
+ const { theme } = useTheme();
328
+ const { language, setLanguage } = useLocalization();
329
+ const { isLoading, withLoading } = useLoading();
330
+
331
+ const handleLanguageChange = (newLanguage: string) => withLoading(
332
+ setLanguage(newLanguage),
333
+ 'Changing language...'
334
+ );
335
+
336
+ if (isLoading) {
337
+ return <LoadingState fullScreen message="Applying changes..." />;
338
+ }
339
+
340
+ return (
341
+ <ScreenLayout>
342
+ <ScreenHeader title="Settings" />
343
+ <ScrollView>
344
+ {/* Settings content */}
345
+ </ScrollView>
346
+ </ScreenLayout>
347
+ );
348
+ };
349
+ ```
350
+
351
+ ---
352
+
353
+ ## Onboarding Screen Example
354
+
355
+ ```typescript
356
+ import { LoadingState, useLoading } from '@domains/loading';
357
+
358
+ const OnboardingScreen = () => {
359
+ const { completeOnboarding } = useOnboarding();
360
+ const { isLoading, withLoading } = useLoading();
361
+
362
+ const handleComplete = () => withLoading(
363
+ completeOnboarding(),
364
+ 'Setting up your account...'
365
+ );
366
+
367
+ return (
368
+ <ScreenLayout>
369
+ {isLoading ? (
370
+ <LoadingState fullScreen message="Almost there..." />
371
+ ) : (
372
+ <OnboardingContent onComplete={handleComplete} />
373
+ )}
374
+ </ScreenLayout>
375
+ );
376
+ };
377
+ ```
378
+
379
+ ---
380
+
381
+ ## Best Practices
382
+
383
+ 1. **Use skeleton loaders for lists** - Better UX than full-screen loading
384
+ 2. **Match emoji to app theme** - Use LOADING_EMOJIS for consistency
385
+ 3. **Show meaningful messages** - "Loading workouts..." not "Please wait..."
386
+ 4. **Use full screen sparingly** - Only for critical app-wide operations
387
+ 5. **Prefer useLoading hook** - Centralized state management
388
+ 6. **Use withLoading wrapper** - Cleaner async code
389
+ 7. **Test loading states** - Ensure they work on slow connections
390
+
391
+ ---
392
+
393
+ ## Migration from Old Loading Patterns
394
+
395
+ ### Before (ActivityIndicator)
396
+
397
+ ```typescript
398
+ // โŒ OLD - Inconsistent
399
+ {isLoading && <ActivityIndicator />}
400
+ {isLoading && <Text>Loading...</Text>}
401
+ ```
402
+
403
+ ### After (LoadingState)
404
+
405
+ ```typescript
406
+ // โœ… NEW - Consistent, themed
407
+ {isLoading && <LoadingState message="Loading..." />}
408
+ ```
409
+
410
+ ### Before (Custom Spinner)
411
+
412
+ ```typescript
413
+ // โŒ OLD - Duplicated code
414
+ <View style={styles.loadingContainer}>
415
+ <ActivityIndicator size="large" />
416
+ <Text style={styles.loadingText}>Please wait...</Text>
417
+ </View>
418
+ ```
419
+
420
+ ### After (LoadingState)
421
+
422
+ ```typescript
423
+ // โœ… NEW - One line, consistent
424
+ <LoadingState size="large" message="Please wait..." />
425
+ ```
426
+
427
+ ---
428
+
429
+ This loading domain ensures **consistent, beautiful, calming loading experiences** across all 100+ generated apps! ๐Ÿง˜