react-native-platform-components 1.2.0 → 1.4.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 +33 -31
- package/android/src/main/java/com/platformcomponents/PCButtonGroupView.kt +498 -0
- package/android/src/main/java/com/platformcomponents/PCButtonGroupViewManager.kt +191 -0
- package/android/src/main/java/com/platformcomponents/PCButtonSupport.kt +127 -0
- package/android/src/main/java/com/platformcomponents/PCButtonView.kt +345 -0
- package/android/src/main/java/com/platformcomponents/PCButtonViewManager.kt +126 -0
- package/android/src/main/java/com/platformcomponents/PCExpressive.kt +107 -0
- package/android/src/main/java/com/platformcomponents/PCFloatingToolbarView.kt +115 -0
- package/android/src/main/java/com/platformcomponents/PCFloatingToolbarViewManager.kt +65 -0
- package/android/src/main/java/com/platformcomponents/PCNativeThemeModule.kt +3 -0
- package/android/src/main/java/com/platformcomponents/PCSegmentedControlView.kt +13 -5
- package/android/src/main/java/com/platformcomponents/PCSegmentedControlViewManager.kt +6 -1
- package/android/src/main/java/com/platformcomponents/PCTextFieldView.kt +1018 -0
- package/android/src/main/java/com/platformcomponents/PCTextFieldViewManager.kt +248 -0
- package/android/src/main/java/com/platformcomponents/PlatformComponentsPackage.kt +13 -6
- package/android/src/main/jni/CMakeLists.txt +13 -1
- package/android/src/main/res/values/attrs.xml +13 -0
- package/android/src/main/res/values/styles.xml +183 -0
- package/ios/PCButton.h +10 -0
- package/ios/PCButton.mm +196 -0
- package/ios/PCButtonGroup.h +10 -0
- package/ios/PCButtonGroup.mm +256 -0
- package/ios/PCButtonGroupView.swift +254 -0
- package/ios/PCButtonSupport.swift +141 -0
- package/ios/PCButtonView.swift +155 -0
- package/ios/PCFloatingToolbar.h +10 -0
- package/ios/PCFloatingToolbar.mm +76 -0
- package/ios/PCFloatingToolbarView.swift +95 -0
- package/ios/PCNativeThemeModule.mm +13 -0
- package/ios/PCSelectionMenu.swift +9 -1
- package/ios/PCTextField.h +10 -0
- package/ios/PCTextField.mm +391 -0
- package/ios/PCTextFieldView.swift +1012 -0
- package/lib/commonjs/Button.js +77 -0
- package/lib/commonjs/Button.js.map +1 -0
- package/lib/commonjs/ButtonGroup.js +99 -0
- package/lib/commonjs/ButtonGroup.js.map +1 -0
- package/lib/commonjs/ButtonGroupNativeComponent.ts +121 -0
- package/lib/commonjs/ButtonNativeComponent.ts +76 -0
- package/lib/commonjs/ContextMenuNativeComponent.ts +5 -4
- package/lib/commonjs/DatePickerNativeComponent.ts +17 -11
- package/lib/commonjs/FloatingToolbar.js +69 -0
- package/lib/commonjs/FloatingToolbar.js.map +1 -0
- package/lib/commonjs/FloatingToolbarNativeComponent.ts +31 -0
- package/lib/commonjs/LiquidGlass.js +24 -4
- package/lib/commonjs/LiquidGlass.js.map +1 -1
- package/lib/commonjs/LiquidGlassNativeComponent.ts +6 -5
- package/lib/commonjs/NativePlatformComponentsTheme.js.map +1 -1
- package/lib/commonjs/SegmentedControl.js +11 -85
- package/lib/commonjs/SegmentedControl.js.map +1 -1
- package/lib/commonjs/SegmentedControlNativeComponent.ts +15 -11
- package/lib/commonjs/SelectionMenuNativeComponent.ts +6 -5
- package/lib/commonjs/TextField.js +195 -0
- package/lib/commonjs/TextField.js.map +1 -0
- package/lib/commonjs/TextFieldNativeComponent.ts +218 -0
- package/lib/commonjs/codegenTypes.js +6 -0
- package/lib/commonjs/codegenTypes.js.map +1 -0
- package/lib/commonjs/focusRegistry.js +78 -0
- package/lib/commonjs/focusRegistry.js.map +1 -0
- package/lib/commonjs/icons.js +92 -0
- package/lib/commonjs/icons.js.map +1 -0
- package/lib/commonjs/index.js +66 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +32 -2
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/labelStyle.js +27 -0
- package/lib/commonjs/labelStyle.js.map +1 -0
- package/lib/commonjs/reactNativeInternals.d.js +2 -0
- package/lib/commonjs/reactNativeInternals.d.js.map +1 -0
- package/lib/module/Button.js +70 -0
- package/lib/module/Button.js.map +1 -0
- package/lib/module/ButtonGroup.js +92 -0
- package/lib/module/ButtonGroup.js.map +1 -0
- package/lib/module/ButtonGroupNativeComponent.ts +121 -0
- package/lib/module/ButtonNativeComponent.ts +76 -0
- package/lib/module/ContextMenuNativeComponent.ts +5 -4
- package/lib/module/DatePickerNativeComponent.ts +17 -11
- package/lib/module/FloatingToolbar.js +62 -0
- package/lib/module/FloatingToolbar.js.map +1 -0
- package/lib/module/FloatingToolbarNativeComponent.ts +31 -0
- package/lib/module/LiquidGlass.js +24 -4
- package/lib/module/LiquidGlass.js.map +1 -1
- package/lib/module/LiquidGlassNativeComponent.ts +6 -5
- package/lib/module/NativePlatformComponentsTheme.js.map +1 -1
- package/lib/module/SegmentedControl.js +12 -87
- package/lib/module/SegmentedControl.js.map +1 -1
- package/lib/module/SegmentedControlNativeComponent.ts +15 -11
- package/lib/module/SelectionMenuNativeComponent.ts +6 -5
- package/lib/module/TextField.js +189 -0
- package/lib/module/TextField.js.map +1 -0
- package/lib/module/TextFieldNativeComponent.ts +218 -0
- package/lib/module/codegenTypes.js +4 -0
- package/lib/module/codegenTypes.js.map +1 -0
- package/lib/module/focusRegistry.js +74 -0
- package/lib/module/focusRegistry.js.map +1 -0
- package/lib/module/icons.js +87 -0
- package/lib/module/icons.js.map +1 -0
- package/lib/module/index.js +6 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +28 -0
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/labelStyle.js +23 -0
- package/lib/module/labelStyle.js.map +1 -0
- package/lib/module/reactNativeInternals.d.js +2 -0
- package/lib/module/reactNativeInternals.d.js.map +1 -0
- package/lib/typescript/commonjs/docs/sidebars.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/Button.d.ts +76 -0
- package/lib/typescript/commonjs/src/Button.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/ButtonGroup.d.ts +102 -0
- package/lib/typescript/commonjs/src/ButtonGroup.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/ButtonGroupNativeComponent.d.ts +93 -0
- package/lib/typescript/commonjs/src/ButtonGroupNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/ButtonNativeComponent.d.ts +57 -0
- package/lib/typescript/commonjs/src/ButtonNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/ContextMenuNativeComponent.d.ts +5 -4
- package/lib/typescript/commonjs/src/ContextMenuNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/DatePickerNativeComponent.d.ts +12 -11
- package/lib/typescript/commonjs/src/DatePickerNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/FloatingToolbar.d.ts +45 -0
- package/lib/typescript/commonjs/src/FloatingToolbar.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/FloatingToolbarNativeComponent.d.ts +24 -0
- package/lib/typescript/commonjs/src/FloatingToolbarNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/LiquidGlass.d.ts +4 -3
- package/lib/typescript/commonjs/src/LiquidGlass.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/LiquidGlassNativeComponent.d.ts +6 -5
- package/lib/typescript/commonjs/src/LiquidGlassNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/NativePlatformComponentsTheme.d.ts +10 -2
- package/lib/typescript/commonjs/src/NativePlatformComponentsTheme.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/SegmentedControl.d.ts +17 -46
- package/lib/typescript/commonjs/src/SegmentedControl.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/SegmentedControlNativeComponent.d.ts +9 -6
- package/lib/typescript/commonjs/src/SegmentedControlNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/SelectionMenuNativeComponent.d.ts +6 -5
- package/lib/typescript/commonjs/src/SelectionMenuNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/TextField.d.ts +174 -0
- package/lib/typescript/commonjs/src/TextField.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/TextFieldNativeComponent.d.ts +162 -0
- package/lib/typescript/commonjs/src/TextFieldNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/codegenTypes.d.ts +12 -0
- package/lib/typescript/commonjs/src/codegenTypes.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/focusRegistry.d.ts +13 -0
- package/lib/typescript/commonjs/src/focusRegistry.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/icons.d.ts +52 -0
- package/lib/typescript/commonjs/src/icons.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/index.d.ts +6 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/index.web.d.ts +121 -0
- package/lib/typescript/commonjs/src/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/labelStyle.d.ts +20 -0
- package/lib/typescript/commonjs/src/labelStyle.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/sharedTypes.d.ts +8 -3
- package/lib/typescript/commonjs/src/sharedTypes.d.ts.map +1 -1
- package/lib/typescript/module/docs/sidebars.d.ts.map +1 -1
- package/lib/typescript/module/src/Button.d.ts +76 -0
- package/lib/typescript/module/src/Button.d.ts.map +1 -0
- package/lib/typescript/module/src/ButtonGroup.d.ts +102 -0
- package/lib/typescript/module/src/ButtonGroup.d.ts.map +1 -0
- package/lib/typescript/module/src/ButtonGroupNativeComponent.d.ts +93 -0
- package/lib/typescript/module/src/ButtonGroupNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/ButtonNativeComponent.d.ts +57 -0
- package/lib/typescript/module/src/ButtonNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/ContextMenuNativeComponent.d.ts +5 -4
- package/lib/typescript/module/src/ContextMenuNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/DatePickerNativeComponent.d.ts +12 -11
- package/lib/typescript/module/src/DatePickerNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/FloatingToolbar.d.ts +45 -0
- package/lib/typescript/module/src/FloatingToolbar.d.ts.map +1 -0
- package/lib/typescript/module/src/FloatingToolbarNativeComponent.d.ts +24 -0
- package/lib/typescript/module/src/FloatingToolbarNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/LiquidGlass.d.ts +4 -3
- package/lib/typescript/module/src/LiquidGlass.d.ts.map +1 -1
- package/lib/typescript/module/src/LiquidGlassNativeComponent.d.ts +6 -5
- package/lib/typescript/module/src/LiquidGlassNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/NativePlatformComponentsTheme.d.ts +10 -2
- package/lib/typescript/module/src/NativePlatformComponentsTheme.d.ts.map +1 -1
- package/lib/typescript/module/src/SegmentedControl.d.ts +17 -46
- package/lib/typescript/module/src/SegmentedControl.d.ts.map +1 -1
- package/lib/typescript/module/src/SegmentedControlNativeComponent.d.ts +9 -6
- package/lib/typescript/module/src/SegmentedControlNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/SelectionMenuNativeComponent.d.ts +6 -5
- package/lib/typescript/module/src/SelectionMenuNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/TextField.d.ts +174 -0
- package/lib/typescript/module/src/TextField.d.ts.map +1 -0
- package/lib/typescript/module/src/TextFieldNativeComponent.d.ts +162 -0
- package/lib/typescript/module/src/TextFieldNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/codegenTypes.d.ts +12 -0
- package/lib/typescript/module/src/codegenTypes.d.ts.map +1 -0
- package/lib/typescript/module/src/focusRegistry.d.ts +13 -0
- package/lib/typescript/module/src/focusRegistry.d.ts.map +1 -0
- package/lib/typescript/module/src/icons.d.ts +52 -0
- package/lib/typescript/module/src/icons.d.ts.map +1 -0
- package/lib/typescript/module/src/index.d.ts +6 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/index.web.d.ts +121 -0
- package/lib/typescript/module/src/index.web.d.ts.map +1 -1
- package/lib/typescript/module/src/labelStyle.d.ts +20 -0
- package/lib/typescript/module/src/labelStyle.d.ts.map +1 -0
- package/lib/typescript/module/src/sharedTypes.d.ts +8 -3
- package/lib/typescript/module/src/sharedTypes.d.ts.map +1 -1
- package/package.json +28 -6
- package/react-native.config.js +3 -0
- package/shared/PCButtonComponentDescriptors-custom.h +22 -0
- package/shared/PCButtonGroupComponentDescriptors-custom.h +22 -0
- package/shared/PCButtonGroupShadowNode-custom.cpp +48 -0
- package/shared/PCButtonGroupShadowNode-custom.h +55 -0
- package/shared/PCButtonGroupState-custom.h +61 -0
- package/shared/PCButtonShadowNode-custom.cpp +48 -0
- package/shared/PCButtonShadowNode-custom.h +55 -0
- package/shared/PCButtonState-custom.h +61 -0
- package/shared/PCDatePickerState-custom.h +2 -2
- package/shared/PCSegmentedControlState-custom.h +2 -2
- package/shared/PCSelectionMenuState-custom.h +2 -2
- package/shared/PCTextFieldComponentDescriptors-custom.h +22 -0
- package/shared/PCTextFieldShadowNode-custom.cpp +47 -0
- package/shared/PCTextFieldShadowNode-custom.h +55 -0
- package/shared/PCTextFieldState-custom.h +61 -0
- package/shared/react/renderer/components/PlatformComponentsViewSpec/ComponentDescriptors.h +3 -0
- package/src/Button.tsx +144 -0
- package/src/ButtonGroup.tsx +233 -0
- package/src/ButtonGroupNativeComponent.ts +121 -0
- package/src/ButtonNativeComponent.ts +76 -0
- package/src/ContextMenuNativeComponent.ts +5 -4
- package/src/DatePickerNativeComponent.ts +17 -11
- package/src/FloatingToolbar.tsx +113 -0
- package/src/FloatingToolbarNativeComponent.ts +31 -0
- package/src/LiquidGlass.tsx +24 -5
- package/src/LiquidGlassNativeComponent.ts +6 -5
- package/src/NativePlatformComponentsTheme.ts +11 -2
- package/src/SegmentedControl.tsx +26 -118
- package/src/SegmentedControlNativeComponent.ts +15 -11
- package/src/SelectionMenuNativeComponent.ts +6 -5
- package/src/TextField.tsx +494 -0
- package/src/TextFieldNativeComponent.ts +218 -0
- package/src/codegenTypes.ts +40 -0
- package/src/focusRegistry.ts +89 -0
- package/src/icons.ts +116 -0
- package/src/index.tsx +6 -0
- package/src/index.web.tsx +194 -0
- package/src/labelStyle.ts +36 -0
- package/src/reactNativeInternals.d.ts +22 -0
- package/src/sharedTypes.ts +9 -3
- /package/{app.plugin.cjs → app.plugin.js} +0 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import UIKit
|
|
2
|
+
|
|
3
|
+
/// The floating toolbar container: a Liquid Glass capsule on iOS 26, and a
|
|
4
|
+
/// blur-material capsule with a soft shadow on earlier versions, where a blur
|
|
5
|
+
/// over a flat background would otherwise have no edge.
|
|
6
|
+
@objcMembers
|
|
7
|
+
public final class PCFloatingToolbarView: UIView {
|
|
8
|
+
// MARK: - Props (set from ObjC++)
|
|
9
|
+
|
|
10
|
+
/// "regular" | "clear"
|
|
11
|
+
public var effectStyle: String = "regular" {
|
|
12
|
+
didSet { if oldValue != effectStyle { applyEffect() } }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/// Tint over the material; nil keeps the plain material
|
|
16
|
+
public var tintUIColor: UIColor? {
|
|
17
|
+
didSet { applyEffect() }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/// React children mount here
|
|
21
|
+
public var contentView: UIView { effectView.contentView }
|
|
22
|
+
|
|
23
|
+
// MARK: - Internal
|
|
24
|
+
|
|
25
|
+
private let effectView = UIVisualEffectView(effect: nil)
|
|
26
|
+
|
|
27
|
+
/// Liquid Glass needs both the iOS 26 SDK at build time and iOS 26 at runtime.
|
|
28
|
+
private static var glassAvailable: Bool {
|
|
29
|
+
#if compiler(>=6.2)
|
|
30
|
+
if #available(iOS 26.0, *) { return true }
|
|
31
|
+
#endif
|
|
32
|
+
return false
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// MARK: - Init
|
|
36
|
+
|
|
37
|
+
public override init(frame: CGRect) {
|
|
38
|
+
super.init(frame: frame)
|
|
39
|
+
setup()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public required init?(coder: NSCoder) {
|
|
43
|
+
super.init(coder: coder)
|
|
44
|
+
setup()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private func setup() {
|
|
48
|
+
clipsToBounds = false
|
|
49
|
+
effectView.layer.cornerCurve = .continuous
|
|
50
|
+
addSubview(effectView)
|
|
51
|
+
|
|
52
|
+
if !Self.glassAvailable {
|
|
53
|
+
// The blur is clipped to the capsule; the shadow lives on this view
|
|
54
|
+
effectView.clipsToBounds = true
|
|
55
|
+
layer.shadowColor = UIColor.black.cgColor
|
|
56
|
+
layer.shadowOpacity = 0.12
|
|
57
|
+
layer.shadowRadius = 10
|
|
58
|
+
layer.shadowOffset = CGSize(width: 0, height: 4)
|
|
59
|
+
}
|
|
60
|
+
applyEffect()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// MARK: - Layout
|
|
64
|
+
|
|
65
|
+
public override func layoutSubviews() {
|
|
66
|
+
super.layoutSubviews()
|
|
67
|
+
effectView.frame = bounds
|
|
68
|
+
let radius = min(bounds.width, bounds.height) / 2
|
|
69
|
+
effectView.layer.cornerRadius = radius
|
|
70
|
+
if !Self.glassAvailable {
|
|
71
|
+
layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: radius).cgPath
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// MARK: - Effect
|
|
76
|
+
|
|
77
|
+
private func applyEffect() {
|
|
78
|
+
#if compiler(>=6.2)
|
|
79
|
+
if #available(iOS 26.0, *) {
|
|
80
|
+
let glass = UIGlassEffect(style: effectStyle == "clear" ? .clear : .regular)
|
|
81
|
+
if let tintUIColor {
|
|
82
|
+
glass.tintColor = tintUIColor
|
|
83
|
+
}
|
|
84
|
+
effectView.effect = glass
|
|
85
|
+
effectView.contentView.backgroundColor = nil
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
#endif
|
|
89
|
+
effectView.effect = UIBlurEffect(
|
|
90
|
+
style: effectStyle == "clear" ? .systemUltraThinMaterial : .systemThinMaterial
|
|
91
|
+
)
|
|
92
|
+
// UIBlurEffect has no tint; wash the content area with the color instead
|
|
93
|
+
effectView.contentView.backgroundColor = tintUIColor?.withAlphaComponent(0.35)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -27,6 +27,19 @@ RCT_EXPORT_MODULE(PlatformComponentsTheme)
|
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/// Reports what this *build* can do, not just what the device runs: with an
|
|
31
|
+
/// older Xcode the glass code is compiled out (see PCLiquidGlass.swift), so
|
|
32
|
+
/// the iOS version alone would be a false positive.
|
|
33
|
+
- (NSNumber *)isLiquidGlassSupported
|
|
34
|
+
{
|
|
35
|
+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 260000
|
|
36
|
+
if (@available(iOS 26.0, *)) {
|
|
37
|
+
return @(PCLiquidGlassView.isSupported);
|
|
38
|
+
}
|
|
39
|
+
#endif
|
|
40
|
+
return @NO;
|
|
41
|
+
}
|
|
42
|
+
|
|
30
43
|
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
31
44
|
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
32
45
|
{
|
|
@@ -473,8 +473,12 @@ private class PCMenuViewController: UIViewController, UITableViewDelegate, UITab
|
|
|
473
473
|
menuContainer.clipsToBounds = true
|
|
474
474
|
view.addSubview(menuContainer)
|
|
475
475
|
|
|
476
|
-
// Use liquid glass on iOS 26+, fall back to system material blur on older
|
|
476
|
+
// Use liquid glass on iOS 26+, fall back to system material blur on older
|
|
477
|
+
// versions. UIGlassEffect only exists in the iOS 26 SDK, so the branch is
|
|
478
|
+
// compiled out entirely on older toolchains — same guard as
|
|
479
|
+
// PCLiquidGlass.swift, which keeps the library buildable without Xcode 26.
|
|
477
480
|
let effectView: UIVisualEffectView
|
|
481
|
+
#if compiler(>=6.2)
|
|
478
482
|
if #available(iOS 26, *) {
|
|
479
483
|
let glassEffect = UIGlassEffect()
|
|
480
484
|
glassEffect.isInteractive = true
|
|
@@ -483,6 +487,10 @@ private class PCMenuViewController: UIViewController, UITableViewDelegate, UITab
|
|
|
483
487
|
let blurEffect = UIBlurEffect(style: .systemMaterial)
|
|
484
488
|
effectView = UIVisualEffectView(effect: blurEffect)
|
|
485
489
|
}
|
|
490
|
+
#else
|
|
491
|
+
let blurEffect = UIBlurEffect(style: .systemMaterial)
|
|
492
|
+
effectView = UIVisualEffectView(effect: blurEffect)
|
|
493
|
+
#endif
|
|
486
494
|
effectView.frame = menuContainer.bounds
|
|
487
495
|
effectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
488
496
|
menuContainer.addSubview(effectView)
|
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
// PCTextField.mm
|
|
2
|
+
|
|
3
|
+
#import "PCTextField.h"
|
|
4
|
+
|
|
5
|
+
#import <React/RCTComponentViewFactory.h>
|
|
6
|
+
#import <React/RCTConversions.h>
|
|
7
|
+
#import <React/RCTFabricComponentsPlugins.h>
|
|
8
|
+
#import <React/RCTFont.h>
|
|
9
|
+
|
|
10
|
+
#import <react/renderer/components/PlatformComponentsViewSpec/ComponentDescriptors.h>
|
|
11
|
+
#import <react/renderer/components/PlatformComponentsViewSpec/EventEmitters.h>
|
|
12
|
+
#import <react/renderer/components/PlatformComponentsViewSpec/Props.h>
|
|
13
|
+
#import <react/renderer/components/PlatformComponentsViewSpec/RCTComponentViewHelpers.h>
|
|
14
|
+
#import <react/renderer/core/LayoutPrimitives.h>
|
|
15
|
+
|
|
16
|
+
#if __has_include(<PlatformComponents/PlatformComponents-Swift.h>)
|
|
17
|
+
#import <PlatformComponents/PlatformComponents-Swift.h>
|
|
18
|
+
#else
|
|
19
|
+
#import "PlatformComponents-Swift.h"
|
|
20
|
+
#endif
|
|
21
|
+
|
|
22
|
+
#import "PCTextFieldComponentDescriptors-custom.h"
|
|
23
|
+
#import "PCTextFieldShadowNode-custom.h"
|
|
24
|
+
#import "PCTextFieldState-custom.h"
|
|
25
|
+
|
|
26
|
+
using namespace facebook::react;
|
|
27
|
+
|
|
28
|
+
namespace {
|
|
29
|
+
static inline NSString *NSStringFromStd(const std::string &s, NSString *fallback) {
|
|
30
|
+
return s.empty() ? fallback : [NSString stringWithUTF8String:s.c_str()];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static inline bool IconEqual(const PCTextFieldLeadingIconStruct &a, const PCTextFieldLeadingIconStruct &b) {
|
|
34
|
+
return a.iconType == b.iconType && a.iconName == b.iconName && a.iconUri == b.iconUri &&
|
|
35
|
+
a.iconScale == b.iconScale && a.iconTinted == b.iconTinted;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static inline bool IconEqual(const PCTextFieldTrailingIconStruct &a, const PCTextFieldTrailingIconStruct &b) {
|
|
39
|
+
return a.iconType == b.iconType && a.iconName == b.iconName && a.iconUri == b.iconUri &&
|
|
40
|
+
a.iconScale == b.iconScale && a.iconTinted == b.iconTinted;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static inline bool TextStyleEqual(
|
|
44
|
+
const PCTextFieldTextStyleStruct &a,
|
|
45
|
+
const PCTextFieldTextStyleStruct &b) {
|
|
46
|
+
return a.fontFamily == b.fontFamily && a.fontSize == b.fontSize &&
|
|
47
|
+
a.fontWeight == b.fontWeight && a.fontStyle == b.fontStyle;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/// Builds the input font from RN-style font props, or nil when every field is
|
|
51
|
+
/// unset so the field keeps the body text style.
|
|
52
|
+
static UIFont *FontFromTextStyle(const PCTextFieldTextStyleStruct &style) {
|
|
53
|
+
if (style.fontFamily.empty() && style.fontSize <= 0 &&
|
|
54
|
+
style.fontWeight.empty() && style.fontStyle.empty()) {
|
|
55
|
+
return nil;
|
|
56
|
+
}
|
|
57
|
+
return [RCTFont updateFont:[UIFont preferredFontForTextStyle:UIFontTextStyleBody]
|
|
58
|
+
withFamily:NSStringFromStd(style.fontFamily, nil)
|
|
59
|
+
size:style.fontSize > 0 ? @(style.fontSize) : nil
|
|
60
|
+
weight:NSStringFromStd(style.fontWeight, nil)
|
|
61
|
+
style:NSStringFromStd(style.fontStyle, nil)
|
|
62
|
+
variant:nil
|
|
63
|
+
scaleMultiplier:1.0];
|
|
64
|
+
}
|
|
65
|
+
} // namespace
|
|
66
|
+
|
|
67
|
+
@interface PCTextField () <RCTPCTextFieldViewProtocol>
|
|
68
|
+
|
|
69
|
+
- (void)updateMeasurements;
|
|
70
|
+
|
|
71
|
+
@end
|
|
72
|
+
|
|
73
|
+
@implementation PCTextField {
|
|
74
|
+
PCTextFieldView *_view;
|
|
75
|
+
MeasuringPCTextFieldShadowNode::ConcreteState::Shared _state;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider {
|
|
79
|
+
return concreteComponentDescriptorProvider<MeasuringPCTextFieldComponentDescriptor>();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// A first responder with typed text is not something to hand to another
|
|
83
|
+
// element; keep every field its own view.
|
|
84
|
+
+ (BOOL)shouldBeRecycled {
|
|
85
|
+
return NO;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
- (instancetype)initWithFrame:(CGRect)frame {
|
|
89
|
+
if (self = [super initWithFrame:frame]) {
|
|
90
|
+
_view = [PCTextFieldView new];
|
|
91
|
+
self.contentView = _view;
|
|
92
|
+
|
|
93
|
+
__weak __typeof(self) weakSelf = self;
|
|
94
|
+
|
|
95
|
+
_view.onChange = ^(NSString *text, NSInteger eventCount) {
|
|
96
|
+
__typeof(self) strongSelf = weakSelf;
|
|
97
|
+
if (!strongSelf) return;
|
|
98
|
+
|
|
99
|
+
auto eventEmitter =
|
|
100
|
+
std::static_pointer_cast<const PCTextFieldEventEmitter>(strongSelf->_eventEmitter);
|
|
101
|
+
if (!eventEmitter) return;
|
|
102
|
+
|
|
103
|
+
PCTextFieldEventEmitter::OnFieldChange payload = {
|
|
104
|
+
.text = text.UTF8String,
|
|
105
|
+
.eventCount = (int)eventCount,
|
|
106
|
+
};
|
|
107
|
+
eventEmitter->onFieldChange(payload);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
_view.onFocusChange = ^(BOOL focused, NSString *text) {
|
|
111
|
+
__typeof(self) strongSelf = weakSelf;
|
|
112
|
+
if (!strongSelf) return;
|
|
113
|
+
|
|
114
|
+
auto eventEmitter =
|
|
115
|
+
std::static_pointer_cast<const PCTextFieldEventEmitter>(strongSelf->_eventEmitter);
|
|
116
|
+
if (!eventEmitter) return;
|
|
117
|
+
|
|
118
|
+
if (focused) {
|
|
119
|
+
eventEmitter->onFieldFocus({.text = text.UTF8String});
|
|
120
|
+
} else {
|
|
121
|
+
eventEmitter->onFieldBlur({.text = text.UTF8String});
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
_view.onSubmit = ^(NSString *text) {
|
|
126
|
+
__typeof(self) strongSelf = weakSelf;
|
|
127
|
+
if (!strongSelf) return;
|
|
128
|
+
|
|
129
|
+
auto eventEmitter =
|
|
130
|
+
std::static_pointer_cast<const PCTextFieldEventEmitter>(strongSelf->_eventEmitter);
|
|
131
|
+
if (!eventEmitter) return;
|
|
132
|
+
|
|
133
|
+
eventEmitter->onFieldSubmit({.text = text.UTF8String});
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
_view.onTrailingIconPress = ^{
|
|
137
|
+
__typeof(self) strongSelf = weakSelf;
|
|
138
|
+
if (!strongSelf) return;
|
|
139
|
+
|
|
140
|
+
auto eventEmitter =
|
|
141
|
+
std::static_pointer_cast<const PCTextFieldEventEmitter>(strongSelf->_eventEmitter);
|
|
142
|
+
if (!eventEmitter) return;
|
|
143
|
+
|
|
144
|
+
eventEmitter->onTrailingIconPress({});
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
_view.onNeedsRemeasure = ^{
|
|
148
|
+
__typeof(self) strongSelf = weakSelf;
|
|
149
|
+
if (!strongSelf) return;
|
|
150
|
+
[strongSelf updateMeasurements];
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
return self;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
- (void)updateProps:(Props::Shared const &)props
|
|
157
|
+
oldProps:(Props::Shared const &)oldProps {
|
|
158
|
+
const auto &newProps = *std::static_pointer_cast<const PCTextFieldProps>(props);
|
|
159
|
+
const auto prevProps = std::static_pointer_cast<const PCTextFieldProps>(oldProps);
|
|
160
|
+
|
|
161
|
+
// Only the first value counts; later text arrives through setText
|
|
162
|
+
if (!prevProps || newProps.initialText != prevProps->initialText) {
|
|
163
|
+
[_view applyInitialText:NSStringFromStd(newProps.initialText, @"")];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (!prevProps || newProps.label != prevProps->label) {
|
|
167
|
+
_view.label = NSStringFromStd(newProps.label, @"");
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (!prevProps || newProps.placeholder != prevProps->placeholder) {
|
|
171
|
+
_view.placeholder = NSStringFromStd(newProps.placeholder, @"");
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (!prevProps || newProps.supportingText != prevProps->supportingText) {
|
|
175
|
+
_view.supportingText = NSStringFromStd(newProps.supportingText, @"");
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (!prevProps || newProps.errorState != prevProps->errorState) {
|
|
179
|
+
_view.errorState = NSStringFromStd(newProps.errorState, @"none");
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (!prevProps || newProps.errorText != prevProps->errorText) {
|
|
183
|
+
_view.errorText = NSStringFromStd(newProps.errorText, @"");
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (!prevProps || newProps.prefix != prevProps->prefix) {
|
|
187
|
+
_view.prefix = NSStringFromStd(newProps.prefix, @"");
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (!prevProps || newProps.suffix != prevProps->suffix) {
|
|
191
|
+
_view.suffix = NSStringFromStd(newProps.suffix, @"");
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// icons: {iconType, iconName, iconUri, iconScale, iconTinted}
|
|
195
|
+
if (!prevProps || !IconEqual(newProps.leadingIcon, prevProps->leadingIcon)) {
|
|
196
|
+
const auto &icon = newProps.leadingIcon;
|
|
197
|
+
[_view setLeadingIconWithType:NSStringFromStd(icon.iconType, @"")
|
|
198
|
+
name:NSStringFromStd(icon.iconName, @"")
|
|
199
|
+
uri:NSStringFromStd(icon.iconUri, @"")
|
|
200
|
+
scale:icon.iconScale
|
|
201
|
+
tinted:(icon.iconTinted != "false")];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (!prevProps || !IconEqual(newProps.trailingIcon, prevProps->trailingIcon)) {
|
|
205
|
+
const auto &icon = newProps.trailingIcon;
|
|
206
|
+
[_view setTrailingIconWithType:NSStringFromStd(icon.iconType, @"")
|
|
207
|
+
name:NSStringFromStd(icon.iconName, @"")
|
|
208
|
+
uri:NSStringFromStd(icon.iconUri, @"")
|
|
209
|
+
scale:icon.iconScale
|
|
210
|
+
tinted:(icon.iconTinted != "false")];
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (!prevProps || newProps.clearButtonMode != prevProps->clearButtonMode) {
|
|
214
|
+
_view.clearButtonMode = NSStringFromStd(newProps.clearButtonMode, @"never");
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (!prevProps || newProps.passwordToggle != prevProps->passwordToggle) {
|
|
218
|
+
_view.passwordToggle = newProps.passwordToggle == "shown";
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (!prevProps || newProps.characterCount != prevProps->characterCount) {
|
|
222
|
+
_view.characterCount = newProps.characterCount == "shown";
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (!prevProps || newProps.maxLength != prevProps->maxLength) {
|
|
226
|
+
_view.maxLength = newProps.maxLength;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (!prevProps || newProps.keyboardType != prevProps->keyboardType) {
|
|
230
|
+
_view.keyboardType = NSStringFromStd(newProps.keyboardType, @"default");
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (!prevProps || newProps.returnKeyType != prevProps->returnKeyType) {
|
|
234
|
+
_view.returnKeyType = NSStringFromStd(newProps.returnKeyType, @"default");
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (!prevProps || newProps.autoCapitalize != prevProps->autoCapitalize) {
|
|
238
|
+
_view.autoCapitalize = NSStringFromStd(newProps.autoCapitalize, @"sentences");
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (!prevProps || newProps.autoCorrect != prevProps->autoCorrect) {
|
|
242
|
+
_view.autoCorrect = newProps.autoCorrect != "disabled";
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (!prevProps || newProps.secureTextEntry != prevProps->secureTextEntry) {
|
|
246
|
+
_view.secureTextEntry = newProps.secureTextEntry == "secure";
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (!prevProps || newProps.lines != prevProps->lines) {
|
|
250
|
+
_view.multiline = newProps.lines == "multiline";
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (!prevProps || newProps.interactivity != prevProps->interactivity) {
|
|
254
|
+
_view.interactivity = NSStringFromStd(newProps.interactivity, @"enabled");
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (!prevProps || newProps.selectTextOnFocus != prevProps->selectTextOnFocus) {
|
|
258
|
+
_view.selectTextOnFocus = newProps.selectTextOnFocus == "select";
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (!prevProps || newProps.autoComplete != prevProps->autoComplete) {
|
|
262
|
+
_view.autoComplete = NSStringFromStd(newProps.autoComplete, @"");
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (!prevProps || newProps.keyboardAppearance != prevProps->keyboardAppearance) {
|
|
266
|
+
_view.keyboardAppearance = NSStringFromStd(newProps.keyboardAppearance, @"default");
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// textStyle: {fontFamily, fontSize, fontWeight, fontStyle}
|
|
270
|
+
if (!prevProps || !TextStyleEqual(newProps.textStyle, prevProps->textStyle)) {
|
|
271
|
+
_view.textFont = FontFromTextStyle(newProps.textStyle);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (!prevProps || newProps.spokenLabel != prevProps->spokenLabel) {
|
|
275
|
+
_view.spokenLabel = NSStringFromStd(newProps.spokenLabel, @"");
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// ios: the text traits
|
|
279
|
+
const auto &newIOS = newProps.ios;
|
|
280
|
+
const auto &oldIOS = prevProps ? prevProps->ios : PCTextFieldIosStruct{};
|
|
281
|
+
if (!prevProps || newIOS.writingTools != oldIOS.writingTools) {
|
|
282
|
+
_view.writingTools = NSStringFromStd(newIOS.writingTools, @"");
|
|
283
|
+
}
|
|
284
|
+
if (!prevProps || newIOS.inlinePrediction != oldIOS.inlinePrediction) {
|
|
285
|
+
_view.inlinePrediction = NSStringFromStd(newIOS.inlinePrediction, @"");
|
|
286
|
+
}
|
|
287
|
+
if (!prevProps || newIOS.smartQuotes != oldIOS.smartQuotes) {
|
|
288
|
+
_view.smartQuotes = NSStringFromStd(newIOS.smartQuotes, @"");
|
|
289
|
+
}
|
|
290
|
+
if (!prevProps || newIOS.smartDashes != oldIOS.smartDashes) {
|
|
291
|
+
_view.smartDashes = NSStringFromStd(newIOS.smartDashes, @"");
|
|
292
|
+
}
|
|
293
|
+
if (!prevProps || newIOS.smartInsertDelete != oldIOS.smartInsertDelete) {
|
|
294
|
+
_view.smartInsertDelete = NSStringFromStd(newIOS.smartInsertDelete, @"");
|
|
295
|
+
}
|
|
296
|
+
if (!prevProps || newIOS.mathExpressionCompletion != oldIOS.mathExpressionCompletion) {
|
|
297
|
+
_view.mathExpressionCompletion = NSStringFromStd(newIOS.mathExpressionCompletion, @"");
|
|
298
|
+
}
|
|
299
|
+
if (!prevProps || newIOS.borderStyle != oldIOS.borderStyle) {
|
|
300
|
+
_view.borderStyle = NSStringFromStd(newIOS.borderStyle, @"");
|
|
301
|
+
}
|
|
302
|
+
if (!prevProps || newIOS.labelPlacement != oldIOS.labelPlacement) {
|
|
303
|
+
_view.labelPlacement = NSStringFromStd(newIOS.labelPlacement, @"");
|
|
304
|
+
}
|
|
305
|
+
if (!prevProps || newIOS.labelWidth != oldIOS.labelWidth) {
|
|
306
|
+
_view.labelWidth = newIOS.labelWidth;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// autoFocus last, once the field is configured
|
|
310
|
+
if (!prevProps || newProps.autoFocus != prevProps->autoFocus) {
|
|
311
|
+
_view.autoFocus = newProps.autoFocus == "focus";
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// android: Android only
|
|
315
|
+
|
|
316
|
+
[super updateProps:props oldProps:oldProps];
|
|
317
|
+
|
|
318
|
+
// Update measurements when props change that affect layout
|
|
319
|
+
[self updateMeasurements];
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
- (void)prepareForRecycle {
|
|
323
|
+
[super prepareForRecycle];
|
|
324
|
+
[_view resetForRecycle];
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
#pragma mark - Commands
|
|
328
|
+
|
|
329
|
+
- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args {
|
|
330
|
+
RCTPCTextFieldHandleCommand(self, commandName, args);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
- (void)focus {
|
|
334
|
+
[_view focus];
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
- (void)blur {
|
|
338
|
+
[_view blur];
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
- (void)clear {
|
|
342
|
+
[_view clear];
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
- (void)setText:(NSInteger)eventCount text:(NSString *)text {
|
|
346
|
+
[_view setText:text ?: @"" eventCount:eventCount];
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
#pragma mark - State (Measuring)
|
|
350
|
+
|
|
351
|
+
- (void)updateState:(const State::Shared &)state
|
|
352
|
+
oldState:(const State::Shared &)oldState {
|
|
353
|
+
_state = std::static_pointer_cast<const MeasuringPCTextFieldShadowNode::ConcreteState>(state);
|
|
354
|
+
|
|
355
|
+
if (oldState == nullptr) {
|
|
356
|
+
// First time: compute initial size.
|
|
357
|
+
[self updateMeasurements];
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
[super updateState:state oldState:oldState];
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
- (void)updateLayoutMetrics:(const LayoutMetrics &)layoutMetrics
|
|
364
|
+
oldLayoutMetrics:(const LayoutMetrics &)oldLayoutMetrics {
|
|
365
|
+
[super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
|
|
366
|
+
// A new width changes how multi-line text and supporting text wrap
|
|
367
|
+
if (layoutMetrics.frame.size.width != oldLayoutMetrics.frame.size.width) {
|
|
368
|
+
[self updateMeasurements];
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
- (void)updateMeasurements {
|
|
373
|
+
if (_state == nullptr)
|
|
374
|
+
return;
|
|
375
|
+
|
|
376
|
+
// The height the field needs at its current width; the width itself is
|
|
377
|
+
// whatever Yoga offers (see the shadow node).
|
|
378
|
+
CGSize size = [_view sizeForLayoutWithConstrainedTo:CGSizeMake(self.bounds.size.width, 0)];
|
|
379
|
+
|
|
380
|
+
PCTextFieldStateFrameSize next;
|
|
381
|
+
next.frameSize = {(Float)size.width, (Float)size.height};
|
|
382
|
+
if (_state->getData() != next) {
|
|
383
|
+
_state->updateState(std::move(next));
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
@end
|
|
388
|
+
|
|
389
|
+
Class<RCTComponentViewProtocol> PCTextFieldCls(void) {
|
|
390
|
+
return PCTextField.class;
|
|
391
|
+
}
|