@umituz/react-native-settings 4.17.14 → 4.17.16

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 (103) hide show
  1. package/package.json +16 -15
  2. package/src/domains/about/__tests__/integration.test.tsx +328 -0
  3. package/src/domains/about/__tests__/types.d.ts +5 -0
  4. package/src/domains/about/domain/entities/AppInfo.ts +74 -0
  5. package/src/domains/about/domain/entities/__tests__/AppInfo.test.ts +93 -0
  6. package/src/domains/about/domain/repositories/IAboutRepository.ts +22 -0
  7. package/src/domains/about/index.ts +10 -0
  8. package/src/domains/about/infrastructure/repositories/AboutRepository.ts +68 -0
  9. package/src/domains/about/infrastructure/repositories/__tests__/AboutRepository.test.ts +153 -0
  10. package/src/domains/about/presentation/components/AboutContent.tsx +104 -0
  11. package/src/domains/about/presentation/components/AboutHeader.tsx +79 -0
  12. package/src/domains/about/presentation/components/AboutSection.tsx +134 -0
  13. package/src/domains/about/presentation/components/AboutSettingItem.tsx +208 -0
  14. package/src/domains/about/presentation/components/__tests__/AboutContent.simple.test.tsx +178 -0
  15. package/src/domains/about/presentation/components/__tests__/AboutContent.test.tsx +293 -0
  16. package/src/domains/about/presentation/components/__tests__/AboutHeader.test.tsx +201 -0
  17. package/src/domains/about/presentation/components/__tests__/AboutSettingItem.test.tsx +71 -0
  18. package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.simple.test.tsx +229 -0
  19. package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.test.tsx +240 -0
  20. package/src/domains/about/presentation/hooks/useAboutInfo.ts +262 -0
  21. package/src/domains/about/presentation/screens/AboutScreen.tsx +195 -0
  22. package/src/domains/about/presentation/screens/__tests__/AboutScreen.simple.test.tsx +199 -0
  23. package/src/domains/about/presentation/screens/__tests__/AboutScreen.test.tsx +366 -0
  24. package/src/domains/about/types/global.d.ts +15 -0
  25. package/src/domains/about/utils/__tests__/index.test.ts +408 -0
  26. package/src/domains/about/utils/index.ts +160 -0
  27. package/src/domains/appearance/__tests__/components/AppearanceScreen.test.tsx +195 -0
  28. package/src/domains/appearance/__tests__/hooks/index.test.tsx +232 -0
  29. package/src/domains/appearance/__tests__/integration/index.test.tsx +207 -0
  30. package/src/domains/appearance/__tests__/services/appearanceService.test.ts +299 -0
  31. package/src/domains/appearance/__tests__/setup.ts +96 -0
  32. package/src/domains/appearance/__tests__/stores/appearanceStore.test.tsx +175 -0
  33. package/src/domains/appearance/data/colorPalettes.ts +94 -0
  34. package/src/domains/appearance/hooks/index.ts +6 -0
  35. package/src/domains/appearance/hooks/useAppearance.ts +61 -0
  36. package/src/domains/appearance/hooks/useAppearanceActions.ts +144 -0
  37. package/src/domains/appearance/index.ts +7 -0
  38. package/src/domains/appearance/infrastructure/services/appearanceService.ts +301 -0
  39. package/src/domains/appearance/infrastructure/services/systemThemeDetection.ts +79 -0
  40. package/src/domains/appearance/infrastructure/services/validation.ts +91 -0
  41. package/src/domains/appearance/infrastructure/storage/appearanceStorage.ts +120 -0
  42. package/src/domains/appearance/infrastructure/stores/appearanceStore.ts +132 -0
  43. package/src/domains/appearance/presentation/components/AppearanceHeader.tsx +67 -0
  44. package/src/domains/appearance/presentation/components/AppearancePreview.tsx +141 -0
  45. package/src/domains/appearance/presentation/components/AppearanceSection.tsx +139 -0
  46. package/src/domains/appearance/presentation/components/ColorPicker.tsx +113 -0
  47. package/src/domains/appearance/presentation/components/CustomColorsSection.tsx +186 -0
  48. package/src/domains/appearance/presentation/components/ThemeModeSection.tsx +110 -0
  49. package/src/domains/appearance/presentation/components/ThemeOption.tsx +138 -0
  50. package/src/domains/appearance/presentation/components/index.ts +6 -0
  51. package/src/domains/appearance/presentation/screens/AppearanceScreen.tsx +226 -0
  52. package/src/domains/appearance/presentation/screens/index.ts +2 -0
  53. package/src/domains/appearance/types/index.ts +54 -0
  54. package/src/domains/faqs/domain/entities/FAQEntity.ts +16 -0
  55. package/src/domains/faqs/domain/services/FAQSearchService.ts +36 -0
  56. package/src/domains/faqs/domain/services/index.ts +1 -0
  57. package/src/domains/faqs/index.ts +7 -0
  58. package/src/domains/faqs/presentation/components/FAQCategory.tsx +71 -0
  59. package/src/domains/faqs/presentation/components/FAQEmptyState.tsx +75 -0
  60. package/src/domains/faqs/presentation/components/FAQItem.tsx +103 -0
  61. package/src/domains/faqs/presentation/components/FAQSearchBar.tsx +70 -0
  62. package/src/domains/faqs/presentation/components/FAQSection.tsx +50 -0
  63. package/src/domains/faqs/presentation/components/index.ts +18 -0
  64. package/src/domains/faqs/presentation/hooks/index.ts +6 -0
  65. package/src/domains/faqs/presentation/hooks/useFAQExpansion.ts +51 -0
  66. package/src/domains/faqs/presentation/hooks/useFAQSearch.ts +33 -0
  67. package/src/domains/faqs/presentation/screens/FAQScreen.tsx +129 -0
  68. package/src/domains/faqs/presentation/screens/index.ts +2 -0
  69. package/src/domains/feedback/domain/entities/FeedbackEntity.ts +92 -0
  70. package/src/domains/feedback/domain/repositories/IFeedbackRepository.ts +28 -0
  71. package/src/domains/feedback/index.ts +6 -0
  72. package/src/domains/feedback/presentation/components/FeedbackForm.tsx +189 -0
  73. package/src/domains/feedback/presentation/components/FeedbackModal.tsx +111 -0
  74. package/src/domains/feedback/presentation/components/SupportSection.tsx +160 -0
  75. package/src/domains/feedback/presentation/hooks/useDeleteFeedback.ts +25 -0
  76. package/src/domains/feedback/presentation/hooks/useFeedbackForm.ts +59 -0
  77. package/src/domains/feedback/presentation/hooks/useSubmitFeedback.ts +55 -0
  78. package/src/domains/feedback/presentation/hooks/useUserFeedback.ts +29 -0
  79. package/src/domains/legal/__tests__/ContentValidationService.test.ts +195 -0
  80. package/src/domains/legal/__tests__/StyleCacheService.test.ts +110 -0
  81. package/src/domains/legal/__tests__/UrlHandlerService.test.ts +71 -0
  82. package/src/domains/legal/__tests__/setup.ts +82 -0
  83. package/src/domains/legal/domain/entities/LegalConfig.ts +26 -0
  84. package/src/domains/legal/domain/services/ContentValidationService.ts +89 -0
  85. package/src/domains/legal/domain/services/StyleCacheService.ts +97 -0
  86. package/src/domains/legal/domain/services/UrlHandlerService.ts +128 -0
  87. package/src/domains/legal/index.ts +8 -0
  88. package/src/domains/legal/presentation/components/LegalItem.tsx +177 -0
  89. package/src/domains/legal/presentation/components/LegalLinks.tsx +154 -0
  90. package/src/domains/legal/presentation/components/LegalSection.tsx +134 -0
  91. package/src/domains/legal/presentation/screens/LegalScreen.tsx +237 -0
  92. package/src/domains/legal/presentation/screens/PrivacyPolicyScreen.tsx +214 -0
  93. package/src/domains/legal/presentation/screens/TermsOfServiceScreen.tsx +214 -0
  94. package/src/index.ts +19 -0
  95. package/src/presentation/components/DevSettingsSection.tsx +2 -2
  96. package/src/presentation/components/SettingItem.tsx +2 -2
  97. package/src/presentation/components/SettingsErrorBoundary.tsx +2 -2
  98. package/src/presentation/components/SettingsFooter.tsx +2 -2
  99. package/src/presentation/components/SettingsSection.tsx +2 -2
  100. package/src/presentation/navigation/SettingsStackNavigator.tsx +2 -2
  101. package/src/presentation/screens/SettingsScreen.tsx +2 -2
  102. package/src/presentation/screens/components/SettingsContent.tsx +2 -2
  103. package/src/presentation/screens/components/SettingsHeader.tsx +2 -2
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Appearance Domain Types
3
+ *
4
+ * Types for appearance settings including theme mode and custom colors
5
+ */
6
+
7
+ import type {
8
+ ThemeMode,
9
+ CustomThemeColors,
10
+ } from "@umituz/react-native-design-system";
11
+
12
+ export type { ThemeMode, CustomThemeColors };
13
+
14
+ export interface AppearanceSettings {
15
+ themeMode: ThemeMode;
16
+ customColors?: CustomThemeColors;
17
+ }
18
+
19
+ export interface AppearanceState {
20
+ settings: AppearanceSettings;
21
+ isInitialized: boolean;
22
+ }
23
+
24
+ export interface AppearanceSectionConfig {
25
+ /** Section title */
26
+ title?: string;
27
+ /** Section description/value */
28
+ description?: string;
29
+ /** Navigation route name */
30
+ route?: string;
31
+ /** Default navigation route name */
32
+ defaultRoute?: string;
33
+ }
34
+
35
+ export interface ThemeModeTextConfig {
36
+ title: string;
37
+ subtitle?: string;
38
+ description?: string;
39
+ features: string[];
40
+ }
41
+
42
+ export interface AppearanceTexts {
43
+ title?: string;
44
+ subtitle?: string;
45
+ themeSectionTitle?: string;
46
+ themeSectionDescription?: string;
47
+ colorsSectionTitle?: string;
48
+ colorsSectionDescription?: string;
49
+ previewSectionTitle?: string;
50
+ previewSectionDescription?: string;
51
+ resetButtonText?: string;
52
+ lightMode?: ThemeModeTextConfig;
53
+ darkMode?: ThemeModeTextConfig;
54
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * FAQ Entity Definitions
3
+ */
4
+
5
+ export interface FAQItem {
6
+ id: string;
7
+ question: string;
8
+ answer: string;
9
+ categoryId?: string;
10
+ }
11
+
12
+ export interface FAQCategory {
13
+ id: string;
14
+ title: string;
15
+ items: FAQItem[];
16
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * FAQ Search Service
3
+ * Handles searching FAQ items
4
+ */
5
+
6
+ import { FAQItem, FAQCategory } from "../entities/FAQEntity";
7
+
8
+ export class FAQSearchService {
9
+ static searchItems(query: string, items: FAQItem[]): FAQItem[] {
10
+ if (!query.trim()) return items;
11
+
12
+ const normalizedQuery = query.toLowerCase().trim();
13
+
14
+ return items.filter(item =>
15
+ item.question.toLowerCase().includes(normalizedQuery) ||
16
+ item.answer.toLowerCase().includes(normalizedQuery)
17
+ );
18
+ }
19
+
20
+ static searchCategories(query: string, categories: FAQCategory[]): FAQCategory[] {
21
+ if (!query.trim()) return categories;
22
+
23
+ const normalizedQuery = query.toLowerCase().trim();
24
+
25
+ return categories
26
+ .map(category => ({
27
+ ...category,
28
+ items: category.items.filter(item =>
29
+ item.question.toLowerCase().includes(normalizedQuery) ||
30
+ item.answer.toLowerCase().includes(normalizedQuery) ||
31
+ category.title.toLowerCase().includes(normalizedQuery)
32
+ )
33
+ }))
34
+ .filter(category => category.items.length > 0);
35
+ }
36
+ }
@@ -0,0 +1 @@
1
+ export { FAQSearchService } from "./FAQSearchService";
@@ -0,0 +1,7 @@
1
+ /**
2
+ * FAQs Domain
3
+ * Frequently asked questions
4
+ */
5
+
6
+ export * from './presentation/screens/FAQsScreen';
7
+ export * from './presentation/components/FAQItem';
@@ -0,0 +1,71 @@
1
+ /**
2
+ * FAQ Category Component
3
+ * Renders a category with its FAQ items
4
+ * Uses design system tokens for theming
5
+ */
6
+
7
+ import React, { useMemo } from 'react';
8
+ import { View, StyleSheet, ViewStyle } from 'react-native';
9
+ import { useResponsiveDesignTokens, AtomicText } from '@umituz/react-native-design-system';
10
+ import { FAQCategory as FAQCategoryType } from '../../domain/entities/FAQEntity';
11
+ import { FAQItemComponent, FAQItemStyles } from './FAQItem';
12
+
13
+ export interface FAQCategoryStyles {
14
+ container?: ViewStyle;
15
+ titleStyle?: object;
16
+ itemStyles?: FAQItemStyles;
17
+ }
18
+
19
+ export interface FAQCategoryProps {
20
+ category: FAQCategoryType;
21
+ isExpanded: (itemId: string) => boolean;
22
+ onToggleItem: (itemId: string) => void;
23
+ styles?: FAQCategoryStyles;
24
+ }
25
+
26
+ export const FAQCategoryComponent: React.FC<FAQCategoryProps> = ({
27
+ category,
28
+ isExpanded,
29
+ onToggleItem,
30
+ styles: customStyles,
31
+ }) => {
32
+ const tokens = useResponsiveDesignTokens();
33
+
34
+ const styles = useMemo(
35
+ () =>
36
+ StyleSheet.create({
37
+ container: {
38
+ marginBottom: tokens.spacing.lg,
39
+ },
40
+ titleContainer: {
41
+ marginBottom: tokens.spacing.md,
42
+ paddingHorizontal: tokens.spacing.md,
43
+ },
44
+ }),
45
+ [tokens]
46
+ );
47
+
48
+ return (
49
+ <View style={[styles.container, customStyles?.container]}>
50
+ <View style={styles.titleContainer}>
51
+ <AtomicText
52
+ type="headlineSmall"
53
+ color="textPrimary"
54
+ style={customStyles?.titleStyle}
55
+ >
56
+ {category.title}
57
+ </AtomicText>
58
+ </View>
59
+ {category.items.map((item, index) => (
60
+ <FAQItemComponent
61
+ key={item.id}
62
+ item={item}
63
+ isExpanded={isExpanded(item.id)}
64
+ onToggle={() => onToggleItem(item.id)}
65
+ isLast={index === category.items.length - 1}
66
+ styles={customStyles?.itemStyles}
67
+ />
68
+ ))}
69
+ </View>
70
+ );
71
+ };
@@ -0,0 +1,75 @@
1
+ /**
2
+ * FAQ Empty State Component
3
+ * Shown when no search results found
4
+ * Uses design system tokens for theming
5
+ */
6
+
7
+ import React, { useMemo } from 'react';
8
+ import { View, Text, StyleSheet, ViewStyle, TextStyle } from 'react-native';
9
+ import { useResponsiveDesignTokens, AtomicText } from '@umituz/react-native-design-system';
10
+
11
+ export interface FAQEmptyStateStyles {
12
+ container?: ViewStyle;
13
+ icon?: TextStyle;
14
+ titleStyle?: object;
15
+ messageStyle?: object;
16
+ }
17
+
18
+ export interface FAQEmptyStateProps {
19
+ title: string;
20
+ message: string;
21
+ icon?: string;
22
+ styles?: FAQEmptyStateStyles;
23
+ }
24
+
25
+ export const FAQEmptyState: React.FC<FAQEmptyStateProps> = ({
26
+ title,
27
+ message,
28
+ icon = '❓',
29
+ styles: customStyles,
30
+ }) => {
31
+ const tokens = useResponsiveDesignTokens();
32
+
33
+ const styles = useMemo(
34
+ () =>
35
+ StyleSheet.create({
36
+ container: {
37
+ flex: 1,
38
+ justifyContent: 'center',
39
+ alignItems: 'center',
40
+ padding: tokens.spacing.lg,
41
+ },
42
+ icon: {
43
+ fontSize: 48,
44
+ marginBottom: tokens.spacing.md,
45
+ },
46
+ textCenter: {
47
+ textAlign: 'center',
48
+ },
49
+ message: {
50
+ marginTop: tokens.spacing.xs,
51
+ },
52
+ }),
53
+ [tokens]
54
+ );
55
+
56
+ return (
57
+ <View style={[styles.container, customStyles?.container]}>
58
+ <Text style={[styles.icon, customStyles?.icon]}>{icon}</Text>
59
+ <AtomicText
60
+ type="headlineSmall"
61
+ color="textPrimary"
62
+ style={[styles.textCenter, customStyles?.titleStyle]}
63
+ >
64
+ {title}
65
+ </AtomicText>
66
+ <AtomicText
67
+ type="bodyMedium"
68
+ color="textSecondary"
69
+ style={[styles.textCenter, styles.message, customStyles?.messageStyle]}
70
+ >
71
+ {message}
72
+ </AtomicText>
73
+ </View>
74
+ );
75
+ };
@@ -0,0 +1,103 @@
1
+ /**
2
+ * FAQ Item Component
3
+ * Individual FAQ question/answer item
4
+ * Uses design system tokens for theming
5
+ */
6
+
7
+ import React, { useMemo } from 'react';
8
+ import { View, TouchableOpacity, StyleSheet, ViewStyle } from 'react-native';
9
+ import { useResponsiveDesignTokens, AtomicText, AtomicIcon } from '@umituz/react-native-design-system';
10
+ import { FAQItem as FAQItemType } from '../../domain/entities/FAQEntity';
11
+
12
+ export interface FAQItemStyles {
13
+ container?: ViewStyle;
14
+ header?: ViewStyle;
15
+ content?: ViewStyle;
16
+ questionStyle?: object;
17
+ answerContainer?: ViewStyle;
18
+ answerStyle?: object;
19
+ }
20
+
21
+ export interface FAQItemProps {
22
+ item: FAQItemType;
23
+ isExpanded: boolean;
24
+ onToggle: () => void;
25
+ isLast?: boolean;
26
+ styles?: FAQItemStyles;
27
+ }
28
+
29
+ export const FAQItemComponent: React.FC<FAQItemProps> = ({
30
+ item,
31
+ isExpanded,
32
+ onToggle,
33
+ styles: customStyles,
34
+ }) => {
35
+ const tokens = useResponsiveDesignTokens();
36
+
37
+ const styles = useMemo(
38
+ () =>
39
+ StyleSheet.create({
40
+ container: {
41
+ marginHorizontal: tokens.spacing.md,
42
+ marginBottom: tokens.spacing.xs,
43
+ borderRadius: 12,
44
+ backgroundColor: tokens.colors.surface,
45
+ borderWidth: 1,
46
+ borderColor: tokens.colors.border,
47
+ },
48
+ header: {
49
+ flexDirection: 'row' as const,
50
+ alignItems: 'center' as const,
51
+ padding: tokens.spacing.md,
52
+ },
53
+ content: {
54
+ flex: 1,
55
+ marginRight: tokens.spacing.xs,
56
+ },
57
+ answerContainer: {
58
+ paddingHorizontal: tokens.spacing.md,
59
+ paddingBottom: tokens.spacing.md,
60
+ borderTopWidth: 1,
61
+ borderTopColor: tokens.colors.borderLight,
62
+ },
63
+ }),
64
+ [tokens]
65
+ );
66
+
67
+ return (
68
+ <View style={[styles.container, customStyles?.container]}>
69
+ <TouchableOpacity
70
+ onPress={onToggle}
71
+ style={[styles.header, customStyles?.header]}
72
+ activeOpacity={0.7}
73
+ >
74
+ <View style={[styles.content, customStyles?.content]}>
75
+ <AtomicText
76
+ type="bodyLarge"
77
+ color="textPrimary"
78
+ style={customStyles?.questionStyle}
79
+ numberOfLines={isExpanded ? undefined : 2}
80
+ >
81
+ {item.question}
82
+ </AtomicText>
83
+ </View>
84
+ <AtomicIcon
85
+ name={isExpanded ? 'chevron-up' : 'chevron-down'}
86
+ size={20}
87
+ />
88
+ </TouchableOpacity>
89
+
90
+ {isExpanded && (
91
+ <View style={[styles.answerContainer, customStyles?.answerContainer]}>
92
+ <AtomicText
93
+ type="bodyMedium"
94
+ color="textSecondary"
95
+ style={customStyles?.answerStyle}
96
+ >
97
+ {item.answer}
98
+ </AtomicText>
99
+ </View>
100
+ )}
101
+ </View>
102
+ );
103
+ };
@@ -0,0 +1,70 @@
1
+ /**
2
+ * FAQ Search Bar Component
3
+ * Search input for filtering FAQ items
4
+ * Uses design system tokens for theming
5
+ */
6
+
7
+ import React, { useMemo } from 'react';
8
+ import { View, TextInput, StyleSheet, ViewStyle, TextStyle } from 'react-native';
9
+ import { useResponsiveDesignTokens, AtomicIcon } from '@umituz/react-native-design-system';
10
+
11
+ export interface FAQSearchBarStyles {
12
+ container?: ViewStyle;
13
+ input?: TextStyle;
14
+ }
15
+
16
+ export interface FAQSearchBarProps {
17
+ value: string;
18
+ onChangeText: (text: string) => void;
19
+ placeholder: string;
20
+ styles?: FAQSearchBarStyles;
21
+ }
22
+
23
+ export const FAQSearchBar: React.FC<FAQSearchBarProps> = ({
24
+ value,
25
+ onChangeText,
26
+ placeholder,
27
+ styles: customStyles,
28
+ }) => {
29
+ const tokens = useResponsiveDesignTokens();
30
+
31
+ const styles = useMemo(
32
+ () =>
33
+ StyleSheet.create({
34
+ container: {
35
+ flexDirection: 'row' as const,
36
+ alignItems: 'center' as const,
37
+ backgroundColor: tokens.colors.surface,
38
+ borderRadius: 12,
39
+ paddingHorizontal: tokens.spacing.sm,
40
+ borderWidth: 1,
41
+ borderColor: tokens.colors.border,
42
+ },
43
+ iconContainer: {
44
+ marginRight: tokens.spacing.xs,
45
+ },
46
+ input: {
47
+ flex: 1,
48
+ paddingVertical: tokens.spacing.sm,
49
+ fontSize: 16,
50
+ color: tokens.colors.textPrimary,
51
+ },
52
+ }),
53
+ [tokens]
54
+ );
55
+
56
+ return (
57
+ <View style={[styles.container, customStyles?.container]}>
58
+ <View style={styles.iconContainer}>
59
+ <AtomicIcon name="search" size={18} />
60
+ </View>
61
+ <TextInput
62
+ style={[styles.input, customStyles?.input]}
63
+ value={value}
64
+ onChangeText={onChangeText}
65
+ placeholder={placeholder}
66
+ placeholderTextColor={tokens.colors.textTertiary}
67
+ />
68
+ </View>
69
+ );
70
+ };
@@ -0,0 +1,50 @@
1
+ /**
2
+ * FAQ Section Component
3
+ * Renders FAQ entry point for settings
4
+ */
5
+
6
+ import React from 'react';
7
+ import { AtomicIcon } from '@umituz/react-native-design-system';
8
+
9
+ export interface FAQConfig {
10
+ enabled?: boolean;
11
+ title?: string;
12
+ description?: string;
13
+ onPress?: () => void;
14
+ }
15
+
16
+ export interface FAQSectionProps {
17
+ config: FAQConfig;
18
+ renderSection: (props: {
19
+ title: string;
20
+ children: React.ReactNode;
21
+ }) => React.ReactElement | null;
22
+ renderItem: (props: {
23
+ title: string;
24
+ icon: any;
25
+ onPress: () => void;
26
+ isLast?: boolean;
27
+ }) => React.ReactElement | null;
28
+ }
29
+
30
+ export const FAQSection: React.FC<FAQSectionProps> = ({
31
+ config,
32
+ renderSection,
33
+ renderItem,
34
+ }) => {
35
+ if (!config.enabled) return null;
36
+
37
+ return (
38
+ <>
39
+ {renderSection({
40
+ title: config.title || 'Help & Support',
41
+ children: renderItem({
42
+ title: config.description || 'FAQ',
43
+ icon: 'help-circle-outline',
44
+ onPress: config.onPress || (() => console.warn('No FAQ handler')),
45
+ isLast: true,
46
+ }),
47
+ })}
48
+ </>
49
+ );
50
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @umituz/react-native-faqs - Components
3
+ */
4
+
5
+ export { FAQSection } from './FAQSection';
6
+ export type { FAQSectionProps, FAQConfig } from './FAQSection';
7
+
8
+ export { FAQItemComponent } from './FAQItem';
9
+ export type { FAQItemProps } from './FAQItem';
10
+
11
+ export { FAQEmptyState } from './FAQEmptyState';
12
+ export type { FAQEmptyStateProps } from './FAQEmptyState';
13
+
14
+ export { FAQSearchBar } from './FAQSearchBar';
15
+ export type { FAQSearchBarProps } from './FAQSearchBar';
16
+
17
+ export { FAQCategoryComponent } from './FAQCategory';
18
+ export type { FAQCategoryProps } from './FAQCategory';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @umituz/react-native-faqs - Hooks
3
+ */
4
+
5
+ export { useFAQSearch } from './useFAQSearch';
6
+ export { useFAQExpansion } from './useFAQExpansion';
@@ -0,0 +1,51 @@
1
+ /**
2
+ * FAQ Expansion Hook
3
+ * Manages FAQ item expansion state
4
+ */
5
+
6
+ import { useState, useCallback } from 'react';
7
+
8
+ export interface UseFAQExpansionResult {
9
+ expandedItems: Set<string>;
10
+ isExpanded: (itemId: string) => boolean;
11
+ toggleExpansion: (itemId: string) => void;
12
+ expandAll: (itemIds: string[]) => void;
13
+ collapseAll: () => void;
14
+ }
15
+
16
+ export function useFAQExpansion(): UseFAQExpansionResult {
17
+ const [expandedItems, setExpandedItems] = useState<Set<string>>(new Set());
18
+
19
+ const isExpanded = useCallback(
20
+ (itemId: string) => expandedItems.has(itemId),
21
+ [expandedItems]
22
+ );
23
+
24
+ const toggleExpansion = useCallback((itemId: string) => {
25
+ setExpandedItems(prev => {
26
+ const newSet = new Set(prev);
27
+ if (newSet.has(itemId)) {
28
+ newSet.delete(itemId);
29
+ } else {
30
+ newSet.add(itemId);
31
+ }
32
+ return newSet;
33
+ });
34
+ }, []);
35
+
36
+ const expandAll = useCallback((itemIds: string[]) => {
37
+ setExpandedItems(new Set(itemIds));
38
+ }, []);
39
+
40
+ const collapseAll = useCallback(() => {
41
+ setExpandedItems(new Set());
42
+ }, []);
43
+
44
+ return {
45
+ expandedItems,
46
+ isExpanded,
47
+ toggleExpansion,
48
+ expandAll,
49
+ collapseAll,
50
+ };
51
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * FAQ Search Hook
3
+ * Handles FAQ search state and filtering
4
+ */
5
+
6
+ import { useState, useMemo } from 'react';
7
+ import { FAQCategory } from '../../domain/entities/FAQEntity';
8
+ import { FAQSearchService } from '../../domain/services/FAQSearchService';
9
+
10
+ export interface UseFAQSearchResult {
11
+ searchQuery: string;
12
+ setSearchQuery: (query: string) => void;
13
+ filteredCategories: FAQCategory[];
14
+ hasResults: boolean;
15
+ }
16
+
17
+ export function useFAQSearch(categories: FAQCategory[]): UseFAQSearchResult {
18
+ const [searchQuery, setSearchQuery] = useState('');
19
+
20
+ const filteredCategories = useMemo(
21
+ () => FAQSearchService.searchCategories(searchQuery, categories),
22
+ [searchQuery, categories]
23
+ );
24
+
25
+ const hasResults = filteredCategories.length > 0 || !searchQuery.trim();
26
+
27
+ return {
28
+ searchQuery,
29
+ setSearchQuery,
30
+ filteredCategories,
31
+ hasResults,
32
+ };
33
+ }