react-native-platform-components 0.8.10 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -891
- package/android/src/main/java/com/platformcomponents/PCDatePickerView.kt +17 -3
- package/android/src/main/java/com/platformcomponents/PCImageLoader.kt +88 -0
- package/android/src/main/java/com/platformcomponents/PCSegmentedControlView.kt +292 -31
- package/android/src/main/java/com/platformcomponents/PCSegmentedControlViewManager.kt +74 -8
- package/android/src/main/java/com/platformcomponents/PCSelectionMenuView.kt +2 -1
- package/android/src/main/java/com/platformcomponents/PCThemeSupport.kt +94 -0
- package/android/src/main/res/values/styles.xml +40 -0
- package/ios/PCImageLoader.swift +58 -0
- package/ios/PCSegmentedControl.mm +85 -25
- package/ios/PCSegmentedControl.swift +231 -308
- package/lib/commonjs/DatePickerNativeComponent.ts +4 -2
- package/lib/commonjs/SegmentedControl.js +138 -6
- package/lib/commonjs/SegmentedControl.js.map +1 -1
- package/lib/commonjs/SegmentedControlNativeComponent.ts +62 -8
- package/lib/commonjs/SelectionMenuNativeComponent.ts +4 -2
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/module/DatePickerNativeComponent.ts +4 -2
- package/lib/module/SegmentedControl.js +138 -7
- package/lib/module/SegmentedControl.js.map +1 -1
- package/lib/module/SegmentedControlNativeComponent.ts +62 -8
- package/lib/module/SelectionMenuNativeComponent.ts +4 -2
- package/lib/module/index.web.js.map +1 -1
- package/lib/typescript/commonjs/docs/docusaurus.config.d.ts +4 -0
- package/lib/typescript/commonjs/docs/docusaurus.config.d.ts.map +1 -0
- package/lib/typescript/commonjs/docs/sidebars.d.ts +4 -0
- package/lib/typescript/commonjs/docs/sidebars.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/DatePickerNativeComponent.d.ts +2 -2
- package/lib/typescript/commonjs/src/DatePickerNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/SegmentedControl.d.ts +111 -6
- package/lib/typescript/commonjs/src/SegmentedControl.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/SegmentedControlNativeComponent.d.ts +46 -7
- package/lib/typescript/commonjs/src/SegmentedControlNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/SelectionMenuNativeComponent.d.ts +2 -2
- package/lib/typescript/commonjs/src/SelectionMenuNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/index.web.d.ts +36 -1
- package/lib/typescript/commonjs/src/index.web.d.ts.map +1 -1
- package/lib/typescript/module/docs/docusaurus.config.d.ts +4 -0
- package/lib/typescript/module/docs/docusaurus.config.d.ts.map +1 -0
- package/lib/typescript/module/docs/sidebars.d.ts +4 -0
- package/lib/typescript/module/docs/sidebars.d.ts.map +1 -0
- package/lib/typescript/module/src/DatePicker.d.ts +1 -1
- package/lib/typescript/module/src/DatePicker.d.ts.map +1 -1
- package/lib/typescript/module/src/DatePickerNativeComponent.d.ts +2 -2
- package/lib/typescript/module/src/DatePickerNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/SegmentedControl.d.ts +111 -6
- package/lib/typescript/module/src/SegmentedControl.d.ts.map +1 -1
- package/lib/typescript/module/src/SegmentedControlNativeComponent.d.ts +46 -7
- package/lib/typescript/module/src/SegmentedControlNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/SelectionMenu.d.ts +1 -1
- package/lib/typescript/module/src/SelectionMenu.d.ts.map +1 -1
- package/lib/typescript/module/src/SelectionMenuNativeComponent.d.ts +2 -2
- package/lib/typescript/module/src/SelectionMenuNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/index.d.ts +6 -6
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/index.web.d.ts +36 -1
- package/lib/typescript/module/src/index.web.d.ts.map +1 -1
- package/package.json +62 -37
- package/plugin/build/index.cjs +58 -17
- package/plugin/build/index.d.ts +32 -15
- package/plugin/build/index.d.ts.map +1 -1
- package/plugin/tsconfig.json +9 -4
- package/src/DatePickerNativeComponent.ts +4 -2
- package/src/SegmentedControl.tsx +238 -11
- package/src/SegmentedControlNativeComponent.ts +62 -8
- package/src/SelectionMenuNativeComponent.ts +4 -2
- package/src/index.web.tsx +34 -1
|
@@ -356,7 +356,8 @@ class PCSelectionMenuView(context: Context) : FrameLayout(context), ReactScrollV
|
|
|
356
356
|
if (mode == MaterialMode.M3) {
|
|
357
357
|
// M3 exposed dropdown menu - the standard Material 3 way
|
|
358
358
|
// Must set box background mode BEFORE setting endIconMode to avoid IllegalStateException
|
|
359
|
-
|
|
359
|
+
// Material widgets need a Material theme; fall back to Material 3 defaults instead of crashing.
|
|
360
|
+
val til = TextInputLayout(PCThemeSupport.materialContext(context, "SelectionMenu")).apply {
|
|
360
361
|
layoutParams = FrameLayout.LayoutParams(
|
|
361
362
|
FrameLayout.LayoutParams.WRAP_CONTENT,
|
|
362
363
|
FrameLayout.LayoutParams.WRAP_CONTENT
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
package com.platformcomponents
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import android.util.TypedValue
|
|
6
|
+
import android.view.ContextThemeWrapper
|
|
7
|
+
import androidx.annotation.AttrRes
|
|
8
|
+
import androidx.appcompat.R as AppCompatR
|
|
9
|
+
import com.google.android.material.R as MaterialR
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Theme guards for the Material and AppCompat widgets this library creates.
|
|
13
|
+
*
|
|
14
|
+
* React Native and Expo templates ship an AppCompat app theme. Material widgets
|
|
15
|
+
* (MaterialButtonToggleGroup, TextInputLayout, MaterialDatePicker, ...) throw during
|
|
16
|
+
* inflation when the host theme is not a Material Components / Material 3 theme.
|
|
17
|
+
* Rather than crash the app, wrap the context in a Material 3 theme (widgets) or
|
|
18
|
+
* hand the picker dialogs a full Material 3 dialog theme, and warn once so the
|
|
19
|
+
* developer knows how to get their own colors applied.
|
|
20
|
+
*/
|
|
21
|
+
internal object PCThemeSupport {
|
|
22
|
+
private const val TAG = "PlatformComponents"
|
|
23
|
+
|
|
24
|
+
@Volatile private var warnedMaterial = false
|
|
25
|
+
@Volatile private var warnedAppCompat = false
|
|
26
|
+
|
|
27
|
+
/** True for Theme.MaterialComponents.* and Theme.Material3.* (and descendants). */
|
|
28
|
+
fun hasMaterialTheme(context: Context): Boolean =
|
|
29
|
+
resolves(context, MaterialR.attr.materialButtonOutlinedStyle) &&
|
|
30
|
+
resolves(context, MaterialR.attr.colorSurface)
|
|
31
|
+
|
|
32
|
+
/** True for Theme.AppCompat.* and descendants, which includes every Material theme. */
|
|
33
|
+
fun hasAppCompatTheme(context: Context): Boolean =
|
|
34
|
+
resolves(context, AppCompatR.attr.alertDialogTheme)
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Context to build Material widgets from. The host context when its theme is a
|
|
38
|
+
* Material theme; otherwise a Theme.Material3.DayNight wrapper, so the widget
|
|
39
|
+
* renders with Material 3 defaults instead of throwing.
|
|
40
|
+
*/
|
|
41
|
+
fun materialContext(context: Context, component: String): Context {
|
|
42
|
+
if (hasMaterialTheme(context)) return context
|
|
43
|
+
warnMaterial(component)
|
|
44
|
+
return ContextThemeWrapper(context, MaterialR.style.Theme_Material3_DayNight_NoActionBar)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Context to build AppCompat dialogs from. The host context when its theme is an
|
|
49
|
+
* AppCompat theme; otherwise a Theme.AppCompat.DayNight.Dialog.Alert wrapper.
|
|
50
|
+
*/
|
|
51
|
+
fun appCompatDialogContext(context: Context, component: String): Context {
|
|
52
|
+
if (hasAppCompatTheme(context)) return context
|
|
53
|
+
warnAppCompat(component)
|
|
54
|
+
return ContextThemeWrapper(context, AppCompatR.style.Theme_AppCompat_DayNight_Dialog_Alert)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Theme override for MaterialDatePicker / MaterialTimePicker when the activity
|
|
59
|
+
* theme is not a Material theme. Returns 0 (no override) when it is.
|
|
60
|
+
*/
|
|
61
|
+
fun materialDialogThemeOverride(context: Context, component: String, fallbackTheme: Int): Int {
|
|
62
|
+
if (hasMaterialTheme(context)) return 0
|
|
63
|
+
warnMaterial(component)
|
|
64
|
+
return fallbackTheme
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private fun resolves(context: Context, @AttrRes attr: Int): Boolean =
|
|
68
|
+
context.theme.resolveAttribute(attr, TypedValue(), true)
|
|
69
|
+
|
|
70
|
+
private fun warnMaterial(component: String) {
|
|
71
|
+
if (warnedMaterial) return
|
|
72
|
+
warnedMaterial = true
|
|
73
|
+
Log.w(
|
|
74
|
+
TAG,
|
|
75
|
+
"$component: the app theme is not a Material 3 theme, so Material components " +
|
|
76
|
+
"fall back to Material 3 default colors. To use your app's colors, make " +
|
|
77
|
+
"AppTheme inherit from Theme.Material3.DayNight.NoActionBar in " +
|
|
78
|
+
"android/app/src/main/res/values/styles.xml (Expo: pass " +
|
|
79
|
+
"{ android: { theme: 'material3' } } to the react-native-platform-components " +
|
|
80
|
+
"config plugin). See the README section \"Android Theme Configuration\"."
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private fun warnAppCompat(component: String) {
|
|
85
|
+
if (warnedAppCompat) return
|
|
86
|
+
warnedAppCompat = true
|
|
87
|
+
Log.w(
|
|
88
|
+
TAG,
|
|
89
|
+
"$component: the app theme is not an AppCompat theme, so system dialogs fall " +
|
|
90
|
+
"back to Theme.AppCompat.DayNight.Dialog.Alert. Make AppTheme inherit from " +
|
|
91
|
+
"Theme.AppCompat.* or Theme.Material3.* to style them with your theme."
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<resources>
|
|
3
|
+
<!--
|
|
4
|
+
Fallback dialog themes for MaterialDatePicker / MaterialTimePicker when the host
|
|
5
|
+
app theme is not a Material theme (see PCThemeSupport). Each is a full
|
|
6
|
+
Theme.Material3 dialog theme plus the items from ThemeOverlay.Material3.MaterialCalendar
|
|
7
|
+
and ThemeOverlay.Material3.MaterialTimePicker (material 1.12.0), which the pickers
|
|
8
|
+
skip resolving when a theme override is supplied.
|
|
9
|
+
-->
|
|
10
|
+
<style name="PCMaterial3CalendarDialogTheme" parent="Theme.Material3.DayNight.Dialog">
|
|
11
|
+
<item name="buttonBarButtonStyle">@style/Widget.Material3.Button.TextButton.Dialog.Flush</item>
|
|
12
|
+
<item name="materialCalendarStyle">@style/Widget.Material3.MaterialCalendar</item>
|
|
13
|
+
<item name="materialCalendarHeaderLayout">@style/Widget.Material3.MaterialCalendar.HeaderLayout</item>
|
|
14
|
+
<item name="materialCalendarHeaderDivider">@style/Widget.Material3.MaterialCalendar.HeaderDivider</item>
|
|
15
|
+
<item name="materialCalendarHeaderTitle">@style/Widget.Material3.MaterialCalendar.HeaderTitle</item>
|
|
16
|
+
<item name="materialCalendarHeaderSelection">@style/Widget.Material3.MaterialCalendar.HeaderSelection</item>
|
|
17
|
+
<item name="materialCalendarHeaderCancelButton">@style/Widget.Material3.MaterialCalendar.HeaderCancelButton</item>
|
|
18
|
+
<item name="materialCalendarHeaderConfirmButton">@style/Widget.Material3.Button.TextButton</item>
|
|
19
|
+
<item name="materialCalendarHeaderToggleButton">@style/Widget.Material3.MaterialCalendar.HeaderToggleButton</item>
|
|
20
|
+
<item name="materialCalendarYearNavigationButton">@style/Widget.Material3.MaterialCalendar.YearNavigationButton</item>
|
|
21
|
+
<item name="materialCalendarMonthNavigationButton">@style/Widget.Material3.MaterialCalendar.MonthNavigationButton</item>
|
|
22
|
+
<item name="materialCalendarDayOfWeekLabel">@style/Widget.Material3.MaterialCalendar.DayOfWeekLabel</item>
|
|
23
|
+
<item name="materialCalendarDay">@style/Widget.Material3.MaterialCalendar.DayTextView</item>
|
|
24
|
+
<item name="materialCalendarMonth">@style/Widget.Material3.MaterialCalendar.MonthTextView</item>
|
|
25
|
+
<item name="buttonBarPositiveButtonStyle">@style/Widget.Material3.Button.TextButton.Dialog</item>
|
|
26
|
+
<item name="buttonBarNegativeButtonStyle">@style/Widget.Material3.Button.TextButton.Dialog</item>
|
|
27
|
+
</style>
|
|
28
|
+
|
|
29
|
+
<style name="PCMaterial3TimePickerDialogTheme" parent="Theme.Material3.DayNight.Dialog">
|
|
30
|
+
<item name="buttonBarButtonStyle">@style/Widget.Material3.Button.TextButton.Dialog.Flush</item>
|
|
31
|
+
<item name="chipStyle">@style/Widget.Material3.MaterialTimePicker.Display</item>
|
|
32
|
+
<item name="textInputStyle">@style/Widget.Material3.MaterialTimePicker.Display.TextInputLayout</item>
|
|
33
|
+
<item name="materialDisplayDividerStyle">@style/Widget.Material3.MaterialTimePicker.Display.Divider</item>
|
|
34
|
+
<item name="materialButtonOutlinedStyle">@style/Widget.Material3.MaterialTimePicker.Button</item>
|
|
35
|
+
<item name="materialClockStyle">@style/Widget.Material3.MaterialTimePicker.Clock</item>
|
|
36
|
+
<item name="materialTimePickerStyle">@style/Widget.Material3.MaterialTimePicker</item>
|
|
37
|
+
<item name="imageButtonStyle">@style/Widget.Material3.MaterialTimePicker.ImageButton</item>
|
|
38
|
+
<item name="materialTimePickerTitleStyle">@style/TextAppearance.Material3.MaterialTimePicker.Title</item>
|
|
39
|
+
</style>
|
|
40
|
+
</resources>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import UIKit
|
|
2
|
+
|
|
3
|
+
/// Loads images referenced by React Native asset URIs for native controls that
|
|
4
|
+
/// take a `UIImage` (segmented control icons).
|
|
5
|
+
///
|
|
6
|
+
/// Release builds bundle local assets next to the JS bundle, so those arrive as
|
|
7
|
+
/// `file://` URLs and load synchronously. Debug builds and remote sources arrive
|
|
8
|
+
/// as `http(s)://` (Metro) or `data:` URLs and load asynchronously.
|
|
9
|
+
///
|
|
10
|
+
/// Must be used from the main thread.
|
|
11
|
+
final class PCImageLoader {
|
|
12
|
+
static let shared = PCImageLoader()
|
|
13
|
+
|
|
14
|
+
private var cache: [String: UIImage] = [:]
|
|
15
|
+
private var pending: [String: [(UIImage?) -> Void]] = [:]
|
|
16
|
+
|
|
17
|
+
/// Returns the image immediately when it is cached or readable from disk.
|
|
18
|
+
/// Otherwise starts a load and calls `completion` on the main thread with
|
|
19
|
+
/// the result; the return value is `nil` in that case.
|
|
20
|
+
@discardableResult
|
|
21
|
+
func image(
|
|
22
|
+
uri: String,
|
|
23
|
+
scale: CGFloat,
|
|
24
|
+
completion: @escaping (UIImage?) -> Void
|
|
25
|
+
) -> UIImage? {
|
|
26
|
+
let key = "\(uri)@\(scale)x"
|
|
27
|
+
if let cached = cache[key] {
|
|
28
|
+
return cached
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
guard let url = URL(string: uri) else { return nil }
|
|
32
|
+
|
|
33
|
+
if url.isFileURL {
|
|
34
|
+
guard let data = try? Data(contentsOf: url),
|
|
35
|
+
let image = UIImage(data: data, scale: scale) else { return nil }
|
|
36
|
+
cache[key] = image
|
|
37
|
+
return image
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if pending[key] != nil {
|
|
41
|
+
pending[key]?.append(completion)
|
|
42
|
+
return nil
|
|
43
|
+
}
|
|
44
|
+
pending[key] = [completion]
|
|
45
|
+
|
|
46
|
+
URLSession.shared.dataTask(with: url) { [weak self] data, _, _ in
|
|
47
|
+
let image = data.flatMap { UIImage(data: $0, scale: scale) }
|
|
48
|
+
DispatchQueue.main.async {
|
|
49
|
+
guard let self else { return }
|
|
50
|
+
if let image { self.cache[key] = image }
|
|
51
|
+
let callbacks = self.pending.removeValue(forKey: key) ?? []
|
|
52
|
+
callbacks.forEach { $0(image) }
|
|
53
|
+
}
|
|
54
|
+
}.resume()
|
|
55
|
+
|
|
56
|
+
return nil
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#import <React/RCTComponentViewFactory.h>
|
|
6
6
|
#import <React/RCTConversions.h>
|
|
7
7
|
#import <React/RCTFabricComponentsPlugins.h>
|
|
8
|
+
#import <React/RCTFont.h>
|
|
8
9
|
|
|
9
10
|
#import <react/renderer/components/PlatformComponentsViewSpec/ComponentDescriptors.h>
|
|
10
11
|
#import <react/renderer/components/PlatformComponentsViewSpec/EventEmitters.h>
|
|
@@ -32,10 +33,46 @@ static inline bool SegmentsEqual(
|
|
|
32
33
|
if (a[i].label != b[i].label) return false;
|
|
33
34
|
if (a[i].value != b[i].value) return false;
|
|
34
35
|
if (a[i].disabled != b[i].disabled) return false;
|
|
35
|
-
if (a[i].
|
|
36
|
+
if (a[i].iconType != b[i].iconType) return false;
|
|
37
|
+
if (a[i].iconName != b[i].iconName) return false;
|
|
38
|
+
if (a[i].iconUri != b[i].iconUri) return false;
|
|
39
|
+
if (a[i].iconScale != b[i].iconScale) return false;
|
|
40
|
+
if (a[i].iconTinted != b[i].iconTinted) return false;
|
|
41
|
+
if (a[i].badge != b[i].badge) return false;
|
|
42
|
+
if (a[i].accessibilityLabel != b[i].accessibilityLabel) return false;
|
|
36
43
|
}
|
|
37
44
|
return true;
|
|
38
45
|
}
|
|
46
|
+
|
|
47
|
+
static inline NSString *NSStringFromStd(const std::string &s, NSString *fallback) {
|
|
48
|
+
return s.empty() ? fallback : [NSString stringWithUTF8String:s.c_str()];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static inline bool LabelStyleEqual(
|
|
52
|
+
const facebook::react::PCSegmentedControlLabelStyleStruct &a,
|
|
53
|
+
const facebook::react::PCSegmentedControlLabelStyleStruct &b) {
|
|
54
|
+
return a.fontFamily == b.fontFamily && a.fontSize == b.fontSize &&
|
|
55
|
+
a.fontWeight == b.fontWeight && a.fontStyle == b.fontStyle;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// Builds the label font from RN-style font props, or nil when every field is
|
|
59
|
+
/// unset so the control keeps the system font.
|
|
60
|
+
static UIFont *FontFromLabelStyle(
|
|
61
|
+
const facebook::react::PCSegmentedControlLabelStyleStruct &style) {
|
|
62
|
+
if (style.fontFamily.empty() && style.fontSize <= 0 &&
|
|
63
|
+
style.fontWeight.empty() && style.fontStyle.empty()) {
|
|
64
|
+
return nil;
|
|
65
|
+
}
|
|
66
|
+
// UISegmentedControl titles default to 13pt; start there so a lone
|
|
67
|
+
// fontWeight or fontStyle doesn't change the size.
|
|
68
|
+
return [RCTFont updateFont:[UIFont systemFontOfSize:13]
|
|
69
|
+
withFamily:NSStringFromStd(style.fontFamily, nil)
|
|
70
|
+
size:style.fontSize > 0 ? @(style.fontSize) : nil
|
|
71
|
+
weight:NSStringFromStd(style.fontWeight, nil)
|
|
72
|
+
style:NSStringFromStd(style.fontStyle, nil)
|
|
73
|
+
variant:nil
|
|
74
|
+
scaleMultiplier:1.0];
|
|
75
|
+
}
|
|
39
76
|
} // namespace
|
|
40
77
|
|
|
41
78
|
@interface PCSegmentedControl ()
|
|
@@ -77,6 +114,12 @@ static inline bool SegmentsEqual(
|
|
|
77
114
|
|
|
78
115
|
eventEmitter->onSelect(payload);
|
|
79
116
|
};
|
|
117
|
+
|
|
118
|
+
_view.onNeedsRemeasure = ^{
|
|
119
|
+
__typeof(self) strongSelf = weakSelf;
|
|
120
|
+
if (!strongSelf) return;
|
|
121
|
+
[strongSelf updateMeasurements];
|
|
122
|
+
};
|
|
80
123
|
}
|
|
81
124
|
return self;
|
|
82
125
|
}
|
|
@@ -88,32 +131,32 @@ static inline bool SegmentsEqual(
|
|
|
88
131
|
const auto prevProps =
|
|
89
132
|
std::static_pointer_cast<const PCSegmentedControlProps>(oldProps);
|
|
90
133
|
|
|
91
|
-
// segments: [{label, value, disabled,
|
|
134
|
+
// segments: [{label, value, disabled, iconType, iconName, iconUri, iconScale,
|
|
135
|
+
// iconTinted, accessibilityLabel}]
|
|
92
136
|
if (!prevProps || !SegmentsEqual(newProps.segments, prevProps->segments)) {
|
|
93
137
|
NSMutableArray *arr = [NSMutableArray new];
|
|
94
138
|
for (const auto &seg : newProps.segments) {
|
|
95
|
-
NSString *label = seg.label.empty()
|
|
96
|
-
? @""
|
|
97
|
-
: [NSString stringWithUTF8String:seg.label.c_str()];
|
|
98
|
-
NSString *value = seg.value.empty()
|
|
99
|
-
? @""
|
|
100
|
-
: [NSString stringWithUTF8String:seg.value.c_str()];
|
|
101
|
-
NSString *disabled = seg.disabled.empty()
|
|
102
|
-
? @"enabled"
|
|
103
|
-
: [NSString stringWithUTF8String:seg.disabled.c_str()];
|
|
104
|
-
NSString *icon = seg.icon.empty()
|
|
105
|
-
? @""
|
|
106
|
-
: [NSString stringWithUTF8String:seg.icon.c_str()];
|
|
107
139
|
[arr addObject:@{
|
|
108
|
-
@"label": label,
|
|
109
|
-
@"value": value,
|
|
110
|
-
@"disabled": disabled,
|
|
111
|
-
@"
|
|
140
|
+
@"label": NSStringFromStd(seg.label, @""),
|
|
141
|
+
@"value": NSStringFromStd(seg.value, @""),
|
|
142
|
+
@"disabled": NSStringFromStd(seg.disabled, @"enabled"),
|
|
143
|
+
@"iconType": NSStringFromStd(seg.iconType, @""),
|
|
144
|
+
@"iconName": NSStringFromStd(seg.iconName, @""),
|
|
145
|
+
@"iconUri": NSStringFromStd(seg.iconUri, @""),
|
|
146
|
+
@"iconScale": @(seg.iconScale),
|
|
147
|
+
@"iconTinted": NSStringFromStd(seg.iconTinted, @"true"),
|
|
148
|
+
@"badge": NSStringFromStd(seg.badge, @""),
|
|
149
|
+
@"accessibilityLabel": NSStringFromStd(seg.accessibilityLabel, @""),
|
|
112
150
|
}];
|
|
113
151
|
}
|
|
114
152
|
_view.segments = arr;
|
|
115
153
|
}
|
|
116
154
|
|
|
155
|
+
// labelVisibility: "auto" | "labeled" | "unlabeled"
|
|
156
|
+
if (!prevProps || newProps.labelVisibility != prevProps->labelVisibility) {
|
|
157
|
+
_view.labelVisibility = NSStringFromStd(newProps.labelVisibility, @"auto");
|
|
158
|
+
}
|
|
159
|
+
|
|
117
160
|
// selectedValue (default "")
|
|
118
161
|
if (!prevProps || newProps.selectedValue != prevProps->selectedValue) {
|
|
119
162
|
if (!newProps.selectedValue.empty()) {
|
|
@@ -147,13 +190,30 @@ static inline bool SegmentsEqual(
|
|
|
147
190
|
_view.apportionsSegmentWidthsByContent = (newIos.apportionsSegmentWidthsByContent == "true");
|
|
148
191
|
}
|
|
149
192
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
193
|
+
// Colors arrive as SharedColor (already processed by React Native)
|
|
194
|
+
if (!prevProps || newProps.selectedSegmentColor != prevProps->selectedSegmentColor) {
|
|
195
|
+
_view.selectedSegmentColor = RCTUIColorFromSharedColor(newProps.selectedSegmentColor);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (!prevProps || newProps.activeTintColor != prevProps->activeTintColor) {
|
|
199
|
+
_view.activeTintColor = RCTUIColorFromSharedColor(newProps.activeTintColor);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (!prevProps || newProps.inactiveTintColor != prevProps->inactiveTintColor) {
|
|
203
|
+
_view.inactiveTintColor = RCTUIColorFromSharedColor(newProps.inactiveTintColor);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// labelStyle: {fontFamily, fontSize, fontWeight, fontStyle}
|
|
207
|
+
if (!prevProps || !LabelStyleEqual(newProps.labelStyle, prevProps->labelStyle)) {
|
|
208
|
+
_view.labelFont = FontFromLabelStyle(newProps.labelStyle);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (!prevProps || newProps.badgeBackgroundColor != prevProps->badgeBackgroundColor) {
|
|
212
|
+
_view.badgeBackgroundColor = RCTUIColorFromSharedColor(newProps.badgeBackgroundColor);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (!prevProps || newProps.badgeTextColor != prevProps->badgeTextColor) {
|
|
216
|
+
_view.badgeTextColor = RCTUIColorFromSharedColor(newProps.badgeTextColor);
|
|
157
217
|
}
|
|
158
218
|
|
|
159
219
|
[super updateProps:props oldProps:oldProps];
|