@umituz/react-native-onboarding 3.6.9 → 3.6.10
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 +1 -1
- package/src/index.ts +2 -1
- package/src/presentation/components/OnboardingFooter.tsx +4 -2
- package/src/presentation/components/OnboardingHeader.tsx +4 -2
- package/src/presentation/components/OnboardingSlide.tsx +4 -2
- package/src/presentation/components/QuestionSlide.tsx +4 -2
- package/src/presentation/components/QuestionSlideHeader.tsx +5 -5
- package/src/presentation/components/questions/MultipleChoiceQuestion.tsx +4 -2
- package/src/presentation/components/questions/RatingQuestion.tsx +4 -2
- package/src/presentation/components/questions/SingleChoiceQuestion.tsx +4 -2
- package/src/presentation/components/questions/TextInputQuestion.tsx +4 -2
- package/src/presentation/providers/OnboardingProvider.tsx +51 -0
- package/src/presentation/screens/OnboardingScreen.tsx +10 -3
- package/src/presentation/types/OnboardingTheme.ts +27 -0
- package/src/domain/entities/OnboardingTheme.ts +0 -6
- package/src/presentation/providers/OnboardingThemeProvider.tsx +0 -103
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-onboarding",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.10",
|
|
4
4
|
"description": "Advanced onboarding flow for React Native apps with personalization questions, theme-aware colors, animations, and customizable slides. SOLID, DRY, KISS principles applied.",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
package/src/index.ts
CHANGED
|
@@ -68,7 +68,8 @@ export {
|
|
|
68
68
|
export { OnboardingScreen, type OnboardingScreenProps } from "./presentation/screens/OnboardingScreen";
|
|
69
69
|
export { OnboardingHeader, type OnboardingHeaderProps } from "./presentation/components/OnboardingHeader";
|
|
70
70
|
export { OnboardingFooter, type OnboardingFooterProps } from "./presentation/components/OnboardingFooter";
|
|
71
|
-
export {
|
|
71
|
+
export { OnboardingProvider, type OnboardingProviderProps, useOnboardingProvider } from "./presentation/providers/OnboardingProvider";
|
|
72
|
+
export type { OnboardingTheme, OnboardingColors } from "./presentation/types/OnboardingTheme";
|
|
72
73
|
|
|
73
74
|
// Export OnboardingSlide component
|
|
74
75
|
// Note: TypeScript doesn't allow exporting both a type and a value with the same name
|
|
@@ -3,7 +3,7 @@ import { View, StyleSheet, TouchableOpacity } from "react-native";
|
|
|
3
3
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
4
4
|
import { useLocalization } from "@umituz/react-native-localization";
|
|
5
5
|
import { AtomicText } from "@umituz/react-native-design-system";
|
|
6
|
-
import {
|
|
6
|
+
import { useOnboardingProvider } from "../providers/OnboardingProvider";
|
|
7
7
|
|
|
8
8
|
export interface OnboardingFooterProps {
|
|
9
9
|
currentIndex: number;
|
|
@@ -32,7 +32,9 @@ export const OnboardingFooter = ({
|
|
|
32
32
|
}: OnboardingFooterProps) => {
|
|
33
33
|
const insets = useSafeAreaInsets();
|
|
34
34
|
const { t } = useLocalization();
|
|
35
|
-
const {
|
|
35
|
+
const {
|
|
36
|
+
theme: { colors },
|
|
37
|
+
} = useOnboardingProvider();
|
|
36
38
|
|
|
37
39
|
const buttonText = isLastSlide
|
|
38
40
|
? getStartedButtonText || t("onboarding.getStarted")
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { View, TouchableOpacity, StyleSheet } from "react-native";
|
|
3
3
|
import { AtomicIcon, AtomicText } from "@umituz/react-native-design-system";
|
|
4
4
|
import { useLocalization } from "@umituz/react-native-localization";
|
|
5
|
-
import {
|
|
5
|
+
import { useOnboardingProvider } from "../providers/OnboardingProvider";
|
|
6
6
|
|
|
7
7
|
export interface OnboardingHeaderProps {
|
|
8
8
|
isFirstSlide: boolean;
|
|
@@ -22,7 +22,9 @@ export const OnboardingHeader = ({
|
|
|
22
22
|
skipButtonText,
|
|
23
23
|
}: OnboardingHeaderProps) => {
|
|
24
24
|
const { t } = useLocalization();
|
|
25
|
-
const {
|
|
25
|
+
const {
|
|
26
|
+
theme: { colors },
|
|
27
|
+
} = useOnboardingProvider();
|
|
26
28
|
|
|
27
29
|
const skipText = skipButtonText || t("onboarding.skip");
|
|
28
30
|
|
|
@@ -8,7 +8,7 @@ import { View, StyleSheet } from "react-native";
|
|
|
8
8
|
import { AtomicIcon, AtomicText } from "@umituz/react-native-design-system";
|
|
9
9
|
import type { OnboardingSlide as OnboardingSlideType } from "../../domain/entities/OnboardingSlide";
|
|
10
10
|
import { BaseSlide } from "./BaseSlide";
|
|
11
|
-
import {
|
|
11
|
+
import { useOnboardingProvider } from "../providers/OnboardingProvider";
|
|
12
12
|
|
|
13
13
|
export interface OnboardingSlideProps {
|
|
14
14
|
slide: OnboardingSlideType;
|
|
@@ -19,7 +19,9 @@ export const OnboardingSlide = ({
|
|
|
19
19
|
slide,
|
|
20
20
|
variant = "default",
|
|
21
21
|
}: OnboardingSlideProps) => {
|
|
22
|
-
const {
|
|
22
|
+
const {
|
|
23
|
+
theme: { colors },
|
|
24
|
+
} = useOnboardingProvider();
|
|
23
25
|
|
|
24
26
|
const shouldShowIcon = slide.icon && !slide.hideIcon;
|
|
25
27
|
const isEmoji = slide.iconType === 'emoji';
|
|
@@ -10,7 +10,7 @@ import type { OnboardingSlide } from "../../domain/entities/OnboardingSlide";
|
|
|
10
10
|
import { QuestionSlideHeader } from "./QuestionSlideHeader";
|
|
11
11
|
import { QuestionRenderer } from "./QuestionRenderer";
|
|
12
12
|
import { BaseSlide } from "./BaseSlide";
|
|
13
|
-
import {
|
|
13
|
+
import { useOnboardingProvider } from "../providers/OnboardingProvider";
|
|
14
14
|
import { useLocalization } from "@umituz/react-native-localization";
|
|
15
15
|
|
|
16
16
|
export interface QuestionSlideProps {
|
|
@@ -26,7 +26,9 @@ export const QuestionSlide = ({
|
|
|
26
26
|
onChange,
|
|
27
27
|
variant: _variant = "default",
|
|
28
28
|
}: QuestionSlideProps) => {
|
|
29
|
-
const {
|
|
29
|
+
const {
|
|
30
|
+
theme: { colors },
|
|
31
|
+
} = useOnboardingProvider();
|
|
30
32
|
const { t } = useLocalization();
|
|
31
33
|
const { question } = slide;
|
|
32
34
|
|
|
@@ -2,16 +2,16 @@ import React from "react";
|
|
|
2
2
|
import { View, StyleSheet } from "react-native";
|
|
3
3
|
import { AtomicIcon, AtomicText } from "@umituz/react-native-design-system";
|
|
4
4
|
import type { OnboardingSlide } from "../../domain/entities/OnboardingSlide";
|
|
5
|
-
import {
|
|
5
|
+
import { useOnboardingProvider } from "../providers/OnboardingProvider";
|
|
6
6
|
|
|
7
7
|
export interface QuestionSlideHeaderProps {
|
|
8
8
|
slide: OnboardingSlide;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export const QuestionSlideHeader = ({
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
export const QuestionSlideHeader = ({ slide }: QuestionSlideHeaderProps) => {
|
|
12
|
+
const {
|
|
13
|
+
theme: { colors },
|
|
14
|
+
} = useOnboardingProvider();
|
|
15
15
|
const isEmoji = slide.iconType === 'emoji';
|
|
16
16
|
|
|
17
17
|
return (
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { View, TouchableOpacity, StyleSheet } from "react-native";
|
|
3
3
|
import { AtomicIcon, AtomicText } from "@umituz/react-native-design-system";
|
|
4
|
-
import {
|
|
4
|
+
import { useOnboardingProvider } from "../../providers/OnboardingProvider";
|
|
5
5
|
import type { OnboardingQuestion, QuestionOption } from "../../../domain/entities/OnboardingQuestion";
|
|
6
6
|
|
|
7
7
|
export interface MultipleChoiceQuestionProps {
|
|
@@ -15,7 +15,9 @@ export const MultipleChoiceQuestion = ({
|
|
|
15
15
|
value = [],
|
|
16
16
|
onChange,
|
|
17
17
|
}: MultipleChoiceQuestionProps) => {
|
|
18
|
-
const {
|
|
18
|
+
const {
|
|
19
|
+
theme: { colors },
|
|
20
|
+
} = useOnboardingProvider();
|
|
19
21
|
|
|
20
22
|
const handleToggle = (optionId: string) => {
|
|
21
23
|
const newValue = value.includes(optionId)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { View, TouchableOpacity, StyleSheet } from "react-native";
|
|
3
3
|
import { AtomicIcon, AtomicText } from "@umituz/react-native-design-system";
|
|
4
|
-
import {
|
|
4
|
+
import { useOnboardingProvider } from "../../providers/OnboardingProvider";
|
|
5
5
|
import type { OnboardingQuestion } from "../../../domain/entities/OnboardingQuestion";
|
|
6
6
|
|
|
7
7
|
export interface RatingQuestionProps {
|
|
@@ -15,7 +15,9 @@ export const RatingQuestion = ({
|
|
|
15
15
|
value = 0,
|
|
16
16
|
onChange,
|
|
17
17
|
}: RatingQuestionProps) => {
|
|
18
|
-
const {
|
|
18
|
+
const {
|
|
19
|
+
theme: { colors },
|
|
20
|
+
} = useOnboardingProvider();
|
|
19
21
|
const max = question.validation?.max ?? 5;
|
|
20
22
|
|
|
21
23
|
return (
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { View, TouchableOpacity, StyleSheet } from "react-native";
|
|
3
3
|
import { AtomicIcon, AtomicText } from "@umituz/react-native-design-system";
|
|
4
|
-
import {
|
|
4
|
+
import { useOnboardingProvider } from "../../providers/OnboardingProvider";
|
|
5
5
|
import type { OnboardingQuestion, QuestionOption } from "../../../domain/entities/OnboardingQuestion";
|
|
6
6
|
|
|
7
7
|
export interface SingleChoiceQuestionProps {
|
|
@@ -15,7 +15,9 @@ export const SingleChoiceQuestion = ({
|
|
|
15
15
|
value,
|
|
16
16
|
onChange,
|
|
17
17
|
}: SingleChoiceQuestionProps) => {
|
|
18
|
-
const {
|
|
18
|
+
const {
|
|
19
|
+
theme: { colors },
|
|
20
|
+
} = useOnboardingProvider();
|
|
19
21
|
|
|
20
22
|
const renderOption = (option: QuestionOption) => {
|
|
21
23
|
const isSelected = value === option.id;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { View, TextInput, StyleSheet } from "react-native";
|
|
3
3
|
import { AtomicText } from "@umituz/react-native-design-system";
|
|
4
|
-
import {
|
|
4
|
+
import { useOnboardingProvider } from "../../providers/OnboardingProvider";
|
|
5
5
|
import type { OnboardingQuestion } from "../../../domain/entities/OnboardingQuestion";
|
|
6
6
|
|
|
7
7
|
export interface TextInputQuestionProps {
|
|
@@ -15,7 +15,9 @@ export const TextInputQuestion = ({
|
|
|
15
15
|
value = "",
|
|
16
16
|
onChange,
|
|
17
17
|
}: TextInputQuestionProps) => {
|
|
18
|
-
const {
|
|
18
|
+
const {
|
|
19
|
+
theme: { colors },
|
|
20
|
+
} = useOnboardingProvider();
|
|
19
21
|
const { validation } = question;
|
|
20
22
|
|
|
21
23
|
return (
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding Provider
|
|
3
|
+
*
|
|
4
|
+
* Central manager for onboarding theme and configuration.
|
|
5
|
+
* All values are passed from the main application.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, { createContext, useContext, useMemo } from "react";
|
|
9
|
+
import type { OnboardingTheme, OnboardingColors } from "../types/OnboardingTheme";
|
|
10
|
+
|
|
11
|
+
interface OnboardingProviderValue {
|
|
12
|
+
theme: OnboardingTheme;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const OnboardingScope = createContext<OnboardingProviderValue | undefined>(undefined);
|
|
16
|
+
|
|
17
|
+
export interface OnboardingProviderProps {
|
|
18
|
+
children: React.ReactNode;
|
|
19
|
+
useGradient: boolean;
|
|
20
|
+
colors: OnboardingColors;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const OnboardingProvider = ({
|
|
24
|
+
children,
|
|
25
|
+
useGradient,
|
|
26
|
+
colors,
|
|
27
|
+
}: OnboardingProviderProps) => {
|
|
28
|
+
const value = useMemo(
|
|
29
|
+
() => ({
|
|
30
|
+
theme: {
|
|
31
|
+
colors,
|
|
32
|
+
useGradient,
|
|
33
|
+
},
|
|
34
|
+
}),
|
|
35
|
+
[colors, useGradient]
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<OnboardingScope.Provider value={value}>
|
|
40
|
+
{children}
|
|
41
|
+
</OnboardingScope.Provider>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const useOnboardingProvider = (): OnboardingProviderValue => {
|
|
46
|
+
const scope = useContext(OnboardingScope);
|
|
47
|
+
if (!scope) {
|
|
48
|
+
throw new Error("useOnboardingProvider must be used within OnboardingProvider");
|
|
49
|
+
}
|
|
50
|
+
return scope;
|
|
51
|
+
};
|
|
@@ -12,7 +12,8 @@ import { StyleSheet } from "react-native";
|
|
|
12
12
|
import type { OnboardingOptions } from "../../domain/entities/OnboardingOptions";
|
|
13
13
|
import { useOnboardingScreenState } from "../hooks/useOnboardingScreenState";
|
|
14
14
|
import { OnboardingScreenContent } from "../components/OnboardingScreenContent";
|
|
15
|
-
import {
|
|
15
|
+
import { OnboardingProvider } from "../providers/OnboardingProvider";
|
|
16
|
+
import type { OnboardingColors } from "../types/OnboardingTheme";
|
|
16
17
|
|
|
17
18
|
export interface OnboardingScreenProps extends OnboardingOptions {
|
|
18
19
|
/**
|
|
@@ -52,6 +53,11 @@ export interface OnboardingScreenProps extends OnboardingOptions {
|
|
|
52
53
|
* When true, shows premium paywall before completing onboarding
|
|
53
54
|
*/
|
|
54
55
|
showPaywallOnComplete?: boolean;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Theme colors for the onboarding (Required to avoid hardcoded values)
|
|
59
|
+
*/
|
|
60
|
+
themeColors: OnboardingColors;
|
|
55
61
|
}
|
|
56
62
|
|
|
57
63
|
export const OnboardingScreen = ({
|
|
@@ -75,6 +81,7 @@ export const OnboardingScreen = ({
|
|
|
75
81
|
showPaywallOnComplete = false,
|
|
76
82
|
useGradient: globalUseGradient = false,
|
|
77
83
|
themeVariant = "default",
|
|
84
|
+
themeColors,
|
|
78
85
|
}: OnboardingScreenProps) => {
|
|
79
86
|
if (__DEV__) {
|
|
80
87
|
console.log("[OnboardingScreen] Rendering with slides:", slides?.length);
|
|
@@ -115,7 +122,7 @@ export const OnboardingScreen = ({
|
|
|
115
122
|
}
|
|
116
123
|
|
|
117
124
|
return (
|
|
118
|
-
<
|
|
125
|
+
<OnboardingProvider useGradient={useGradient} colors={themeColors}>
|
|
119
126
|
<OnboardingScreenContent
|
|
120
127
|
containerStyle={[styles.container, containerStyle]}
|
|
121
128
|
useGradient={useGradient}
|
|
@@ -145,7 +152,7 @@ export const OnboardingScreen = ({
|
|
|
145
152
|
showPaywallOnComplete={showPaywallOnComplete}
|
|
146
153
|
variant={themeVariant}
|
|
147
154
|
/>
|
|
148
|
-
</
|
|
155
|
+
</OnboardingProvider>
|
|
149
156
|
);
|
|
150
157
|
};
|
|
151
158
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding Theme Types
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface OnboardingColors {
|
|
6
|
+
iconColor: string;
|
|
7
|
+
textColor: string;
|
|
8
|
+
subTextColor: string;
|
|
9
|
+
buttonBg: string;
|
|
10
|
+
buttonTextColor: string;
|
|
11
|
+
progressBarBg: string;
|
|
12
|
+
progressFillColor: string;
|
|
13
|
+
dotColor: string;
|
|
14
|
+
activeDotColor: string;
|
|
15
|
+
progressTextColor: string;
|
|
16
|
+
headerButtonBg: string;
|
|
17
|
+
headerButtonBorder: string;
|
|
18
|
+
iconBg: string;
|
|
19
|
+
iconBorder: string;
|
|
20
|
+
errorColor: string;
|
|
21
|
+
featureItemBg: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface OnboardingTheme {
|
|
25
|
+
colors: OnboardingColors;
|
|
26
|
+
useGradient: boolean;
|
|
27
|
+
}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import React, { createContext, useContext, useMemo } from 'react';
|
|
2
|
-
import { useAppDesignTokens } from '@umituz/react-native-design-system';
|
|
3
|
-
|
|
4
|
-
interface OnboardingColors {
|
|
5
|
-
iconColor: string;
|
|
6
|
-
textColor: string;
|
|
7
|
-
subTextColor: string;
|
|
8
|
-
buttonBg: string;
|
|
9
|
-
buttonTextColor: string;
|
|
10
|
-
progressBarBg: string;
|
|
11
|
-
progressFillColor: string;
|
|
12
|
-
dotColor: string;
|
|
13
|
-
activeDotColor: string;
|
|
14
|
-
progressTextColor: string;
|
|
15
|
-
headerButtonBg: string;
|
|
16
|
-
headerButtonBorder: string;
|
|
17
|
-
iconBg: string;
|
|
18
|
-
iconBorder: string;
|
|
19
|
-
errorColor: string;
|
|
20
|
-
featureItemBg: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface OnboardingThemeValue {
|
|
24
|
-
colors: OnboardingColors;
|
|
25
|
-
useGradient: boolean;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const OnboardingThemeInternal = createContext<OnboardingThemeValue | undefined>(undefined);
|
|
29
|
-
|
|
30
|
-
export interface OnboardingThemeProviderProps {
|
|
31
|
-
children: React.ReactNode;
|
|
32
|
-
useGradient?: boolean;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export const OnboardingThemeProvider = ({
|
|
36
|
-
children,
|
|
37
|
-
useGradient = false,
|
|
38
|
-
}: OnboardingThemeProviderProps) => {
|
|
39
|
-
const tokens = useAppDesignTokens();
|
|
40
|
-
|
|
41
|
-
const colors = useMemo<OnboardingColors>(() => {
|
|
42
|
-
const primaryContent = tokens.colors.onPrimary || "#FFFFFF";
|
|
43
|
-
|
|
44
|
-
if (useGradient) {
|
|
45
|
-
return {
|
|
46
|
-
iconColor: primaryContent,
|
|
47
|
-
textColor: primaryContent,
|
|
48
|
-
subTextColor: primaryContent + "CC",
|
|
49
|
-
buttonBg: primaryContent,
|
|
50
|
-
buttonTextColor: tokens.colors.primary,
|
|
51
|
-
progressBarBg: primaryContent + "40",
|
|
52
|
-
progressFillColor: primaryContent,
|
|
53
|
-
dotColor: primaryContent + "66",
|
|
54
|
-
activeDotColor: primaryContent,
|
|
55
|
-
progressTextColor: primaryContent + "CC",
|
|
56
|
-
headerButtonBg: primaryContent + "33",
|
|
57
|
-
headerButtonBorder: primaryContent + "59",
|
|
58
|
-
iconBg: primaryContent + "33",
|
|
59
|
-
iconBorder: primaryContent + "59",
|
|
60
|
-
errorColor: "#FFCDD2",
|
|
61
|
-
featureItemBg: primaryContent + "1A",
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return {
|
|
66
|
-
iconColor: tokens.colors.primary,
|
|
67
|
-
textColor: tokens.colors.textPrimary,
|
|
68
|
-
subTextColor: tokens.colors.textSecondary,
|
|
69
|
-
buttonBg: tokens.colors.primary,
|
|
70
|
-
buttonTextColor: tokens.colors.onPrimary,
|
|
71
|
-
progressBarBg: tokens.colors.borderLight,
|
|
72
|
-
progressFillColor: tokens.colors.primary,
|
|
73
|
-
dotColor: tokens.colors.borderLight,
|
|
74
|
-
activeDotColor: tokens.colors.primary,
|
|
75
|
-
progressTextColor: tokens.colors.textSecondary,
|
|
76
|
-
headerButtonBg: tokens.colors.surface,
|
|
77
|
-
headerButtonBorder: tokens.colors.borderLight,
|
|
78
|
-
iconBg: tokens.colors.primary + '15',
|
|
79
|
-
iconBorder: tokens.colors.primary + '30',
|
|
80
|
-
errorColor: tokens.colors.error,
|
|
81
|
-
featureItemBg: tokens.colors.surfaceSecondary || tokens.colors.surfaceVariant || "rgba(0,0,0,0.05)",
|
|
82
|
-
};
|
|
83
|
-
}, [tokens, useGradient]);
|
|
84
|
-
|
|
85
|
-
const value = useMemo(
|
|
86
|
-
() => ({ colors, useGradient }),
|
|
87
|
-
[colors, useGradient]
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
return (
|
|
91
|
-
<OnboardingThemeInternal.Provider value={value}>
|
|
92
|
-
{children}
|
|
93
|
-
</OnboardingThemeInternal.Provider>
|
|
94
|
-
);
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
export const useOnboardingTheme = (): OnboardingThemeValue => {
|
|
98
|
-
const theme = useContext(OnboardingThemeInternal);
|
|
99
|
-
if (!theme) {
|
|
100
|
-
throw new Error('useOnboardingTheme must be used within OnboardingThemeProvider');
|
|
101
|
-
}
|
|
102
|
-
return theme;
|
|
103
|
-
};
|