react-native-platform-components 1.4.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 +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.d.ts +3 -2
- package/plugin/build/index.d.ts.map +1 -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
|
@@ -2,6 +2,9 @@ import UIKit
|
|
|
2
2
|
|
|
3
3
|
/// A row of native buttons (`UIButton` with configurations), with optional
|
|
4
4
|
/// single / multiple selection shown through the buttons' selected state.
|
|
5
|
+
/// Buttons that don't fit can fold into a "…" button with a `UIMenu`
|
|
6
|
+
/// (overflow "menu"). In split mode the row is one button joined to a
|
|
7
|
+
/// chevron button that opens a `UIMenu` (SplitButton).
|
|
5
8
|
@objcMembers
|
|
6
9
|
public final class PCButtonGroupView: UIView {
|
|
7
10
|
private struct Item {
|
|
@@ -78,10 +81,46 @@ public final class PCButtonGroupView: UIView {
|
|
|
78
81
|
didSet { applyConfigurations() }
|
|
79
82
|
}
|
|
80
83
|
|
|
84
|
+
/// "none" | "menu" | "wrap" (Android only; the same as "none" here)
|
|
85
|
+
public var overflow: String = "none" {
|
|
86
|
+
didSet {
|
|
87
|
+
guard oldValue != overflow else { return }
|
|
88
|
+
overflowDirty = true
|
|
89
|
+
invalidateIntrinsicContentSize()
|
|
90
|
+
setNeedsLayout()
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/// Split mode: the first button joined to a chevron button with `menu`.
|
|
95
|
+
public var split: Bool = false {
|
|
96
|
+
didSet { if oldValue != split { rebuild() } }
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/// ObjC++ sets this as an array of dictionaries: the split button's
|
|
100
|
+
/// flattened menu items
|
|
101
|
+
public var menuItems: [Any] = [] {
|
|
102
|
+
didSet {
|
|
103
|
+
splitItems = PCMenuSupport.items(from: menuItems)
|
|
104
|
+
updateSplitMenu()
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/// What VoiceOver announces for the split button's chevron.
|
|
109
|
+
public var menuAccessibilityLabel: String = "" {
|
|
110
|
+
didSet { chevronButton?.accessibilityLabel = menuAccessibilityLabel.isEmpty ? nil : menuAccessibilityLabel }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/// The `haptics` prop: PCButtonGroup.mm plays it on a press (an overflow
|
|
114
|
+
/// pick included), the split menu handler on a pick
|
|
115
|
+
public let haptics = PCHaptics()
|
|
116
|
+
|
|
81
117
|
// MARK: - Events back to ObjC++
|
|
82
118
|
|
|
83
119
|
public var onPress: ((Int, String) -> Void)? // (index, value)
|
|
84
120
|
public var onSelectionChange: (([String]) -> Void)?
|
|
121
|
+
public var onMenuSelect: ((String, String) -> Void)? // (id, title)
|
|
122
|
+
public var onMenuOpen: (() -> Void)?
|
|
123
|
+
public var onMenuClose: (() -> Void)?
|
|
85
124
|
|
|
86
125
|
/// Called when content changed after layout (an icon finished loading),
|
|
87
126
|
/// so the Fabric measurement can be refreshed.
|
|
@@ -94,6 +133,20 @@ public final class PCButtonGroupView: UIView {
|
|
|
94
133
|
private var uiButtons: [UIButton] = []
|
|
95
134
|
private var iconImages: [UIImage?] = []
|
|
96
135
|
|
|
136
|
+
/// Split mode: the chevron button after the button, and its menu items.
|
|
137
|
+
private var chevronButton: PCMenuButton?
|
|
138
|
+
private var splitItems: [PCMenuItem] = []
|
|
139
|
+
private let splitMenuImages = PCMenuImageState()
|
|
140
|
+
private let overflowMenuImages = PCMenuImageState()
|
|
141
|
+
|
|
142
|
+
/// Overflow "menu": the "…" button that holds the buttons that don't
|
|
143
|
+
/// fit (made the first time it is needed), and how many buttons are
|
|
144
|
+
/// showing (all of them when nil).
|
|
145
|
+
private var overflowButton: PCMenuButton?
|
|
146
|
+
private var visibleCount: Int?
|
|
147
|
+
/// Set when the buttons changed, so the next layout folds them again.
|
|
148
|
+
private var overflowDirty = true
|
|
149
|
+
|
|
97
150
|
/// Bumped on every rebuild so late image loads can't touch stale buttons.
|
|
98
151
|
private var rebuildGeneration = 0
|
|
99
152
|
|
|
@@ -144,13 +197,23 @@ public final class PCButtonGroupView: UIView {
|
|
|
144
197
|
|
|
145
198
|
uiButtons.forEach { $0.removeFromSuperview() }
|
|
146
199
|
uiButtons = []
|
|
200
|
+
chevronButton?.removeFromSuperview()
|
|
201
|
+
chevronButton = nil
|
|
202
|
+
visibleCount = nil
|
|
203
|
+
overflowButton?.isHidden = true
|
|
204
|
+
overflowDirty = true
|
|
205
|
+
// A split button is one button and its chevron
|
|
206
|
+
if split && items.count > 1 { items = Array(items.prefix(1)) }
|
|
207
|
+
overflowMenuImages.retain(icons: items.map(\.icon))
|
|
147
208
|
iconImages = Array(repeating: nil, count: items.count)
|
|
148
209
|
|
|
149
210
|
for (index, item) in items.enumerated() {
|
|
150
211
|
let button = UIButton(type: .system)
|
|
151
212
|
button.tag = index
|
|
152
213
|
button.addTarget(self, action: #selector(tapped(_:)), for: .touchUpInside)
|
|
153
|
-
|
|
214
|
+
button.addTarget(self, action: #selector(touchedDown), for: .touchDown)
|
|
215
|
+
// Before the overflow button, which stays last
|
|
216
|
+
stack.insertArrangedSubview(button, at: index)
|
|
154
217
|
uiButtons.append(button)
|
|
155
218
|
|
|
156
219
|
iconImages[index] = PCButtonSupport.image(for: item.icon) { [weak self] image in
|
|
@@ -161,8 +224,19 @@ public final class PCButtonGroupView: UIView {
|
|
|
161
224
|
}
|
|
162
225
|
}
|
|
163
226
|
|
|
227
|
+
if split {
|
|
228
|
+
let chevron = PCMenuButton(type: .system)
|
|
229
|
+
chevron.accessibilityLabel = menuAccessibilityLabel.isEmpty ? nil : menuAccessibilityLabel
|
|
230
|
+
chevron.onMenuOpen = { [weak self] in self?.onMenuOpen?() }
|
|
231
|
+
chevron.onMenuClose = { [weak self] in self?.onMenuClose?() }
|
|
232
|
+
stack.insertArrangedSubview(chevron, at: items.count)
|
|
233
|
+
chevronButton = chevron
|
|
234
|
+
updateSplitMenu()
|
|
235
|
+
}
|
|
236
|
+
|
|
164
237
|
applyConfigurations()
|
|
165
238
|
updateEnabled()
|
|
239
|
+
setNeedsLayout()
|
|
166
240
|
}
|
|
167
241
|
|
|
168
242
|
private func applyLayout() {
|
|
@@ -191,7 +265,11 @@ public final class PCButtonGroupView: UIView {
|
|
|
191
265
|
)
|
|
192
266
|
button.accessibilityLabel = item.spokenLabel.isEmpty ? nil : item.spokenLabel
|
|
193
267
|
}
|
|
268
|
+
if let chevron = chevronButton { configureSymbolButton(chevron, symbol: "chevron.down") }
|
|
269
|
+
if let more = overflowButton { configureSymbolButton(more, symbol: "ellipsis") }
|
|
270
|
+
overflowDirty = true
|
|
194
271
|
invalidateIntrinsicContentSize()
|
|
272
|
+
setNeedsLayout()
|
|
195
273
|
}
|
|
196
274
|
|
|
197
275
|
private func updateEnabled() {
|
|
@@ -200,18 +278,148 @@ public final class PCButtonGroupView: UIView {
|
|
|
200
278
|
for (index, button) in uiButtons.enumerated() where index < items.count {
|
|
201
279
|
button.isEnabled = enabled && !items[index].disabled
|
|
202
280
|
}
|
|
281
|
+
chevronButton?.isEnabled = enabled
|
|
282
|
+
overflowButton?.isEnabled = enabled
|
|
283
|
+
updateOverflowMenu()
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/// The chevron and "…" buttons take the variant of the buttons.
|
|
287
|
+
private func configureSymbolButton(_ button: UIButton, symbol: String) {
|
|
288
|
+
button.configuration = PCButtonSupport.makeConfiguration(
|
|
289
|
+
variant: variant,
|
|
290
|
+
selected: false,
|
|
291
|
+
size: size,
|
|
292
|
+
shape: shape,
|
|
293
|
+
label: "",
|
|
294
|
+
image: UIImage(systemName: symbol),
|
|
295
|
+
containerColor: containerColor,
|
|
296
|
+
foregroundColor: foregroundColor,
|
|
297
|
+
font: labelFont
|
|
298
|
+
)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// MARK: - Split menu
|
|
302
|
+
|
|
303
|
+
private func updateSplitMenu() {
|
|
304
|
+
splitMenuImages.retain(icons: splitItems.map(\.icon))
|
|
305
|
+
guard let chevron = chevronButton else { return }
|
|
306
|
+
chevron.setMenu(splitItems.isEmpty ? nil : PCMenuSupport.menu(
|
|
307
|
+
title: "",
|
|
308
|
+
items: splitItems,
|
|
309
|
+
imageState: splitMenuImages,
|
|
310
|
+
onImageLoaded: { [weak self] in self?.updateSplitMenu() },
|
|
311
|
+
handler: { [weak self] item in
|
|
312
|
+
guard let self else { return }
|
|
313
|
+
self.haptics.perform(in: self, override: item.haptics)
|
|
314
|
+
self.onMenuSelect?(item.id, item.title)
|
|
315
|
+
}
|
|
316
|
+
))
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// MARK: - Overflow
|
|
320
|
+
|
|
321
|
+
/// Folds the trailing buttons that don't fit into the "…" button, which
|
|
322
|
+
/// takes their place at the end of the row.
|
|
323
|
+
public override func layoutSubviews() {
|
|
324
|
+
updateOverflow()
|
|
325
|
+
super.layoutSubviews()
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
private func updateOverflow() {
|
|
329
|
+
let count: Int? = overflow == "menu" && !split && bounds.width > 0 ? fittingCount() : nil
|
|
330
|
+
guard overflowDirty || count != visibleCount else { return }
|
|
331
|
+
overflowDirty = false
|
|
332
|
+
visibleCount = count
|
|
333
|
+
for (index, button) in uiButtons.enumerated() {
|
|
334
|
+
button.isHidden = count.map { index >= $0 } ?? false
|
|
335
|
+
}
|
|
336
|
+
if count != nil {
|
|
337
|
+
makeOverflowButton().isHidden = false
|
|
338
|
+
} else {
|
|
339
|
+
overflowButton?.isHidden = true
|
|
340
|
+
}
|
|
341
|
+
updateOverflowMenu()
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/// The "…" button, at the end of the row. The ellipsis symbol reads as
|
|
345
|
+
/// "More" in VoiceOver.
|
|
346
|
+
private func makeOverflowButton() -> PCMenuButton {
|
|
347
|
+
if let button = overflowButton { return button }
|
|
348
|
+
let button = PCMenuButton(type: .system)
|
|
349
|
+
button.isHidden = true
|
|
350
|
+
button.isEnabled = interactivity != "disabled"
|
|
351
|
+
configureSymbolButton(button, symbol: "ellipsis")
|
|
352
|
+
stack.addArrangedSubview(button)
|
|
353
|
+
overflowButton = button
|
|
354
|
+
return button
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/// How many buttons fit before the "…" button, or nil when all of them
|
|
358
|
+
/// fit.
|
|
359
|
+
private func fittingCount() -> Int? {
|
|
360
|
+
let widths = uiButtons.map { $0.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).width }
|
|
361
|
+
let gap = stack.spacing
|
|
362
|
+
let all = widths.reduce(0, +) + gap * CGFloat(max(widths.count - 1, 0))
|
|
363
|
+
guard all > bounds.width + 0.5 else { return nil }
|
|
364
|
+
var used = makeOverflowButton().systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).width
|
|
365
|
+
var count = 0
|
|
366
|
+
for width in widths {
|
|
367
|
+
guard used + gap + width <= bounds.width + 0.5 else { break }
|
|
368
|
+
used += gap + width
|
|
369
|
+
count += 1
|
|
370
|
+
}
|
|
371
|
+
return count
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/// The "…" button's menu: the hidden buttons, with their icons, disabled
|
|
375
|
+
/// state and selection checkmark. A pick acts like a press.
|
|
376
|
+
private func updateOverflowMenu() {
|
|
377
|
+
guard let overflowButton else { return }
|
|
378
|
+
guard let count = visibleCount else {
|
|
379
|
+
overflowMenuImages.retain(icons: [])
|
|
380
|
+
overflowButton.setMenu(nil)
|
|
381
|
+
return
|
|
382
|
+
}
|
|
383
|
+
let enabled = interactivity != "disabled"
|
|
384
|
+
let hidden = items.enumerated().dropFirst(count).map { index, item in
|
|
385
|
+
PCMenuItem(
|
|
386
|
+
index: index,
|
|
387
|
+
id: item.value,
|
|
388
|
+
title: item.label.isEmpty ? item.accessibilityLabel : item.label,
|
|
389
|
+
icon: item.icon,
|
|
390
|
+
disabled: !enabled || item.disabled,
|
|
391
|
+
state: selection != "none" && selectedValues.contains(item.value) ? "on" : ""
|
|
392
|
+
)
|
|
393
|
+
}
|
|
394
|
+
overflowButton.setMenu(PCMenuSupport.menu(
|
|
395
|
+
title: "",
|
|
396
|
+
items: hidden,
|
|
397
|
+
imageState: overflowMenuImages,
|
|
398
|
+
onImageLoaded: { [weak self] in self?.updateOverflowMenu() },
|
|
399
|
+
handler: { [weak self] item in self?.press(at: item.index) }
|
|
400
|
+
))
|
|
203
401
|
}
|
|
204
402
|
|
|
205
403
|
// MARK: - Selection
|
|
206
404
|
|
|
405
|
+
/// Readies the haptic for the press that is likely to follow.
|
|
406
|
+
@objc private func touchedDown() {
|
|
407
|
+
haptics.prepare(in: self)
|
|
408
|
+
}
|
|
409
|
+
|
|
207
410
|
@objc private func tapped(_ sender: UIButton) {
|
|
208
|
-
|
|
411
|
+
press(at: sender.tag)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/// A press on a button, or a pick of its overflow menu item.
|
|
415
|
+
private func press(at index: Int) {
|
|
209
416
|
guard index >= 0, index < items.count else { return }
|
|
210
417
|
let item = items[index]
|
|
211
418
|
onPress?(index, item.value)
|
|
212
419
|
|
|
213
420
|
guard selection != "none", let next = nextSelection(tapping: item.value) else { return }
|
|
214
|
-
|
|
421
|
+
// The parent owns selection. A rejected change must leave the
|
|
422
|
+
// existing buttons (and overflow checkmarks) selected.
|
|
215
423
|
onSelectionChange?(next)
|
|
216
424
|
}
|
|
217
425
|
|
|
@@ -238,17 +446,28 @@ public final class PCButtonGroupView: UIView {
|
|
|
238
446
|
|
|
239
447
|
// MARK: - Sizing
|
|
240
448
|
|
|
449
|
+
/// The row with every button showing: an overflowing group reports its
|
|
450
|
+
/// full width, and Yoga clamps it to the space there is.
|
|
451
|
+
private func naturalSize() -> CGSize {
|
|
452
|
+
guard visibleCount != nil else {
|
|
453
|
+
return stack.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
|
|
454
|
+
}
|
|
455
|
+
let sizes = uiButtons.map { $0.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) }
|
|
456
|
+
let width = sizes.map(\.width).reduce(0, +) + stack.spacing * CGFloat(max(sizes.count - 1, 0))
|
|
457
|
+
return CGSize(width: width, height: sizes.map(\.height).max() ?? 0)
|
|
458
|
+
}
|
|
459
|
+
|
|
241
460
|
public override var intrinsicContentSize: CGSize {
|
|
242
|
-
|
|
461
|
+
naturalSize()
|
|
243
462
|
}
|
|
244
463
|
|
|
245
464
|
public override func sizeThatFits(_ size: CGSize) -> CGSize {
|
|
246
|
-
|
|
465
|
+
naturalSize()
|
|
247
466
|
}
|
|
248
467
|
|
|
249
468
|
/// Called by the measuring pipeline to get the size for Yoga layout.
|
|
250
469
|
@objc public func sizeForLayout(withConstrainedTo constrainedSize: CGSize) -> CGSize {
|
|
251
|
-
let fitted =
|
|
470
|
+
let fitted = naturalSize()
|
|
252
471
|
return CGSize(width: ceil(fitted.width), height: ceil(fitted.height))
|
|
253
472
|
}
|
|
254
473
|
}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
import Symbols
|
|
1
2
|
import UIKit
|
|
2
3
|
|
|
3
4
|
/// UIButton configuration and icon handling shared by PCButtonView and
|
|
4
5
|
/// PCButtonGroupView.
|
|
5
6
|
enum PCButtonSupport {
|
|
6
|
-
struct Icon:
|
|
7
|
+
struct Icon: Hashable {
|
|
7
8
|
/// "", "sfSymbol", "drawable" (ignored on iOS) or "image"
|
|
8
9
|
var type: String = ""
|
|
9
10
|
var name: String = ""
|
|
10
11
|
var uri: String = ""
|
|
11
12
|
var scale: CGFloat = 1
|
|
12
13
|
var tinted: Bool = true
|
|
14
|
+
var request: String = ""
|
|
13
15
|
|
|
14
16
|
var isPresent: Bool { type == "sfSymbol" || type == "image" }
|
|
15
17
|
|
|
@@ -17,12 +19,13 @@ enum PCButtonSupport {
|
|
|
17
19
|
|
|
18
20
|
init() {}
|
|
19
21
|
|
|
20
|
-
init(type: String, name: String, uri: String, scale: CGFloat, tinted: Bool) {
|
|
22
|
+
init(type: String, name: String, uri: String, scale: CGFloat, tinted: Bool, request: String = "") {
|
|
21
23
|
self.type = type
|
|
22
24
|
self.name = name
|
|
23
25
|
self.uri = uri
|
|
24
26
|
self.scale = scale > 0 ? scale : 1
|
|
25
27
|
self.tinted = tinted
|
|
28
|
+
self.request = request
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
/// Reads the flat icon fields (iconType, iconName, ...) bridged as a dictionary.
|
|
@@ -33,7 +36,8 @@ enum PCButtonSupport {
|
|
|
33
36
|
name: (dictionary["iconName"] as? String) ?? "",
|
|
34
37
|
uri: (dictionary["iconUri"] as? String) ?? "",
|
|
35
38
|
scale: scale,
|
|
36
|
-
tinted: (dictionary["iconTinted"] as? String) != "false"
|
|
39
|
+
tinted: (dictionary["iconTinted"] as? String) != "false",
|
|
40
|
+
request: (dictionary["iconRequest"] as? String) ?? ""
|
|
37
41
|
)
|
|
38
42
|
}
|
|
39
43
|
}
|
|
@@ -48,17 +52,81 @@ enum PCButtonSupport {
|
|
|
48
52
|
/// | outlined | .bordered() |
|
|
49
53
|
/// | text | .plain() |
|
|
50
54
|
/// | elevated | .gray() |
|
|
55
|
+
/// | glass | .glass() on iOS 26+, .gray() before |
|
|
56
|
+
/// | prominentGlass | .prominentGlass() on iOS 26+, .filled() before |
|
|
57
|
+
/// | clearGlass | .clearGlass() on iOS 26+, .gray() before |
|
|
58
|
+
/// | prominentClearGlass | .prominentClearGlass() on iOS 26+, .filled() before |
|
|
59
|
+
///
|
|
60
|
+
/// Selected glass buttons, clear or not, use the prominent glass style.
|
|
51
61
|
static func configuration(variant: String, selected: Bool) -> UIButton.Configuration {
|
|
52
|
-
if selected {
|
|
62
|
+
if selected {
|
|
63
|
+
switch variant {
|
|
64
|
+
// Prominent clear glass has no tint unless given a color, so a
|
|
65
|
+
// selected clear glass button takes the prominent glass too
|
|
66
|
+
case "glass", "prominentGlass", "clearGlass", "prominentClearGlass": return prominentGlass()
|
|
67
|
+
default: return .filled()
|
|
68
|
+
}
|
|
69
|
+
}
|
|
53
70
|
switch variant {
|
|
54
71
|
case "tonal": return .tinted()
|
|
55
72
|
case "outlined": return .bordered()
|
|
56
73
|
case "text": return .plain()
|
|
57
74
|
case "elevated": return .gray()
|
|
75
|
+
case "glass": return glassConfiguration()
|
|
76
|
+
case "prominentGlass": return prominentGlass()
|
|
77
|
+
case "clearGlass": return clearGlass()
|
|
78
|
+
case "prominentClearGlass": return prominentClearGlass()
|
|
58
79
|
default: return .filled()
|
|
59
80
|
}
|
|
60
81
|
}
|
|
61
82
|
|
|
83
|
+
/// The variant a toggle button shows. UIKit gives most configurations a
|
|
84
|
+
/// selected look of their own (tinted becomes filled; bordered, plain,
|
|
85
|
+
/// gray and glass become tinted), but none for the prominent styles and
|
|
86
|
+
/// clear glass. Those toggles show a quieter style while off (filled is
|
|
87
|
+
/// gray, prominent glass is glass), and clear glass takes the prominent
|
|
88
|
+
/// glass while on.
|
|
89
|
+
static func toggleVariant(_ variant: String, selected: Bool) -> String {
|
|
90
|
+
switch variant {
|
|
91
|
+
case "filled": return selected ? "filled" : "elevated"
|
|
92
|
+
case "prominentGlass": return selected ? "prominentGlass" : "glass"
|
|
93
|
+
case "clearGlass", "prominentClearGlass": return selected ? "prominentGlass" : "clearGlass"
|
|
94
|
+
default: return variant
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/// `.glass()` needs the iOS 26 SDK and runtime; `.gray()` otherwise.
|
|
99
|
+
private static func glassConfiguration() -> UIButton.Configuration {
|
|
100
|
+
#if compiler(>=6.2)
|
|
101
|
+
if #available(iOS 26.0, *) { return .glass() }
|
|
102
|
+
#endif
|
|
103
|
+
return .gray()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/// `.prominentGlass()` needs the iOS 26 SDK and runtime; `.filled()` otherwise.
|
|
107
|
+
private static func prominentGlass() -> UIButton.Configuration {
|
|
108
|
+
#if compiler(>=6.2)
|
|
109
|
+
if #available(iOS 26.0, *) { return .prominentGlass() }
|
|
110
|
+
#endif
|
|
111
|
+
return .filled()
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/// `.clearGlass()` needs the iOS 26 SDK and runtime; `.gray()` otherwise.
|
|
115
|
+
private static func clearGlass() -> UIButton.Configuration {
|
|
116
|
+
#if compiler(>=6.2)
|
|
117
|
+
if #available(iOS 26.0, *) { return .clearGlass() }
|
|
118
|
+
#endif
|
|
119
|
+
return .gray()
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/// `.prominentClearGlass()` needs the iOS 26 SDK and runtime; `.filled()` otherwise.
|
|
123
|
+
private static func prominentClearGlass() -> UIButton.Configuration {
|
|
124
|
+
#if compiler(>=6.2)
|
|
125
|
+
if #available(iOS 26.0, *) { return .prominentClearGlass() }
|
|
126
|
+
#endif
|
|
127
|
+
return .filled()
|
|
128
|
+
}
|
|
129
|
+
|
|
62
130
|
/// Material's five sizes onto UIKit's four.
|
|
63
131
|
static func buttonSize(_ size: String) -> UIButton.Configuration.Size {
|
|
64
132
|
switch size {
|
|
@@ -87,15 +155,24 @@ enum PCButtonSupport {
|
|
|
87
155
|
image: UIImage?,
|
|
88
156
|
containerColor: UIColor?,
|
|
89
157
|
foregroundColor: UIColor?,
|
|
90
|
-
font: UIFont
|
|
158
|
+
font: UIFont?,
|
|
159
|
+
imagePlacement: NSDirectionalRectEdge = .leading,
|
|
160
|
+
cornerRadius: CGFloat? = nil,
|
|
161
|
+
maxFontSizeMultiplier: CGFloat = 0,
|
|
162
|
+
traits: UITraitCollection? = nil
|
|
91
163
|
) -> UIButton.Configuration {
|
|
92
164
|
var config = configuration(variant: variant, selected: selected)
|
|
93
165
|
config.title = label.isEmpty ? nil : label
|
|
94
166
|
config.image = image
|
|
95
167
|
config.imagePadding = (image != nil && !label.isEmpty) ? 8 : 0
|
|
168
|
+
config.imagePlacement = imagePlacement
|
|
96
169
|
config.buttonSize = buttonSize(size)
|
|
97
170
|
config.titleLineBreakMode = .byTruncatingTail
|
|
98
|
-
if let
|
|
171
|
+
if let cornerRadius {
|
|
172
|
+
// A numeric radius overrides the shape
|
|
173
|
+
config.cornerStyle = .fixed
|
|
174
|
+
config.background.cornerRadius = cornerRadius
|
|
175
|
+
} else if let corner = cornerStyle(shape) {
|
|
99
176
|
config.cornerStyle = corner
|
|
100
177
|
}
|
|
101
178
|
if let containerColor {
|
|
@@ -104,26 +181,62 @@ enum PCButtonSupport {
|
|
|
104
181
|
if let foregroundColor {
|
|
105
182
|
config.baseForegroundColor = foregroundColor
|
|
106
183
|
}
|
|
107
|
-
|
|
184
|
+
var titleFont = font
|
|
185
|
+
if titleFont == nil, maxFontSizeMultiplier >= 1, !label.isEmpty, let traits,
|
|
186
|
+
let systemFont = defaultTitleFont(for: config) {
|
|
187
|
+
titleFont = cappedFont(systemFont, maxFontSizeMultiplier: maxFontSizeMultiplier, traits: traits)
|
|
188
|
+
}
|
|
189
|
+
if let titleFont {
|
|
108
190
|
config.titleTextAttributesTransformer = UIConfigurationTextAttributesTransformer { incoming in
|
|
109
191
|
var outgoing = incoming
|
|
110
|
-
outgoing.font =
|
|
192
|
+
outgoing.font = titleFont
|
|
111
193
|
return outgoing
|
|
112
194
|
}
|
|
113
195
|
}
|
|
114
196
|
return config
|
|
115
197
|
}
|
|
116
198
|
|
|
199
|
+
/// The title font UIKit picks for a configuration, read from a throwaway
|
|
200
|
+
/// button.
|
|
201
|
+
private static func defaultTitleFont(for config: UIButton.Configuration) -> UIFont? {
|
|
202
|
+
let probe = UIButton(configuration: config)
|
|
203
|
+
probe.updateConfiguration()
|
|
204
|
+
probe.layoutIfNeeded()
|
|
205
|
+
return probe.titleLabel?.font
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/// Caps a Dynamic Type font at `maxFontSizeMultiplier` times its size at
|
|
209
|
+
/// the default content size category, as React Native's `Text` does. The
|
|
210
|
+
/// size is read for `traits`, so the probe's own traits don't matter.
|
|
211
|
+
/// nil when the cap doesn't bind, or the font has no text style (it
|
|
212
|
+
/// doesn't scale), so UIKit keeps its own font.
|
|
213
|
+
static func cappedFont(_ font: UIFont, maxFontSizeMultiplier: CGFloat, traits: UITraitCollection) -> UIFont? {
|
|
214
|
+
guard maxFontSizeMultiplier >= 1,
|
|
215
|
+
let style = font.fontDescriptor.object(forKey: .textStyle) as? String
|
|
216
|
+
else { return nil }
|
|
217
|
+
let textStyle = UIFont.TextStyle(rawValue: style)
|
|
218
|
+
let defaultTraits = UITraitCollection(preferredContentSizeCategory: .large)
|
|
219
|
+
let base = UIFont.preferredFont(forTextStyle: textStyle, compatibleWith: defaultTraits).pointSize
|
|
220
|
+
let current = UIFont.preferredFont(forTextStyle: textStyle, compatibleWith: traits).pointSize
|
|
221
|
+
let cap = base * maxFontSizeMultiplier
|
|
222
|
+
guard current > cap else { return nil }
|
|
223
|
+
// A plain system font at the capped size: a font that keeps its text
|
|
224
|
+
// style could be scaled again by the label.
|
|
225
|
+
let fontTraits = font.fontDescriptor.object(forKey: .traits) as? [UIFontDescriptor.TraitKey: Any]
|
|
226
|
+
let weight = (fontTraits?[.weight] as? CGFloat).map { UIFont.Weight($0) } ?? .regular
|
|
227
|
+
return UIFont.systemFont(ofSize: cap, weight: weight)
|
|
228
|
+
}
|
|
229
|
+
|
|
117
230
|
/// Resolves the icon's image. SF Symbols resolve synchronously; images
|
|
118
231
|
/// that are still loading return nil and call `completion` on the main
|
|
119
232
|
/// thread once they arrive.
|
|
120
233
|
static func image(for icon: Icon, completion: @escaping (UIImage?) -> Void) -> UIImage? {
|
|
121
234
|
switch icon.type {
|
|
122
235
|
case "sfSymbol":
|
|
123
|
-
return
|
|
236
|
+
return PCImageLoader.symbol(named: icon.name).map { decorate($0, tinted: icon.tinted) }
|
|
124
237
|
|
|
125
238
|
case "image":
|
|
126
|
-
let cached = PCImageLoader.shared.image(uri: icon.uri, scale: icon.scale) { image in
|
|
239
|
+
let cached = PCImageLoader.shared.image(uri: icon.uri, scale: icon.scale, request: icon.request) { image in
|
|
127
240
|
completion(image.map { decorate($0, tinted: icon.tinted) })
|
|
128
241
|
}
|
|
129
242
|
return cached.map { decorate($0, tinted: icon.tinted) }
|
|
@@ -139,3 +252,61 @@ enum PCButtonSupport {
|
|
|
139
252
|
image.withRenderingMode(tinted ? .alwaysTemplate : .alwaysOriginal)
|
|
140
253
|
}
|
|
141
254
|
}
|
|
255
|
+
|
|
256
|
+
/// SF Symbol effects for Button's `ios.symbolEffect`, through
|
|
257
|
+
/// `UIImageView.addSymbolEffect`. `bounce`, `pulse` and `variableColor` need
|
|
258
|
+
/// iOS 17; `wiggle`, `rotate` and `breathe` iOS 18. Unknown names and effects
|
|
259
|
+
/// the running iOS doesn't have do nothing.
|
|
260
|
+
@available(iOS 17.0, *)
|
|
261
|
+
enum PCSymbolEffects {
|
|
262
|
+
/// Adds the effect: repeating until the image view's effects are
|
|
263
|
+
/// removed, or played once.
|
|
264
|
+
static func add(_ name: String, to view: UIImageView, repeating: Bool) {
|
|
265
|
+
switch name {
|
|
266
|
+
case "bounce":
|
|
267
|
+
if repeating {
|
|
268
|
+
if #available(iOS 18.0, *) {
|
|
269
|
+
indefinite(.bounce, view)
|
|
270
|
+
} else {
|
|
271
|
+
// Bounce is a one-shot effect on iOS 17; repeat it
|
|
272
|
+
discrete(.bounce, view, options: .repeating)
|
|
273
|
+
}
|
|
274
|
+
} else {
|
|
275
|
+
discrete(.bounce, view)
|
|
276
|
+
}
|
|
277
|
+
case "pulse":
|
|
278
|
+
repeating ? indefinite(.pulse, view) : discrete(.pulse, view)
|
|
279
|
+
case "variableColor":
|
|
280
|
+
repeating ? indefinite(.variableColor, view) : discrete(.variableColor, view)
|
|
281
|
+
case "wiggle":
|
|
282
|
+
if #available(iOS 18.0, *) {
|
|
283
|
+
repeating ? indefinite(.wiggle, view) : discrete(.wiggle, view)
|
|
284
|
+
}
|
|
285
|
+
case "rotate":
|
|
286
|
+
if #available(iOS 18.0, *) {
|
|
287
|
+
repeating ? indefinite(.rotate, view) : discrete(.rotate, view)
|
|
288
|
+
}
|
|
289
|
+
case "breathe":
|
|
290
|
+
if #available(iOS 18.0, *) {
|
|
291
|
+
repeating ? indefinite(.breathe, view) : discrete(.breathe, view)
|
|
292
|
+
}
|
|
293
|
+
default:
|
|
294
|
+
break
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Typed entry points, so an effect that is both discrete and indefinite
|
|
299
|
+
// takes the overload that matches the mode.
|
|
300
|
+
|
|
301
|
+
private static func discrete(
|
|
302
|
+
_ effect: some DiscreteSymbolEffect & SymbolEffect,
|
|
303
|
+
_ view: UIImageView,
|
|
304
|
+
options: SymbolEffectOptions = .default
|
|
305
|
+
) {
|
|
306
|
+
view.addSymbolEffect(effect, options: options)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
private static func indefinite(_ effect: some IndefiniteSymbolEffect & SymbolEffect, _ view: UIImageView) {
|
|
310
|
+
view.addSymbolEffect(effect)
|
|
311
|
+
}
|
|
312
|
+
}
|