react-native-platform-components 1.3.0 → 1.5.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 +47 -51
- package/android/src/main/java/com/platformcomponents/PCButtonGroupView.kt +664 -0
- package/android/src/main/java/com/platformcomponents/PCButtonGroupViewManager.kt +241 -0
- package/android/src/main/java/com/platformcomponents/PCButtonSupport.kt +159 -0
- package/android/src/main/java/com/platformcomponents/PCButtonView.kt +527 -0
- package/android/src/main/java/com/platformcomponents/PCButtonViewManager.kt +204 -0
- 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 +112 -0
- 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 +247 -0
- package/android/src/main/java/com/platformcomponents/PCFloatingToolbarViewManager.kt +73 -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 +35 -17
- package/android/src/main/java/com/platformcomponents/PCSegmentedControlViewManager.kt +20 -3
- 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 +1393 -0
- package/android/src/main/java/com/platformcomponents/PCTextFieldViewManager.kt +354 -0
- package/android/src/main/java/com/platformcomponents/PCThemeSupport.kt +37 -0
- package/android/src/main/java/com/platformcomponents/PlatformComponentsPackage.kt +8 -0
- package/android/src/main/res/drawable/pc_ic_search.xml +12 -0
- package/android/src/main/res/values/attrs.xml +13 -0
- package/android/src/main/res/values/ids.xml +5 -0
- package/android/src/main/res/values/styles.xml +207 -0
- package/ios/PCButton.h +10 -0
- package/ios/PCButton.mm +311 -0
- package/ios/PCButtonGroup.h +10 -0
- package/ios/PCButtonGroup.mm +323 -0
- package/ios/PCButtonGroupView.swift +473 -0
- package/ios/PCButtonSupport.swift +312 -0
- package/ios/PCButtonView.swift +438 -0
- 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.h +10 -0
- package/ios/PCFloatingToolbar.mm +103 -0
- package/ios/PCFloatingToolbarView.swift +336 -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.h +10 -0
- package/ios/PCTextField.mm +546 -0
- package/ios/PCTextFieldView.swift +1558 -0
- package/lib/commonjs/Button.js +149 -0
- package/lib/commonjs/Button.js.map +1 -0
- package/lib/commonjs/ButtonGroup.js +109 -0
- package/lib/commonjs/ButtonGroup.js.map +1 -0
- package/lib/commonjs/ButtonGroupNativeComponent.ts +191 -0
- package/lib/commonjs/ButtonNativeComponent.ts +192 -0
- 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 +77 -0
- package/lib/commonjs/FloatingToolbar.js.map +1 -0
- package/lib/commonjs/FloatingToolbarNativeComponent.ts +47 -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 +18 -85
- package/lib/commonjs/SegmentedControl.js.map +1 -1
- package/lib/commonjs/SegmentedControlNativeComponent.ts +14 -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 +358 -0
- package/lib/commonjs/TextField.js.map +1 -0
- package/lib/commonjs/TextFieldNativeComponent.ts +324 -0
- package/lib/commonjs/focusRegistry.js +79 -0
- package/lib/commonjs/focusRegistry.js.map +1 -0
- package/lib/commonjs/haptics.js +2 -0
- package/lib/commonjs/haptics.js.map +1 -0
- package/lib/commonjs/icons.js +106 -0
- package/lib/commonjs/icons.js.map +1 -0
- package/lib/commonjs/index.js +143 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +157 -63
- 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/labelStyle.js +27 -0
- package/lib/commonjs/labelStyle.js.map +1 -0
- package/lib/commonjs/menuItems.js +68 -0
- package/lib/commonjs/menuItems.js.map +1 -0
- package/lib/commonjs/reactNativeInternals.d.js +2 -0
- package/lib/commonjs/reactNativeInternals.d.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 +142 -0
- package/lib/module/Button.js.map +1 -0
- package/lib/module/ButtonGroup.js +102 -0
- package/lib/module/ButtonGroup.js.map +1 -0
- package/lib/module/ButtonGroupNativeComponent.ts +191 -0
- package/lib/module/ButtonNativeComponent.ts +192 -0
- 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 +70 -0
- package/lib/module/FloatingToolbar.js.map +1 -0
- package/lib/module/FloatingToolbarNativeComponent.ts +47 -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 +18 -85
- package/lib/module/SegmentedControl.js.map +1 -1
- package/lib/module/SegmentedControlNativeComponent.ts +14 -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 +352 -0
- package/lib/module/TextField.js.map +1 -0
- package/lib/module/TextFieldNativeComponent.ts +324 -0
- package/lib/module/focusRegistry.js +75 -0
- package/lib/module/focusRegistry.js.map +1 -0
- package/lib/module/haptics.js +2 -0
- package/lib/module/haptics.js.map +1 -0
- package/lib/module/icons.js +101 -0
- package/lib/module/icons.js.map +1 -0
- package/lib/module/index.js +13 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +12 -59
- 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/labelStyle.js +23 -0
- package/lib/module/labelStyle.js.map +1 -0
- package/lib/module/menuItems.js +65 -0
- package/lib/module/menuItems.js.map +1 -0
- package/lib/module/reactNativeInternals.d.js +2 -0
- package/lib/module/reactNativeInternals.d.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 +184 -0
- package/lib/typescript/commonjs/src/Button.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/ButtonGroup.d.ts +117 -0
- package/lib/typescript/commonjs/src/ButtonGroup.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/ButtonGroupNativeComponent.d.ts +154 -0
- package/lib/typescript/commonjs/src/ButtonGroupNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/ButtonNativeComponent.d.ts +148 -0
- package/lib/typescript/commonjs/src/ButtonNativeComponent.d.ts.map +1 -0
- 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 +75 -0
- package/lib/typescript/commonjs/src/FloatingToolbar.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/FloatingToolbarNativeComponent.d.ts +36 -0
- package/lib/typescript/commonjs/src/FloatingToolbarNativeComponent.d.ts.map +1 -0
- 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 +35 -47
- package/lib/typescript/commonjs/src/SegmentedControl.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/SegmentedControlNativeComponent.d.ts +11 -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 +332 -0
- package/lib/typescript/commonjs/src/TextField.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/TextFieldNativeComponent.d.ts +240 -0
- package/lib/typescript/commonjs/src/TextFieldNativeComponent.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/haptics.d.ts +20 -0
- package/lib/typescript/commonjs/src/haptics.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/icons.d.ts +58 -0
- package/lib/typescript/commonjs/src/icons.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/index.d.ts +13 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/index.web.d.ts +25 -133
- 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/labelStyle.d.ts +20 -0
- package/lib/typescript/commonjs/src/labelStyle.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/sharedTypes.d.ts +6 -1
- package/lib/typescript/commonjs/src/sharedTypes.d.ts.map +1 -1
- 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 +184 -0
- package/lib/typescript/module/src/Button.d.ts.map +1 -0
- package/lib/typescript/module/src/ButtonGroup.d.ts +117 -0
- package/lib/typescript/module/src/ButtonGroup.d.ts.map +1 -0
- package/lib/typescript/module/src/ButtonGroupNativeComponent.d.ts +154 -0
- package/lib/typescript/module/src/ButtonGroupNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/ButtonNativeComponent.d.ts +148 -0
- package/lib/typescript/module/src/ButtonNativeComponent.d.ts.map +1 -0
- 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 +75 -0
- package/lib/typescript/module/src/FloatingToolbar.d.ts.map +1 -0
- package/lib/typescript/module/src/FloatingToolbarNativeComponent.d.ts +36 -0
- package/lib/typescript/module/src/FloatingToolbarNativeComponent.d.ts.map +1 -0
- 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 +35 -47
- package/lib/typescript/module/src/SegmentedControl.d.ts.map +1 -1
- package/lib/typescript/module/src/SegmentedControlNativeComponent.d.ts +11 -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 +332 -0
- package/lib/typescript/module/src/TextField.d.ts.map +1 -0
- package/lib/typescript/module/src/TextFieldNativeComponent.d.ts +240 -0
- package/lib/typescript/module/src/TextFieldNativeComponent.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/haptics.d.ts +20 -0
- package/lib/typescript/module/src/haptics.d.ts.map +1 -0
- package/lib/typescript/module/src/icons.d.ts +58 -0
- package/lib/typescript/module/src/icons.d.ts.map +1 -0
- package/lib/typescript/module/src/index.d.ts +13 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/index.web.d.ts +25 -133
- 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/labelStyle.d.ts +20 -0
- package/lib/typescript/module/src/labelStyle.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/sharedTypes.d.ts +6 -1
- package/lib/typescript/module/src/sharedTypes.d.ts.map +1 -1
- 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 +55 -4
- package/plugin/build/index.d.ts +3 -2
- package/plugin/build/index.d.ts.map +1 -1
- package/react-native.config.js +6 -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/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/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 +6 -0
- package/src/Button.tsx +359 -0
- package/src/ButtonGroup.tsx +251 -0
- package/src/ButtonGroupNativeComponent.ts +191 -0
- package/src/ButtonNativeComponent.ts +192 -0
- 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 +164 -0
- package/src/FloatingToolbarNativeComponent.ts +47 -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 +57 -119
- package/src/SegmentedControlNativeComponent.ts +14 -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 +908 -0
- package/src/TextFieldNativeComponent.ts +324 -0
- package/src/focusRegistry.ts +90 -0
- package/src/haptics.ts +31 -0
- package/src/icons.ts +143 -0
- package/src/index.tsx +13 -0
- package/src/index.web.tsx +53 -199
- package/src/jest.tsx +958 -0
- package/src/labelStyle.ts +36 -0
- package/src/menuItems.ts +152 -0
- package/src/reactNativeInternals.d.ts +22 -0
- package/src/selectionIdentifiers.ts +17 -0
- package/src/sharedTypes.ts +7 -1
- 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
|
@@ -0,0 +1,671 @@
|
|
|
1
|
+
import UIKit
|
|
2
|
+
|
|
3
|
+
/// A tab bar item, bridged from ObjC++ as a dictionary.
|
|
4
|
+
struct PCTabBarTab {
|
|
5
|
+
let label: String
|
|
6
|
+
let value: String
|
|
7
|
+
let disabled: Bool
|
|
8
|
+
let icon: PCButtonSupport.Icon
|
|
9
|
+
let selectedIcon: PCButtonSupport.Icon
|
|
10
|
+
/// "" = no badge, " " = a dot, anything else is the badge text
|
|
11
|
+
let badge: String
|
|
12
|
+
let accessibilityLabel: String
|
|
13
|
+
let testID: String
|
|
14
|
+
/// "" | "search"
|
|
15
|
+
let role: String
|
|
16
|
+
/// "" | a UITabBarItem.SystemItem name
|
|
17
|
+
let systemItem: String
|
|
18
|
+
|
|
19
|
+
/// The system item the tab is drawn as, if any: the search role is the
|
|
20
|
+
/// system search item, which iOS 26 sets apart as its own circle.
|
|
21
|
+
var system: UITabBarItem.SystemItem? {
|
|
22
|
+
if role == "search" { return .search }
|
|
23
|
+
switch systemItem {
|
|
24
|
+
case "bookmarks": return .bookmarks
|
|
25
|
+
case "contacts": return .contacts
|
|
26
|
+
case "downloads": return .downloads
|
|
27
|
+
case "favorites": return .favorites
|
|
28
|
+
case "featured": return .featured
|
|
29
|
+
case "history": return .history
|
|
30
|
+
case "more": return .more
|
|
31
|
+
case "mostRecent": return .mostRecent
|
|
32
|
+
case "mostViewed": return .mostViewed
|
|
33
|
+
case "recents": return .recents
|
|
34
|
+
case "search": return .search
|
|
35
|
+
case "topRated": return .topRated
|
|
36
|
+
default: return nil
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/// A standalone `UITabBar`: the system tab bar, icons over labels, badges and
|
|
42
|
+
/// the selection look of the running iOS (the Liquid Glass selection on iOS
|
|
43
|
+
/// 26), without a `UITabBarController`. Selection is controlled from JS; a
|
|
44
|
+
/// press reports the tab and whether it was already selected. On iOS 26 a
|
|
45
|
+
/// bar that minimizes or carries a bottom accessory is hosted in a
|
|
46
|
+
/// `UITabBarController` instead, which provides both.
|
|
47
|
+
@objcMembers
|
|
48
|
+
public final class PCTabBarView: UIView, UITabBarDelegate, UITabBarControllerDelegate {
|
|
49
|
+
// MARK: - Props (set from ObjC++)
|
|
50
|
+
|
|
51
|
+
/// ObjC++ sets this as an array of dictionaries; see `rebuildItems` for keys.
|
|
52
|
+
public var items: [Any] = [] { didSet { rebuildItems() } }
|
|
53
|
+
|
|
54
|
+
/// Controlled selection by value; "" = none.
|
|
55
|
+
public var selectedValue: String = "" { didSet { updateSelection() } }
|
|
56
|
+
|
|
57
|
+
/// "auto" | "labeled" | "selected" | "unlabeled"
|
|
58
|
+
public var labelVisibility: String = "auto" {
|
|
59
|
+
didSet { if oldValue != labelVisibility { rebuildItems() } }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public var activeTintColor: UIColor? { didSet { applyAppearance() } }
|
|
63
|
+
public var inactiveTintColor: UIColor? { didSet { applyAppearance() } }
|
|
64
|
+
public var barColor: UIColor? { didSet { applyAppearance() } }
|
|
65
|
+
public var badgeBackgroundColor: UIColor? { didSet { applyAppearance() } }
|
|
66
|
+
public var badgeTextColor: UIColor? { didSet { applyAppearance() } }
|
|
67
|
+
|
|
68
|
+
/// Label font; nil keeps the system font
|
|
69
|
+
public var labelFont: UIFont? { didSet { applyAppearance() } }
|
|
70
|
+
|
|
71
|
+
/// iOS 26: "" (a standalone bar) | "automatic" | "never" | "onScrollDown"
|
|
72
|
+
/// | "onScrollUp". Any value but "" hosts the bar in a UITabBarController,
|
|
73
|
+
/// which minimizes it as the content scroll view scrolls.
|
|
74
|
+
public var minimizeBehavior: String = "" {
|
|
75
|
+
didSet { if oldValue != minimizeBehavior { configureHost() } }
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/// nativeID of the ScrollView whose scrolling minimizes the bar
|
|
79
|
+
public var scrollViewNativeID: String = "" {
|
|
80
|
+
didSet { if oldValue != scrollViewNativeID { attachedScrollView = nil; attachScrollView() } }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/// iOS 26: the id of the accessory content (PCTabBarAccessoryView) to
|
|
84
|
+
/// host as the controller's bottom accessory; "" = none. Hosts the bar.
|
|
85
|
+
public var accessoryID: String = "" {
|
|
86
|
+
didSet {
|
|
87
|
+
guard oldValue != accessoryID else { return }
|
|
88
|
+
configureHost()
|
|
89
|
+
attachAccessory()
|
|
90
|
+
onNeedsRemeasure?()
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/// The `haptics` prop; PCTabBar.mm plays it on a tab press
|
|
95
|
+
public let haptics = PCHaptics()
|
|
96
|
+
|
|
97
|
+
// MARK: - Events back to ObjC++
|
|
98
|
+
|
|
99
|
+
/// (index, value, reselected)
|
|
100
|
+
public var onTabPress: ((Int, String, Bool) -> Void)?
|
|
101
|
+
|
|
102
|
+
/// Called when the bar's height may have changed.
|
|
103
|
+
public var onNeedsRemeasure: (() -> Void)?
|
|
104
|
+
|
|
105
|
+
/// iOS 26: the hosted accessory's frame in this view, and its
|
|
106
|
+
/// environment ("regular" | "inline").
|
|
107
|
+
public var onAccessoryLayout: ((CGRect, String) -> Void)?
|
|
108
|
+
|
|
109
|
+
// MARK: - Internal
|
|
110
|
+
|
|
111
|
+
private let tabBar = PCLayoutReportingTabBar()
|
|
112
|
+
|
|
113
|
+
/// The controller hosting the bar when it minimizes or carries an
|
|
114
|
+
/// accessory (iOS 26), else nil
|
|
115
|
+
private var host: UITabBarController?
|
|
116
|
+
private weak var attachedScrollView: UIScrollView?
|
|
117
|
+
|
|
118
|
+
/// The bar on screen: the hosted controller's, or the standalone one
|
|
119
|
+
private var activeBar: UITabBar { host?.tabBar ?? tabBar }
|
|
120
|
+
private var tabs: [PCTabBarTab] = []
|
|
121
|
+
|
|
122
|
+
/// Bumped on every rebuild so late image loads can't touch stale items.
|
|
123
|
+
private var generation = 0
|
|
124
|
+
|
|
125
|
+
/// The accessory content hosted as the bottom accessory (iOS 26)
|
|
126
|
+
private weak var hostedAccessory: PCTabBarAccessoryView?
|
|
127
|
+
|
|
128
|
+
/// The room the accessory takes above the bar, added to the bar's
|
|
129
|
+
/// height: measured from UIKit's layout, the iOS 26.0 metrics until then
|
|
130
|
+
/// (a 48pt row and an 8pt gap)
|
|
131
|
+
private var accessoryRoom: CGFloat = 56
|
|
132
|
+
|
|
133
|
+
private var lastAccessoryReport: (frame: CGRect, environment: String)?
|
|
134
|
+
|
|
135
|
+
public override init(frame: CGRect) {
|
|
136
|
+
super.init(frame: frame)
|
|
137
|
+
setup()
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public required init?(coder: NSCoder) {
|
|
141
|
+
super.init(coder: coder)
|
|
142
|
+
setup()
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private func setup() {
|
|
146
|
+
tabBar.delegate = self
|
|
147
|
+
// UIKit rebuilds the tab buttons as the bar lays out; follow every pass
|
|
148
|
+
tabBar.onLayout = { [weak self] in self?.applyTestIDs() }
|
|
149
|
+
// Frame layout, as UITabBarController gives its bar: the iOS 26 bar
|
|
150
|
+
// lays its tabs out wrongly under Auto Layout constraints
|
|
151
|
+
addSubview(tabBar)
|
|
152
|
+
applyAppearance()
|
|
153
|
+
// The accessory content may mount after the bar
|
|
154
|
+
NotificationCenter.default.addObserver(
|
|
155
|
+
self, selector: #selector(accessoryDidChange(_:)),
|
|
156
|
+
name: PCTabBarAccessoryView.didChangeNotification, object: nil)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@objc private func accessoryDidChange(_ note: Notification) {
|
|
160
|
+
guard let id = note.object as? String, id == accessoryID else { return }
|
|
161
|
+
attachAccessory()
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// MARK: - Items
|
|
165
|
+
|
|
166
|
+
private func rebuildItems() {
|
|
167
|
+
tabs = items.compactMap { any in
|
|
168
|
+
guard let dict = any as? [String: Any] else { return nil }
|
|
169
|
+
func icon(_ prefix: String) -> PCButtonSupport.Icon {
|
|
170
|
+
let key = { (name: String) in prefix.isEmpty ? name : prefix + name.prefix(1).uppercased() + name.dropFirst() }
|
|
171
|
+
let scale = (dict[key("iconScale")] as? NSNumber).map { CGFloat(truncating: $0) } ?? 1
|
|
172
|
+
return PCButtonSupport.Icon(
|
|
173
|
+
type: (dict[key("iconType")] as? String) ?? "",
|
|
174
|
+
name: (dict[key("iconName")] as? String) ?? "",
|
|
175
|
+
uri: (dict[key("iconUri")] as? String) ?? "",
|
|
176
|
+
scale: scale > 0 ? scale : 1,
|
|
177
|
+
tinted: (dict[key("iconTinted")] as? String) != "false",
|
|
178
|
+
request: (dict[key("iconRequest")] as? String) ?? ""
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
return PCTabBarTab(
|
|
182
|
+
label: (dict["label"] as? String) ?? "",
|
|
183
|
+
value: (dict["value"] as? String) ?? "",
|
|
184
|
+
disabled: (dict["disabled"] as? String) == "disabled",
|
|
185
|
+
icon: icon(""),
|
|
186
|
+
selectedIcon: icon("selected"),
|
|
187
|
+
badge: (dict["badge"] as? String) ?? "",
|
|
188
|
+
accessibilityLabel: (dict["accessibilityLabel"] as? String) ?? "",
|
|
189
|
+
testID: (dict["testID"] as? String) ?? "",
|
|
190
|
+
role: (dict["role"] as? String) ?? "",
|
|
191
|
+
systemItem: (dict["systemItem"] as? String) ?? ""
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
generation += 1
|
|
196
|
+
let current = generation
|
|
197
|
+
let unlabeled = labelVisibility == "unlabeled"
|
|
198
|
+
|
|
199
|
+
let barItems = tabs.enumerated().map { index, tab -> UITabBarItem in
|
|
200
|
+
let item: UITabBarItem
|
|
201
|
+
var title = tab.label
|
|
202
|
+
if let system = tab.system {
|
|
203
|
+
// The system's localized title and icon
|
|
204
|
+
item = UITabBarItem(tabBarSystemItem: system, tag: index)
|
|
205
|
+
title = item.title ?? tab.label
|
|
206
|
+
if unlabeled { item.title = nil }
|
|
207
|
+
} else {
|
|
208
|
+
item = UITabBarItem(title: unlabeled ? nil : tab.label, image: nil, tag: index)
|
|
209
|
+
item.image = PCTabBarView.symbol(tab.icon) ?? PCButtonSupport.image(for: tab.icon) { [weak self, weak item] image in
|
|
210
|
+
guard let self, let item, self.generation == current else { return }
|
|
211
|
+
item.image = image
|
|
212
|
+
}
|
|
213
|
+
if !tab.selectedIcon.isPresent {
|
|
214
|
+
item.selectedImage = nil
|
|
215
|
+
} else {
|
|
216
|
+
item.selectedImage = PCTabBarView.symbol(tab.selectedIcon) ?? PCButtonSupport.image(for: tab.selectedIcon) { [weak self, weak item] image in
|
|
217
|
+
guard let self, let item, self.generation == current else { return }
|
|
218
|
+
item.selectedImage = image
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
item.isEnabled = !tab.disabled
|
|
223
|
+
item.badgeValue = tab.badge.isEmpty ? nil : (tab.badge == " " ? "" : tab.badge)
|
|
224
|
+
let spoken = tab.accessibilityLabel.isEmpty ? title : tab.accessibilityLabel
|
|
225
|
+
item.accessibilityLabel = tab.badge.isEmpty || tab.badge == " " ? spoken : "\(spoken), \(tab.badge)"
|
|
226
|
+
return item
|
|
227
|
+
}
|
|
228
|
+
if let host {
|
|
229
|
+
// A controller's bar takes its items from view controllers
|
|
230
|
+
host.setViewControllers(barItems.map { item in
|
|
231
|
+
let child = UIViewController()
|
|
232
|
+
child.view.backgroundColor = .clear
|
|
233
|
+
child.view.isUserInteractionEnabled = false
|
|
234
|
+
child.tabBarItem = item
|
|
235
|
+
return child
|
|
236
|
+
}, animated: false)
|
|
237
|
+
attachScrollView(force: true)
|
|
238
|
+
} else {
|
|
239
|
+
tabBar.setItems(barItems, animated: false)
|
|
240
|
+
}
|
|
241
|
+
applyAppearance()
|
|
242
|
+
updateSelection()
|
|
243
|
+
invalidateIntrinsicContentSize()
|
|
244
|
+
onNeedsRemeasure?()
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/// An SF Symbol as UIKit gives it, so the tab bar applies its own symbol
|
|
248
|
+
/// configuration (size and weight for the running iOS)
|
|
249
|
+
private static func symbol(_ icon: PCButtonSupport.Icon) -> UIImage? {
|
|
250
|
+
guard icon.type == "sfSymbol" else { return nil }
|
|
251
|
+
return UIImage(systemName: icon.name)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
private func updateSelection() {
|
|
255
|
+
if let host {
|
|
256
|
+
if let index = tabs.firstIndex(where: { $0.value == selectedValue }),
|
|
257
|
+
index < (host.viewControllers?.count ?? 0) {
|
|
258
|
+
host.selectedIndex = index
|
|
259
|
+
}
|
|
260
|
+
return
|
|
261
|
+
}
|
|
262
|
+
guard let barItems = tabBar.items else { return }
|
|
263
|
+
if let index = tabs.firstIndex(where: { $0.value == selectedValue }), index < barItems.count {
|
|
264
|
+
tabBar.selectedItem = barItems[index]
|
|
265
|
+
} else {
|
|
266
|
+
tabBar.selectedItem = nil
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// MARK: - Appearance
|
|
271
|
+
|
|
272
|
+
/// Colors, background and font through `UITabBarAppearance`, which covers
|
|
273
|
+
/// the stacked (phone), inline and compact-inline item layouts.
|
|
274
|
+
private func applyAppearance() {
|
|
275
|
+
let customized = activeTintColor != nil || inactiveTintColor != nil || barColor != nil
|
|
276
|
+
|| badgeBackgroundColor != nil || badgeTextColor != nil || labelFont != nil
|
|
277
|
+
guard customized else {
|
|
278
|
+
activeBar.standardAppearance = UITabBarAppearance()
|
|
279
|
+
activeBar.scrollEdgeAppearance = nil
|
|
280
|
+
activeBar.tintColor = nil
|
|
281
|
+
activeBar.unselectedItemTintColor = nil
|
|
282
|
+
onNeedsRemeasure?()
|
|
283
|
+
return
|
|
284
|
+
}
|
|
285
|
+
let appearance = UITabBarAppearance()
|
|
286
|
+
if let barColor {
|
|
287
|
+
if barColor.cgColor.alpha == 0 {
|
|
288
|
+
appearance.configureWithTransparentBackground()
|
|
289
|
+
} else {
|
|
290
|
+
appearance.configureWithOpaqueBackground()
|
|
291
|
+
appearance.backgroundColor = barColor
|
|
292
|
+
}
|
|
293
|
+
} else {
|
|
294
|
+
appearance.configureWithDefaultBackground()
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
for layout in [appearance.stackedLayoutAppearance, appearance.inlineLayoutAppearance, appearance.compactInlineLayoutAppearance] {
|
|
298
|
+
style(layout.normal, color: inactiveTintColor)
|
|
299
|
+
style(layout.selected, color: activeTintColor)
|
|
300
|
+
style(layout.disabled, color: nil)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
activeBar.standardAppearance = appearance
|
|
304
|
+
activeBar.scrollEdgeAppearance = appearance
|
|
305
|
+
// The selected tint also drives template images and the selection
|
|
306
|
+
activeBar.tintColor = activeTintColor
|
|
307
|
+
activeBar.unselectedItemTintColor = inactiveTintColor
|
|
308
|
+
onNeedsRemeasure?()
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
private func style(_ state: UITabBarItemStateAppearance, color: UIColor?) {
|
|
312
|
+
var attributes: [NSAttributedString.Key: Any] = [:]
|
|
313
|
+
if let color {
|
|
314
|
+
state.iconColor = color
|
|
315
|
+
attributes[.foregroundColor] = color
|
|
316
|
+
}
|
|
317
|
+
if let labelFont {
|
|
318
|
+
attributes[.font] = labelFont
|
|
319
|
+
}
|
|
320
|
+
if !attributes.isEmpty {
|
|
321
|
+
state.titleTextAttributes = attributes
|
|
322
|
+
}
|
|
323
|
+
if let badgeBackgroundColor {
|
|
324
|
+
state.badgeBackgroundColor = badgeBackgroundColor
|
|
325
|
+
}
|
|
326
|
+
if let badgeTextColor {
|
|
327
|
+
state.badgeTextAttributes = [.foregroundColor: badgeTextColor]
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// MARK: - UITabBarDelegate
|
|
332
|
+
|
|
333
|
+
public func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
|
|
334
|
+
let index = item.tag
|
|
335
|
+
guard index >= 0, index < tabs.count else { return }
|
|
336
|
+
let reselected = tabs[index].value == selectedValue
|
|
337
|
+
onTabPress?(index, tabs[index].value, reselected)
|
|
338
|
+
// Controlled: the selection follows selectedValue, so a press JS
|
|
339
|
+
// doesn't act on leaves the previous tab selected
|
|
340
|
+
DispatchQueue.main.async { [weak self] in self?.updateSelection() }
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// MARK: - UITabBarControllerDelegate (hosted bar)
|
|
344
|
+
|
|
345
|
+
public func tabBarController(_ controller: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
|
|
346
|
+
guard let index = controller.viewControllers?.firstIndex(of: viewController), index < tabs.count else { return false }
|
|
347
|
+
onTabPress?(index, tabs[index].value, tabs[index].value == selectedValue)
|
|
348
|
+
// Controlled: the selection changes when selectedValue does
|
|
349
|
+
return false
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// MARK: - Hosting (iOS 26 minimize and accessory)
|
|
353
|
+
|
|
354
|
+
private var wantsHost: Bool {
|
|
355
|
+
guard #available(iOS 26.0, *) else { return false }
|
|
356
|
+
return !minimizeBehavior.isEmpty || wantsAccessory
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/// An accessory is linked and this build can host it (iOS 26 SDK)
|
|
360
|
+
private var wantsAccessory: Bool {
|
|
361
|
+
#if compiler(>=6.2)
|
|
362
|
+
if #available(iOS 26.0, *) { return !accessoryID.isEmpty }
|
|
363
|
+
#endif
|
|
364
|
+
return false
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/// Moves the bar into a UITabBarController, or back to the standalone
|
|
368
|
+
/// bar, for the current minimizeBehavior.
|
|
369
|
+
private func configureHost() {
|
|
370
|
+
if wantsHost {
|
|
371
|
+
if host == nil {
|
|
372
|
+
let controller = PCHostTabBarController()
|
|
373
|
+
controller.delegate = self
|
|
374
|
+
// The bar rebuilds its buttons as it minimizes and expands,
|
|
375
|
+
// and places the accessory
|
|
376
|
+
controller.onLayout = { [weak self] in
|
|
377
|
+
// Its subviews (the accessory's container) are placed
|
|
378
|
+
// after this pass
|
|
379
|
+
DispatchQueue.main.async {
|
|
380
|
+
self?.reportAccessoryLayout()
|
|
381
|
+
self?.applyTestIDs()
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
controller.view.backgroundColor = .clear
|
|
385
|
+
// Always the bottom bar: a regular width (iPad, a Max
|
|
386
|
+
// iPhone in landscape) would move the tabs to the top
|
|
387
|
+
if #available(iOS 17.0, *) {
|
|
388
|
+
controller.traitOverrides.horizontalSizeClass = .compact
|
|
389
|
+
}
|
|
390
|
+
host = controller
|
|
391
|
+
tabBar.removeFromSuperview()
|
|
392
|
+
addSubview(controller.view)
|
|
393
|
+
attachHostToParent()
|
|
394
|
+
rebuildItems()
|
|
395
|
+
attachAccessory()
|
|
396
|
+
}
|
|
397
|
+
applyMinimizeBehavior()
|
|
398
|
+
} else if let controller = host {
|
|
399
|
+
releaseAccessory()
|
|
400
|
+
controller.willMove(toParent: nil)
|
|
401
|
+
controller.view.removeFromSuperview()
|
|
402
|
+
controller.removeFromParent()
|
|
403
|
+
host = nil
|
|
404
|
+
addSubview(tabBar)
|
|
405
|
+
rebuildItems()
|
|
406
|
+
}
|
|
407
|
+
setNeedsLayout()
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
private func applyMinimizeBehavior() {
|
|
411
|
+
#if compiler(>=6.2)
|
|
412
|
+
guard #available(iOS 26.0, *), let host else { return }
|
|
413
|
+
switch minimizeBehavior {
|
|
414
|
+
case "": host.tabBarMinimizeBehavior = .never // hosted for the accessory only
|
|
415
|
+
case "never": host.tabBarMinimizeBehavior = .never
|
|
416
|
+
case "onScrollDown": host.tabBarMinimizeBehavior = .onScrollDown
|
|
417
|
+
case "onScrollUp": host.tabBarMinimizeBehavior = .onScrollUp
|
|
418
|
+
default: host.tabBarMinimizeBehavior = .automatic
|
|
419
|
+
}
|
|
420
|
+
#endif
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// MARK: - Accessory (iOS 26)
|
|
424
|
+
|
|
425
|
+
/// Hosts the accessory content registered for accessoryID as the
|
|
426
|
+
/// controller's bottom accessory, or removes it.
|
|
427
|
+
private func attachAccessory() {
|
|
428
|
+
#if compiler(>=6.2)
|
|
429
|
+
guard #available(iOS 26.0, *), let host else { return }
|
|
430
|
+
let content = wantsAccessory ? PCTabBarAccessoryView.content(for: accessoryID) : nil
|
|
431
|
+
if content === hostedAccessory, (content == nil) == (host.bottomAccessory == nil) { return }
|
|
432
|
+
releaseAccessory()
|
|
433
|
+
if let content {
|
|
434
|
+
content.removeFromSuperview()
|
|
435
|
+
hostedAccessory = content
|
|
436
|
+
// Reported once UIKit's layout pass has placed the container too
|
|
437
|
+
content.onLayoutChange = { [weak self] in
|
|
438
|
+
DispatchQueue.main.async { self?.reportAccessoryLayout() }
|
|
439
|
+
}
|
|
440
|
+
host.bottomAccessory = UITabAccessory(contentView: content)
|
|
441
|
+
}
|
|
442
|
+
onNeedsRemeasure?()
|
|
443
|
+
setNeedsLayout()
|
|
444
|
+
#endif
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/// Hands the accessory content back to its placeholder.
|
|
448
|
+
private func releaseAccessory() {
|
|
449
|
+
#if compiler(>=6.2)
|
|
450
|
+
if #available(iOS 26.0, *) { host?.bottomAccessory = nil }
|
|
451
|
+
#endif
|
|
452
|
+
guard let content = hostedAccessory else { return }
|
|
453
|
+
content.onLayoutChange = nil
|
|
454
|
+
hostedAccessory = nil
|
|
455
|
+
lastAccessoryReport = nil
|
|
456
|
+
content.returnHome()
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/// Reports where UIKit put the accessory, so JS lays its content out at
|
|
460
|
+
/// that size, and measures the room it takes above the bar.
|
|
461
|
+
private func reportAccessoryLayout() {
|
|
462
|
+
guard let host, let content = hostedAccessory, content.superview != nil else { return }
|
|
463
|
+
let environment = content.environment
|
|
464
|
+
if environment == "regular" {
|
|
465
|
+
// Inline, the accessory moves beside the bar; the bar keeps the
|
|
466
|
+
// room it takes when regular
|
|
467
|
+
let barTop = host.tabBar.convert(host.tabBar.bounds, to: host.view).minY
|
|
468
|
+
let room = ceil(barTop - content.convert(content.bounds, to: host.view).minY)
|
|
469
|
+
if room > 0, abs(room - accessoryRoom) > 0.5 {
|
|
470
|
+
accessoryRoom = room
|
|
471
|
+
onNeedsRemeasure?()
|
|
472
|
+
setNeedsLayout()
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
let frame = content.convert(content.bounds, to: self)
|
|
476
|
+
guard frame.width > 0, frame.height > 0 else { return }
|
|
477
|
+
if let last = lastAccessoryReport, last.frame == frame, last.environment == environment { return }
|
|
478
|
+
lastAccessoryReport = (frame, environment)
|
|
479
|
+
onAccessoryLayout?(frame, environment)
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/// Height added to the bar's for the hosted accessory
|
|
483
|
+
private var accessoryReserve: CGFloat { wantsAccessory ? accessoryRoom : 0 }
|
|
484
|
+
|
|
485
|
+
/// A child view controller of the nearest view controller, so the host
|
|
486
|
+
/// gets appearance and trait updates.
|
|
487
|
+
private func attachHostToParent() {
|
|
488
|
+
guard let host, host.parent == nil, window != nil else { return }
|
|
489
|
+
var responder: UIResponder? = next
|
|
490
|
+
while let current = responder, !(current is UIViewController) { responder = current.next }
|
|
491
|
+
guard let parent = responder as? UIViewController else { return }
|
|
492
|
+
parent.addChild(host)
|
|
493
|
+
host.didMove(toParent: parent)
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/// Hands the ScrollView with scrollViewNativeID to the hosted tabs as
|
|
497
|
+
/// their content scroll view, which drives the minimize behavior.
|
|
498
|
+
private func attachScrollView(force: Bool = false) {
|
|
499
|
+
guard let host, !scrollViewNativeID.isEmpty, let window else { return }
|
|
500
|
+
if !force, attachedScrollView != nil { return }
|
|
501
|
+
guard let scrollView = PCTabBarView.scrollView(nativeID: scrollViewNativeID, in: window) else { return }
|
|
502
|
+
attachedScrollView = scrollView
|
|
503
|
+
for child in host.viewControllers ?? [] {
|
|
504
|
+
child.setContentScrollView(scrollView, for: .bottom)
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/// The UIScrollView of the React Native view with this nativeID.
|
|
509
|
+
private static func scrollView(nativeID: String, in root: UIView) -> UIScrollView? {
|
|
510
|
+
var match: UIView?
|
|
511
|
+
func find(_ view: UIView) {
|
|
512
|
+
guard match == nil else { return }
|
|
513
|
+
if view.responds(to: NSSelectorFromString("nativeId")),
|
|
514
|
+
view.value(forKey: "nativeId") as? String == nativeID {
|
|
515
|
+
match = view
|
|
516
|
+
return
|
|
517
|
+
}
|
|
518
|
+
view.subviews.forEach(find)
|
|
519
|
+
}
|
|
520
|
+
find(root)
|
|
521
|
+
guard let match else { return nil }
|
|
522
|
+
if let scroll = match as? UIScrollView { return scroll }
|
|
523
|
+
var scroll: UIScrollView?
|
|
524
|
+
func firstScroll(_ view: UIView) {
|
|
525
|
+
guard scroll == nil else { return }
|
|
526
|
+
if let s = view as? UIScrollView { scroll = s; return }
|
|
527
|
+
view.subviews.forEach(firstScroll)
|
|
528
|
+
}
|
|
529
|
+
firstScroll(match)
|
|
530
|
+
return scroll
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
public override func didMoveToWindow() {
|
|
534
|
+
super.didMoveToWindow()
|
|
535
|
+
attachHostToParent()
|
|
536
|
+
attachScrollView()
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// MARK: - Sizing
|
|
540
|
+
|
|
541
|
+
public override var intrinsicContentSize: CGSize {
|
|
542
|
+
CGSize(width: UIView.noIntrinsicMetric, height: tabBar.sizeThatFits(bounds.size).height)
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/// Called by the measuring pipeline: the bar fills the width it is given
|
|
546
|
+
/// and takes the height UIKit wants for it at that width.
|
|
547
|
+
@objc public func sizeForLayout(withConstrainedTo constrainedSize: CGSize) -> CGSize {
|
|
548
|
+
let width = constrainedSize.width > 0 ? constrainedSize.width : PCConstants.fallbackWidth
|
|
549
|
+
let fitted = tabBar.sizeThatFits(CGSize(width: width, height: .greatestFiniteMagnitude))
|
|
550
|
+
return CGSize(width: width, height: fitted.height + accessoryReserve)
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
public override func layoutSubviews() {
|
|
554
|
+
super.layoutSubviews()
|
|
555
|
+
// Frame layout, as UITabBarController gives its bar: under Auto Layout
|
|
556
|
+
// constraints the iOS 26 bar squeezes its tab labels out of view
|
|
557
|
+
// A bar given more height than it needs keeps its own height at the
|
|
558
|
+
// bottom of it, as the system places its bar; stretched, UITabBar
|
|
559
|
+
// spreads the icons and labels apart
|
|
560
|
+
let fitted = ceil(tabBar.sizeThatFits(CGSize(width: bounds.width, height: .greatestFiniteMagnitude)).height)
|
|
561
|
+
let height = min(bounds.height, fitted)
|
|
562
|
+
tabBar.frame = CGRect(x: 0, y: bounds.height - height, width: bounds.width, height: height)
|
|
563
|
+
// The hosted bar also holds the accessory above it
|
|
564
|
+
let hostHeight = min(bounds.height, fitted + accessoryReserve)
|
|
565
|
+
host?.view.frame = CGRect(x: 0, y: bounds.height - hostHeight, width: bounds.width, height: hostHeight)
|
|
566
|
+
// The ScrollView may mount after the bar
|
|
567
|
+
attachScrollView()
|
|
568
|
+
if host != nil {
|
|
569
|
+
DispatchQueue.main.async { [weak self] in
|
|
570
|
+
self?.reportAccessoryLayout()
|
|
571
|
+
self?.applyTestIDs()
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/// Only the bar and the accessory take touches; the host's empty room
|
|
577
|
+
/// (above a minimized bar, beside the accessory) and the space above a
|
|
578
|
+
/// stretched bar let them through.
|
|
579
|
+
public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
|
580
|
+
guard let hit = super.hitTest(point, with: event) else { return nil }
|
|
581
|
+
if hit.isDescendant(of: activeBar) { return hit }
|
|
582
|
+
if let container = hostedAccessory?.superview, hit.isDescendant(of: container) { return hit }
|
|
583
|
+
return nil
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/// Puts each tab's testID on its tab button, the view E2E drivers find
|
|
587
|
+
/// and tap. An identifier on the UITabBarItem doesn't reach every
|
|
588
|
+
/// button (a badged tab's, on iOS 26). The iOS 26 bar draws each button
|
|
589
|
+
/// twice, once for the glass selection and once in front; the front one
|
|
590
|
+
/// takes the touches, so it gets the id.
|
|
591
|
+
private func applyTestIDs() {
|
|
592
|
+
guard tabs.contains(where: { !$0.testID.isEmpty }) else { return }
|
|
593
|
+
var buttons: [UIView] = []
|
|
594
|
+
func collect(_ view: UIView) {
|
|
595
|
+
let name = NSStringFromClass(type(of: view))
|
|
596
|
+
if name.hasSuffix("TabBarButton") || name.hasSuffix("_UITabButton") {
|
|
597
|
+
buttons.append(view)
|
|
598
|
+
return
|
|
599
|
+
}
|
|
600
|
+
view.subviews.forEach(collect)
|
|
601
|
+
}
|
|
602
|
+
let bar = activeBar
|
|
603
|
+
collect(bar)
|
|
604
|
+
// The hosted iOS 26 bar keeps a hidden button for its minimized state
|
|
605
|
+
func shown(_ view: UIView) -> Bool {
|
|
606
|
+
var current: UIView? = view
|
|
607
|
+
while let v = current, v !== bar {
|
|
608
|
+
if v.isHidden || v.alpha < 0.01 { return false }
|
|
609
|
+
current = v.superview
|
|
610
|
+
}
|
|
611
|
+
return true
|
|
612
|
+
}
|
|
613
|
+
buttons = buttons.filter(shown)
|
|
614
|
+
// One button per position, the frontmost (last collected) copy
|
|
615
|
+
func inOrder(_ buttons: [UIView]) -> [UIView] {
|
|
616
|
+
var byPosition: [Int: UIView] = [:]
|
|
617
|
+
for button in buttons {
|
|
618
|
+
byPosition[Int(bar.convert(button.bounds, from: button).minX.rounded())] = button
|
|
619
|
+
}
|
|
620
|
+
var ordered = Array(byPosition.values)
|
|
621
|
+
ordered.sort { bar.convert($0.bounds, from: $0).minX < bar.convert($1.bounds, from: $1).minX }
|
|
622
|
+
if bar.effectiveUserInterfaceLayoutDirection == .rightToLeft { ordered.reverse() }
|
|
623
|
+
return ordered
|
|
624
|
+
}
|
|
625
|
+
// iOS 26 draws the search tab apart, in an auxiliary view at the end
|
|
626
|
+
// of the bar, wherever it is among the items
|
|
627
|
+
func isAuxiliary(_ view: UIView) -> Bool {
|
|
628
|
+
var current = view.superview
|
|
629
|
+
while let v = current, v !== bar {
|
|
630
|
+
if NSStringFromClass(type(of: v)).hasSuffix("AuxiliaryView") { return true }
|
|
631
|
+
current = v.superview
|
|
632
|
+
}
|
|
633
|
+
return false
|
|
634
|
+
}
|
|
635
|
+
let auxiliary = inOrder(buttons.filter(isAuxiliary))
|
|
636
|
+
let regular = inOrder(buttons.filter { !isAuxiliary($0) })
|
|
637
|
+
let apart = auxiliary.isEmpty ? [] : tabs.filter { $0.system == .search }
|
|
638
|
+
let inline = auxiliary.isEmpty ? tabs : tabs.filter { $0.system != .search }
|
|
639
|
+
guard regular.count == inline.count, auxiliary.count == apart.count else { return }
|
|
640
|
+
for (button, tab) in zip(regular + auxiliary, inline + apart) {
|
|
641
|
+
button.accessibilityIdentifier = tab.testID.isEmpty ? nil : tab.testID
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
public override func safeAreaInsetsDidChange() {
|
|
646
|
+
super.safeAreaInsetsDidChange()
|
|
647
|
+
// A bar at the bottom of the screen grows over the home indicator
|
|
648
|
+
onNeedsRemeasure?()
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/// A UITabBar that reports its layout passes.
|
|
653
|
+
final class PCLayoutReportingTabBar: UITabBar {
|
|
654
|
+
var onLayout: (() -> Void)?
|
|
655
|
+
|
|
656
|
+
override func layoutSubviews() {
|
|
657
|
+
super.layoutSubviews()
|
|
658
|
+
onLayout?()
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/// The tab bar controller hosting a minimizing bar, reporting its layout
|
|
663
|
+
/// passes (the bar lays its buttons out again as it minimizes and expands).
|
|
664
|
+
final class PCHostTabBarController: UITabBarController {
|
|
665
|
+
var onLayout: (() -> Void)?
|
|
666
|
+
|
|
667
|
+
override func viewDidLayoutSubviews() {
|
|
668
|
+
super.viewDidLayoutSubviews()
|
|
669
|
+
onLayout?()
|
|
670
|
+
}
|
|
671
|
+
}
|