react-native-platform-components 1.4.0 → 1.6.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/PlatformComponents.podspec +1 -1
- package/README.md +33 -31
- package/android/src/main/java/com/platformcomponents/PCButtonGroupView.kt +175 -9
- package/android/src/main/java/com/platformcomponents/PCButtonGroupViewManager.kt +52 -2
- package/android/src/main/java/com/platformcomponents/PCButtonSupport.kt +44 -12
- package/android/src/main/java/com/platformcomponents/PCButtonView.kt +187 -5
- package/android/src/main/java/com/platformcomponents/PCButtonViewManager.kt +85 -7
- package/android/src/main/java/com/platformcomponents/PCContextMenuView.kt +41 -151
- package/android/src/main/java/com/platformcomponents/PCContextMenuViewManager.kt +7 -63
- package/android/src/main/java/com/platformcomponents/PCDatePickerView.kt +310 -115
- package/android/src/main/java/com/platformcomponents/PCDatePickerViewManager.kt +23 -3
- package/android/src/main/java/com/platformcomponents/PCExpressive.kt +6 -1
- package/android/src/main/java/com/platformcomponents/PCFloatingActionButtonView.kt +485 -0
- package/android/src/main/java/com/platformcomponents/PCFloatingActionButtonViewManager.kt +109 -0
- package/android/src/main/java/com/platformcomponents/PCFloatingToolbarView.kt +132 -0
- package/android/src/main/java/com/platformcomponents/PCFloatingToolbarViewManager.kt +8 -0
- package/android/src/main/java/com/platformcomponents/PCHaptics.kt +46 -0
- package/android/src/main/java/com/platformcomponents/PCImageLoader.kt +42 -7
- package/android/src/main/java/com/platformcomponents/PCLiquidGlassContainerView.kt +32 -0
- package/android/src/main/java/com/platformcomponents/PCLiquidGlassContainerViewManager.kt +31 -0
- package/android/src/main/java/com/platformcomponents/PCLiquidGlassView.kt +32 -6
- package/android/src/main/java/com/platformcomponents/PCLiquidGlassViewManager.kt +4 -0
- package/android/src/main/java/com/platformcomponents/PCMenuSupport.kt +280 -0
- package/android/src/main/java/com/platformcomponents/PCNavigationBarSupport.kt +332 -0
- package/android/src/main/java/com/platformcomponents/PCNavigationRailView.kt +448 -0
- package/android/src/main/java/com/platformcomponents/PCNavigationRailViewManager.kt +176 -0
- package/android/src/main/java/com/platformcomponents/PCSegmentedControlView.kt +24 -14
- package/android/src/main/java/com/platformcomponents/PCSegmentedControlViewManager.kt +14 -2
- package/android/src/main/java/com/platformcomponents/PCSelectionMenuView.kt +371 -39
- package/android/src/main/java/com/platformcomponents/PCSelectionMenuViewManager.kt +18 -4
- package/android/src/main/java/com/platformcomponents/PCTabBarView.kt +397 -0
- package/android/src/main/java/com/platformcomponents/PCTabBarViewManager.kt +182 -0
- package/android/src/main/java/com/platformcomponents/PCTextFieldView.kt +415 -40
- package/android/src/main/java/com/platformcomponents/PCTextFieldViewManager.kt +109 -3
- package/android/src/main/java/com/platformcomponents/PCThemeSupport.kt +37 -0
- package/android/src/main/java/com/platformcomponents/PlatformComponentsPackage.kt +4 -0
- package/android/src/main/res/drawable/pc_ic_search.xml +12 -0
- package/android/src/main/res/values/ids.xml +5 -0
- package/android/src/main/res/values/styles.xml +24 -0
- package/ios/PCButton.mm +122 -7
- package/ios/PCButtonGroup.mm +68 -1
- package/ios/PCButtonGroupView.swift +225 -6
- package/ios/PCButtonSupport.swift +181 -10
- package/ios/PCButtonView.swift +297 -14
- package/ios/PCConstants.swift +23 -2
- package/ios/PCContextMenu.mm +28 -110
- package/ios/PCContextMenu.swift +106 -167
- package/ios/PCDatePicker.mm +21 -9
- package/ios/PCDatePickerView.swift +94 -20
- package/ios/PCFloatingActionButton.h +10 -0
- package/ios/PCFloatingActionButton.mm +177 -0
- package/ios/PCFloatingActionButtonView.swift +426 -0
- package/ios/PCFloatingToolbar.mm +27 -0
- package/ios/PCFloatingToolbarView.swift +241 -0
- package/ios/PCHaptics.swift +91 -0
- package/ios/PCImageLoader.swift +76 -12
- package/ios/PCLiquidGlass.mm +36 -0
- package/ios/PCLiquidGlass.swift +221 -114
- package/ios/PCLiquidGlassContainer.h +10 -0
- package/ios/PCLiquidGlassContainer.mm +84 -0
- package/ios/PCLiquidGlassContainer.swift +69 -0
- package/ios/PCMenuItems.h +76 -0
- package/ios/PCMenuSupport.swift +350 -0
- package/ios/PCNavigationRail.h +10 -0
- package/ios/PCNavigationRail.mm +270 -0
- package/ios/PCNavigationRailView.swift +415 -0
- package/ios/PCSegmentedControl.mm +17 -2
- package/ios/PCSegmentedControl.swift +57 -7
- package/ios/PCSelectionMenu.mm +36 -8
- package/ios/PCSelectionMenu.swift +224 -48
- package/ios/PCTabBar.h +10 -0
- package/ios/PCTabBar.mm +285 -0
- package/ios/PCTabBarAccessory.h +10 -0
- package/ios/PCTabBarAccessory.mm +93 -0
- package/ios/PCTabBarAccessoryView.swift +96 -0
- package/ios/PCTabBarView.swift +671 -0
- package/ios/PCTextField.mm +159 -4
- package/ios/PCTextFieldView.swift +603 -57
- package/lib/commonjs/Button.js +73 -1
- package/lib/commonjs/Button.js.map +1 -1
- package/lib/commonjs/ButtonGroup.js +13 -3
- package/lib/commonjs/ButtonGroup.js.map +1 -1
- package/lib/commonjs/ButtonGroupNativeComponent.ts +74 -4
- package/lib/commonjs/ButtonNativeComponent.ts +119 -3
- package/lib/commonjs/ContextMenu.js +9 -48
- package/lib/commonjs/ContextMenu.js.map +1 -1
- package/lib/commonjs/ContextMenuNativeComponent.ts +47 -49
- package/lib/commonjs/DatePicker.js +98 -2
- package/lib/commonjs/DatePicker.js.map +1 -1
- package/lib/commonjs/DatePickerNativeComponent.ts +19 -2
- package/lib/commonjs/FloatingActionButton.js +60 -0
- package/lib/commonjs/FloatingActionButton.js.map +1 -0
- package/lib/commonjs/FloatingActionButtonNativeComponent.ts +58 -0
- package/lib/commonjs/FloatingToolbar.js +9 -1
- package/lib/commonjs/FloatingToolbar.js.map +1 -1
- package/lib/commonjs/FloatingToolbarNativeComponent.ts +16 -0
- package/lib/commonjs/LiquidGlass.js +7 -1
- package/lib/commonjs/LiquidGlass.js.map +1 -1
- package/lib/commonjs/LiquidGlassContainer.js +32 -0
- package/lib/commonjs/LiquidGlassContainer.js.map +1 -0
- package/lib/commonjs/LiquidGlassContainerNativeComponent.ts +17 -0
- package/lib/commonjs/LiquidGlassNativeComponent.ts +8 -0
- package/lib/commonjs/NavigationRail.js +104 -0
- package/lib/commonjs/NavigationRail.js.map +1 -0
- package/lib/commonjs/NavigationRailNativeComponent.ts +107 -0
- package/lib/commonjs/PlatformComponentsProvider.js +18 -0
- package/lib/commonjs/PlatformComponentsProvider.js.map +1 -0
- package/lib/commonjs/SegmentedControl.js +7 -0
- package/lib/commonjs/SegmentedControl.js.map +1 -1
- package/lib/commonjs/SegmentedControlNativeComponent.ts +11 -0
- package/lib/commonjs/SelectionMenu.js +27 -3
- package/lib/commonjs/SelectionMenu.js.map +1 -1
- package/lib/commonjs/SelectionMenuNativeComponent.ts +26 -4
- package/lib/commonjs/SplitButton.js +98 -0
- package/lib/commonjs/SplitButton.js.map +1 -0
- package/lib/commonjs/TabBar.js +203 -0
- package/lib/commonjs/TabBar.js.map +1 -0
- package/lib/commonjs/TabBarAccessoryNativeComponent.ts +19 -0
- package/lib/commonjs/TabBarNativeComponent.ts +145 -0
- package/lib/commonjs/TextField.js +171 -8
- package/lib/commonjs/TextField.js.map +1 -1
- package/lib/commonjs/TextFieldNativeComponent.ts +110 -4
- package/lib/commonjs/focusRegistry.js +2 -1
- package/lib/commonjs/focusRegistry.js.map +1 -1
- package/lib/commonjs/haptics.js +2 -0
- package/lib/commonjs/haptics.js.map +1 -0
- package/lib/commonjs/icons.js +15 -1
- package/lib/commonjs/icons.js.map +1 -1
- package/lib/commonjs/index.js +77 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +156 -92
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/jest.js +910 -0
- package/lib/commonjs/jest.js.map +1 -0
- package/lib/commonjs/menuItems.js +68 -0
- package/lib/commonjs/menuItems.js.map +1 -0
- package/lib/commonjs/selectionIdentifiers.js +18 -0
- package/lib/commonjs/selectionIdentifiers.js.map +1 -0
- package/lib/commonjs/submitBehavior.js +19 -0
- package/lib/commonjs/submitBehavior.js.map +1 -0
- package/lib/commonjs/tabItems.js +49 -0
- package/lib/commonjs/tabItems.js.map +1 -0
- package/lib/commonjs/web/Button.js +170 -0
- package/lib/commonjs/web/Button.js.map +1 -0
- package/lib/commonjs/web/ButtonGroup.js +119 -0
- package/lib/commonjs/web/ButtonGroup.js.map +1 -0
- package/lib/commonjs/web/DatePicker.js +168 -0
- package/lib/commonjs/web/DatePicker.js.map +1 -0
- package/lib/commonjs/web/DateRangePicker.js +137 -0
- package/lib/commonjs/web/DateRangePicker.js.map +1 -0
- package/lib/commonjs/web/Dialog.js +54 -0
- package/lib/commonjs/web/Dialog.js.map +1 -0
- package/lib/commonjs/web/FloatingActionButton.js +98 -0
- package/lib/commonjs/web/FloatingActionButton.js.map +1 -0
- package/lib/commonjs/web/Icon.js +34 -0
- package/lib/commonjs/web/Icon.js.map +1 -0
- package/lib/commonjs/web/NativeTheme.js +28 -0
- package/lib/commonjs/web/NativeTheme.js.map +1 -0
- package/lib/commonjs/web/NavigationRail.js +139 -0
- package/lib/commonjs/web/NavigationRail.js.map +1 -0
- package/lib/commonjs/web/PlatformComponentsProvider.js +51 -0
- package/lib/commonjs/web/PlatformComponentsProvider.js.map +1 -0
- package/lib/commonjs/web/SegmentedControl.js +117 -0
- package/lib/commonjs/web/SegmentedControl.js.map +1 -0
- package/lib/commonjs/web/SelectionMenu.js +142 -0
- package/lib/commonjs/web/SelectionMenu.js.map +1 -0
- package/lib/commonjs/web/SplitButton.js +35 -0
- package/lib/commonjs/web/SplitButton.js.map +1 -0
- package/lib/commonjs/web/TabBar.js +131 -0
- package/lib/commonjs/web/TabBar.js.map +1 -0
- package/lib/commonjs/web/TextField.js +322 -0
- package/lib/commonjs/web/TextField.js.map +1 -0
- package/lib/commonjs/web/components.js +36 -0
- package/lib/commonjs/web/components.js.map +1 -0
- package/lib/commonjs/web/containers.js +121 -0
- package/lib/commonjs/web/containers.js.map +1 -0
- package/lib/commonjs/web/dateInput.js +116 -0
- package/lib/commonjs/web/dateInput.js.map +1 -0
- package/lib/commonjs/web/shared.js +192 -0
- package/lib/commonjs/web/shared.js.map +1 -0
- package/lib/commonjs/webComponents.js +6 -0
- package/lib/commonjs/webComponents.js.map +1 -0
- package/lib/module/Button.js +74 -2
- package/lib/module/Button.js.map +1 -1
- package/lib/module/ButtonGroup.js +13 -3
- package/lib/module/ButtonGroup.js.map +1 -1
- package/lib/module/ButtonGroupNativeComponent.ts +74 -4
- package/lib/module/ButtonNativeComponent.ts +119 -3
- package/lib/module/ContextMenu.js +9 -48
- package/lib/module/ContextMenu.js.map +1 -1
- package/lib/module/ContextMenuNativeComponent.ts +47 -49
- package/lib/module/DatePicker.js +98 -4
- package/lib/module/DatePicker.js.map +1 -1
- package/lib/module/DatePickerNativeComponent.ts +19 -2
- package/lib/module/FloatingActionButton.js +53 -0
- package/lib/module/FloatingActionButton.js.map +1 -0
- package/lib/module/FloatingActionButtonNativeComponent.ts +58 -0
- package/lib/module/FloatingToolbar.js +9 -1
- package/lib/module/FloatingToolbar.js.map +1 -1
- package/lib/module/FloatingToolbarNativeComponent.ts +16 -0
- package/lib/module/LiquidGlass.js +7 -1
- package/lib/module/LiquidGlass.js.map +1 -1
- package/lib/module/LiquidGlassContainer.js +26 -0
- package/lib/module/LiquidGlassContainer.js.map +1 -0
- package/lib/module/LiquidGlassContainerNativeComponent.ts +17 -0
- package/lib/module/LiquidGlassNativeComponent.ts +8 -0
- package/lib/module/NavigationRail.js +99 -0
- package/lib/module/NavigationRail.js.map +1 -0
- package/lib/module/NavigationRailNativeComponent.ts +107 -0
- package/lib/module/PlatformComponentsProvider.js +13 -0
- package/lib/module/PlatformComponentsProvider.js.map +1 -0
- package/lib/module/SegmentedControl.js +9 -1
- package/lib/module/SegmentedControl.js.map +1 -1
- package/lib/module/SegmentedControlNativeComponent.ts +11 -0
- package/lib/module/SelectionMenu.js +27 -3
- package/lib/module/SelectionMenu.js.map +1 -1
- package/lib/module/SelectionMenuNativeComponent.ts +26 -4
- package/lib/module/SplitButton.js +91 -0
- package/lib/module/SplitButton.js.map +1 -0
- package/lib/module/TabBar.js +196 -0
- package/lib/module/TabBar.js.map +1 -0
- package/lib/module/TabBarAccessoryNativeComponent.ts +19 -0
- package/lib/module/TabBarNativeComponent.ts +145 -0
- package/lib/module/TextField.js +172 -9
- package/lib/module/TextField.js.map +1 -1
- package/lib/module/TextFieldNativeComponent.ts +110 -4
- package/lib/module/focusRegistry.js +1 -0
- package/lib/module/focusRegistry.js.map +1 -1
- package/lib/module/haptics.js +2 -0
- package/lib/module/haptics.js.map +1 -0
- package/lib/module/icons.js +15 -1
- package/lib/module/icons.js.map +1 -1
- package/lib/module/index.js +7 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +12 -87
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/jest.js +840 -0
- package/lib/module/jest.js.map +1 -0
- package/lib/module/menuItems.js +65 -0
- package/lib/module/menuItems.js.map +1 -0
- package/lib/module/selectionIdentifiers.js +14 -0
- package/lib/module/selectionIdentifiers.js.map +1 -0
- package/lib/module/submitBehavior.js +15 -0
- package/lib/module/submitBehavior.js.map +1 -0
- package/lib/module/tabItems.js +45 -0
- package/lib/module/tabItems.js.map +1 -0
- package/lib/module/web/Button.js +164 -0
- package/lib/module/web/Button.js.map +1 -0
- package/lib/module/web/ButtonGroup.js +113 -0
- package/lib/module/web/ButtonGroup.js.map +1 -0
- package/lib/module/web/DatePicker.js +162 -0
- package/lib/module/web/DatePicker.js.map +1 -0
- package/lib/module/web/DateRangePicker.js +131 -0
- package/lib/module/web/DateRangePicker.js.map +1 -0
- package/lib/module/web/Dialog.js +48 -0
- package/lib/module/web/Dialog.js.map +1 -0
- package/lib/module/web/FloatingActionButton.js +94 -0
- package/lib/module/web/FloatingActionButton.js.map +1 -0
- package/lib/module/web/Icon.js +29 -0
- package/lib/module/web/Icon.js.map +1 -0
- package/lib/module/web/NativeTheme.js +23 -0
- package/lib/module/web/NativeTheme.js.map +1 -0
- package/lib/module/web/NavigationRail.js +133 -0
- package/lib/module/web/NavigationRail.js.map +1 -0
- package/lib/module/web/PlatformComponentsProvider.js +44 -0
- package/lib/module/web/PlatformComponentsProvider.js.map +1 -0
- package/lib/module/web/SegmentedControl.js +112 -0
- package/lib/module/web/SegmentedControl.js.map +1 -0
- package/lib/module/web/SelectionMenu.js +137 -0
- package/lib/module/web/SelectionMenu.js.map +1 -0
- package/lib/module/web/SplitButton.js +30 -0
- package/lib/module/web/SplitButton.js.map +1 -0
- package/lib/module/web/TabBar.js +126 -0
- package/lib/module/web/TabBar.js.map +1 -0
- package/lib/module/web/TextField.js +316 -0
- package/lib/module/web/TextField.js.map +1 -0
- package/lib/module/web/components.js +33 -0
- package/lib/module/web/components.js.map +1 -0
- package/lib/module/web/containers.js +112 -0
- package/lib/module/web/containers.js.map +1 -0
- package/lib/module/web/dateInput.js +109 -0
- package/lib/module/web/dateInput.js.map +1 -0
- package/lib/module/web/shared.js +179 -0
- package/lib/module/web/shared.js.map +1 -0
- package/lib/module/webComponents.js +4 -0
- package/lib/module/webComponents.js.map +1 -0
- package/lib/typescript/commonjs/docs/sidebars.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/Button.d.ts +111 -3
- package/lib/typescript/commonjs/src/Button.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/ButtonGroup.d.ts +21 -6
- package/lib/typescript/commonjs/src/ButtonGroup.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/ButtonGroupNativeComponent.d.ts +64 -3
- package/lib/typescript/commonjs/src/ButtonGroupNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/ButtonNativeComponent.d.ts +94 -3
- package/lib/typescript/commonjs/src/ButtonNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/ContextMenu.d.ts +20 -33
- package/lib/typescript/commonjs/src/ContextMenu.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/ContextMenuNativeComponent.d.ts +45 -47
- package/lib/typescript/commonjs/src/ContextMenuNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/DatePicker.d.ts +74 -1
- package/lib/typescript/commonjs/src/DatePicker.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/DatePickerNativeComponent.d.ts +16 -1
- package/lib/typescript/commonjs/src/DatePickerNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/FloatingActionButton.d.ts +67 -0
- package/lib/typescript/commonjs/src/FloatingActionButton.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/FloatingActionButtonNativeComponent.d.ts +43 -0
- package/lib/typescript/commonjs/src/FloatingActionButtonNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/FloatingToolbar.d.ts +30 -0
- package/lib/typescript/commonjs/src/FloatingToolbar.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/FloatingToolbarNativeComponent.d.ts +12 -0
- package/lib/typescript/commonjs/src/FloatingToolbarNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/LiquidGlass.d.ts +17 -0
- package/lib/typescript/commonjs/src/LiquidGlass.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/LiquidGlassContainer.d.ts +27 -0
- package/lib/typescript/commonjs/src/LiquidGlassContainer.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/LiquidGlassContainerNativeComponent.d.ts +13 -0
- package/lib/typescript/commonjs/src/LiquidGlassContainerNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/LiquidGlassNativeComponent.d.ts +7 -0
- package/lib/typescript/commonjs/src/LiquidGlassNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/NavigationRail.d.ts +86 -0
- package/lib/typescript/commonjs/src/NavigationRail.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/NavigationRailNativeComponent.d.ts +81 -0
- package/lib/typescript/commonjs/src/NavigationRailNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/PlatformComponentsProvider.d.ts +6 -0
- package/lib/typescript/commonjs/src/PlatformComponentsProvider.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/SegmentedControl.d.ts +18 -1
- package/lib/typescript/commonjs/src/SegmentedControl.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/SegmentedControlNativeComponent.d.ts +9 -0
- package/lib/typescript/commonjs/src/SegmentedControlNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/SelectionMenu.d.ts +44 -2
- package/lib/typescript/commonjs/src/SelectionMenu.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/SelectionMenuNativeComponent.d.ts +20 -4
- package/lib/typescript/commonjs/src/SelectionMenuNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/SplitButton.d.ts +83 -0
- package/lib/typescript/commonjs/src/SplitButton.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/TabBar.d.ts +144 -0
- package/lib/typescript/commonjs/src/TabBar.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/TabBarAccessoryNativeComponent.d.ts +13 -0
- package/lib/typescript/commonjs/src/TabBarAccessoryNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/TabBarNativeComponent.d.ts +110 -0
- package/lib/typescript/commonjs/src/TabBarNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/TextField.d.ts +166 -8
- package/lib/typescript/commonjs/src/TextField.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/TextFieldNativeComponent.d.ts +81 -3
- package/lib/typescript/commonjs/src/TextFieldNativeComponent.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/focusRegistry.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/haptics.d.ts +20 -0
- package/lib/typescript/commonjs/src/haptics.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/icons.d.ts +7 -1
- package/lib/typescript/commonjs/src/icons.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/index.d.ts +7 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/index.web.d.ts +25 -254
- package/lib/typescript/commonjs/src/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/jest.d.ts +139 -0
- package/lib/typescript/commonjs/src/jest.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/menuItems.d.ts +100 -0
- package/lib/typescript/commonjs/src/menuItems.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/selectionIdentifiers.d.ts +3 -0
- package/lib/typescript/commonjs/src/selectionIdentifiers.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/submitBehavior.d.ts +9 -0
- package/lib/typescript/commonjs/src/submitBehavior.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/tabItems.d.ts +55 -0
- package/lib/typescript/commonjs/src/tabItems.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/Button.d.ts +9 -0
- package/lib/typescript/commonjs/src/web/Button.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/ButtonGroup.d.ts +11 -0
- package/lib/typescript/commonjs/src/web/ButtonGroup.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/DatePicker.d.ts +14 -0
- package/lib/typescript/commonjs/src/web/DatePicker.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/DateRangePicker.d.ts +11 -0
- package/lib/typescript/commonjs/src/web/DateRangePicker.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/Dialog.d.ts +12 -0
- package/lib/typescript/commonjs/src/web/Dialog.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/FloatingActionButton.d.ts +8 -0
- package/lib/typescript/commonjs/src/web/FloatingActionButton.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/Icon.d.ts +12 -0
- package/lib/typescript/commonjs/src/web/Icon.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/NativeTheme.d.ts +10 -0
- package/lib/typescript/commonjs/src/web/NativeTheme.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/NavigationRail.d.ts +8 -0
- package/lib/typescript/commonjs/src/web/NavigationRail.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/PlatformComponentsProvider.d.ts +10 -0
- package/lib/typescript/commonjs/src/web/PlatformComponentsProvider.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/SegmentedControl.d.ts +8 -0
- package/lib/typescript/commonjs/src/web/SegmentedControl.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/SelectionMenu.d.ts +10 -0
- package/lib/typescript/commonjs/src/web/SelectionMenu.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/SplitButton.d.ts +9 -0
- package/lib/typescript/commonjs/src/web/SplitButton.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/TabBar.d.ts +9 -0
- package/lib/typescript/commonjs/src/web/TabBar.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/TextField.d.ts +9 -0
- package/lib/typescript/commonjs/src/web/TextField.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/components.d.ts +17 -0
- package/lib/typescript/commonjs/src/web/components.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/containers.d.ts +24 -0
- package/lib/typescript/commonjs/src/web/containers.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/dateInput.d.ts +20 -0
- package/lib/typescript/commonjs/src/web/dateInput.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/web/shared.d.ts +43 -0
- package/lib/typescript/commonjs/src/web/shared.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/webComponents.d.ts +43 -0
- package/lib/typescript/commonjs/src/webComponents.d.ts.map +1 -0
- package/lib/typescript/module/docs/sidebars.d.ts.map +1 -1
- package/lib/typescript/module/src/Button.d.ts +111 -3
- package/lib/typescript/module/src/Button.d.ts.map +1 -1
- package/lib/typescript/module/src/ButtonGroup.d.ts +21 -6
- package/lib/typescript/module/src/ButtonGroup.d.ts.map +1 -1
- package/lib/typescript/module/src/ButtonGroupNativeComponent.d.ts +64 -3
- package/lib/typescript/module/src/ButtonGroupNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/ButtonNativeComponent.d.ts +94 -3
- package/lib/typescript/module/src/ButtonNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/ContextMenu.d.ts +20 -33
- package/lib/typescript/module/src/ContextMenu.d.ts.map +1 -1
- package/lib/typescript/module/src/ContextMenuNativeComponent.d.ts +45 -47
- package/lib/typescript/module/src/ContextMenuNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/DatePicker.d.ts +74 -1
- package/lib/typescript/module/src/DatePicker.d.ts.map +1 -1
- package/lib/typescript/module/src/DatePickerNativeComponent.d.ts +16 -1
- package/lib/typescript/module/src/DatePickerNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/FloatingActionButton.d.ts +67 -0
- package/lib/typescript/module/src/FloatingActionButton.d.ts.map +1 -0
- package/lib/typescript/module/src/FloatingActionButtonNativeComponent.d.ts +43 -0
- package/lib/typescript/module/src/FloatingActionButtonNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/FloatingToolbar.d.ts +30 -0
- package/lib/typescript/module/src/FloatingToolbar.d.ts.map +1 -1
- package/lib/typescript/module/src/FloatingToolbarNativeComponent.d.ts +12 -0
- package/lib/typescript/module/src/FloatingToolbarNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/LiquidGlass.d.ts +17 -0
- package/lib/typescript/module/src/LiquidGlass.d.ts.map +1 -1
- package/lib/typescript/module/src/LiquidGlassContainer.d.ts +27 -0
- package/lib/typescript/module/src/LiquidGlassContainer.d.ts.map +1 -0
- package/lib/typescript/module/src/LiquidGlassContainerNativeComponent.d.ts +13 -0
- package/lib/typescript/module/src/LiquidGlassContainerNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/LiquidGlassNativeComponent.d.ts +7 -0
- package/lib/typescript/module/src/LiquidGlassNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/NavigationRail.d.ts +86 -0
- package/lib/typescript/module/src/NavigationRail.d.ts.map +1 -0
- package/lib/typescript/module/src/NavigationRailNativeComponent.d.ts +81 -0
- package/lib/typescript/module/src/NavigationRailNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/PlatformComponentsProvider.d.ts +6 -0
- package/lib/typescript/module/src/PlatformComponentsProvider.d.ts.map +1 -0
- package/lib/typescript/module/src/SegmentedControl.d.ts +18 -1
- package/lib/typescript/module/src/SegmentedControl.d.ts.map +1 -1
- package/lib/typescript/module/src/SegmentedControlNativeComponent.d.ts +9 -0
- package/lib/typescript/module/src/SegmentedControlNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/SelectionMenu.d.ts +44 -2
- package/lib/typescript/module/src/SelectionMenu.d.ts.map +1 -1
- package/lib/typescript/module/src/SelectionMenuNativeComponent.d.ts +20 -4
- package/lib/typescript/module/src/SelectionMenuNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/SplitButton.d.ts +83 -0
- package/lib/typescript/module/src/SplitButton.d.ts.map +1 -0
- package/lib/typescript/module/src/TabBar.d.ts +144 -0
- package/lib/typescript/module/src/TabBar.d.ts.map +1 -0
- package/lib/typescript/module/src/TabBarAccessoryNativeComponent.d.ts +13 -0
- package/lib/typescript/module/src/TabBarAccessoryNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/TabBarNativeComponent.d.ts +110 -0
- package/lib/typescript/module/src/TabBarNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/TextField.d.ts +166 -8
- package/lib/typescript/module/src/TextField.d.ts.map +1 -1
- package/lib/typescript/module/src/TextFieldNativeComponent.d.ts +81 -3
- package/lib/typescript/module/src/TextFieldNativeComponent.d.ts.map +1 -1
- package/lib/typescript/module/src/focusRegistry.d.ts.map +1 -1
- package/lib/typescript/module/src/haptics.d.ts +20 -0
- package/lib/typescript/module/src/haptics.d.ts.map +1 -0
- package/lib/typescript/module/src/icons.d.ts +7 -1
- package/lib/typescript/module/src/icons.d.ts.map +1 -1
- package/lib/typescript/module/src/index.d.ts +7 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/index.web.d.ts +25 -254
- package/lib/typescript/module/src/index.web.d.ts.map +1 -1
- package/lib/typescript/module/src/jest.d.ts +139 -0
- package/lib/typescript/module/src/jest.d.ts.map +1 -0
- package/lib/typescript/module/src/menuItems.d.ts +100 -0
- package/lib/typescript/module/src/menuItems.d.ts.map +1 -0
- package/lib/typescript/module/src/selectionIdentifiers.d.ts +3 -0
- package/lib/typescript/module/src/selectionIdentifiers.d.ts.map +1 -0
- package/lib/typescript/module/src/submitBehavior.d.ts +9 -0
- package/lib/typescript/module/src/submitBehavior.d.ts.map +1 -0
- package/lib/typescript/module/src/tabItems.d.ts +55 -0
- package/lib/typescript/module/src/tabItems.d.ts.map +1 -0
- package/lib/typescript/module/src/web/Button.d.ts +9 -0
- package/lib/typescript/module/src/web/Button.d.ts.map +1 -0
- package/lib/typescript/module/src/web/ButtonGroup.d.ts +11 -0
- package/lib/typescript/module/src/web/ButtonGroup.d.ts.map +1 -0
- package/lib/typescript/module/src/web/DatePicker.d.ts +14 -0
- package/lib/typescript/module/src/web/DatePicker.d.ts.map +1 -0
- package/lib/typescript/module/src/web/DateRangePicker.d.ts +11 -0
- package/lib/typescript/module/src/web/DateRangePicker.d.ts.map +1 -0
- package/lib/typescript/module/src/web/Dialog.d.ts +12 -0
- package/lib/typescript/module/src/web/Dialog.d.ts.map +1 -0
- package/lib/typescript/module/src/web/FloatingActionButton.d.ts +8 -0
- package/lib/typescript/module/src/web/FloatingActionButton.d.ts.map +1 -0
- package/lib/typescript/module/src/web/Icon.d.ts +12 -0
- package/lib/typescript/module/src/web/Icon.d.ts.map +1 -0
- package/lib/typescript/module/src/web/NativeTheme.d.ts +10 -0
- package/lib/typescript/module/src/web/NativeTheme.d.ts.map +1 -0
- package/lib/typescript/module/src/web/NavigationRail.d.ts +8 -0
- package/lib/typescript/module/src/web/NavigationRail.d.ts.map +1 -0
- package/lib/typescript/module/src/web/PlatformComponentsProvider.d.ts +10 -0
- package/lib/typescript/module/src/web/PlatformComponentsProvider.d.ts.map +1 -0
- package/lib/typescript/module/src/web/SegmentedControl.d.ts +8 -0
- package/lib/typescript/module/src/web/SegmentedControl.d.ts.map +1 -0
- package/lib/typescript/module/src/web/SelectionMenu.d.ts +10 -0
- package/lib/typescript/module/src/web/SelectionMenu.d.ts.map +1 -0
- package/lib/typescript/module/src/web/SplitButton.d.ts +9 -0
- package/lib/typescript/module/src/web/SplitButton.d.ts.map +1 -0
- package/lib/typescript/module/src/web/TabBar.d.ts +9 -0
- package/lib/typescript/module/src/web/TabBar.d.ts.map +1 -0
- package/lib/typescript/module/src/web/TextField.d.ts +9 -0
- package/lib/typescript/module/src/web/TextField.d.ts.map +1 -0
- package/lib/typescript/module/src/web/components.d.ts +17 -0
- package/lib/typescript/module/src/web/components.d.ts.map +1 -0
- package/lib/typescript/module/src/web/containers.d.ts +24 -0
- package/lib/typescript/module/src/web/containers.d.ts.map +1 -0
- package/lib/typescript/module/src/web/dateInput.d.ts +20 -0
- package/lib/typescript/module/src/web/dateInput.d.ts.map +1 -0
- package/lib/typescript/module/src/web/shared.d.ts +43 -0
- package/lib/typescript/module/src/web/shared.d.ts.map +1 -0
- package/lib/typescript/module/src/webComponents.d.ts +43 -0
- package/lib/typescript/module/src/webComponents.d.ts.map +1 -0
- package/package.json +32 -2
- package/plugin/build/index.cjs +79 -6
- package/plugin/build/index.d.ts +27 -2
- package/plugin/build/index.d.ts.map +1 -1
- package/plugin/tsconfig.json +2 -1
- package/react-native.config.js +3 -0
- package/shared/PCFloatingActionButtonComponentDescriptors-custom.h +22 -0
- package/shared/PCFloatingActionButtonShadowNode-custom.cpp +48 -0
- package/shared/PCFloatingActionButtonShadowNode-custom.h +54 -0
- package/shared/PCFloatingActionButtonState-custom.h +61 -0
- package/shared/PCNavigationRailComponentDescriptors-custom.h +47 -0
- package/shared/PCNavigationRailShadowNode-custom.h +42 -0
- package/shared/PCNavigationRailState-custom.h +62 -0
- package/shared/PCTabBarComponentDescriptors-custom.h +22 -0
- package/shared/PCTabBarShadowNode-custom.cpp +54 -0
- package/shared/PCTabBarShadowNode-custom.h +54 -0
- package/shared/PCTabBarState-custom.h +62 -0
- package/shared/react/renderer/components/PlatformComponentsViewSpec/ComponentDescriptors.h +3 -0
- package/src/Button.tsx +222 -7
- package/src/ButtonGroup.tsx +29 -11
- package/src/ButtonGroupNativeComponent.ts +74 -4
- package/src/ButtonNativeComponent.ts +119 -3
- package/src/ContextMenu.tsx +34 -81
- package/src/ContextMenuNativeComponent.ts +47 -49
- package/src/DatePicker.tsx +182 -4
- package/src/DatePickerNativeComponent.ts +19 -2
- package/src/FloatingActionButton.tsx +121 -0
- package/src/FloatingActionButtonNativeComponent.ts +58 -0
- package/src/FloatingToolbar.tsx +54 -3
- package/src/FloatingToolbarNativeComponent.ts +16 -0
- package/src/LiquidGlass.tsx +24 -1
- package/src/LiquidGlassContainer.tsx +42 -0
- package/src/LiquidGlassContainerNativeComponent.ts +17 -0
- package/src/LiquidGlassNativeComponent.ts +8 -0
- package/src/NavigationRail.tsx +203 -0
- package/src/NavigationRailNativeComponent.ts +107 -0
- package/src/PlatformComponentsProvider.tsx +15 -0
- package/src/SegmentedControl.tsx +31 -1
- package/src/SegmentedControlNativeComponent.ts +11 -0
- package/src/SelectionMenu.tsx +81 -6
- package/src/SelectionMenuNativeComponent.ts +26 -4
- package/src/SplitButton.tsx +198 -0
- package/src/TabBar.tsx +373 -0
- package/src/TabBarAccessoryNativeComponent.ts +19 -0
- package/src/TabBarNativeComponent.ts +145 -0
- package/src/TextField.tsx +428 -14
- package/src/TextFieldNativeComponent.ts +110 -4
- package/src/focusRegistry.ts +1 -0
- package/src/haptics.ts +31 -0
- package/src/icons.ts +28 -1
- package/src/index.tsx +7 -0
- package/src/index.web.tsx +51 -391
- package/src/jest.tsx +958 -0
- package/src/menuItems.ts +152 -0
- package/src/selectionIdentifiers.ts +17 -0
- package/src/submitBehavior.ts +16 -0
- package/src/tabItems.ts +113 -0
- package/src/web/Button.tsx +201 -0
- package/src/web/ButtonGroup.tsx +154 -0
- package/src/web/DatePicker.tsx +204 -0
- package/src/web/DateRangePicker.tsx +135 -0
- package/src/web/Dialog.tsx +54 -0
- package/src/web/FloatingActionButton.tsx +76 -0
- package/src/web/Icon.tsx +33 -0
- package/src/web/NativeTheme.ts +23 -0
- package/src/web/NavigationRail.tsx +148 -0
- package/src/web/PlatformComponentsProvider.tsx +48 -0
- package/src/web/SegmentedControl.tsx +127 -0
- package/src/web/SelectionMenu.tsx +149 -0
- package/src/web/SplitButton.tsx +32 -0
- package/src/web/TabBar.tsx +150 -0
- package/src/web/TextField.tsx +361 -0
- package/src/web/components.tsx +71 -0
- package/src/web/containers.tsx +130 -0
- package/src/web/dateInput.ts +137 -0
- package/src/web/shared.ts +176 -0
- package/src/webComponents.ts +45 -0
- package/android/src/main/java/com/platformcomponents/DateConstraints.kt +0 -83
|
@@ -9,7 +9,7 @@ import UIKit
|
|
|
9
9
|
/// saw, and a push older than the latest edit is dropped so a slow JS
|
|
10
10
|
/// round-trip can't erase what was typed meanwhile.
|
|
11
11
|
@objcMembers
|
|
12
|
-
public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDelegate {
|
|
12
|
+
public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDelegate, UIGestureRecognizerDelegate {
|
|
13
13
|
// MARK: - Props (set from ObjC++)
|
|
14
14
|
|
|
15
15
|
public var label: String = "" {
|
|
@@ -83,6 +83,21 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
83
83
|
didSet { if oldValue != multiline { rebuildInput() } }
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
/// What the return key does: "submit" | "blurAndSubmit" | "newline";
|
|
87
|
+
/// "" keeps the defaults (a newline in multi-line fields, else blur and submit)
|
|
88
|
+
public var submitBehavior: String = ""
|
|
89
|
+
|
|
90
|
+
/// UITextInputPasswordRules descriptor; "" = none
|
|
91
|
+
public var passwordRules: String = "" {
|
|
92
|
+
didSet { if oldValue != passwordRules { applyTraits() } }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/// The keyboard toolbar's items (kind, itemId, title, systemItem, icon
|
|
96
|
+
/// fields, prominent, accessibilityLabel, testID); empty = no toolbar
|
|
97
|
+
public var keyboardToolbarItems: [NSDictionary] = [] {
|
|
98
|
+
didSet { if oldValue != keyboardToolbarItems { applyKeyboardToolbar() } }
|
|
99
|
+
}
|
|
100
|
+
|
|
86
101
|
/// "enabled" | "disabled"
|
|
87
102
|
public var interactivity: String = "enabled" {
|
|
88
103
|
didSet { if oldValue != interactivity { applyEnabled() } }
|
|
@@ -155,7 +170,86 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
155
170
|
didSet { if oldValue != labelWidth { setNeedsLayout(); onNeedsRemeasure?() } }
|
|
156
171
|
}
|
|
157
172
|
|
|
173
|
+
/// Test id of the inner input, where E2E drivers type (see PCTextField.mm)
|
|
174
|
+
public var inputTestID: String = "" {
|
|
175
|
+
didSet { if oldValue != inputTestID { applyAccessibility() } }
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
public var leadingIconTestID: String = "" {
|
|
179
|
+
didSet { if oldValue != leadingIconTestID { applyAccessories() } }
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
public var leadingIconSpokenLabel: String = "" {
|
|
183
|
+
didSet { if oldValue != leadingIconSpokenLabel { applyAccessories() } }
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
public var trailingIconTestID: String = "" {
|
|
187
|
+
didSet { if oldValue != trailingIconTestID { applyAccessories() } }
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
public var trailingIconSpokenLabel: String = "" {
|
|
191
|
+
didSet { if oldValue != trailingIconSpokenLabel { applyAccessories() } }
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Colors; nil keeps the system color
|
|
195
|
+
public var activeColor: UIColor? {
|
|
196
|
+
didSet { if oldValue != activeColor { applyBorderStyle(); applyColors() } }
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
public var outlineColor: UIColor? {
|
|
200
|
+
didSet { if oldValue != outlineColor { applyBorderStyle(); applyColors() } }
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
public var errorColor: UIColor? {
|
|
204
|
+
didSet { if oldValue != errorColor { applyColors() } }
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
public var containerColor: UIColor? {
|
|
208
|
+
didSet { if oldValue != containerColor { applyBorderStyle(); applyColors() } }
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
public var textColor: UIColor? {
|
|
212
|
+
didSet { if oldValue != textColor { applyColors() } }
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
public var placeholderTextColor: UIColor? {
|
|
216
|
+
didSet { if oldValue != placeholderTextColor { applyPlaceholder() } }
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/// Cap on the Dynamic Type scale of every text; values below 1 mean no cap
|
|
220
|
+
public var maxFontSizeMultiplier: CGFloat = 0 {
|
|
221
|
+
didSet { if oldValue != maxFontSizeMultiplier { applyFonts(); applyAccessories() } }
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/// "" | "left" | "center" | "right"
|
|
225
|
+
public var textAlign: String = "" {
|
|
226
|
+
didSet { if oldValue != textAlign { applyAlignment() } }
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/// Multi-line height bounds in lines; 0 = unset
|
|
230
|
+
public var minLines: Int = 0 {
|
|
231
|
+
didSet { if oldValue != minLines { setNeedsLayout(); onNeedsRemeasure?() } }
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
public var maxLines: Int = 0 {
|
|
235
|
+
didSet { if oldValue != maxLines { setNeedsLayout(); onNeedsRemeasure?() } }
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/// A non-editable field that reports presses, as a picker's anchor
|
|
239
|
+
public var pressable: Bool = false {
|
|
240
|
+
didSet { if oldValue != pressable { applyEnabled() } }
|
|
241
|
+
}
|
|
242
|
+
|
|
158
243
|
private var leadingLabel: Bool { labelPlacement == "leading" && !label.isEmpty }
|
|
244
|
+
|
|
245
|
+
/// Whether the field acts as a button: pressable and not editable
|
|
246
|
+
private var actsAsButton: Bool { pressable && interactivity == "disabled" }
|
|
247
|
+
|
|
248
|
+
/// The rounded rect drawn here instead of by UIKit, whose border can't be colored
|
|
249
|
+
private var drawsBox: Bool {
|
|
250
|
+
(borderStyle.isEmpty || borderStyle == "roundedRect")
|
|
251
|
+
&& (activeColor != nil || outlineColor != nil || containerColor != nil)
|
|
252
|
+
}
|
|
159
253
|
private var leadingColumnWidth: CGFloat { labelWidth > 0 ? labelWidth : 100 }
|
|
160
254
|
private let leadingSpacing: CGFloat = 8
|
|
161
255
|
|
|
@@ -164,7 +258,10 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
164
258
|
public var onChange: ((String, Int) -> Void)?
|
|
165
259
|
public var onFocusChange: ((Bool, String) -> Void)?
|
|
166
260
|
public var onSubmit: ((String) -> Void)?
|
|
261
|
+
public var onSelectionChange: ((Int, Int) -> Void)?
|
|
262
|
+
public var onKeyboardToolbarPress: ((String) -> Void)?
|
|
167
263
|
public var onTrailingIconPress: (() -> Void)?
|
|
264
|
+
public var onPress: (() -> Void)?
|
|
168
265
|
|
|
169
266
|
/// Called when content changed in a way that affects the height (a
|
|
170
267
|
/// multi-line edit, an error message appearing), so the Fabric
|
|
@@ -181,10 +278,19 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
181
278
|
/// Whether a secure field is currently showing its text (password toggle)
|
|
182
279
|
private var revealed = false
|
|
183
280
|
|
|
281
|
+
/// The selection JS last heard of, so a change is reported once. Changes
|
|
282
|
+
/// made from JS (text or selection) update it without an event.
|
|
283
|
+
private var lastReportedSelection = NSRange(location: NSNotFound, length: 0)
|
|
284
|
+
private var applyingFromJS = false
|
|
285
|
+
|
|
286
|
+
/// The toolbar above the keyboard, while there are toolbar items
|
|
287
|
+
private var keyboardToolbar: UIToolbar?
|
|
288
|
+
private var toolbarGeneration = 0
|
|
289
|
+
|
|
184
290
|
// MARK: - Subviews
|
|
185
291
|
|
|
186
292
|
private let captionLabel = UILabel()
|
|
187
|
-
private let textField =
|
|
293
|
+
private let textField = PCInputTextField()
|
|
188
294
|
private let textView = PCPlaceholderTextView()
|
|
189
295
|
private let footerLabel = UILabel()
|
|
190
296
|
private let counterLabel = UILabel()
|
|
@@ -193,7 +299,8 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
193
299
|
private var trailingIcon = PCButtonSupport.Icon.none
|
|
194
300
|
private var leadingImage: UIImage?
|
|
195
301
|
private var trailingImage: UIImage?
|
|
196
|
-
private var
|
|
302
|
+
private var leadingIconGeneration = 0
|
|
303
|
+
private var trailingIconGeneration = 0
|
|
197
304
|
|
|
198
305
|
// MARK: - Layout metrics
|
|
199
306
|
|
|
@@ -243,6 +350,14 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
243
350
|
addSubview(footerLabel)
|
|
244
351
|
addSubview(counterLabel)
|
|
245
352
|
|
|
353
|
+
// Presses of a field that acts as a button; accessory buttons keep their own
|
|
354
|
+
pressRecognizer.addTarget(self, action: #selector(handlePress))
|
|
355
|
+
pressRecognizer.delegate = self
|
|
356
|
+
pressRecognizer.isEnabled = false
|
|
357
|
+
addGestureRecognizer(pressRecognizer)
|
|
358
|
+
textField.onActivate = { [weak self] in self?.activateAsButton() ?? false }
|
|
359
|
+
textView.onActivate = { [weak self] in self?.activateAsButton() ?? false }
|
|
360
|
+
|
|
246
361
|
applyFonts()
|
|
247
362
|
applyColors()
|
|
248
363
|
applyBorderStyle()
|
|
@@ -252,6 +367,7 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
252
367
|
applyFooter()
|
|
253
368
|
applyAccessories()
|
|
254
369
|
applyAccessibility()
|
|
370
|
+
applyAlignment()
|
|
255
371
|
}
|
|
256
372
|
|
|
257
373
|
// MARK: - Text
|
|
@@ -279,6 +395,28 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
279
395
|
guard !text.isEmpty else { return }
|
|
280
396
|
setTextInternal("", moveCursorToEnd: true)
|
|
281
397
|
reportEdit()
|
|
398
|
+
lastReportedSelection = NSRange(location: NSNotFound, length: 0)
|
|
399
|
+
reportSelection()
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/// A selection from JS, in UTF-16 offsets clamped to the text. Dropped
|
|
403
|
+
/// like a stale `setText` when the user has edited since `eventCount`.
|
|
404
|
+
public func setSelection(start: Int, end: Int, eventCount: Int) {
|
|
405
|
+
guard eventCount >= nativeEventCount else { return }
|
|
406
|
+
guard activeInput.markedTextRange == nil else { return }
|
|
407
|
+
let length = (text as NSString).length
|
|
408
|
+
let from = min(max(0, start), length)
|
|
409
|
+
let to = min(max(from, end), length)
|
|
410
|
+
let range = NSRange(location: from, length: to - from)
|
|
411
|
+
applyingFromJS = true
|
|
412
|
+
if multiline {
|
|
413
|
+
textView.selectedRange = range
|
|
414
|
+
} else if let startPosition = textField.position(from: textField.beginningOfDocument, offset: from),
|
|
415
|
+
let endPosition = textField.position(from: startPosition, offset: to - from) {
|
|
416
|
+
textField.selectedTextRange = textField.textRange(from: startPosition, to: endPosition)
|
|
417
|
+
}
|
|
418
|
+
applyingFromJS = false
|
|
419
|
+
lastReportedSelection = currentSelection() ?? range
|
|
282
420
|
}
|
|
283
421
|
|
|
284
422
|
public func focus() {
|
|
@@ -289,28 +427,28 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
289
427
|
activeInput.resignFirstResponder()
|
|
290
428
|
}
|
|
291
429
|
|
|
292
|
-
public func setLeadingIcon(type: String, name: String, uri: String, scale: CGFloat, tinted: Bool) {
|
|
293
|
-
let next = PCButtonSupport.Icon(type: type, name: name, uri: uri, scale: scale, tinted: tinted)
|
|
430
|
+
public func setLeadingIcon(type: String, name: String, request: String, uri: String, scale: CGFloat, tinted: Bool) {
|
|
431
|
+
let next = PCButtonSupport.Icon(type: type, name: name, uri: uri, scale: scale, tinted: tinted, request: request)
|
|
294
432
|
guard next != leadingIcon else { return }
|
|
295
433
|
leadingIcon = next
|
|
296
|
-
|
|
297
|
-
let generation =
|
|
434
|
+
leadingIconGeneration += 1
|
|
435
|
+
let generation = leadingIconGeneration
|
|
298
436
|
leadingImage = PCButtonSupport.image(for: next) { [weak self] image in
|
|
299
|
-
guard let self, self.
|
|
437
|
+
guard let self, self.leadingIconGeneration == generation else { return }
|
|
300
438
|
self.leadingImage = image
|
|
301
439
|
self.applyAccessories()
|
|
302
440
|
}
|
|
303
441
|
applyAccessories()
|
|
304
442
|
}
|
|
305
443
|
|
|
306
|
-
public func setTrailingIcon(type: String, name: String, uri: String, scale: CGFloat, tinted: Bool) {
|
|
307
|
-
let next = PCButtonSupport.Icon(type: type, name: name, uri: uri, scale: scale, tinted: tinted)
|
|
444
|
+
public func setTrailingIcon(type: String, name: String, request: String, uri: String, scale: CGFloat, tinted: Bool) {
|
|
445
|
+
let next = PCButtonSupport.Icon(type: type, name: name, uri: uri, scale: scale, tinted: tinted, request: request)
|
|
308
446
|
guard next != trailingIcon else { return }
|
|
309
447
|
trailingIcon = next
|
|
310
|
-
|
|
311
|
-
let generation =
|
|
448
|
+
trailingIconGeneration += 1
|
|
449
|
+
let generation = trailingIconGeneration
|
|
312
450
|
trailingImage = PCButtonSupport.image(for: next) { [weak self] image in
|
|
313
|
-
guard let self, self.
|
|
451
|
+
guard let self, self.trailingIconGeneration == generation else { return }
|
|
314
452
|
self.trailingImage = image
|
|
315
453
|
self.applyAccessories()
|
|
316
454
|
}
|
|
@@ -320,11 +458,14 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
320
458
|
/// Resets the text state for a recycled view.
|
|
321
459
|
public func resetForRecycle() {
|
|
322
460
|
blur()
|
|
461
|
+
leadingIconGeneration += 1
|
|
462
|
+
trailingIconGeneration += 1
|
|
323
463
|
initialTextApplied = false
|
|
324
464
|
autoFocusDone = false
|
|
325
465
|
nativeEventCount = 0
|
|
326
466
|
revealed = false
|
|
327
467
|
setTextInternal("", moveCursorToEnd: true)
|
|
468
|
+
lastReportedSelection = NSRange(location: NSNotFound, length: 0)
|
|
328
469
|
}
|
|
329
470
|
|
|
330
471
|
private var activeInput: UIView & UITextInput {
|
|
@@ -332,6 +473,12 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
332
473
|
}
|
|
333
474
|
|
|
334
475
|
private func setTextInternal(_ value: String, moveCursorToEnd: Bool) {
|
|
476
|
+
// The cursor moves with the text; JS knows, so there is no event
|
|
477
|
+
applyingFromJS = true
|
|
478
|
+
defer {
|
|
479
|
+
applyingFromJS = false
|
|
480
|
+
lastReportedSelection = currentSelection() ?? lastReportedSelection
|
|
481
|
+
}
|
|
335
482
|
if multiline {
|
|
336
483
|
let wasAtEnd = textView.selectedRange.location == (textView.text as NSString).length
|
|
337
484
|
let cursor = textView.selectedRange.location
|
|
@@ -366,6 +513,31 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
366
513
|
onChange?(text, nativeEventCount)
|
|
367
514
|
}
|
|
368
515
|
|
|
516
|
+
/// The selection in UTF-16 offsets, as JS strings count them.
|
|
517
|
+
private func currentSelection() -> NSRange? {
|
|
518
|
+
if multiline { return textView.selectedRange }
|
|
519
|
+
guard let range = textField.selectedTextRange else { return nil }
|
|
520
|
+
let start = textField.offset(from: textField.beginningOfDocument, to: range.start)
|
|
521
|
+
let end = textField.offset(from: textField.beginningOfDocument, to: range.end)
|
|
522
|
+
return NSRange(location: start, length: max(0, end - start))
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
private func reportSelection() {
|
|
526
|
+
guard !applyingFromJS, let selection = currentSelection(), selection != lastReportedSelection else { return }
|
|
527
|
+
lastReportedSelection = selection
|
|
528
|
+
onSelectionChange?(selection.location, selection.location + selection.length)
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/// The return key: submits unless it inserts a newline, and blurs
|
|
532
|
+
/// unless submitBehavior is "submit". Returns whether it submitted.
|
|
533
|
+
private func handleReturn() -> Bool {
|
|
534
|
+
let behavior = submitBehavior.isEmpty ? (multiline ? "newline" : "blurAndSubmit") : submitBehavior
|
|
535
|
+
if multiline && behavior == "newline" { return false }
|
|
536
|
+
onSubmit?(text)
|
|
537
|
+
if behavior != "submit" { activeInput.resignFirstResponder() }
|
|
538
|
+
return true
|
|
539
|
+
}
|
|
540
|
+
|
|
369
541
|
// MARK: - UITextField
|
|
370
542
|
|
|
371
543
|
@objc private func fieldEditingChanged() {
|
|
@@ -387,17 +559,69 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
387
559
|
onFocusChange?(false, text)
|
|
388
560
|
}
|
|
389
561
|
|
|
562
|
+
public func textFieldShouldBeginEditing(_ field: UITextField) -> Bool {
|
|
563
|
+
!actsAsButton
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/// The clear button doesn't send .editingChanged on every iOS version;
|
|
567
|
+
/// report the cleared text once UIKit has applied it, unless it did.
|
|
568
|
+
public func textFieldShouldClear(_ field: UITextField) -> Bool {
|
|
569
|
+
DispatchQueue.main.async { [weak self] in
|
|
570
|
+
guard let self, (self.textField.text ?? "") != self.text else { return }
|
|
571
|
+
self.fieldEditingChanged()
|
|
572
|
+
}
|
|
573
|
+
return true
|
|
574
|
+
}
|
|
575
|
+
|
|
390
576
|
public func textFieldShouldReturn(_ field: UITextField) -> Bool {
|
|
391
|
-
|
|
392
|
-
//
|
|
393
|
-
|
|
577
|
+
// Single-line fields blur on submit unless submitBehavior is
|
|
578
|
+
// "submit", as the core TextInput does
|
|
579
|
+
_ = handleReturn()
|
|
394
580
|
return true
|
|
395
581
|
}
|
|
396
582
|
|
|
583
|
+
public func textFieldDidChangeSelection(_ field: UITextField) {
|
|
584
|
+
reportSelection()
|
|
585
|
+
}
|
|
586
|
+
|
|
397
587
|
public func textField(_ field: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
|
398
588
|
allowsChange(current: field.text ?? "", range: range, replacement: string, input: field)
|
|
399
589
|
}
|
|
400
590
|
|
|
591
|
+
// MARK: - Press (a field acting as a button)
|
|
592
|
+
|
|
593
|
+
private let pressRecognizer = UITapGestureRecognizer()
|
|
594
|
+
|
|
595
|
+
@objc private func handlePress() {
|
|
596
|
+
guard actsAsButton else { return }
|
|
597
|
+
// Brief highlight, as a plain UIButton gives
|
|
598
|
+
activeInput.alpha = 0.5
|
|
599
|
+
UIView.animate(withDuration: 0.25, delay: 0.05, options: [.allowUserInteraction]) {
|
|
600
|
+
self.activeInput.alpha = 1
|
|
601
|
+
}
|
|
602
|
+
onPress?()
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
private func activateAsButton() -> Bool {
|
|
606
|
+
guard actsAsButton else { return false }
|
|
607
|
+
onPress?()
|
|
608
|
+
return true
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
public func gestureRecognizer(_ recognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
|
|
612
|
+
// The trailing icon and the password toggle handle their own taps
|
|
613
|
+
!(touch.view is PCAccessoryButton)
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/// UITextField's own tap recognizers would otherwise take the tap (and
|
|
617
|
+
/// then find editing refused), leaving the press unreported
|
|
618
|
+
public func gestureRecognizer(
|
|
619
|
+
_ recognizer: UIGestureRecognizer,
|
|
620
|
+
shouldRecognizeSimultaneouslyWith other: UIGestureRecognizer
|
|
621
|
+
) -> Bool {
|
|
622
|
+
recognizer === pressRecognizer
|
|
623
|
+
}
|
|
624
|
+
|
|
401
625
|
// MARK: - UITextView
|
|
402
626
|
|
|
403
627
|
public func textViewDidChange(_ view: UITextView) {
|
|
@@ -422,7 +646,15 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
422
646
|
}
|
|
423
647
|
|
|
424
648
|
public func textView(_ view: UITextView, shouldChangeTextIn range: NSRange, replacementText string: String) -> Bool {
|
|
425
|
-
|
|
649
|
+
// Return submits instead of inserting a newline, unless submitBehavior is "newline"
|
|
650
|
+
if string == "\n", view.markedTextRange == nil, handleReturn() {
|
|
651
|
+
return false
|
|
652
|
+
}
|
|
653
|
+
return allowsChange(current: view.text ?? "", range: range, replacement: string, input: view)
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
public func textViewDidChangeSelection(_ view: UITextView) {
|
|
657
|
+
reportSelection()
|
|
426
658
|
}
|
|
427
659
|
|
|
428
660
|
/// Enforces `maxLength` in UTF-16 units, like the core TextInput and the
|
|
@@ -437,7 +669,15 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
437
669
|
// MARK: - Props handling
|
|
438
670
|
|
|
439
671
|
private func rebuildInput() {
|
|
440
|
-
|
|
672
|
+
// `multiline` already has its new value in didSet, so activeInput
|
|
673
|
+
// points to the replacement. Read focus and selection from the old input.
|
|
674
|
+
let previousInput: UIView & UITextInput = multiline ? textField : textView
|
|
675
|
+
let focused = previousInput.isFirstResponder
|
|
676
|
+
let selection = previousInput.selectedTextRange.map { range in
|
|
677
|
+
let start = previousInput.offset(from: previousInput.beginningOfDocument, to: range.start)
|
|
678
|
+
let end = previousInput.offset(from: previousInput.beginningOfDocument, to: range.end)
|
|
679
|
+
return NSRange(location: start, length: max(0, end - start))
|
|
680
|
+
}
|
|
441
681
|
textField.removeFromSuperview()
|
|
442
682
|
textView.removeFromSuperview()
|
|
443
683
|
if multiline {
|
|
@@ -456,7 +696,11 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
456
696
|
applyAccessories()
|
|
457
697
|
applyEnabled()
|
|
458
698
|
applyAccessibility()
|
|
699
|
+
applyAlignment()
|
|
459
700
|
if focused { activeInput.becomeFirstResponder() }
|
|
701
|
+
if let selection {
|
|
702
|
+
setSelection(start: selection.location, end: NSMaxRange(selection), eventCount: nativeEventCount)
|
|
703
|
+
}
|
|
460
704
|
setNeedsLayout()
|
|
461
705
|
onNeedsRemeasure?()
|
|
462
706
|
}
|
|
@@ -470,8 +714,18 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
470
714
|
}
|
|
471
715
|
|
|
472
716
|
private func applyPlaceholder() {
|
|
473
|
-
|
|
717
|
+
if placeholder.isEmpty {
|
|
718
|
+
textField.placeholder = nil
|
|
719
|
+
} else if let placeholderTextColor {
|
|
720
|
+
textField.attributedPlaceholder = NSAttributedString(
|
|
721
|
+
string: placeholder,
|
|
722
|
+
attributes: [.foregroundColor: placeholderTextColor]
|
|
723
|
+
)
|
|
724
|
+
} else {
|
|
725
|
+
textField.placeholder = placeholder
|
|
726
|
+
}
|
|
474
727
|
textView.placeholder = placeholder
|
|
728
|
+
textView.placeholderLabel.textColor = placeholderTextColor ?? .placeholderText
|
|
475
729
|
}
|
|
476
730
|
|
|
477
731
|
/// Supporting text, error message and counter below the field.
|
|
@@ -494,11 +748,33 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
494
748
|
onNeedsRemeasure?()
|
|
495
749
|
}
|
|
496
750
|
|
|
751
|
+
/// A text style's font at the current text size, capped at
|
|
752
|
+
/// `maxFontSizeMultiplier` times its size at the default text size.
|
|
753
|
+
/// `base` replaces the style's own font (the `textStyle` font, given at
|
|
754
|
+
/// its default-size point size), scaled along the style's curve.
|
|
755
|
+
private func scaledFont(_ style: UIFont.TextStyle, base: UIFont? = nil) -> UIFont {
|
|
756
|
+
let font = base ?? .preferredFont(
|
|
757
|
+
forTextStyle: style,
|
|
758
|
+
compatibleWith: UITraitCollection(preferredContentSizeCategory: .large)
|
|
759
|
+
)
|
|
760
|
+
let metrics = UIFontMetrics(forTextStyle: style)
|
|
761
|
+
if maxFontSizeMultiplier >= 1 {
|
|
762
|
+
return metrics.scaledFont(
|
|
763
|
+
for: font,
|
|
764
|
+
maximumPointSize: font.pointSize * maxFontSizeMultiplier,
|
|
765
|
+
compatibleWith: traitCollection
|
|
766
|
+
)
|
|
767
|
+
}
|
|
768
|
+
return metrics.scaledFont(for: font, compatibleWith: traitCollection)
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
private var inputFont: UIFont { scaledFont(.body, base: textFont) }
|
|
772
|
+
|
|
497
773
|
private func applyFonts() {
|
|
498
|
-
captionLabel.font =
|
|
499
|
-
footerLabel.font =
|
|
500
|
-
counterLabel.font =
|
|
501
|
-
let inputFont =
|
|
774
|
+
captionLabel.font = scaledFont(leadingLabel ? .body : .subheadline)
|
|
775
|
+
footerLabel.font = scaledFont(.footnote)
|
|
776
|
+
counterLabel.font = scaledFont(.footnote)
|
|
777
|
+
let inputFont = self.inputFont
|
|
502
778
|
textField.font = inputFont
|
|
503
779
|
textView.font = inputFont
|
|
504
780
|
textView.placeholderLabel.font = inputFont
|
|
@@ -509,14 +785,33 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
509
785
|
private func applyColors() {
|
|
510
786
|
let showsError = errorState == "error"
|
|
511
787
|
let focused = activeInput.isFirstResponder
|
|
788
|
+
let error = errorColor ?? .systemRed
|
|
512
789
|
captionLabel.textColor = showsError
|
|
513
|
-
?
|
|
514
|
-
: (leadingLabel ? .label : (focused ? tintColor : .secondaryLabel))
|
|
515
|
-
footerLabel.textColor = showsError ?
|
|
790
|
+
? error
|
|
791
|
+
: (leadingLabel ? .label : (focused ? (activeColor ?? tintColor) : .secondaryLabel))
|
|
792
|
+
footerLabel.textColor = showsError ? error : .secondaryLabel
|
|
516
793
|
counterLabel.textColor = showsError && maxLength > 0 && (text as NSString).length > maxLength
|
|
517
|
-
?
|
|
794
|
+
? error
|
|
518
795
|
: .secondaryLabel
|
|
519
|
-
|
|
796
|
+
|
|
797
|
+
// The outline of the text view and of a field whose box is drawn here
|
|
798
|
+
let outline: UIColor
|
|
799
|
+
if showsError {
|
|
800
|
+
outline = error
|
|
801
|
+
} else if focused {
|
|
802
|
+
outline = activeColor ?? outlineColor ?? .systemGray4
|
|
803
|
+
} else {
|
|
804
|
+
outline = outlineColor ?? .systemGray4
|
|
805
|
+
}
|
|
806
|
+
let resolved = outline.resolvedColor(with: traitCollection).cgColor
|
|
807
|
+
textView.layer.borderColor = resolved
|
|
808
|
+
textField.layer.borderColor = drawsBox ? resolved : nil
|
|
809
|
+
|
|
810
|
+
// Cursor and selection
|
|
811
|
+
textField.tintColor = activeColor
|
|
812
|
+
textView.tintColor = activeColor
|
|
813
|
+
textField.textColor = textColor ?? .label
|
|
814
|
+
textView.textColor = textColor ?? .label
|
|
520
815
|
}
|
|
521
816
|
|
|
522
817
|
private func applyBorderStyle() {
|
|
@@ -527,28 +822,69 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
527
822
|
case "bezel": style = .bezel
|
|
528
823
|
default: style = .roundedRect
|
|
529
824
|
}
|
|
530
|
-
|
|
825
|
+
// UIKit's rounded rect can't take colors; draw its look instead
|
|
826
|
+
let drawsBox = self.drawsBox
|
|
827
|
+
textField.borderStyle = drawsBox ? .none : style
|
|
828
|
+
textField.layer.borderWidth = drawsBox ? 1 : 0
|
|
829
|
+
textField.layer.cornerRadius = drawsBox ? 5 : 0
|
|
830
|
+
textField.textInsets = drawsBox ? UIEdgeInsets(top: 0, left: 7, bottom: 0, right: 7) : .zero
|
|
831
|
+
if drawsBox {
|
|
832
|
+
textField.backgroundColor = containerColor ?? .systemBackground
|
|
833
|
+
} else {
|
|
834
|
+
textField.backgroundColor = style == .none ? containerColor : nil
|
|
835
|
+
}
|
|
531
836
|
// The text view mirrors the rounded-rect field
|
|
532
837
|
let bordered = style != .none
|
|
533
838
|
textView.layer.borderWidth = bordered ? 1 : 0
|
|
534
839
|
textView.layer.cornerRadius = style == .roundedRect ? 5 : 0
|
|
535
|
-
textView.backgroundColor = bordered ? .systemBackground : .clear
|
|
840
|
+
textView.backgroundColor = containerColor ?? (bordered ? .systemBackground : .clear)
|
|
841
|
+
applyColors()
|
|
536
842
|
setNeedsLayout()
|
|
537
843
|
onNeedsRemeasure?()
|
|
538
844
|
}
|
|
539
845
|
|
|
540
846
|
private func applyEnabled() {
|
|
541
847
|
let enabled = interactivity != "disabled"
|
|
542
|
-
|
|
848
|
+
let button = actsAsButton
|
|
849
|
+
// A field acting as a button keeps its enabled look; editing is
|
|
850
|
+
// refused in textFieldShouldBeginEditing and presses come from the
|
|
851
|
+
// gesture recognizer
|
|
852
|
+
textField.isEnabled = enabled || button
|
|
543
853
|
textView.isEditable = enabled
|
|
544
854
|
textView.isUserInteractionEnabled = enabled
|
|
545
|
-
textView.alpha = enabled ? 1 : 0.5
|
|
855
|
+
textView.alpha = enabled || button ? 1 : 0.5
|
|
856
|
+
pressRecognizer.isEnabled = button
|
|
857
|
+
if button, activeInput.isFirstResponder { blur() }
|
|
858
|
+
applyAccessibility()
|
|
546
859
|
}
|
|
547
860
|
|
|
548
861
|
private func applyAccessibility() {
|
|
549
862
|
let spoken = spokenLabel.isEmpty ? (label.isEmpty ? nil : label) : spokenLabel
|
|
550
863
|
textField.accessibilityLabel = spoken
|
|
551
864
|
textView.accessibilityLabel = spoken
|
|
865
|
+
let id = inputTestID.isEmpty ? nil : inputTestID
|
|
866
|
+
textField.accessibilityIdentifier = id
|
|
867
|
+
textView.accessibilityIdentifier = id
|
|
868
|
+
for input in [textField as UIView, textView] {
|
|
869
|
+
if actsAsButton {
|
|
870
|
+
input.accessibilityTraits.insert(.button)
|
|
871
|
+
} else {
|
|
872
|
+
input.accessibilityTraits.remove(.button)
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
private func applyAlignment() {
|
|
878
|
+
let alignment: NSTextAlignment
|
|
879
|
+
switch textAlign {
|
|
880
|
+
case "left": alignment = .left
|
|
881
|
+
case "center": alignment = .center
|
|
882
|
+
case "right": alignment = .right
|
|
883
|
+
default: alignment = .natural
|
|
884
|
+
}
|
|
885
|
+
textField.textAlignment = alignment
|
|
886
|
+
textView.textAlignment = alignment
|
|
887
|
+
textView.placeholderLabel.textAlignment = alignment
|
|
552
888
|
}
|
|
553
889
|
|
|
554
890
|
private func applyTraits() {
|
|
@@ -571,6 +907,7 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
571
907
|
input.isSecureTextEntry = secureTextEntry && !revealed
|
|
572
908
|
input.textContentType = PCTextFieldView.contentType(autoComplete)
|
|
573
909
|
input.keyboardAppearance = PCTextFieldView.keyboardAppearance(keyboardAppearance)
|
|
910
|
+
input.passwordRules = passwordRules.isEmpty ? nil : UITextInputPasswordRules(descriptor: passwordRules)
|
|
574
911
|
input.smartQuotesType = PCTextFieldView.smartQuotesType(smartQuotes)
|
|
575
912
|
input.smartDashesType = PCTextFieldView.smartDashesType(smartDashes)
|
|
576
913
|
input.smartInsertDeleteType = PCTextFieldView.smartInsertDeleteType(smartInsertDelete)
|
|
@@ -592,6 +929,7 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
592
929
|
input.isSecureTextEntry = secureTextEntry && !revealed
|
|
593
930
|
input.textContentType = PCTextFieldView.contentType(autoComplete)
|
|
594
931
|
input.keyboardAppearance = PCTextFieldView.keyboardAppearance(keyboardAppearance)
|
|
932
|
+
input.passwordRules = passwordRules.isEmpty ? nil : UITextInputPasswordRules(descriptor: passwordRules)
|
|
595
933
|
input.smartQuotesType = PCTextFieldView.smartQuotesType(smartQuotes)
|
|
596
934
|
input.smartDashesType = PCTextFieldView.smartDashesType(smartDashes)
|
|
597
935
|
input.smartInsertDeleteType = PCTextFieldView.smartInsertDeleteType(smartInsertDelete)
|
|
@@ -604,6 +942,102 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
604
942
|
}
|
|
605
943
|
}
|
|
606
944
|
|
|
945
|
+
/// The keyboard toolbar: a `UIToolbar` as the input's
|
|
946
|
+
/// `inputAccessoryView`, with the given buttons, flexible spaces and a
|
|
947
|
+
/// Done button that dismisses the keyboard.
|
|
948
|
+
private func applyKeyboardToolbar() {
|
|
949
|
+
toolbarGeneration += 1
|
|
950
|
+
if keyboardToolbarItems.isEmpty {
|
|
951
|
+
keyboardToolbar = nil
|
|
952
|
+
} else {
|
|
953
|
+
let toolbar = keyboardToolbar ?? UIToolbar(frame: CGRect(x: 0, y: 0, width: 320, height: 44))
|
|
954
|
+
toolbar.items = keyboardToolbarItems.map { toolbarItem(from: $0) }
|
|
955
|
+
toolbar.sizeToFit()
|
|
956
|
+
keyboardToolbar = toolbar
|
|
957
|
+
}
|
|
958
|
+
textField.inputAccessoryView = keyboardToolbar
|
|
959
|
+
textView.inputAccessoryView = keyboardToolbar
|
|
960
|
+
if activeInput.isFirstResponder {
|
|
961
|
+
activeInput.reloadInputViews()
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
private func toolbarItem(from spec: NSDictionary) -> UIBarButtonItem {
|
|
966
|
+
let kind = spec["kind"] as? String ?? "button"
|
|
967
|
+
if kind == "flexibleSpace" {
|
|
968
|
+
return .flexibleSpace()
|
|
969
|
+
}
|
|
970
|
+
let itemId = spec["itemId"] as? String ?? ""
|
|
971
|
+
let title = spec["title"] as? String ?? ""
|
|
972
|
+
let spokenLabel = spec["accessibilityLabel"] as? String ?? ""
|
|
973
|
+
let testID = spec["testID"] as? String ?? ""
|
|
974
|
+
let action: UIAction
|
|
975
|
+
if kind == "done" {
|
|
976
|
+
action = UIAction { [weak self] _ in self?.blur() }
|
|
977
|
+
} else {
|
|
978
|
+
action = UIAction { [weak self] _ in self?.onKeyboardToolbarPress?(itemId) }
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
let item: UIBarButtonItem
|
|
982
|
+
let systemItem = kind == "done" && title.isEmpty
|
|
983
|
+
? UIBarButtonItem.SystemItem.done
|
|
984
|
+
: PCTextFieldView.toolbarSystemItem(spec["systemItem"] as? String ?? "")
|
|
985
|
+
let icon = PCButtonSupport.Icon(dictionary: spec as? [String: Any] ?? [:])
|
|
986
|
+
if let systemItem {
|
|
987
|
+
item = UIBarButtonItem(systemItem: systemItem, primaryAction: action)
|
|
988
|
+
} else if icon.isPresent {
|
|
989
|
+
item = UIBarButtonItem(title: nil, image: nil, primaryAction: action, menu: nil)
|
|
990
|
+
// The title is what VoiceOver reads for an icon button
|
|
991
|
+
item.accessibilityLabel = title.isEmpty ? nil : title
|
|
992
|
+
let generation = toolbarGeneration
|
|
993
|
+
item.image = PCButtonSupport.image(for: icon) { [weak self, weak item] image in
|
|
994
|
+
guard let self, self.toolbarGeneration == generation else { return }
|
|
995
|
+
item?.image = image
|
|
996
|
+
}
|
|
997
|
+
} else {
|
|
998
|
+
item = UIBarButtonItem(title: title, image: nil, primaryAction: action, menu: nil)
|
|
999
|
+
}
|
|
1000
|
+
if (spec["prominent"] as? String) == "true" {
|
|
1001
|
+
PCTextFieldView.makeProminent(item)
|
|
1002
|
+
}
|
|
1003
|
+
if !spokenLabel.isEmpty {
|
|
1004
|
+
item.accessibilityLabel = spokenLabel
|
|
1005
|
+
}
|
|
1006
|
+
item.accessibilityIdentifier = testID.isEmpty ? nil : testID
|
|
1007
|
+
return item
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
/// The prominent style: tinted glass on iOS 26, bold before
|
|
1011
|
+
private static func makeProminent(_ item: UIBarButtonItem) {
|
|
1012
|
+
#if compiler(>=6.2)
|
|
1013
|
+
if #available(iOS 26.0, *) {
|
|
1014
|
+
item.style = .prominent
|
|
1015
|
+
return
|
|
1016
|
+
}
|
|
1017
|
+
#endif
|
|
1018
|
+
item.style = .done
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
private static func toolbarSystemItem(_ value: String) -> UIBarButtonItem.SystemItem? {
|
|
1022
|
+
switch value {
|
|
1023
|
+
case "done": return .done
|
|
1024
|
+
case "cancel": return .cancel
|
|
1025
|
+
case "save": return .save
|
|
1026
|
+
case "add": return .add
|
|
1027
|
+
case "edit": return .edit
|
|
1028
|
+
case "close": return .close
|
|
1029
|
+
case "search": return .search
|
|
1030
|
+
case "compose": return .compose
|
|
1031
|
+
case "reply": return .reply
|
|
1032
|
+
case "action": return .action
|
|
1033
|
+
case "camera": return .camera
|
|
1034
|
+
case "trash": return .trash
|
|
1035
|
+
case "undo": return .undo
|
|
1036
|
+
case "redo": return .redo
|
|
1037
|
+
default: return nil
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
|
|
607
1041
|
/// Prefix and suffix labels, icons, the clear button and the password
|
|
608
1042
|
/// toggle. Single-line only: a text view has no accessory views.
|
|
609
1043
|
private func applyAccessories() {
|
|
@@ -612,7 +1046,10 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
612
1046
|
textField.leftViewMode = .never
|
|
613
1047
|
textField.rightViewMode = .never
|
|
614
1048
|
|
|
615
|
-
if let leading = accessoryView(
|
|
1049
|
+
if let leading = accessoryView(
|
|
1050
|
+
image: leadingImage, tinted: leadingIcon.tinted, text: prefix, action: nil,
|
|
1051
|
+
testID: leadingIconTestID, spokenLabel: leadingIconSpokenLabel
|
|
1052
|
+
) {
|
|
616
1053
|
textField.leftView = leading
|
|
617
1054
|
textField.leftViewMode = .always
|
|
618
1055
|
}
|
|
@@ -630,7 +1067,12 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
630
1067
|
trailingAction = nil
|
|
631
1068
|
}
|
|
632
1069
|
let trailingTinted = trailingImage != nil ? trailingIcon.tinted : true
|
|
633
|
-
|
|
1070
|
+
let customTrailing = trailingImage != nil
|
|
1071
|
+
if let trailing = accessoryView(
|
|
1072
|
+
image: trailingImageForSlot, tinted: trailingTinted, text: suffix, action: trailingAction,
|
|
1073
|
+
testID: customTrailing ? trailingIconTestID : "",
|
|
1074
|
+
spokenLabel: customTrailing ? trailingIconSpokenLabel : ""
|
|
1075
|
+
) {
|
|
634
1076
|
textField.rightView = trailing
|
|
635
1077
|
textField.rightViewMode = .always
|
|
636
1078
|
}
|
|
@@ -646,7 +1088,10 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
646
1088
|
}
|
|
647
1089
|
|
|
648
1090
|
/// A label and/or an image button for the field's left or right slot.
|
|
649
|
-
private func accessoryView(
|
|
1091
|
+
private func accessoryView(
|
|
1092
|
+
image: UIImage?, tinted: Bool, text: String, action: (() -> Void)?,
|
|
1093
|
+
testID: String, spokenLabel: String
|
|
1094
|
+
) -> UIView? {
|
|
650
1095
|
guard image != nil || !text.isEmpty else { return nil }
|
|
651
1096
|
let stack = UIStackView()
|
|
652
1097
|
stack.axis = .horizontal
|
|
@@ -656,7 +1101,7 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
656
1101
|
stack.layoutMargins = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 8)
|
|
657
1102
|
|
|
658
1103
|
if let image {
|
|
659
|
-
let config = UIImage.SymbolConfiguration(
|
|
1104
|
+
let config = UIImage.SymbolConfiguration(font: inputFont)
|
|
660
1105
|
if let action {
|
|
661
1106
|
let button = PCAccessoryButton(type: .system)
|
|
662
1107
|
button.setImage(image.applyingSymbolConfiguration(config) ?? image, for: .normal)
|
|
@@ -664,19 +1109,25 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
664
1109
|
button.action = action
|
|
665
1110
|
button.accessibilityLabel = passwordToggle && trailingImage == nil
|
|
666
1111
|
? (revealed ? "Hide password" : "Show password")
|
|
667
|
-
: nil
|
|
1112
|
+
: (spokenLabel.isEmpty ? nil : spokenLabel)
|
|
1113
|
+
button.accessibilityIdentifier = testID.isEmpty ? nil : testID
|
|
668
1114
|
stack.addArrangedSubview(button)
|
|
669
1115
|
} else {
|
|
670
1116
|
let imageView = UIImageView(image: image.applyingSymbolConfiguration(config) ?? image)
|
|
671
1117
|
imageView.tintColor = tinted ? .secondaryLabel : nil
|
|
672
1118
|
imageView.contentMode = .scaleAspectFit
|
|
1119
|
+
imageView.accessibilityIdentifier = testID.isEmpty ? nil : testID
|
|
1120
|
+
if !spokenLabel.isEmpty {
|
|
1121
|
+
imageView.isAccessibilityElement = true
|
|
1122
|
+
imageView.accessibilityLabel = spokenLabel
|
|
1123
|
+
}
|
|
673
1124
|
stack.addArrangedSubview(imageView)
|
|
674
1125
|
}
|
|
675
1126
|
}
|
|
676
1127
|
if !text.isEmpty {
|
|
677
1128
|
let label = UILabel()
|
|
678
1129
|
label.text = text
|
|
679
|
-
label.font =
|
|
1130
|
+
label.font = inputFont
|
|
680
1131
|
label.textColor = .secondaryLabel
|
|
681
1132
|
label.adjustsFontForContentSizeCategory = true
|
|
682
1133
|
stack.addArrangedSubview(label)
|
|
@@ -718,6 +1169,7 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
718
1169
|
super.traitCollectionDidChange(previousTraitCollection)
|
|
719
1170
|
if previousTraitCollection?.preferredContentSizeCategory != traitCollection.preferredContentSizeCategory {
|
|
720
1171
|
applyFonts()
|
|
1172
|
+
applyAccessories()
|
|
721
1173
|
}
|
|
722
1174
|
if previousTraitCollection?.hasDifferentColorAppearance(comparedTo: traitCollection) == true {
|
|
723
1175
|
applyColors()
|
|
@@ -731,6 +1183,8 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
731
1183
|
var inputHeight: CGFloat
|
|
732
1184
|
var footerHeight: CGFloat
|
|
733
1185
|
var leading: Bool
|
|
1186
|
+
/// A multi-line field past maxLines scrolls its text
|
|
1187
|
+
var inputScrolls: Bool
|
|
734
1188
|
var total: CGFloat {
|
|
735
1189
|
var height = leading ? max(inputHeight, captionHeight) : inputHeight
|
|
736
1190
|
if captionHeight > 0 && !leading { height += captionHeight + 6 }
|
|
@@ -748,10 +1202,21 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
748
1202
|
let captionHeight = label.isEmpty ? 0 : ceil(captionLabel.font.lineHeight)
|
|
749
1203
|
let fieldWidth = max(1, width - fieldOffset())
|
|
750
1204
|
|
|
751
|
-
|
|
1205
|
+
var inputHeight: CGFloat
|
|
1206
|
+
var inputScrolls = false
|
|
752
1207
|
if multiline {
|
|
753
|
-
let fitted = textView.sizeThatFits(CGSize(width: fieldWidth, height: .greatestFiniteMagnitude))
|
|
754
|
-
inputHeight = max(singleLineMinHeight,
|
|
1208
|
+
let fitted = ceil(textView.sizeThatFits(CGSize(width: fieldWidth, height: .greatestFiniteMagnitude)).height)
|
|
1209
|
+
inputHeight = max(singleLineMinHeight, fitted)
|
|
1210
|
+
let lineHeight = inputFont.lineHeight
|
|
1211
|
+
let chrome = textViewInsets.top + textViewInsets.bottom
|
|
1212
|
+
if minLines > 0 {
|
|
1213
|
+
inputHeight = max(inputHeight, ceil(lineHeight * CGFloat(minLines) + chrome))
|
|
1214
|
+
}
|
|
1215
|
+
if maxLines > 0 {
|
|
1216
|
+
let cap = max(singleLineMinHeight, ceil(lineHeight * CGFloat(maxLines) + chrome))
|
|
1217
|
+
inputScrolls = fitted > cap
|
|
1218
|
+
inputHeight = min(inputHeight, cap)
|
|
1219
|
+
}
|
|
755
1220
|
} else {
|
|
756
1221
|
let fitted = textField.sizeThatFits(CGSize(width: fieldWidth, height: .greatestFiniteMagnitude))
|
|
757
1222
|
inputHeight = max(singleLineMinHeight, ceil(fitted.height))
|
|
@@ -769,7 +1234,13 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
769
1234
|
let counterHeight = counterLabel.isHidden ? 0 : ceil(counterLabel.font.lineHeight)
|
|
770
1235
|
footerHeight = max(messageHeight, counterHeight)
|
|
771
1236
|
}
|
|
772
|
-
return Metrics(
|
|
1237
|
+
return Metrics(
|
|
1238
|
+
captionHeight: captionHeight,
|
|
1239
|
+
inputHeight: inputHeight,
|
|
1240
|
+
footerHeight: footerHeight,
|
|
1241
|
+
leading: leadingLabel,
|
|
1242
|
+
inputScrolls: inputScrolls
|
|
1243
|
+
)
|
|
773
1244
|
}
|
|
774
1245
|
|
|
775
1246
|
public override func layoutSubviews() {
|
|
@@ -779,6 +1250,9 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
779
1250
|
let x = fieldOffset()
|
|
780
1251
|
let fieldWidth = max(0, width - x)
|
|
781
1252
|
var y: CGFloat = 0
|
|
1253
|
+
if multiline, textView.isScrollEnabled != m.inputScrolls {
|
|
1254
|
+
textView.isScrollEnabled = m.inputScrolls
|
|
1255
|
+
}
|
|
782
1256
|
|
|
783
1257
|
if m.leading {
|
|
784
1258
|
// Label column and field side by side, centred on the taller one
|
|
@@ -874,28 +1348,59 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
874
1348
|
}
|
|
875
1349
|
}
|
|
876
1350
|
|
|
1351
|
+
/// React Native autoComplete values onto text content types, as the
|
|
1352
|
+
/// core TextInput maps them, plus the names it leaves out. Values with no
|
|
1353
|
+
/// iOS equivalent, and unknown ones, give no content type.
|
|
877
1354
|
private static func contentType(_ value: String) -> UITextContentType? {
|
|
878
1355
|
switch value {
|
|
879
|
-
case "username": return .username
|
|
880
|
-
case "password": return .password
|
|
881
|
-
case "new-password": return .newPassword
|
|
882
|
-
case "one-time-code": return .oneTimeCode
|
|
1356
|
+
case "username", "username-new": return .username
|
|
1357
|
+
case "password", "current-password": return .password
|
|
1358
|
+
case "new-password", "password-new": return .newPassword
|
|
1359
|
+
case "one-time-code", "sms-otp", "email-otp", "2fa-app-otp": return .oneTimeCode
|
|
883
1360
|
case "email": return .emailAddress
|
|
884
1361
|
case "name": return .name
|
|
885
|
-
case "given-name": return .givenName
|
|
886
|
-
case "family-name": return .familyName
|
|
887
|
-
case "
|
|
888
|
-
case "
|
|
1362
|
+
case "given-name", "name-given": return .givenName
|
|
1363
|
+
case "family-name", "name-family": return .familyName
|
|
1364
|
+
case "additional-name", "name-middle": return .middleName
|
|
1365
|
+
case "honorific-prefix", "name-prefix": return .namePrefix
|
|
1366
|
+
case "honorific-suffix", "name-suffix": return .nameSuffix
|
|
1367
|
+
case "nickname": return .nickname
|
|
1368
|
+
case "organization": return .organizationName
|
|
1369
|
+
case "organization-title": return .jobTitle
|
|
1370
|
+
case "tel", "tel-national", "tel-device": return .telephoneNumber
|
|
1371
|
+
case "street-address", "postal-address": return .fullStreetAddress
|
|
1372
|
+
case "address-line1": return .streetAddressLine1
|
|
1373
|
+
case "address-line2", "postal-address-extended": return .streetAddressLine2
|
|
1374
|
+
case "postal-address-locality": return .addressCity
|
|
1375
|
+
case "postal-address-region": return .addressState
|
|
1376
|
+
case "postal-address-dependent-locality": return .sublocality
|
|
889
1377
|
case "postal-code": return .postalCode
|
|
890
|
-
case "country": return .countryName
|
|
1378
|
+
case "country", "postal-address-country": return .countryName
|
|
891
1379
|
case "cc-number": return .creditCardNumber
|
|
892
|
-
case "cc-exp":
|
|
893
|
-
if #available(iOS 17.0, *) { return .creditCardExpiration }
|
|
894
|
-
return nil
|
|
895
|
-
case "cc-csc":
|
|
896
|
-
if #available(iOS 17.0, *) { return .creditCardSecurityCode }
|
|
897
|
-
return nil
|
|
898
1380
|
case "url": return .URL
|
|
1381
|
+
case "flight-number": return .flightNumber
|
|
1382
|
+
default:
|
|
1383
|
+
if #available(iOS 17.0, *) { return contentType17(value) }
|
|
1384
|
+
return nil
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
@available(iOS 17.0, *)
|
|
1389
|
+
private static func contentType17(_ value: String) -> UITextContentType? {
|
|
1390
|
+
switch value {
|
|
1391
|
+
case "cc-exp": return .creditCardExpiration
|
|
1392
|
+
case "cc-exp-month": return .creditCardExpirationMonth
|
|
1393
|
+
case "cc-exp-year": return .creditCardExpirationYear
|
|
1394
|
+
case "cc-csc": return .creditCardSecurityCode
|
|
1395
|
+
case "cc-name": return .creditCardName
|
|
1396
|
+
case "cc-given-name": return .creditCardGivenName
|
|
1397
|
+
case "cc-middle-name": return .creditCardMiddleName
|
|
1398
|
+
case "cc-family-name": return .creditCardFamilyName
|
|
1399
|
+
case "cc-type": return .creditCardType
|
|
1400
|
+
case "birthdate-full": return .birthdate
|
|
1401
|
+
case "birthdate-day": return .birthdateDay
|
|
1402
|
+
case "birthdate-month": return .birthdateMonth
|
|
1403
|
+
case "birthdate-year": return .birthdateYear
|
|
899
1404
|
default: return nil
|
|
900
1405
|
}
|
|
901
1406
|
}
|
|
@@ -955,10 +1460,51 @@ public final class PCTextFieldView: UIView, UITextFieldDelegate, UITextViewDeleg
|
|
|
955
1460
|
|
|
956
1461
|
// MARK: - Helpers
|
|
957
1462
|
|
|
1463
|
+
/// The single-line input: insets for the box the field view draws, and
|
|
1464
|
+
/// VoiceOver activation for a field acting as a button.
|
|
1465
|
+
final class PCInputTextField: UITextField {
|
|
1466
|
+
var textInsets: UIEdgeInsets = .zero {
|
|
1467
|
+
didSet { if oldValue != textInsets { setNeedsLayout() } }
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
/// Returns true when it handled the activation
|
|
1471
|
+
var onActivate: (() -> Bool)?
|
|
1472
|
+
|
|
1473
|
+
private func inset(_ rect: CGRect) -> CGRect {
|
|
1474
|
+
// Accessory views bring their own margins
|
|
1475
|
+
let left = leftView == nil ? textInsets.left : 0
|
|
1476
|
+
let right = rightView == nil ? textInsets.right : 0
|
|
1477
|
+
return rect.inset(by: UIEdgeInsets(top: textInsets.top, left: left, bottom: textInsets.bottom, right: right))
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
override func textRect(forBounds bounds: CGRect) -> CGRect {
|
|
1481
|
+
inset(super.textRect(forBounds: bounds))
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
override func editingRect(forBounds bounds: CGRect) -> CGRect {
|
|
1485
|
+
inset(super.editingRect(forBounds: bounds))
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
|
|
1489
|
+
inset(super.placeholderRect(forBounds: bounds))
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
override func accessibilityActivate() -> Bool {
|
|
1493
|
+
onActivate?() == true || super.accessibilityActivate()
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
|
|
958
1497
|
/// A `UITextView` with a placeholder, drawn where the text starts.
|
|
959
1498
|
final class PCPlaceholderTextView: UITextView {
|
|
960
1499
|
let placeholderLabel = UILabel()
|
|
961
1500
|
|
|
1501
|
+
/// Returns true when it handled the activation
|
|
1502
|
+
var onActivate: (() -> Bool)?
|
|
1503
|
+
|
|
1504
|
+
override func accessibilityActivate() -> Bool {
|
|
1505
|
+
onActivate?() == true || super.accessibilityActivate()
|
|
1506
|
+
}
|
|
1507
|
+
|
|
962
1508
|
var placeholder: String = "" {
|
|
963
1509
|
didSet {
|
|
964
1510
|
placeholderLabel.text = placeholder
|