@umituz/react-native-design-system 2.6.128 → 2.8.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.
Files changed (66) hide show
  1. package/package.json +4 -2
  2. package/src/exports/onboarding.ts +6 -0
  3. package/src/index.ts +5 -0
  4. package/src/molecules/navigation/utils/AppNavigation.ts +53 -28
  5. package/src/molecules/splash/hooks/useSplashFlow.ts +33 -7
  6. package/src/onboarding/domain/entities/OnboardingOptions.ts +104 -0
  7. package/src/onboarding/domain/entities/OnboardingQuestion.ts +165 -0
  8. package/src/onboarding/domain/entities/OnboardingSlide.ts +152 -0
  9. package/src/onboarding/domain/entities/OnboardingUserData.ts +43 -0
  10. package/src/onboarding/hooks/useOnboardingFlow.ts +50 -0
  11. package/src/onboarding/index.ts +108 -0
  12. package/src/onboarding/infrastructure/hooks/__tests__/useOnboardingAnswers.test.ts +163 -0
  13. package/src/onboarding/infrastructure/hooks/__tests__/useOnboardingNavigation.test.ts +121 -0
  14. package/src/onboarding/infrastructure/hooks/useOnboardingAnswers.ts +69 -0
  15. package/src/onboarding/infrastructure/hooks/useOnboardingNavigation.ts +75 -0
  16. package/src/onboarding/infrastructure/services/SlideManager.ts +53 -0
  17. package/src/onboarding/infrastructure/services/ValidationManager.ts +127 -0
  18. package/src/onboarding/infrastructure/storage/OnboardingStore.ts +99 -0
  19. package/src/onboarding/infrastructure/storage/OnboardingStoreActions.ts +50 -0
  20. package/src/onboarding/infrastructure/storage/OnboardingStoreSelectors.ts +25 -0
  21. package/src/onboarding/infrastructure/storage/OnboardingStoreState.ts +22 -0
  22. package/src/onboarding/infrastructure/storage/__tests__/OnboardingStore.test.ts +85 -0
  23. package/src/onboarding/infrastructure/storage/actions/answerActions.ts +47 -0
  24. package/src/onboarding/infrastructure/storage/actions/completeAction.ts +45 -0
  25. package/src/onboarding/infrastructure/storage/actions/index.ts +22 -0
  26. package/src/onboarding/infrastructure/storage/actions/initializeAction.ts +40 -0
  27. package/src/onboarding/infrastructure/storage/actions/resetAction.ts +37 -0
  28. package/src/onboarding/infrastructure/storage/actions/skipAction.ts +46 -0
  29. package/src/onboarding/infrastructure/storage/actions/storageHelpers.ts +60 -0
  30. package/src/onboarding/infrastructure/utils/arrayUtils.ts +28 -0
  31. package/src/onboarding/infrastructure/utils/backgroundUtils.ts +38 -0
  32. package/src/onboarding/infrastructure/utils/layouts/collageLayout.ts +81 -0
  33. package/src/onboarding/infrastructure/utils/layouts/gridLayouts.ts +78 -0
  34. package/src/onboarding/infrastructure/utils/layouts/honeycombLayout.ts +36 -0
  35. package/src/onboarding/infrastructure/utils/layouts/index.ts +12 -0
  36. package/src/onboarding/infrastructure/utils/layouts/layoutTypes.ts +37 -0
  37. package/src/onboarding/infrastructure/utils/layouts/masonryLayout.ts +37 -0
  38. package/src/onboarding/infrastructure/utils/layouts/scatteredLayout.ts +34 -0
  39. package/src/onboarding/infrastructure/utils/layouts/screenDimensions.ts +11 -0
  40. package/src/onboarding/infrastructure/utils/layouts/tilesLayout.ts +34 -0
  41. package/src/onboarding/presentation/components/BackgroundImageCollage.tsx +90 -0
  42. package/src/onboarding/presentation/components/BackgroundVideo.tsx +24 -0
  43. package/src/onboarding/presentation/components/BaseSlide.tsx +47 -0
  44. package/src/onboarding/presentation/components/OnboardingBackground.tsx +91 -0
  45. package/src/onboarding/presentation/components/OnboardingFooter.tsx +151 -0
  46. package/src/onboarding/presentation/components/OnboardingHeader.tsx +92 -0
  47. package/src/onboarding/presentation/components/OnboardingResetSetting.tsx +70 -0
  48. package/src/onboarding/presentation/components/OnboardingScreenContent.tsx +146 -0
  49. package/src/onboarding/presentation/components/OnboardingSlide.tsx +124 -0
  50. package/src/onboarding/presentation/components/QuestionRenderer.tsx +60 -0
  51. package/src/onboarding/presentation/components/QuestionSlide.tsx +67 -0
  52. package/src/onboarding/presentation/components/QuestionSlideHeader.tsx +75 -0
  53. package/src/onboarding/presentation/components/questions/MultipleChoiceQuestion.tsx +74 -0
  54. package/src/onboarding/presentation/components/questions/QuestionOptionItem.tsx +115 -0
  55. package/src/onboarding/presentation/components/questions/RatingQuestion.tsx +66 -0
  56. package/src/onboarding/presentation/components/questions/SingleChoiceQuestion.tsx +117 -0
  57. package/src/onboarding/presentation/components/questions/TextInputQuestion.tsx +71 -0
  58. package/src/onboarding/presentation/hooks/__tests__/useOnboardingContainerStyle.test.ts +96 -0
  59. package/src/onboarding/presentation/hooks/useOnboardingContainerStyle.ts +37 -0
  60. package/src/onboarding/presentation/hooks/useOnboardingGestures.ts +45 -0
  61. package/src/onboarding/presentation/hooks/useOnboardingScreenHandlers.ts +114 -0
  62. package/src/onboarding/presentation/hooks/useOnboardingScreenState.ts +146 -0
  63. package/src/onboarding/presentation/providers/OnboardingProvider.tsx +51 -0
  64. package/src/onboarding/presentation/screens/OnboardingScreen.tsx +189 -0
  65. package/src/onboarding/presentation/types/OnboardingProps.ts +46 -0
  66. 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.6.128",
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 offline utilities",
3
+ "version": "2.8.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",
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Onboarding Exports
3
+ * Generic onboarding flow for React Native apps
4
+ */
5
+
6
+ export * from '../onboarding';
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';
@@ -3,58 +3,47 @@ import { NavigationContainerRef, CommonActions, StackActions } from '@react-navi
3
3
  export class AppNavigation {
4
4
  private static navigationRef: NavigationContainerRef<any> | null = null;
5
5
 
6
- /**
7
- * Set the global navigation reference
8
- */
9
6
  static setRef(ref: NavigationContainerRef<any> | null): void {
10
7
  this.navigationRef = ref;
11
8
  }
12
9
 
13
10
  /**
14
- * Set the global navigation reference (alias for setRef)
15
11
  * @deprecated Use setRef instead
16
12
  */
17
13
  static setNavigationRef(ref: NavigationContainerRef<any> | null): void {
18
14
  this.setRef(ref);
19
15
  }
20
16
 
21
- /**
22
- * Get the global navigation reference
23
- */
24
17
  static getRef(): NavigationContainerRef<any> | null {
25
18
  return this.navigationRef;
26
19
  }
27
20
 
28
- /**
29
- * Navigate to a route
30
- */
21
+ static isReady(): boolean {
22
+ return this.navigationRef?.isReady() ?? false;
23
+ }
24
+
25
+ static canGoBack(): boolean {
26
+ return this.navigationRef?.canGoBack() ?? false;
27
+ }
28
+
31
29
  static navigate(name: string, params?: object): void {
32
30
  if (this.navigationRef?.isReady()) {
33
31
  this.navigationRef.navigate(name, params);
34
32
  }
35
33
  }
36
34
 
37
- /**
38
- * Push a route onto the stack
39
- */
40
35
  static push(name: string, params?: object): void {
41
36
  if (this.navigationRef?.isReady()) {
42
37
  this.navigationRef.dispatch(StackActions.push(name, params));
43
38
  }
44
39
  }
45
40
 
46
- /**
47
- * Go back to the previous screen
48
- */
49
41
  static goBack(): void {
50
42
  if (this.navigationRef?.isReady() && this.navigationRef.canGoBack()) {
51
43
  this.navigationRef.goBack();
52
44
  }
53
45
  }
54
46
 
55
- /**
56
- * Reset the navigation state
57
- */
58
47
  static reset(name: string, params?: object): void {
59
48
  if (this.navigationRef?.isReady()) {
60
49
  this.navigationRef.dispatch(
@@ -66,27 +55,18 @@ export class AppNavigation {
66
55
  }
67
56
  }
68
57
 
69
- /**
70
- * Replace the current route
71
- */
72
58
  static replace(name: string, params?: object): void {
73
59
  if (this.navigationRef?.isReady()) {
74
60
  this.navigationRef.dispatch(StackActions.replace(name, params));
75
61
  }
76
62
  }
77
63
 
78
- /**
79
- * Navigate to a screen in a nested navigator (e.g. Tab > Stack > Screen)
80
- */
81
64
  static navigateToNested(parentParams: { screen: string; params?: any }): void {
82
65
  if (this.navigationRef?.isReady()) {
83
66
  this.navigationRef.navigate(parentParams.screen, parentParams.params);
84
67
  }
85
68
  }
86
69
 
87
- /**
88
- * Navigate to a screen in the parent navigator
89
- */
90
70
  static navigateToParent(name: string, params?: object): void {
91
71
  if (this.navigationRef?.isReady()) {
92
72
  const parent = this.navigationRef.getParent();
@@ -95,4 +75,49 @@ export class AppNavigation {
95
75
  }
96
76
  }
97
77
  }
78
+
79
+ static popToTop(): void {
80
+ if (this.navigationRef?.isReady()) {
81
+ this.navigationRef.dispatch(StackActions.popToTop());
82
+ }
83
+ }
84
+
85
+ static pop(count: number = 1): void {
86
+ if (this.navigationRef?.isReady()) {
87
+ this.navigationRef.dispatch(StackActions.pop(count));
88
+ }
89
+ }
90
+
91
+ static getCurrentRoute(): string | undefined {
92
+ return this.navigationRef?.getCurrentRoute()?.name;
93
+ }
94
+
95
+ static getCurrentParams<T extends object>(): T | undefined {
96
+ return this.navigationRef?.getCurrentRoute()?.params as T | undefined;
97
+ }
98
+
99
+ static goToSettings(): void {
100
+ this.navigate('Settings');
101
+ }
102
+
103
+ static goToProfile(): void {
104
+ this.navigate('Profile');
105
+ }
106
+
107
+ static goToHome(): void {
108
+ this.navigate('Home');
109
+ }
110
+
111
+ static openModal(name: string, params?: object): void {
112
+ this.navigateToParent(name, params);
113
+ }
114
+
115
+ static closeModal(): void {
116
+ if (this.navigationRef?.isReady()) {
117
+ const parent = this.navigationRef.getParent();
118
+ if (parent?.canGoBack()) {
119
+ parent.goBack();
120
+ }
121
+ }
122
+ }
98
123
  }
@@ -1,12 +1,24 @@
1
1
  /**
2
2
  * Splash Flow Hook
3
3
  * Manages splash screen initialization state
4
+ *
5
+ * IMPORTANT: Use isAppReady prop instead of duration for real initialization tracking.
6
+ * Artificial delays cause poor UX - the splash should transition as soon as app is ready.
4
7
  */
5
8
 
6
9
  import { useState, useEffect } from 'react';
7
10
  import { DeviceEventEmitter } from 'react-native';
8
11
 
9
12
  export interface UseSplashFlowOptions {
13
+ /**
14
+ * External readiness signal from app initialization
15
+ * When true, splash will transition to main content
16
+ */
17
+ isAppReady?: boolean;
18
+ /**
19
+ * @deprecated Use isAppReady instead. Artificial delays cause poor UX.
20
+ * Only use for fallback/timeout scenarios.
21
+ */
10
22
  duration?: number;
11
23
  }
12
24
 
@@ -15,17 +27,31 @@ export interface UseSplashFlowResult {
15
27
  }
16
28
 
17
29
  export const useSplashFlow = (options: UseSplashFlowOptions = {}): UseSplashFlowResult => {
18
- const { duration = 1500 } = options;
30
+ const { isAppReady, duration } = options;
19
31
  const [isInitialized, setIsInitialized] = useState(false);
20
32
 
21
33
  useEffect(() => {
22
- const timer = setTimeout(() => {
23
- setIsInitialized(true);
24
- DeviceEventEmitter.emit('splash-ready');
25
- }, duration);
34
+ // Primary: Use external app ready signal (preferred)
35
+ if (isAppReady !== undefined) {
36
+ if (isAppReady && !isInitialized) {
37
+ setIsInitialized(true);
38
+ DeviceEventEmitter.emit('splash-ready');
39
+ }
40
+ return undefined;
41
+ }
26
42
 
27
- return () => clearTimeout(timer);
28
- }, [duration]);
43
+ // Fallback: Use duration timer if isAppReady not provided (legacy support)
44
+ if (duration !== undefined) {
45
+ const timer = setTimeout(() => {
46
+ setIsInitialized(true);
47
+ DeviceEventEmitter.emit('splash-ready');
48
+ }, duration);
49
+
50
+ return () => clearTimeout(timer);
51
+ }
52
+
53
+ return undefined;
54
+ }, [isAppReady, duration, isInitialized]);
29
55
 
30
56
  return { isInitialized };
31
57
  };
@@ -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
+ }