@umituz/react-native-settings 5.3.74 → 5.3.76
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/dist/utils/iconPaths.d.ts +40 -0
- package/package.json +1 -1
- package/src/domains/appearance/presentation/components/ColorPicker.tsx +6 -1
- package/src/domains/faqs/presentation/components/FAQItem.tsx +7 -3
- package/src/domains/faqs/presentation/components/FAQSearchBar.tsx +6 -1
- package/src/domains/faqs/presentation/screens/FAQScreen.tsx +50 -35
- package/src/domains/feedback/presentation/screens/FeatureRequestScreen.tsx +26 -5
- package/src/domains/localization/presentation/components/LanguageItem.tsx +8 -1
- package/src/utils/iconPaths.ts +59 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common Icon SVG Paths
|
|
3
|
+
*
|
|
4
|
+
* Centralized SVG paths for frequently used icons
|
|
5
|
+
* Works without external icon libraries
|
|
6
|
+
*/
|
|
7
|
+
export declare const ICON_PATHS: {
|
|
8
|
+
readonly 'chevron-up': "M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z";
|
|
9
|
+
readonly 'chevron-down': "M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6z";
|
|
10
|
+
readonly 'chevron-forward': "M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z";
|
|
11
|
+
readonly 'chevron-back': "M15.41 7.41L10.83 12l4.58 4.59L14 18l-6-6 6-6z";
|
|
12
|
+
readonly 'arrow-right': "M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z";
|
|
13
|
+
readonly 'arrow-forward': "M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z";
|
|
14
|
+
readonly 'arrow-left': "M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z";
|
|
15
|
+
readonly close: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z";
|
|
16
|
+
readonly checkmark: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z";
|
|
17
|
+
readonly 'checkmark-circle': "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z";
|
|
18
|
+
readonly plus: "M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z";
|
|
19
|
+
readonly search: "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z";
|
|
20
|
+
readonly star: "M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z";
|
|
21
|
+
readonly 'alert-circle': "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z";
|
|
22
|
+
readonly 'information-circle': "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z";
|
|
23
|
+
readonly warning: "M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z";
|
|
24
|
+
readonly 'chatbubble-outline': "M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z";
|
|
25
|
+
readonly mail: "M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z";
|
|
26
|
+
readonly time: "M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z";
|
|
27
|
+
readonly moon: "M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9c0-.46-.04-.92-.1-1.36-.98 1.37-2.58 2.26-4.4 2.26-2.98 0-5.4-2.42-5.4-5.4 0-1.81.89-3.42 2.26-4.4-.44-.06-.9-.1-1.36-.1z";
|
|
28
|
+
readonly users: "M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z";
|
|
29
|
+
readonly person: "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z";
|
|
30
|
+
readonly create: "M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z";
|
|
31
|
+
readonly trash: "M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z";
|
|
32
|
+
readonly share: "M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z";
|
|
33
|
+
readonly globe: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z";
|
|
34
|
+
readonly settings: "M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z";
|
|
35
|
+
readonly heart: "M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z";
|
|
36
|
+
readonly 'heart-outline': "M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-.1.1-.1-.1C7.14 14.24 4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z";
|
|
37
|
+
readonly notifications: "M12 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm6-6v-5c0-3.07-1.63-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.64 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2zm-2 1H8v-6c0-2.48 1.51-4.5 4-4.5s4 2.02 4 4.5v6z";
|
|
38
|
+
readonly 'notifications-off': "M12 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm0-18c.83 0 1.5.67 1.5 1.5 0 .24-.05.46-.14.67l.94.94C14.74 6.57 15 5.82 15 5c0-1.66-1.34-3-3-3-.82 0-1.57.26-2.18.69l.95.95c.2-.09.43-.14.67-.14zM2.81 2.81L1.39 4.22l2.68 2.68C3.06 8.08 2.38 9.5 2.12 11H4.14c.24-1.12.76-2.13 1.48-2.96l1.94 1.94c-.06.34-.1.69-.1 1.02 0 2.48 1.51 4.5 4 4.5.33 0 .68-.04 1.02-.1l4.23 4.23c-.66.32-1.39.51-2.17.51-2.48 0-4.5-2.02-4.5-4.5h-2c0 2.93 1.81 5.45 4.38 6.51l2.5 2.5 1.41-1.41L2.81 2.81z";
|
|
39
|
+
};
|
|
40
|
+
export type IconPathName = keyof typeof ICON_PATHS;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "5.3.
|
|
3
|
+
"version": "5.3.76",
|
|
4
4
|
"description": "Complete settings hub for React Native apps - consolidated package with settings, localization, about, legal, appearance, feedback, FAQs, rating, and gamification - expo-store-review and expo-device now lazy loaded",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -10,6 +10,7 @@ import { View, TouchableOpacity, StyleSheet } from "react-native";
|
|
|
10
10
|
import { AtomicIcon, AtomicText } from "@umituz/react-native-design-system/atoms";
|
|
11
11
|
import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
|
|
12
12
|
import { isDev } from "../../../../utils/devUtils";
|
|
13
|
+
import { ICON_PATHS } from "../../../../utils/iconPaths";
|
|
13
14
|
|
|
14
15
|
interface ColorPickerProps {
|
|
15
16
|
label: string;
|
|
@@ -64,7 +65,11 @@ export const ColorPicker: React.FC<ColorPickerProps> = ({
|
|
|
64
65
|
accessibilityHint={`Select ${color} color`}
|
|
65
66
|
>
|
|
66
67
|
{isSelected && (
|
|
67
|
-
<AtomicIcon
|
|
68
|
+
<AtomicIcon
|
|
69
|
+
svgPath={ICON_PATHS['checkmark']}
|
|
70
|
+
customSize={16}
|
|
71
|
+
customColor={tokens.colors.textInverse}
|
|
72
|
+
/>
|
|
68
73
|
)}
|
|
69
74
|
</TouchableOpacity>
|
|
70
75
|
);
|
|
@@ -27,6 +27,10 @@ export interface FAQItemProps {
|
|
|
27
27
|
styles?: FAQItemStyles;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
// SVG paths for chevron icons
|
|
31
|
+
const CHEVRON_UP_PATH = "M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z";
|
|
32
|
+
const CHEVRON_DOWN_PATH = "M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6z";
|
|
33
|
+
|
|
30
34
|
export const FAQItemComponent: React.FC<FAQItemProps> = React.memo(({
|
|
31
35
|
item,
|
|
32
36
|
isExpanded,
|
|
@@ -96,9 +100,9 @@ export const FAQItemComponent: React.FC<FAQItemProps> = React.memo(({
|
|
|
96
100
|
</View>
|
|
97
101
|
<View style={styles.iconContainer}>
|
|
98
102
|
<AtomicIcon
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
svgPath={isExpanded ? CHEVRON_UP_PATH : CHEVRON_DOWN_PATH}
|
|
104
|
+
customSize={20}
|
|
105
|
+
customColor={isExpanded ? tokens.colors.onPrimary : tokens.colors.secondary}
|
|
102
106
|
/>
|
|
103
107
|
</View>
|
|
104
108
|
</TouchableOpacity>
|
|
@@ -8,6 +8,7 @@ import React, { useMemo } from 'react';
|
|
|
8
8
|
import { View, TextInput, StyleSheet, ViewStyle, TextStyle } from 'react-native';
|
|
9
9
|
import { AtomicIcon } from '@umituz/react-native-design-system/atoms';
|
|
10
10
|
import { useAppDesignTokens } from '@umituz/react-native-design-system/theme';
|
|
11
|
+
import { ICON_PATHS } from '../../../../utils/iconPaths';
|
|
11
12
|
|
|
12
13
|
export interface FAQSearchBarStyles {
|
|
13
14
|
container?: ViewStyle;
|
|
@@ -58,7 +59,11 @@ export const FAQSearchBar: React.FC<FAQSearchBarProps> = ({
|
|
|
58
59
|
return (
|
|
59
60
|
<View style={[styles.container, customStyles?.container]}>
|
|
60
61
|
<View style={styles.iconContainer}>
|
|
61
|
-
<AtomicIcon
|
|
62
|
+
<AtomicIcon
|
|
63
|
+
svgPath={ICON_PATHS['search']}
|
|
64
|
+
customSize={20}
|
|
65
|
+
customColor={tokens.colors.secondary}
|
|
66
|
+
/>
|
|
62
67
|
</View>
|
|
63
68
|
<TextInput
|
|
64
69
|
style={[styles.input, customStyles?.input]}
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import React, { useMemo } from 'react';
|
|
8
|
-
import { View, StyleSheet, ViewStyle, TextStyle, useWindowDimensions } from 'react-native';
|
|
8
|
+
import { View, StyleSheet, ViewStyle, TextStyle, useWindowDimensions, FlatList } from 'react-native';
|
|
9
9
|
import { getContentMaxWidth } from '@umituz/react-native-design-system/device';
|
|
10
10
|
import { ScreenLayout } from '@umituz/react-native-design-system/layouts';
|
|
11
|
-
import { useAppNavigation } from '@umituz/react-native-design-system/molecules';
|
|
11
|
+
import { NavigationHeader, useAppNavigation } from '@umituz/react-native-design-system/molecules';
|
|
12
12
|
import { useAppDesignTokens } from '@umituz/react-native-design-system/theme';
|
|
13
13
|
import { FAQCategory } from '../../domain/entities/FAQEntity';
|
|
14
14
|
import { useFAQSearch } from '../hooks/useFAQSearch';
|
|
@@ -43,6 +43,7 @@ export const FAQScreen: React.FC<FAQScreenProps> = ({
|
|
|
43
43
|
searchPlaceholder,
|
|
44
44
|
emptySearchTitle,
|
|
45
45
|
emptySearchMessage,
|
|
46
|
+
headerTitle,
|
|
46
47
|
onBack,
|
|
47
48
|
renderHeader,
|
|
48
49
|
styles: customStyles,
|
|
@@ -75,45 +76,59 @@ export const FAQScreen: React.FC<FAQScreenProps> = ({
|
|
|
75
76
|
}
|
|
76
77
|
};
|
|
77
78
|
|
|
78
|
-
const header = renderHeader ? renderHeader({ onBack: handleBack }) :
|
|
79
|
+
const header = renderHeader ? renderHeader({ onBack: handleBack }) : (
|
|
80
|
+
<NavigationHeader title={headerTitle} onBackPress={handleBack} />
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// Render search bar as list header
|
|
84
|
+
const ListHeader = useMemo(() => (
|
|
85
|
+
<View style={{ alignSelf: 'center', width: '100%', maxWidth: contentMaxWidth }}>
|
|
86
|
+
<View style={[styles.searchBar, customStyles?.header]}>
|
|
87
|
+
<FAQSearchBar
|
|
88
|
+
value={searchQuery}
|
|
89
|
+
onChangeText={setSearchQuery}
|
|
90
|
+
placeholder={searchPlaceholder}
|
|
91
|
+
styles={customStyles?.searchBar}
|
|
92
|
+
/>
|
|
93
|
+
</View>
|
|
94
|
+
|
|
95
|
+
{searchQuery && !hasResults && (
|
|
96
|
+
<FAQEmptyState
|
|
97
|
+
title={emptySearchTitle}
|
|
98
|
+
message={emptySearchMessage}
|
|
99
|
+
styles={customStyles?.emptyState}
|
|
100
|
+
/>
|
|
101
|
+
)}
|
|
102
|
+
</View>
|
|
103
|
+
), [searchQuery, hasResults, searchPlaceholder, emptySearchTitle, emptySearchMessage, customStyles, tokens, contentMaxWidth]);
|
|
104
|
+
|
|
105
|
+
const renderCategory = ({ item }: { item: FAQCategory }) => (
|
|
106
|
+
<View style={{ alignSelf: 'center', width: '100%', maxWidth: contentMaxWidth }}>
|
|
107
|
+
<FAQCategoryComponent
|
|
108
|
+
category={item}
|
|
109
|
+
isExpanded={isExpanded}
|
|
110
|
+
onToggleItem={toggleExpansion}
|
|
111
|
+
styles={customStyles?.category}
|
|
112
|
+
/>
|
|
113
|
+
</View>
|
|
114
|
+
);
|
|
79
115
|
|
|
80
116
|
return (
|
|
81
117
|
<ScreenLayout
|
|
82
118
|
edges={['top', 'bottom', 'left', 'right']}
|
|
83
|
-
scrollable={
|
|
119
|
+
scrollable={false}
|
|
84
120
|
header={header}
|
|
85
|
-
contentContainerStyle={customStyles?.content}
|
|
86
121
|
>
|
|
87
|
-
<
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
{searchQuery && !hasResults ? (
|
|
98
|
-
<FAQEmptyState
|
|
99
|
-
title={emptySearchTitle}
|
|
100
|
-
message={emptySearchMessage}
|
|
101
|
-
styles={customStyles?.emptyState}
|
|
102
|
-
/>
|
|
103
|
-
) : (
|
|
104
|
-
filteredCategories.map((cat) => (
|
|
105
|
-
<FAQCategoryComponent
|
|
106
|
-
key={cat.id}
|
|
107
|
-
category={cat}
|
|
108
|
-
isExpanded={isExpanded}
|
|
109
|
-
onToggleItem={toggleExpansion}
|
|
110
|
-
styles={customStyles?.category}
|
|
111
|
-
/>
|
|
112
|
-
))
|
|
113
|
-
)}
|
|
114
|
-
|
|
115
|
-
<View style={styles.footer} />
|
|
116
|
-
</View>
|
|
122
|
+
<FlatList
|
|
123
|
+
data={filteredCategories}
|
|
124
|
+
renderItem={renderCategory}
|
|
125
|
+
keyExtractor={(item) => item.id}
|
|
126
|
+
ListHeaderComponent={hasResults ? ListHeader : null}
|
|
127
|
+
ListEmptyComponent={!hasResults ? ListHeader : null}
|
|
128
|
+
ListFooterComponent={<View style={styles.footer} />}
|
|
129
|
+
showsVerticalScrollIndicator={false}
|
|
130
|
+
contentContainerStyle={{ paddingBottom: tokens.spacing.xl }}
|
|
131
|
+
/>
|
|
117
132
|
</ScreenLayout>
|
|
118
133
|
);
|
|
119
134
|
};
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
|
|
14
14
|
import { ScreenLayout } from "@umituz/react-native-design-system/layouts";
|
|
15
15
|
import { FeedbackModal } from "../components/FeedbackModal";
|
|
16
|
+
import { ICON_PATHS } from "../../../../utils/iconPaths";
|
|
16
17
|
import { useFeatureRequests } from "../../infrastructure/useFeatureRequests";
|
|
17
18
|
import type { FeedbackRating } from "../../domain/entities/FeedbackEntity";
|
|
18
19
|
import type { FeatureRequestItem } from "../../domain/entities/FeatureRequestEntity";
|
|
@@ -100,13 +101,21 @@ export const FeatureRequestScreen: React.FC<FeatureRequestScreenProps> = ({ conf
|
|
|
100
101
|
<View key={item.id} style={[styles.card, { backgroundColor: tokens.colors.surfaceSecondary, borderColor: tokens.colors.borderLight }]}>
|
|
101
102
|
<View style={styles.voteColumn}>
|
|
102
103
|
<TouchableOpacity onPress={() => vote(item.id, 'up')}>
|
|
103
|
-
<AtomicIcon
|
|
104
|
+
<AtomicIcon
|
|
105
|
+
svgPath={ICON_PATHS['chevron-up']}
|
|
106
|
+
customSize={20}
|
|
107
|
+
customColor={voted === 'up' ? tokens.colors.primary : tokens.colors.textSecondary}
|
|
108
|
+
/>
|
|
104
109
|
</TouchableOpacity>
|
|
105
110
|
<AtomicText style={[styles.voteCount, { color: voted === 'up' ? tokens.colors.primary : tokens.colors.textPrimary }]}>
|
|
106
111
|
{item.votes}
|
|
107
112
|
</AtomicText>
|
|
108
113
|
<TouchableOpacity onPress={() => vote(item.id, 'down')}>
|
|
109
|
-
<AtomicIcon
|
|
114
|
+
<AtomicIcon
|
|
115
|
+
svgPath={ICON_PATHS['chevron-down']}
|
|
116
|
+
customSize={20}
|
|
117
|
+
customColor={voted === 'down' ? tokens.colors.primary : tokens.colors.textSecondary}
|
|
118
|
+
/>
|
|
110
119
|
</TouchableOpacity>
|
|
111
120
|
</View>
|
|
112
121
|
|
|
@@ -144,7 +153,11 @@ export const FeatureRequestScreen: React.FC<FeatureRequestScreenProps> = ({ conf
|
|
|
144
153
|
style={[styles.addButton, { backgroundColor: tokens.colors.primary }]}
|
|
145
154
|
onPress={() => setIsModalVisible(true)}
|
|
146
155
|
>
|
|
147
|
-
<AtomicIcon
|
|
156
|
+
<AtomicIcon
|
|
157
|
+
svgPath={ICON_PATHS['plus']}
|
|
158
|
+
customSize={16}
|
|
159
|
+
customColor={tokens.colors.onPrimary}
|
|
160
|
+
/>
|
|
148
161
|
</TouchableOpacity>
|
|
149
162
|
</View>
|
|
150
163
|
);
|
|
@@ -178,7 +191,11 @@ export const FeatureRequestScreen: React.FC<FeatureRequestScreenProps> = ({ conf
|
|
|
178
191
|
<ScrollView style={styles.container} showsVerticalScrollIndicator={false}>
|
|
179
192
|
<View style={[styles.banner, { backgroundColor: tokens.colors.primary + '10', borderColor: tokens.colors.primary + '20' }]}>
|
|
180
193
|
<View style={styles.bannerIconContainer}>
|
|
181
|
-
<AtomicIcon
|
|
194
|
+
<AtomicIcon
|
|
195
|
+
svgPath={ICON_PATHS['users']}
|
|
196
|
+
customSize={24}
|
|
197
|
+
customColor={tokens.colors.primary}
|
|
198
|
+
/>
|
|
182
199
|
<View style={styles.pulseDot} />
|
|
183
200
|
</View>
|
|
184
201
|
<View>
|
|
@@ -193,7 +210,11 @@ export const FeatureRequestScreen: React.FC<FeatureRequestScreenProps> = ({ conf
|
|
|
193
210
|
|
|
194
211
|
{filteredRequests.length === 0 ? (
|
|
195
212
|
<View style={styles.emptyState}>
|
|
196
|
-
<AtomicIcon
|
|
213
|
+
<AtomicIcon
|
|
214
|
+
svgPath={ICON_PATHS['chatbubble-outline']}
|
|
215
|
+
customSize={32}
|
|
216
|
+
customColor={tokens.colors.textTertiary}
|
|
217
|
+
/>
|
|
197
218
|
<AtomicText style={[styles.emptyText, { color: tokens.colors.textTertiary }]}>
|
|
198
219
|
{t.empty || "No requests yet. Be the first!"}
|
|
199
220
|
</AtomicText>
|
|
@@ -31,6 +31,9 @@ interface LanguageItemProps {
|
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// SVG path for checkmark icon (works without external icon library)
|
|
35
|
+
const CHECKMARK_PATH = "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z";
|
|
36
|
+
|
|
34
37
|
export const LanguageItem: React.FC<LanguageItemProps> = ({
|
|
35
38
|
item,
|
|
36
39
|
isSelected,
|
|
@@ -113,7 +116,11 @@ export const LanguageItem: React.FC<LanguageItemProps> = ({
|
|
|
113
116
|
</View>
|
|
114
117
|
</View>
|
|
115
118
|
{isSelected && (
|
|
116
|
-
<AtomicIcon
|
|
119
|
+
<AtomicIcon
|
|
120
|
+
svgPath={CHECKMARK_PATH}
|
|
121
|
+
customSize={24}
|
|
122
|
+
customColor={tokens.colors.primary}
|
|
123
|
+
/>
|
|
117
124
|
)}
|
|
118
125
|
</TouchableOpacity>
|
|
119
126
|
);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common Icon SVG Paths
|
|
3
|
+
*
|
|
4
|
+
* Centralized SVG paths for frequently used icons
|
|
5
|
+
* Works without external icon libraries
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const ICON_PATHS = {
|
|
9
|
+
// Navigation
|
|
10
|
+
'chevron-up': "M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z",
|
|
11
|
+
'chevron-down': "M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6z",
|
|
12
|
+
'chevron-forward': "M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z",
|
|
13
|
+
'chevron-back': "M15.41 7.41L10.83 12l4.58 4.59L14 18l-6-6 6-6z",
|
|
14
|
+
'arrow-right': "M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z",
|
|
15
|
+
'arrow-forward': "M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z",
|
|
16
|
+
'arrow-left': "M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z",
|
|
17
|
+
|
|
18
|
+
// UI Elements
|
|
19
|
+
'close': "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z",
|
|
20
|
+
'checkmark': "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z",
|
|
21
|
+
'checkmark-circle': "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",
|
|
22
|
+
'plus': "M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z",
|
|
23
|
+
'search': "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z",
|
|
24
|
+
|
|
25
|
+
// Status & Feedback
|
|
26
|
+
'star': "M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z",
|
|
27
|
+
'alert-circle': "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z",
|
|
28
|
+
'information-circle': "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z",
|
|
29
|
+
'warning': "M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z",
|
|
30
|
+
|
|
31
|
+
// Communication
|
|
32
|
+
'chatbubble-outline': "M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z",
|
|
33
|
+
'mail': "M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z",
|
|
34
|
+
|
|
35
|
+
// Time & Notifications
|
|
36
|
+
'time': "M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z",
|
|
37
|
+
'moon': "M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9c0-.46-.04-.92-.1-1.36-.98 1.37-2.58 2.26-4.4 2.26-2.98 0-5.4-2.42-5.4-5.4 0-1.81.89-3.42 2.26-4.4-.44-.06-.9-.1-1.36-.1z",
|
|
38
|
+
|
|
39
|
+
// Users & Social
|
|
40
|
+
'users': "M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z",
|
|
41
|
+
'person': "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z",
|
|
42
|
+
|
|
43
|
+
// Actions
|
|
44
|
+
'create': "M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z",
|
|
45
|
+
'trash': "M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z",
|
|
46
|
+
'share': "M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z",
|
|
47
|
+
|
|
48
|
+
// Misc
|
|
49
|
+
'globe': "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z",
|
|
50
|
+
'settings': "M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z",
|
|
51
|
+
'heart': "M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z",
|
|
52
|
+
'heart-outline': "M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-.1.1-.1-.1C7.14 14.24 4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z",
|
|
53
|
+
|
|
54
|
+
// Notifications
|
|
55
|
+
'notifications': "M12 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm6-6v-5c0-3.07-1.63-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.64 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2zm-2 1H8v-6c0-2.48 1.51-4.5 4-4.5s4 2.02 4 4.5v6z",
|
|
56
|
+
'notifications-off': "M12 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm0-18c.83 0 1.5.67 1.5 1.5 0 .24-.05.46-.14.67l.94.94C14.74 6.57 15 5.82 15 5c0-1.66-1.34-3-3-3-.82 0-1.57.26-2.18.69l.95.95c.2-.09.43-.14.67-.14zM2.81 2.81L1.39 4.22l2.68 2.68C3.06 8.08 2.38 9.5 2.12 11H4.14c.24-1.12.76-2.13 1.48-2.96l1.94 1.94c-.06.34-.1.69-.1 1.02 0 2.48 1.51 4.5 4 4.5.33 0 .68-.04 1.02-.1l4.23 4.23c-.66.32-1.39.51-2.17.51-2.48 0-4.5-2.02-4.5-4.5h-2c0 2.93 1.81 5.45 4.38 6.51l2.5 2.5 1.41-1.41L2.81 2.81z",
|
|
57
|
+
} as const;
|
|
58
|
+
|
|
59
|
+
export type IconPathName = keyof typeof ICON_PATHS;
|