@bm-fe/react-native-ui-components 1.0.1 → 1.1.4

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 (81) hide show
  1. package/android/design/build.gradle +51 -0
  2. package/android/design/consumer-rules.pro +1 -0
  3. package/android/design/proguard-rules.pro +1 -0
  4. package/android/design/src/main/AndroidManifest.xml +2 -0
  5. package/android/design/src/main/java/com/bitmart/react/design/DataUriFetcher.kt +42 -0
  6. package/android/design/src/main/java/com/bitmart/react/design/DesignComponentPackage.kt +35 -0
  7. package/android/design/src/main/java/com/bitmart/react/design/PrimaryXLargeViewManager.kt +785 -0
  8. package/android/design/src/main/java/com/bitmart/react/design/TextButtonViewManager.kt +294 -0
  9. package/ios/DemoProject/NativeDesign/PrimaryButtonViewManager.m +25 -0
  10. package/ios/DemoProject/NativeDesign/PrimaryButtonViewManager.swift +321 -0
  11. package/ios/DemoProject/NativeDesign/TextButtonViewManager.m +21 -0
  12. package/ios/DemoProject/NativeDesign/TextButtonViewManager.swift +184 -0
  13. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Bitmart Card.imageset/Contents.json +21 -0
  14. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Bitmart Card.imageset/Property 1=Bitmart Card.svg +3 -0
  15. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Contents.json +6 -0
  16. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Credit Debit Card.imageset/Contents.json +21 -0
  17. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Credit Debit Card.imageset/Property 1=Credit Debit Card.svg +3 -0
  18. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Crypto Prepaid Card.imageset/Contents.json +21 -0
  19. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Crypto Prepaid Card.imageset/Property 1=Crypto Prepaid Card.svg +3 -0
  20. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Mobile Recharge.imageset/Contents.json +21 -0
  21. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Mobile Recharge.imageset/Mobile Recharge.svg +3 -0
  22. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/P2P Trading.imageset/Contents.json +21 -0
  23. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/P2P Trading.imageset/Property 1=P2P Trading.svg +3 -0
  24. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/SEPA Deposit.imageset/Contents.json +21 -0
  25. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/SEPA Deposit.imageset/SEPA Deposit.svg +3 -0
  26. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Third-Party Payment.imageset/Contents.json +21 -0
  27. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/BuyCrypto/Third-Party Payment.imageset/Property 1=Third-Party Payment.svg +3 -0
  28. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Components/Contents.json +6 -0
  29. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/Contents.json +6 -0
  30. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/checkmark.imageset/Contents.json +21 -0
  31. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/checkmark.imageset/checkmark.pdf +0 -0
  32. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/close_icon.imageset/Contents.json +22 -0
  33. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/close_icon.imageset/close_icon@2x.png +0 -0
  34. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/close_icon.imageset/close_icon@3x.png +0 -0
  35. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/cross.imageset/Contents.json +21 -0
  36. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/cross.imageset/cross.pdf +0 -0
  37. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/progress.imageset/Contents.json +21 -0
  38. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/progress.imageset/progress.pdf +0 -0
  39. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/progress_circular.imageset/Contents.json +21 -0
  40. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/progress_circular.imageset/progress_circular.pdf +0 -0
  41. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/refresh_footer_dark.imageset/Contents.json +22 -0
  42. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/refresh_footer_dark.imageset/refresh_footer_dark@2x.png +0 -0
  43. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/refresh_footer_dark.imageset/refresh_footer_dark@3x.png +0 -0
  44. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/refresh_footer_light.imageset/Contents.json +22 -0
  45. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/refresh_footer_light.imageset/refresh_footer_light@2x.png +0 -0
  46. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/refresh_footer_light.imageset/refresh_footer_light@3x.png +0 -0
  47. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/search_icon.imageset/Contents.json +21 -0
  48. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/search_icon.imageset/Group 13994.svg +7 -0
  49. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_dark_chose.imageset/Contents.json +21 -0
  50. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_dark_chose.imageset/Frame.svg +3 -0
  51. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_list_arrow.imageset/Contents.json +22 -0
  52. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_list_arrow.imageset/sheet_list_arrow@2x.png +0 -0
  53. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_list_arrow.imageset/sheet_list_arrow@3x.png +0 -0
  54. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_list_cell_checkbox.imageset/Contents.json +21 -0
  55. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_list_cell_checkbox.imageset/Frame (1).svg +3 -0
  56. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_list_chose.imageset/Contents.json +21 -0
  57. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/sheet_list_chose.imageset/Frame.png +0 -0
  58. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/slider_bubble.imageset/Contents.json +22 -0
  59. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/slider_bubble.imageset/slider_bubble@2x.png +0 -0
  60. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/slider_bubble.imageset/slider_bubble@3x.png +0 -0
  61. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/spot_second_floor_refresh_arrow.imageset/Contents.json +21 -0
  62. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Assets.xcassets/spot_second_floor_refresh_arrow.imageset/spot_second_floor_refresh_arrow.svg +8 -0
  63. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Font/Alexandria-Medium.ttf +0 -0
  64. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Font/Alexandria-Regular.ttf +0 -0
  65. package/ios/Modules/BMUIComponents/BMUIComponents/Assets/Font/Alexandria-SemiBold.ttf +0 -0
  66. package/ios/Modules/BMUIComponents/BMUIComponents/Classes/BMFont/BMFont.swift +82 -0
  67. package/ios/Modules/BMUIComponents/BMUIComponents/Classes/BMFont/UIFontExtensions.swift +120 -0
  68. package/ios/Modules/BMUIComponents/BMUIComponents/Classes/Components/AlertView/BMComponentAlertController.swift +574 -0
  69. package/ios/Modules/BMUIComponents/BMUIComponents/Classes/Components/Buttons/BMComponentButton+Examples.swift +77 -0
  70. package/ios/Modules/BMUIComponents/BMUIComponents/Classes/Components/Buttons/BMComponentButton.swift +373 -0
  71. package/ios/Modules/BMUIComponents/BMUIComponents/Classes/Components/Buttons/BMComponentButtonConfiguration.swift +181 -0
  72. package/ios/Modules/BMUIComponents/BMUIComponents/Classes/Components/Popup/BMComponentPopupController.swift +312 -0
  73. package/ios/Modules/BMUIComponents/BMUIComponents/Classes/Components/SegmentView/BMComponentSegmentedTitleCell.swift +294 -0
  74. package/ios/Modules/BMUIComponents/BMUIComponents/Classes/Components/SegmentView/BMComponentSegmentedTitleDataSource.swift +49 -0
  75. package/ios/Modules/BMUIComponents/BMUIComponents/Classes/Components/SegmentView/BMComponentSegmentedView.swift +292 -0
  76. package/ios/Modules/BMUIComponents/LICENSE +19 -0
  77. package/ios/Modules/BMUIComponents/README.md +29 -0
  78. package/package.json +10 -1
  79. package/react-native-ui-components.podspec +52 -0
  80. package/react-native.config.js +16 -0
  81. package/src/screens/NativeButtonsScreen.tsx +0 -335
@@ -1,335 +0,0 @@
1
- import React, { useState } from 'react';
2
- import {
3
- Alert,
4
- SafeAreaView,
5
- ScrollView,
6
- StyleSheet,
7
- Switch,
8
- Text,
9
- TouchableOpacity,
10
- View,
11
- } from 'react-native';
12
- import { Button, ButtonStyleName, ButtonStyles, TextButton } from '../components/NativeDesign';
13
- import { IC_BUTTON_SVG } from '../assets/svgs/svgStrings';
14
-
15
- const NativeButtonsScreen: React.FC = () => {
16
- const [activeTab, setActiveTab] = useState(0);
17
-
18
- const handleButtonPress = (styleName: string) => {
19
- Alert.alert('按钮点击', `点击了样式: ${styleName}`);
20
- };
21
-
22
- const tabs = [
23
- { id: 0, title: '文本按钮' },
24
- { id: 1, title: 'Primary' },
25
- { id: 2, title: 'Secondary' },
26
- { id: 3, title: 'Green' },
27
- { id: 4, title: 'Red' },
28
- { id: 5, title: 'White' },
29
- { id: 6, title: 'Footer' },
30
- ];
31
-
32
- const renderTabContent = () => {
33
- switch (activeTab) {
34
- case 0: return <TextButtonsTab onButtonPress={handleButtonPress} />;
35
- case 1: return <PrimaryButtonsTab onButtonPress={handleButtonPress} />;
36
- case 2: return <SecondaryButtonsTab onButtonPress={handleButtonPress} />;
37
- case 3: return <GreenButtonsTab onButtonPress={handleButtonPress} />;
38
- case 4: return <RedButtonsTab onButtonPress={handleButtonPress} />;
39
- case 5: return <WhiteButtonsTab onButtonPress={handleButtonPress} />;
40
- case 6: return <FooterButtonsTab onButtonPress={handleButtonPress} />;
41
- default: return null;
42
- }
43
- };
44
-
45
- return (
46
- <SafeAreaView style={styles.safeArea}>
47
- {/* Header */}
48
- <View style={styles.header}>
49
- <Text style={styles.headerTitle}>Native Buttons</Text>
50
- </View>
51
-
52
- {/* Tab 导航 */}
53
- <View style={styles.tabContainer}>
54
- <ScrollView
55
- horizontal
56
- showsHorizontalScrollIndicator={false}
57
- contentContainerStyle={styles.tabScrollContent}
58
- >
59
- {tabs.map((tab) => (
60
- <TouchableOpacity
61
- key={tab.id}
62
- style={[styles.tab, activeTab === tab.id && styles.tabActive]}
63
- onPress={() => setActiveTab(tab.id)}
64
- >
65
- <Text style={[styles.tabText, activeTab === tab.id && styles.tabTextActive]}>
66
- {tab.title}
67
- </Text>
68
- </TouchableOpacity>
69
- ))}
70
- </ScrollView>
71
- </View>
72
-
73
- {/* Tab 内容 */}
74
- <ScrollView
75
- style={styles.container}
76
- contentContainerStyle={styles.contentContainer}
77
- showsVerticalScrollIndicator={false}
78
- >
79
- {renderTabContent()}
80
- </ScrollView>
81
- </SafeAreaView>
82
- );
83
- };
84
-
85
- // ─── Text Buttons Tab ────────────────────────────────────────────────────────
86
-
87
- const TextButtonsTab: React.FC<{ onButtonPress: (style: string) => void }> = ({ onButtonPress }) => (
88
- <View style={styles.tabContent}>
89
- <SectionTitle title="常规文本按钮" />
90
- <View style={styles.buttonGroup}>
91
- <TextButton text="Black Text Button" styleName={ButtonStyles.Text.Black} onPress={() => onButtonPress('TextButton.Black')} />
92
- <TextButton text="Gray Text Button" styleName={ButtonStyles.Text.Gray} onPress={() => onButtonPress('TextButton.Gray')} style={styles.buttonMargin} />
93
- <TextButton text="Blue Text Button" styleName={ButtonStyles.Text.Blue} onPress={() => onButtonPress('TextButton.Blue')} style={styles.buttonMargin} />
94
- </View>
95
-
96
- <SectionTitle title="禁用状态" />
97
- <View style={styles.buttonGroup}>
98
- <TextButton text="Black Text Button (Disabled)" styleName={ButtonStyles.Text.Black} enabled={false} onPress={() => onButtonPress('TextButton.Black.Disabled')} />
99
- <TextButton text="Gray Text Button (Disabled)" styleName={ButtonStyles.Text.Gray} enabled={false} onPress={() => onButtonPress('TextButton.Gray.Disabled')} style={styles.buttonMargin} />
100
- <TextButton text="Blue Text Button (Disabled)" styleName={ButtonStyles.Text.Blue} enabled={false} onPress={() => onButtonPress('TextButton.Blue.Disabled')} style={styles.buttonMargin} />
101
- </View>
102
- </View>
103
- );
104
-
105
- // ─── Primary Buttons Tab ─────────────────────────────────────────────────────
106
-
107
- const PrimaryButtonsTab: React.FC<{ onButtonPress: (style: string) => void }> = ({ onButtonPress }) => {
108
- const [loading, setLoading] = useState(false);
109
- return (
110
- <View style={styles.tabContent}>
111
- <SectionTitle title="常规" />
112
- <View style={styles.buttonGroup}>
113
- {(['XLarge', 'Large', 'Medium', 'Small', 'XSmall', 'XXSmall'] as const).map((size, i) => (
114
- <Button key={size} text={`Primary ${size}`} styleName={ButtonStyles.Primary[size]} onPress={() => onButtonPress(`Primary.${size}`)} style={i > 0 ? styles.buttonMargin : undefined} />
115
- ))}
116
- </View>
117
-
118
- <SectionTitle title="左图标(SVG原生)" />
119
- <View style={styles.buttonGroup}>
120
- {(['XLarge', 'Large', 'Medium', 'Small', 'XSmall', 'XXSmall'] as const).map((size, i) => (
121
- <Button key={size} text="Button" styleName={ButtonStyles.Primary[size]} iconLeft={IC_BUTTON_SVG} onPress={() => onButtonPress(`Primary.${size}.Icon.Leading`)} style={i > 0 ? styles.buttonMargin : undefined} />
122
- ))}
123
- </View>
124
-
125
- <SectionTitle title="右图标(SVG原生)" />
126
- <View style={styles.buttonGroup}>
127
- {(['XLarge', 'Large', 'Medium', 'Small', 'XSmall', 'XXSmall'] as const).map((size, i) => (
128
- <Button key={size} text="Button" styleName={ButtonStyles.Primary[size]} iconRight={IC_BUTTON_SVG} onPress={() => onButtonPress(`Primary.${size}.Icon.Trailing`)} style={i > 0 ? styles.buttonMargin : undefined} />
129
- ))}
130
- </View>
131
-
132
- <SectionTitle title="加载状态" rightElement={<LoadingSwitch value={loading} onChange={setLoading} />} />
133
- <View style={styles.buttonGroup}>
134
- <Button text="Primary XLarge" styleName={ButtonStyles.Primary.XLarge} loading={loading} onPress={() => onButtonPress('Primary.XLarge')} />
135
- <Button text="Primary Large" styleName={ButtonStyles.Primary.Large} loading={loading} onPress={() => onButtonPress('Primary.Large')} style={styles.buttonMargin} />
136
- <Button text="Primary Medium" styleName={ButtonStyles.Primary.Medium} loading={loading} onPress={() => onButtonPress('Primary.Medium')} style={styles.buttonMargin} />
137
- <Button text="Button" styleName={ButtonStyles.Primary.Large} loading={loading} iconLeft={IC_BUTTON_SVG} onPress={() => onButtonPress('Primary.Large.Icon.Leading')} style={styles.buttonMargin} />
138
- </View>
139
-
140
- <SectionTitle title="禁用状态" />
141
- <View style={styles.buttonGroup}>
142
- <Button text="Primary Large (Disabled)" styleName={ButtonStyles.Primary.Large} enabled={false} onPress={() => onButtonPress('Primary.Large.Disabled')} />
143
- <Button text="Primary Medium (Disabled)" styleName={ButtonStyles.Primary.Medium} enabled={false} onPress={() => onButtonPress('Primary.Medium.Disabled')} style={styles.buttonMargin} />
144
- </View>
145
- </View>
146
- );
147
- };
148
-
149
- // ─── Generic Color Tabs (Secondary / Green / Red / White) ────────────────────
150
-
151
- type ColorTabProps = { colorKey: 'Secondary' | 'Green' | 'Red' | 'White'; onButtonPress: (style: string) => void };
152
-
153
- const ColorButtonsTab: React.FC<ColorTabProps> = ({ colorKey, onButtonPress }) => {
154
- const [loading, setLoading] = useState(false);
155
- const sizes = ['XLarge', 'Large', 'Medium', 'Small', 'XSmall', 'XXSmall'] as const;
156
- const styleMap = ButtonStyles[colorKey] as Record<string, string>;
157
-
158
- return (
159
- <View style={styles.tabContent}>
160
- <SectionTitle title="常规" />
161
- <View style={styles.buttonGroup}>
162
- {sizes.map((size, i) => (
163
- <Button key={size} text="Button" styleName={styleMap[size] as ButtonStyleName} onPress={() => onButtonPress(`${colorKey}.${size}`)} style={i > 0 ? styles.buttonMargin : undefined} />
164
- ))}
165
- </View>
166
-
167
- <SectionTitle title="左图标(SVG原生)" />
168
- <View style={styles.buttonGroup}>
169
- {sizes.map((size, i) => (
170
- <Button key={size} text="Button" styleName={styleMap[size] as ButtonStyleName} iconLeft={IC_BUTTON_SVG} onPress={() => onButtonPress(`${colorKey}.${size}.Icon.Leading`)} style={i > 0 ? styles.buttonMargin : undefined} />
171
- ))}
172
- </View>
173
-
174
- <SectionTitle title="右图标(SVG原生)" />
175
- <View style={styles.buttonGroup}>
176
- {sizes.map((size, i) => (
177
- <Button key={size} text="Button" styleName={styleMap[size] as ButtonStyleName} iconRight={IC_BUTTON_SVG} onPress={() => onButtonPress(`${colorKey}.${size}.Icon.Trailing`)} style={i > 0 ? styles.buttonMargin : undefined} />
178
- ))}
179
- </View>
180
-
181
- <SectionTitle title="加载状态" rightElement={<LoadingSwitch value={loading} onChange={setLoading} />} />
182
- <View style={styles.buttonGroup}>
183
- {sizes.slice(0, 4).map((size, i) => (
184
- <Button key={size} text="Button" styleName={styleMap[size] as ButtonStyleName} loading={loading} onPress={() => onButtonPress(`${colorKey}.${size}`)} style={i > 0 ? styles.buttonMargin : undefined} />
185
- ))}
186
- </View>
187
- </View>
188
- );
189
- };
190
-
191
- const SecondaryButtonsTab: React.FC<{ onButtonPress: (style: string) => void }> = ({ onButtonPress }) => (
192
- <ColorButtonsTab colorKey="Secondary" onButtonPress={onButtonPress} />
193
- );
194
- const GreenButtonsTab: React.FC<{ onButtonPress: (style: string) => void }> = ({ onButtonPress }) => (
195
- <ColorButtonsTab colorKey="Green" onButtonPress={onButtonPress} />
196
- );
197
- const RedButtonsTab: React.FC<{ onButtonPress: (style: string) => void }> = ({ onButtonPress }) => (
198
- <ColorButtonsTab colorKey="Red" onButtonPress={onButtonPress} />
199
- );
200
- const WhiteButtonsTab: React.FC<{ onButtonPress: (style: string) => void }> = ({ onButtonPress }) => (
201
- <ColorButtonsTab colorKey="White" onButtonPress={onButtonPress} />
202
- );
203
-
204
- // ─── Footer Buttons Tab ──────────────────────────────────────────────────────
205
-
206
- const FooterButtonsTab: React.FC<{ onButtonPress: (style: string) => void }> = ({ onButtonPress }) => (
207
- <View style={styles.tabContent}>
208
- <SectionTitle title="底部全宽按钮" />
209
- <View style={styles.footerButtonGroup}>
210
- <Button text="Button" styleName={ButtonStyles.Primary.Large} fullWidth onPress={() => onButtonPress('Primary.Large')} />
211
- <Button text="Button" styleName={ButtonStyles.Secondary.Large} fullWidth onPress={() => onButtonPress('Secondary.Large')} style={styles.footerButtonSpacing} />
212
- <View style={styles.footerTwoButtonRow}>
213
- <Button text="Button" styleName={ButtonStyles.Secondary.Large} fullWidth onPress={() => onButtonPress('Secondary.Large')} />
214
- <Button text="Button" styleName={ButtonStyles.Primary.Large} fullWidth onPress={() => onButtonPress('Primary.Large')} />
215
- </View>
216
- </View>
217
- </View>
218
- );
219
-
220
- // ─── Shared helpers ──────────────────────────────────────────────────────────
221
-
222
- const SectionTitle: React.FC<{ title: string; rightElement?: React.ReactNode }> = ({ title, rightElement }) => (
223
- <View style={styles.titleRow}>
224
- <Text style={styles.title}>{title}</Text>
225
- {rightElement}
226
- </View>
227
- );
228
-
229
- const LoadingSwitch: React.FC<{ value: boolean; onChange: (v: boolean) => void }> = ({ value, onChange }) => (
230
- <View style={styles.switchRow}>
231
- <Text style={styles.switchLabel}>进度条</Text>
232
- <Switch value={value} onValueChange={onChange} />
233
- </View>
234
- );
235
-
236
- // ─── Styles ──────────────────────────────────────────────────────────────────
237
-
238
- const styles = StyleSheet.create({
239
- safeArea: {
240
- flex: 1,
241
- backgroundColor: '#FFFFFF',
242
- },
243
- header: {
244
- height: 56,
245
- paddingHorizontal: 16,
246
- justifyContent: 'center',
247
- borderBottomWidth: StyleSheet.hairlineWidth,
248
- borderBottomColor: '#E0E0E0',
249
- backgroundColor: '#FFFFFF',
250
- },
251
- headerTitle: {
252
- fontSize: 18,
253
- fontWeight: '600',
254
- color: '#151515',
255
- },
256
- tabContainer: {
257
- backgroundColor: '#FFFFFF',
258
- borderBottomWidth: 1,
259
- borderBottomColor: '#E0E0E0',
260
- },
261
- tabScrollContent: {
262
- paddingHorizontal: 16,
263
- },
264
- tab: {
265
- paddingVertical: 12,
266
- paddingHorizontal: 16,
267
- marginRight: 8,
268
- borderBottomWidth: 2,
269
- borderBottomColor: 'transparent',
270
- },
271
- tabActive: {
272
- borderBottomColor: '#2196F3',
273
- },
274
- tabText: {
275
- fontSize: 14,
276
- fontWeight: '400',
277
- color: '#666666',
278
- },
279
- tabTextActive: {
280
- fontWeight: '600',
281
- color: '#2196F3',
282
- },
283
- container: {
284
- flex: 1,
285
- backgroundColor: '#FFFFFF',
286
- },
287
- contentContainer: {
288
- paddingBottom: 24,
289
- },
290
- tabContent: {
291
- padding: 24,
292
- },
293
- titleRow: {
294
- flexDirection: 'row',
295
- alignItems: 'center',
296
- marginBottom: 16,
297
- },
298
- title: {
299
- flex: 1,
300
- fontSize: 20,
301
- fontWeight: '600',
302
- color: '#151515',
303
- },
304
- switchRow: {
305
- flexDirection: 'row',
306
- alignItems: 'center',
307
- gap: 8,
308
- },
309
- switchLabel: {
310
- fontSize: 14,
311
- color: '#666666',
312
- },
313
- buttonGroup: {
314
- alignItems: 'center',
315
- marginBottom: 32,
316
- },
317
- buttonMargin: {
318
- marginTop: 16,
319
- },
320
- footerButtonGroup: {
321
- width: '100%',
322
- alignSelf: 'stretch',
323
- },
324
- footerButtonSpacing: {
325
- marginTop: 16,
326
- },
327
- footerTwoButtonRow: {
328
- flexDirection: 'row',
329
- width: '100%',
330
- marginTop: 16,
331
- gap: 16,
332
- },
333
- });
334
-
335
- export default NativeButtonsScreen;