@umituz/react-native-design-system 2.6.127 → 2.7.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 +4 -2
- package/src/exports/onboarding.ts +6 -0
- package/src/index.ts +5 -0
- package/src/onboarding/domain/entities/OnboardingOptions.ts +104 -0
- package/src/onboarding/domain/entities/OnboardingQuestion.ts +165 -0
- package/src/onboarding/domain/entities/OnboardingSlide.ts +152 -0
- package/src/onboarding/domain/entities/OnboardingUserData.ts +43 -0
- package/src/onboarding/hooks/useOnboardingFlow.ts +50 -0
- package/src/onboarding/index.ts +108 -0
- package/src/onboarding/infrastructure/hooks/__tests__/useOnboardingAnswers.test.ts +163 -0
- package/src/onboarding/infrastructure/hooks/__tests__/useOnboardingNavigation.test.ts +121 -0
- package/src/onboarding/infrastructure/hooks/useOnboardingAnswers.ts +69 -0
- package/src/onboarding/infrastructure/hooks/useOnboardingNavigation.ts +75 -0
- package/src/onboarding/infrastructure/services/SlideManager.ts +53 -0
- package/src/onboarding/infrastructure/services/ValidationManager.ts +127 -0
- package/src/onboarding/infrastructure/storage/OnboardingStore.ts +99 -0
- package/src/onboarding/infrastructure/storage/OnboardingStoreActions.ts +50 -0
- package/src/onboarding/infrastructure/storage/OnboardingStoreSelectors.ts +25 -0
- package/src/onboarding/infrastructure/storage/OnboardingStoreState.ts +22 -0
- package/src/onboarding/infrastructure/storage/__tests__/OnboardingStore.test.ts +85 -0
- package/src/onboarding/infrastructure/storage/actions/answerActions.ts +47 -0
- package/src/onboarding/infrastructure/storage/actions/completeAction.ts +45 -0
- package/src/onboarding/infrastructure/storage/actions/index.ts +22 -0
- package/src/onboarding/infrastructure/storage/actions/initializeAction.ts +40 -0
- package/src/onboarding/infrastructure/storage/actions/resetAction.ts +37 -0
- package/src/onboarding/infrastructure/storage/actions/skipAction.ts +46 -0
- package/src/onboarding/infrastructure/storage/actions/storageHelpers.ts +60 -0
- package/src/onboarding/infrastructure/utils/arrayUtils.ts +28 -0
- package/src/onboarding/infrastructure/utils/backgroundUtils.ts +38 -0
- package/src/onboarding/infrastructure/utils/layouts/collageLayout.ts +81 -0
- package/src/onboarding/infrastructure/utils/layouts/gridLayouts.ts +78 -0
- package/src/onboarding/infrastructure/utils/layouts/honeycombLayout.ts +36 -0
- package/src/onboarding/infrastructure/utils/layouts/index.ts +12 -0
- package/src/onboarding/infrastructure/utils/layouts/layoutTypes.ts +37 -0
- package/src/onboarding/infrastructure/utils/layouts/masonryLayout.ts +37 -0
- package/src/onboarding/infrastructure/utils/layouts/scatteredLayout.ts +34 -0
- package/src/onboarding/infrastructure/utils/layouts/screenDimensions.ts +11 -0
- package/src/onboarding/infrastructure/utils/layouts/tilesLayout.ts +34 -0
- package/src/onboarding/presentation/components/BackgroundImageCollage.tsx +90 -0
- package/src/onboarding/presentation/components/BackgroundVideo.tsx +24 -0
- package/src/onboarding/presentation/components/BaseSlide.tsx +47 -0
- package/src/onboarding/presentation/components/OnboardingBackground.tsx +91 -0
- package/src/onboarding/presentation/components/OnboardingFooter.tsx +151 -0
- package/src/onboarding/presentation/components/OnboardingHeader.tsx +92 -0
- package/src/onboarding/presentation/components/OnboardingResetSetting.tsx +70 -0
- package/src/onboarding/presentation/components/OnboardingScreenContent.tsx +146 -0
- package/src/onboarding/presentation/components/OnboardingSlide.tsx +124 -0
- package/src/onboarding/presentation/components/QuestionRenderer.tsx +60 -0
- package/src/onboarding/presentation/components/QuestionSlide.tsx +67 -0
- package/src/onboarding/presentation/components/QuestionSlideHeader.tsx +75 -0
- package/src/onboarding/presentation/components/questions/MultipleChoiceQuestion.tsx +74 -0
- package/src/onboarding/presentation/components/questions/QuestionOptionItem.tsx +115 -0
- package/src/onboarding/presentation/components/questions/RatingQuestion.tsx +66 -0
- package/src/onboarding/presentation/components/questions/SingleChoiceQuestion.tsx +117 -0
- package/src/onboarding/presentation/components/questions/TextInputQuestion.tsx +71 -0
- package/src/onboarding/presentation/hooks/__tests__/useOnboardingContainerStyle.test.ts +96 -0
- package/src/onboarding/presentation/hooks/useOnboardingContainerStyle.ts +37 -0
- package/src/onboarding/presentation/hooks/useOnboardingGestures.ts +45 -0
- package/src/onboarding/presentation/hooks/useOnboardingScreenHandlers.ts +114 -0
- package/src/onboarding/presentation/hooks/useOnboardingScreenState.ts +146 -0
- package/src/onboarding/presentation/providers/OnboardingProvider.tsx +51 -0
- package/src/onboarding/presentation/screens/OnboardingScreen.tsx +189 -0
- package/src/onboarding/presentation/types/OnboardingProps.ts +46 -0
- package/src/onboarding/presentation/types/OnboardingTheme.ts +27 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-design-system",
|
|
3
|
-
"version": "2.
|
|
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 and
|
|
3
|
+
"version": "2.7.0",
|
|
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, and onboarding utilities",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
7
7
|
"exports": {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"./image": "./src/image/index.ts",
|
|
23
23
|
"./timezone": "./src/timezone/index.ts",
|
|
24
24
|
"./offline": "./src/offline/index.ts",
|
|
25
|
+
"./onboarding": "./src/onboarding/index.ts",
|
|
25
26
|
"./package.json": "./package.json"
|
|
26
27
|
},
|
|
27
28
|
"scripts": {
|
|
@@ -74,6 +75,7 @@
|
|
|
74
75
|
"expo-network": ">=8.0.0",
|
|
75
76
|
"expo-secure-store": ">=14.0.0",
|
|
76
77
|
"expo-sharing": ">=12.0.0",
|
|
78
|
+
"expo-video": ">=3.0.0",
|
|
77
79
|
"react": ">=19.0.0",
|
|
78
80
|
"react-native": ">=0.81.0",
|
|
79
81
|
"react-native-gesture-handler": ">=2.20.0",
|
package/src/index.ts
CHANGED
|
@@ -101,3 +101,8 @@ export * from './exports/variants';
|
|
|
101
101
|
// UTILITIES
|
|
102
102
|
// =============================================================================
|
|
103
103
|
export * from './exports/utilities';
|
|
104
|
+
|
|
105
|
+
// =============================================================================
|
|
106
|
+
// ONBOARDING EXPORTS
|
|
107
|
+
// =============================================================================
|
|
108
|
+
export * from './exports/onboarding';
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding Options
|
|
3
|
+
*
|
|
4
|
+
* Configuration options for onboarding flow
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { OnboardingSlide } from "./OnboardingSlide";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Onboarding Options
|
|
11
|
+
* Customize the onboarding experience
|
|
12
|
+
*/
|
|
13
|
+
export interface OnboardingOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Array of slides to display
|
|
16
|
+
*/
|
|
17
|
+
slides: OnboardingSlide[];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Callback when onboarding is completed
|
|
21
|
+
*/
|
|
22
|
+
onComplete?: () => void | Promise<void>;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Callback when onboarding is skipped
|
|
26
|
+
*/
|
|
27
|
+
onSkip?: () => void | Promise<void>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Custom skip button text (default: "Skip")
|
|
31
|
+
*/
|
|
32
|
+
skipButtonText?: string;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Custom next button text (default: "Next")
|
|
36
|
+
*/
|
|
37
|
+
nextButtonText?: string;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Custom get started button text (default: "Get Started")
|
|
41
|
+
*/
|
|
42
|
+
getStartedButtonText?: string;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Show skip button (default: true)
|
|
46
|
+
*/
|
|
47
|
+
showSkipButton?: boolean;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Show back button (default: true)
|
|
51
|
+
*/
|
|
52
|
+
showBackButton?: boolean;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Show progress bar (default: true)
|
|
56
|
+
*/
|
|
57
|
+
showProgressBar?: boolean;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Show dots indicator (default: true)
|
|
61
|
+
*/
|
|
62
|
+
showDots?: boolean;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Show progress text (default: true)
|
|
66
|
+
*/
|
|
67
|
+
showProgressText?: boolean;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Storage key for completion state (default: "@onboarding_completed")
|
|
71
|
+
*/
|
|
72
|
+
storageKey?: string;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Auto-complete onboarding on last slide (default: false)
|
|
76
|
+
*/
|
|
77
|
+
autoComplete?: boolean;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Callback when user wants to upgrade from onboarding
|
|
81
|
+
*/
|
|
82
|
+
onUpgrade?: () => void;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Show paywall modal on onboarding completion (default: false)
|
|
86
|
+
*/
|
|
87
|
+
showPaywallOnComplete?: boolean;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Use custom background for all slides (default: false)
|
|
91
|
+
* When true, all slides will use custom backgrounds if available
|
|
92
|
+
*/
|
|
93
|
+
useCustomBackground?: boolean;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Visual theme variant (default: "default")
|
|
97
|
+
* - default: Standard layout
|
|
98
|
+
* - card: Content in a card with shadow
|
|
99
|
+
* - minimal: Clean, text-focused layout
|
|
100
|
+
* - fullscreen: Immersive fullscreen layout
|
|
101
|
+
*/
|
|
102
|
+
themeVariant?: "default" | "card" | "minimal" | "fullscreen";
|
|
103
|
+
}
|
|
104
|
+
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding Question Entity
|
|
3
|
+
*
|
|
4
|
+
* Domain entity representing a personalization question in the onboarding flow
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Question types for different input methods
|
|
9
|
+
*/
|
|
10
|
+
export type QuestionType =
|
|
11
|
+
| "single_choice" // Radio buttons - single selection
|
|
12
|
+
| "multiple_choice" // Checkboxes - multiple selections
|
|
13
|
+
| "text_input" // Text input field
|
|
14
|
+
| "rating" // Star rating or numeric rating
|
|
15
|
+
| "date" // Date picker
|
|
16
|
+
| "image_picker"; // Image selection from gallery
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Option for single/multiple choice questions
|
|
20
|
+
*/
|
|
21
|
+
export interface QuestionOption {
|
|
22
|
+
/**
|
|
23
|
+
* Unique identifier for the option
|
|
24
|
+
*/
|
|
25
|
+
id: string;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Display label for the option
|
|
29
|
+
*/
|
|
30
|
+
label: string;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Optional icon (emoji or Ionicons name)
|
|
34
|
+
*/
|
|
35
|
+
icon?: string;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Optional image URL
|
|
39
|
+
*/
|
|
40
|
+
image?: string;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Optional value (if different from label)
|
|
44
|
+
*/
|
|
45
|
+
value?: string;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Type of icon: 'emoji' or 'icon' (default: 'icon')
|
|
49
|
+
*/
|
|
50
|
+
iconType?: 'emoji' | 'icon';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Validation rules for questions
|
|
55
|
+
*/
|
|
56
|
+
export interface QuestionValidation {
|
|
57
|
+
/**
|
|
58
|
+
* Is this question required?
|
|
59
|
+
*/
|
|
60
|
+
required?: boolean;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Minimum value (for rating)
|
|
64
|
+
*/
|
|
65
|
+
min?: number;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Maximum value (for rating)
|
|
69
|
+
*/
|
|
70
|
+
max?: number;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Minimum length (for text input)
|
|
74
|
+
*/
|
|
75
|
+
minLength?: number;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Maximum length (for text input)
|
|
79
|
+
*/
|
|
80
|
+
maxLength?: number;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Minimum selections (for multiple choice)
|
|
84
|
+
*/
|
|
85
|
+
minSelections?: number;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Maximum selections (for multiple choice)
|
|
89
|
+
*/
|
|
90
|
+
maxSelections?: number;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Custom validation function
|
|
94
|
+
*/
|
|
95
|
+
customValidator?: (value: any) => boolean | string;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Onboarding Question
|
|
100
|
+
* Represents a personalization question in the onboarding flow
|
|
101
|
+
*/
|
|
102
|
+
export interface OnboardingQuestion {
|
|
103
|
+
/**
|
|
104
|
+
* Unique identifier for the question
|
|
105
|
+
*/
|
|
106
|
+
id: string;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Question type
|
|
110
|
+
*/
|
|
111
|
+
type: QuestionType;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Question text
|
|
115
|
+
*/
|
|
116
|
+
question: string;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Optional subtitle/description
|
|
120
|
+
*/
|
|
121
|
+
subtitle?: string;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Optional placeholder text (for text input)
|
|
125
|
+
*/
|
|
126
|
+
placeholder?: string;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Options for single/multiple choice questions
|
|
130
|
+
*/
|
|
131
|
+
options?: QuestionOption[];
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Validation rules
|
|
135
|
+
*/
|
|
136
|
+
validation?: QuestionValidation;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Default value
|
|
140
|
+
*/
|
|
141
|
+
defaultValue?: any;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Storage key for saving the answer
|
|
145
|
+
*/
|
|
146
|
+
storageKey: string;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Optional icon for the question
|
|
150
|
+
*/
|
|
151
|
+
icon?: string;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Type of icon: 'emoji' or 'icon' (default: 'icon')
|
|
155
|
+
*/
|
|
156
|
+
iconType?: 'emoji' | 'icon';
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Skip this question if condition is met
|
|
160
|
+
* @param answers - Previous answers
|
|
161
|
+
* @returns true to skip, false to show
|
|
162
|
+
*/
|
|
163
|
+
skipIf?: (answers: Record<string, any>) => boolean;
|
|
164
|
+
}
|
|
165
|
+
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding Slide Entity
|
|
3
|
+
*
|
|
4
|
+
* Domain entity representing a single onboarding slide
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { OnboardingQuestion } from "./OnboardingQuestion";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Slide type - determines the content and behavior
|
|
11
|
+
*/
|
|
12
|
+
export type SlideType = "info" | "question" | "welcome" | "completion";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Content position - determines where the text content is positioned
|
|
16
|
+
*/
|
|
17
|
+
export type ContentPosition = "center" | "bottom";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Onboarding Slide
|
|
21
|
+
* Each slide represents one step in the onboarding flow
|
|
22
|
+
*/
|
|
23
|
+
export interface OnboardingSlide {
|
|
24
|
+
/**
|
|
25
|
+
* Unique identifier for the slide
|
|
26
|
+
*/
|
|
27
|
+
id: string;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Slide type (default: "info")
|
|
31
|
+
*/
|
|
32
|
+
type?: SlideType;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Slide title
|
|
36
|
+
*/
|
|
37
|
+
title: string;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Slide description/body text
|
|
41
|
+
*/
|
|
42
|
+
description: string;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Icon to display (emoji or icon name)
|
|
46
|
+
*/
|
|
47
|
+
icon?: string;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Type of icon: 'emoji' or 'icon' (default: 'icon')
|
|
51
|
+
*/
|
|
52
|
+
iconType?: 'emoji' | 'icon';
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Hide icon even if provided (default: false)
|
|
56
|
+
*/
|
|
57
|
+
hideIcon?: boolean;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Content position: 'center' or 'bottom' (default: 'center')
|
|
61
|
+
*/
|
|
62
|
+
contentPosition?: ContentPosition;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Background color for the slide background (optional)
|
|
66
|
+
* Only used if useCustomBackground is true
|
|
67
|
+
*/
|
|
68
|
+
backgroundColor?: string;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Use custom background color instead of theme defaults (default: false)
|
|
72
|
+
* If true and backgroundColor is provided, it will be used
|
|
73
|
+
*/
|
|
74
|
+
useCustomBackground?: boolean;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Optional image URL (alternative to icon)
|
|
78
|
+
*/
|
|
79
|
+
image?: any;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Optional background image (URL or require path)
|
|
83
|
+
* Stretches to fill the screen behind content
|
|
84
|
+
*/
|
|
85
|
+
backgroundImage?: any;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Optional multiple background images (URLs or require paths)
|
|
89
|
+
* Displayed in a collage/grid pattern behind content
|
|
90
|
+
* If provided, takes precedence over single backgroundImage
|
|
91
|
+
*/
|
|
92
|
+
backgroundImages?: any[];
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Layout pattern for multiple background images
|
|
96
|
+
* 'grid' - Equal sized grid (auto columns)
|
|
97
|
+
* 'dense' - Dense grid with many small images (6 columns)
|
|
98
|
+
* 'masonry' - Pinterest-style masonry layout
|
|
99
|
+
* 'collage' - Random sizes and positions
|
|
100
|
+
* 'scattered' - Small randomly placed images
|
|
101
|
+
* 'tiles' - Fixed size tiles centered
|
|
102
|
+
* 'honeycomb' - Hexagonal pattern
|
|
103
|
+
* Default: 'grid'
|
|
104
|
+
*/
|
|
105
|
+
backgroundImagesLayout?: 'grid' | 'dense' | 'masonry' | 'collage' | 'scattered' | 'tiles' | 'honeycomb';
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Number of columns for grid-based layouts
|
|
109
|
+
* Only applies to: grid, dense, masonry, tiles
|
|
110
|
+
*/
|
|
111
|
+
backgroundImagesColumns?: number;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Gap between images in pixels
|
|
115
|
+
*/
|
|
116
|
+
backgroundImagesGap?: number;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Border radius for images
|
|
120
|
+
*/
|
|
121
|
+
backgroundImagesBorderRadius?: number;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Optional background video (URL or require path)
|
|
125
|
+
* Plays in loop behind content
|
|
126
|
+
*/
|
|
127
|
+
backgroundVideo?: any;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Opacity of the overlay color on top of background media
|
|
131
|
+
* Range: 0.0 to 1.0 (Default: 0.5)
|
|
132
|
+
*/
|
|
133
|
+
overlayOpacity?: number;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Optional features list to display
|
|
137
|
+
*/
|
|
138
|
+
features?: string[];
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Optional question for personalization
|
|
142
|
+
* Only used when type is "question"
|
|
143
|
+
*/
|
|
144
|
+
question?: OnboardingQuestion;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Skip this slide if condition is met
|
|
148
|
+
* @param answers - Previous answers
|
|
149
|
+
* @returns true to skip, false to show
|
|
150
|
+
*/
|
|
151
|
+
skipIf?: (answers: Record<string, any>) => boolean;
|
|
152
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding User Data Entity
|
|
3
|
+
*
|
|
4
|
+
* Domain entity representing collected user data from onboarding
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* User data collected during onboarding
|
|
9
|
+
*/
|
|
10
|
+
export interface OnboardingUserData {
|
|
11
|
+
/**
|
|
12
|
+
* User's answers to questions
|
|
13
|
+
* Key: question ID, Value: answer
|
|
14
|
+
*/
|
|
15
|
+
answers: Record<string, any>;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Timestamp when onboarding was completed
|
|
19
|
+
*/
|
|
20
|
+
completedAt?: string;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Was onboarding skipped?
|
|
24
|
+
*/
|
|
25
|
+
skipped?: boolean;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* User preferences derived from answers
|
|
29
|
+
*/
|
|
30
|
+
preferences?: Record<string, any>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* User profile data
|
|
34
|
+
*/
|
|
35
|
+
profile?: {
|
|
36
|
+
name?: string;
|
|
37
|
+
email?: string;
|
|
38
|
+
age?: number;
|
|
39
|
+
gender?: string;
|
|
40
|
+
[key: string]: any;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding Flow Hook
|
|
3
|
+
* Manages onboarding completion state with persistence
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
7
|
+
import { DeviceEventEmitter } from 'react-native';
|
|
8
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
9
|
+
|
|
10
|
+
const ONBOARDING_KEY = 'onboarding_complete';
|
|
11
|
+
|
|
12
|
+
export interface UseOnboardingFlowResult {
|
|
13
|
+
isOnboardingComplete: boolean;
|
|
14
|
+
completeOnboarding: () => Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const useOnboardingFlow = (): UseOnboardingFlowResult => {
|
|
18
|
+
const [isOnboardingComplete, setIsOnboardingComplete] = useState(false);
|
|
19
|
+
|
|
20
|
+
// Load persisted state
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
const loadPersistedState = async () => {
|
|
23
|
+
const value = await AsyncStorage.getItem(ONBOARDING_KEY);
|
|
24
|
+
setIsOnboardingComplete(value === 'true');
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
loadPersistedState();
|
|
28
|
+
|
|
29
|
+
const subscription = DeviceEventEmitter.addListener(
|
|
30
|
+
'onboarding-complete',
|
|
31
|
+
() => {
|
|
32
|
+
setIsOnboardingComplete(true);
|
|
33
|
+
AsyncStorage.setItem(ONBOARDING_KEY, 'true');
|
|
34
|
+
},
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
return () => subscription.remove();
|
|
38
|
+
}, []);
|
|
39
|
+
|
|
40
|
+
const completeOnboarding = useCallback(async () => {
|
|
41
|
+
await AsyncStorage.setItem(ONBOARDING_KEY, 'true');
|
|
42
|
+
setIsOnboardingComplete(true);
|
|
43
|
+
DeviceEventEmitter.emit('onboarding-complete');
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
isOnboardingComplete,
|
|
48
|
+
completeOnboarding,
|
|
49
|
+
};
|
|
50
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Native Onboarding - Public API
|
|
3
|
+
*
|
|
4
|
+
* Generic onboarding flow for React Native apps with custom backgrounds,
|
|
5
|
+
* animations, and customizable slides. Follows SOLID, DRY, KISS principles.
|
|
6
|
+
*
|
|
7
|
+
* Architecture:
|
|
8
|
+
* - Domain: Entities and interfaces (business logic)
|
|
9
|
+
* - Infrastructure: Storage and hooks (state management)
|
|
10
|
+
* - Presentation: Components and screens (UI)
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* import { OnboardingScreen, OnboardingSlide } from '@umituz/react-native-onboarding';
|
|
14
|
+
*
|
|
15
|
+
* <OnboardingScreen
|
|
16
|
+
* slides={[
|
|
17
|
+
* {
|
|
18
|
+
* id: '1',
|
|
19
|
+
* title: 'Welcome',
|
|
20
|
+
* description: 'Welcome to the app',
|
|
21
|
+
* icon: '🎉',
|
|
22
|
+
* backgroundColor: '#3B82F6',
|
|
23
|
+
* },
|
|
24
|
+
* ]}
|
|
25
|
+
* onComplete={() => console.log('Completed')}
|
|
26
|
+
* />
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
// =============================================================================
|
|
30
|
+
// DOMAIN LAYER - Entities and Interfaces
|
|
31
|
+
// =============================================================================
|
|
32
|
+
|
|
33
|
+
export type { OnboardingSlide, SlideType } from "./domain/entities/OnboardingSlide";
|
|
34
|
+
export type { OnboardingOptions } from "./domain/entities/OnboardingOptions";
|
|
35
|
+
export type {
|
|
36
|
+
OnboardingQuestion,
|
|
37
|
+
QuestionType,
|
|
38
|
+
QuestionOption,
|
|
39
|
+
QuestionValidation,
|
|
40
|
+
} from "./domain/entities/OnboardingQuestion";
|
|
41
|
+
export type { OnboardingUserData } from "./domain/entities/OnboardingUserData";
|
|
42
|
+
|
|
43
|
+
// =============================================================================
|
|
44
|
+
// INFRASTRUCTURE LAYER - Storage and Hooks
|
|
45
|
+
// =============================================================================
|
|
46
|
+
|
|
47
|
+
export {
|
|
48
|
+
useOnboardingStore,
|
|
49
|
+
useOnboarding,
|
|
50
|
+
} from "./infrastructure/storage/OnboardingStore";
|
|
51
|
+
export type { OnboardingStoreState } from "./infrastructure/storage/OnboardingStoreState";
|
|
52
|
+
export type { OnboardingStoreActions } from "./infrastructure/storage/OnboardingStoreActions";
|
|
53
|
+
export type { OnboardingStoreSelectors } from "./infrastructure/storage/OnboardingStoreSelectors";
|
|
54
|
+
export {
|
|
55
|
+
useOnboardingNavigation,
|
|
56
|
+
type UseOnboardingNavigationReturn,
|
|
57
|
+
} from "./infrastructure/hooks/useOnboardingNavigation";
|
|
58
|
+
export {
|
|
59
|
+
useOnboardingContainerStyle,
|
|
60
|
+
type UseOnboardingContainerStyleProps,
|
|
61
|
+
type UseOnboardingContainerStyleReturn,
|
|
62
|
+
} from "./presentation/hooks/useOnboardingContainerStyle";
|
|
63
|
+
|
|
64
|
+
// =============================================================================
|
|
65
|
+
// PRESENTATION LAYER - Components and Screens
|
|
66
|
+
// =============================================================================
|
|
67
|
+
|
|
68
|
+
export { OnboardingScreen, type OnboardingScreenProps } from "./presentation/screens/OnboardingScreen";
|
|
69
|
+
export { OnboardingHeader, type OnboardingHeaderProps } from "./presentation/components/OnboardingHeader";
|
|
70
|
+
export { OnboardingFooter, type OnboardingFooterProps } from "./presentation/components/OnboardingFooter";
|
|
71
|
+
export { OnboardingProvider, type OnboardingProviderProps, useOnboardingProvider } from "./presentation/providers/OnboardingProvider";
|
|
72
|
+
export { BackgroundImageCollage, type CollageLayout, type BackgroundImageCollageProps } from "./presentation/components/BackgroundImageCollage";
|
|
73
|
+
export type { OnboardingTheme, OnboardingColors } from "./presentation/types/OnboardingTheme";
|
|
74
|
+
|
|
75
|
+
// =============================================================================
|
|
76
|
+
// UTILITIES - Helper functions
|
|
77
|
+
// =============================================================================
|
|
78
|
+
|
|
79
|
+
export { ensureArray, safeIncludes, safeFilter } from "./infrastructure/utils/arrayUtils";
|
|
80
|
+
export type { ImageLayoutItem, LayoutConfig } from "./infrastructure/utils/layouts";
|
|
81
|
+
|
|
82
|
+
// Export OnboardingSlide component
|
|
83
|
+
// Note: TypeScript doesn't allow exporting both a type and a value with the same name
|
|
84
|
+
// The type is exported above as OnboardingSlide
|
|
85
|
+
// The component is exported here with a different name to avoid conflict
|
|
86
|
+
import { OnboardingSlide as OnboardingSlideComponent } from "./presentation/components/OnboardingSlide";
|
|
87
|
+
export { OnboardingSlideComponent };
|
|
88
|
+
export type { OnboardingSlideProps } from "./presentation/components/OnboardingSlide";
|
|
89
|
+
|
|
90
|
+
// Export QuestionSlide component
|
|
91
|
+
export { QuestionSlide } from "./presentation/components/QuestionSlide";
|
|
92
|
+
export type { QuestionSlideProps } from "./presentation/components/QuestionSlide";
|
|
93
|
+
|
|
94
|
+
// Export question components
|
|
95
|
+
export { SingleChoiceQuestion } from "./presentation/components/questions/SingleChoiceQuestion";
|
|
96
|
+
export type { SingleChoiceQuestionProps } from "./presentation/components/questions/SingleChoiceQuestion";
|
|
97
|
+
export { MultipleChoiceQuestion } from "./presentation/components/questions/MultipleChoiceQuestion";
|
|
98
|
+
export type { MultipleChoiceQuestionProps } from "./presentation/components/questions/MultipleChoiceQuestion";
|
|
99
|
+
export { TextInputQuestion } from "./presentation/components/questions/TextInputQuestion";
|
|
100
|
+
export type { TextInputQuestionProps } from "./presentation/components/questions/TextInputQuestion";
|
|
101
|
+
export { RatingQuestion } from "./presentation/components/questions/RatingQuestion";
|
|
102
|
+
export type { RatingQuestionProps } from "./presentation/components/questions/RatingQuestion";
|
|
103
|
+
|
|
104
|
+
export { OnboardingResetSetting } from "./presentation/components/OnboardingResetSetting";
|
|
105
|
+
export type { OnboardingResetSettingProps } from "./presentation/components/OnboardingResetSetting";
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
export { useOnboardingFlow, type UseOnboardingFlowResult } from './hooks/useOnboardingFlow';
|