diff --git a/.flowconfig b/.flowconfig index 18ef1cbc..b3428a50 100644 --- a/.flowconfig +++ b/.flowconfig @@ -36,6 +36,7 @@ emoji=true esproposal.optional_chaining=enable esproposal.nullish_coalescing=enable +module.file_ext=.ts module.file_ext=.js module.file_ext=.json module.file_ext=.ios.js diff --git a/codegen/SegmentedControlNativeComponent.ts b/codegen/SegmentedControlNativeComponent.ts new file mode 100644 index 00000000..50f4fb2e --- /dev/null +++ b/codegen/SegmentedControlNativeComponent.ts @@ -0,0 +1,51 @@ +import type {ViewProps} from 'ViewPropTypes'; +import type {HostComponent, ColorValue} from 'react-native'; +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; + +import type { + BubblingEventHandler, + Int32, + WithDefault, + Float, +} from 'react-native/Libraries/Types/CodegenTypes'; + +type RNCSegmentedControlValue = { + type: Int32; // 1: text, 2: image + stringValue?: string; // title + imgValue?: { + // ImageResolvedAssetSource + height: Int32; + width: Int32; + scale: Float; + uri: string; + }; +}; + +type OnChangeEvent = { + // works only with text values (not with images) + value: string; + selectedSegmentIndex: Int32; +}; + +type SCFontStyle = { + color?: ColorValue; + fontSize?: WithDefault; + fontFamily?: string; +}; + +export interface NativeProps extends ViewProps { + values: Array; + selectedIndex?: WithDefault; + tintColor?: ColorValue; + backgroundColor?: ColorValue; + momentary?: WithDefault; + enabled?: WithDefault; + onChange?: BubblingEventHandler; + appearance?: string; + fontStyle?: SCFontStyle; + activeFontStyle?: SCFontStyle; +} + +export default codegenNativeComponent( + 'RNCSegmentedControl', +) as HostComponent; diff --git a/ios/RNCSegmentedControl.xcodeproj/project.pbxproj b/ios/RNCSegmentedControl.xcodeproj/project.pbxproj index 56e8e1a9..7ba8321b 100644 --- a/ios/RNCSegmentedControl.xcodeproj/project.pbxproj +++ b/ios/RNCSegmentedControl.xcodeproj/project.pbxproj @@ -3,36 +3,41 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 56; objects = { /* Begin PBXBuildFile section */ - B3E7B58A1CC2AC0600A0062D /* RNCSegmentedControl.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNCSegmentedControl.m */; }; - E1248FAB23D5F9D700C2FB80 /* RNCSegmentedControlManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E1248FAA23D5F9D700C2FB80 /* RNCSegmentedControlManager.m */; }; + E47AD8772A698C10006FF43F /* RNCSegmentedControl.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = E47AD8742A698C10006FF43F /* RNCSegmentedControl.h */; }; + E47AD87E2A698C95006FF43F /* RNCSegmentedControl.mm in Sources */ = {isa = PBXBuildFile; fileRef = E47AD87D2A698C95006FF43F /* RNCSegmentedControl.mm */; }; + E47AD8832A698CC8006FF43F /* RNCSegmentedControlImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = E47AD8802A698CC7006FF43F /* RNCSegmentedControlImpl.m */; }; + E47AD8842A698CC8006FF43F /* RNCSegmentedControlManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = E47AD8822A698CC8006FF43F /* RNCSegmentedControlManager.mm */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ - 58B511D91A9E6C8500147676 /* CopyFiles */ = { + E47AD86F2A698C10006FF43F /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = "include/$(PRODUCT_NAME)"; dstSubfolderSpec = 16; files = ( + E47AD8772A698C10006FF43F /* RNCSegmentedControl.h in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 134814201AA4EA6300B7C361 /* libRNCSegmentedControl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNCSegmentedControl.a; sourceTree = BUILT_PRODUCTS_DIR; }; - B3E7B5881CC2AC0600A0062D /* RNCSegmentedControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCSegmentedControl.h; sourceTree = ""; }; - B3E7B5891CC2AC0600A0062D /* RNCSegmentedControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCSegmentedControl.m; sourceTree = ""; }; - E1248FA923D5F9D700C2FB80 /* RNCSegmentedControlManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCSegmentedControlManager.h; sourceTree = ""; }; - E1248FAA23D5F9D700C2FB80 /* RNCSegmentedControlManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCSegmentedControlManager.m; sourceTree = ""; }; + E47AD8712A698C10006FF43F /* libRNCSegmentedControl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNCSegmentedControl.a; sourceTree = BUILT_PRODUCTS_DIR; }; + E47AD8742A698C10006FF43F /* RNCSegmentedControl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCSegmentedControl.h; sourceTree = ""; }; + E47AD87D2A698C95006FF43F /* RNCSegmentedControl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RNCSegmentedControl.mm; sourceTree = ""; }; + E47AD87F2A698CC7006FF43F /* RNCSegmentedControlImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCSegmentedControlImpl.h; sourceTree = ""; }; + E47AD8802A698CC7006FF43F /* RNCSegmentedControlImpl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCSegmentedControlImpl.m; sourceTree = ""; }; + E47AD8812A698CC8006FF43F /* RNCSegmentedControlManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCSegmentedControlManager.h; sourceTree = ""; }; + E47AD8822A698CC8006FF43F /* RNCSegmentedControlManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RNCSegmentedControlManager.mm; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 58B511D81A9E6C8500147676 /* Frameworks */ = { + E47AD86E2A698C10006FF43F /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( @@ -42,113 +47,138 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 134814211AA4EA7D00B7C361 /* Products */ = { + E47AD8682A698C10006FF43F = { isa = PBXGroup; children = ( - 134814201AA4EA6300B7C361 /* libRNCSegmentedControl.a */, + E47AD8732A698C10006FF43F /* RNCSegmentedControl */, + E47AD8722A698C10006FF43F /* Products */, + ); + sourceTree = ""; + }; + E47AD8722A698C10006FF43F /* Products */ = { + isa = PBXGroup; + children = ( + E47AD8712A698C10006FF43F /* libRNCSegmentedControl.a */, ); name = Products; sourceTree = ""; }; - 58B511D21A9E6C8500147676 = { + E47AD8732A698C10006FF43F /* RNCSegmentedControl */ = { isa = PBXGroup; children = ( - E1248FA923D5F9D700C2FB80 /* RNCSegmentedControlManager.h */, - E1248FAA23D5F9D700C2FB80 /* RNCSegmentedControlManager.m */, - B3E7B5881CC2AC0600A0062D /* RNCSegmentedControl.h */, - B3E7B5891CC2AC0600A0062D /* RNCSegmentedControl.m */, - 134814211AA4EA7D00B7C361 /* Products */, + E47AD8742A698C10006FF43F /* RNCSegmentedControl.h */, + E47AD87D2A698C95006FF43F /* RNCSegmentedControl.mm */, + E47AD87F2A698CC7006FF43F /* RNCSegmentedControlImpl.h */, + E47AD8802A698CC7006FF43F /* RNCSegmentedControlImpl.m */, + E47AD8812A698CC8006FF43F /* RNCSegmentedControlManager.h */, + E47AD8822A698CC8006FF43F /* RNCSegmentedControlManager.mm */, ); + path = RNCSegmentedControl; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 58B511DA1A9E6C8500147676 /* RNCSegmentedControl */ = { + E47AD8702A698C10006FF43F /* RNCSegmentedControl */ = { isa = PBXNativeTarget; - buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNCSegmentedControl" */; + buildConfigurationList = E47AD87A2A698C10006FF43F /* Build configuration list for PBXNativeTarget "RNCSegmentedControl" */; buildPhases = ( - 58B511D71A9E6C8500147676 /* Sources */, - 58B511D81A9E6C8500147676 /* Frameworks */, - 58B511D91A9E6C8500147676 /* CopyFiles */, + E47AD86D2A698C10006FF43F /* Sources */, + E47AD86E2A698C10006FF43F /* Frameworks */, + E47AD86F2A698C10006FF43F /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); name = RNCSegmentedControl; - productName = RCTDataManager; - productReference = 134814201AA4EA6300B7C361 /* libRNCSegmentedControl.a */; + productName = RNCSegmentedControl; + productReference = E47AD8712A698C10006FF43F /* libRNCSegmentedControl.a */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 58B511D31A9E6C8500147676 /* Project object */ = { + E47AD8692A698C10006FF43F /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0830; - ORGANIZATIONNAME = Facebook; + BuildIndependentTargetsInParallel = 1; + LastUpgradeCheck = 1430; TargetAttributes = { - 58B511DA1A9E6C8500147676 = { - CreatedOnToolsVersion = 6.1.1; + E47AD8702A698C10006FF43F = { + CreatedOnToolsVersion = 14.3.1; }; }; }; - buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNCSegmentedControl" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + buildConfigurationList = E47AD86C2A698C10006FF43F /* Build configuration list for PBXProject "RNCSegmentedControl" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( - English, en, + Base, ); - mainGroup = 58B511D21A9E6C8500147676; - productRefGroup = 58B511D21A9E6C8500147676; + mainGroup = E47AD8682A698C10006FF43F; + productRefGroup = E47AD8722A698C10006FF43F /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 58B511DA1A9E6C8500147676 /* RNCSegmentedControl */, + E47AD8702A698C10006FF43F /* RNCSegmentedControl */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ - 58B511D71A9E6C8500147676 /* Sources */ = { + E47AD86D2A698C10006FF43F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - E1248FAB23D5F9D700C2FB80 /* RNCSegmentedControlManager.m in Sources */, - B3E7B58A1CC2AC0600A0062D /* RNCSegmentedControl.m in Sources */, + E47AD8832A698CC8006FF43F /* RNCSegmentedControlImpl.m in Sources */, + E47AD8842A698CC8006FF43F /* RNCSegmentedControlManager.mm in Sources */, + E47AD87E2A698C95006FF43F /* RNCSegmentedControl.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ - 58B511ED1A9E6C8500147676 /* Debug */ = { + E47AD8782A698C10006FF43F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -156,43 +186,57 @@ "DEBUG=1", "$(inherited)", ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.4; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; name = Debug; }; - 58B511EE1A9E6C8500147676 /* Release */ = { + E47AD8792A698C10006FF43F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -200,67 +244,60 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.4; MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; name = Release; }; - 58B511F01A9E6C8500147676 /* Debug */ = { + E47AD87B2A698C10006FF43F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../../React/**", - "$(SRCROOT)/../../react-native/React/**", - ); - LIBRARY_SEARCH_PATHS = "$(inherited)"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 7BW78VSQAU; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = RNCSegmentedControl; + PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; - 58B511F11A9E6C8500147676 /* Release */ = { + E47AD87C2A698C10006FF43F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../../../React/**", - "$(SRCROOT)/../../react-native/React/**", - ); - LIBRARY_SEARCH_PATHS = "$(inherited)"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 7BW78VSQAU; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = RNCSegmentedControl; + PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNCSegmentedControl" */ = { + E47AD86C2A698C10006FF43F /* Build configuration list for PBXProject "RNCSegmentedControl" */ = { isa = XCConfigurationList; buildConfigurations = ( - 58B511ED1A9E6C8500147676 /* Debug */, - 58B511EE1A9E6C8500147676 /* Release */, + E47AD8782A698C10006FF43F /* Debug */, + E47AD8792A698C10006FF43F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNCSegmentedControl" */ = { + E47AD87A2A698C10006FF43F /* Build configuration list for PBXNativeTarget "RNCSegmentedControl" */ = { isa = XCConfigurationList; buildConfigurations = ( - 58B511F01A9E6C8500147676 /* Debug */, - 58B511F11A9E6C8500147676 /* Release */, + E47AD87B2A698C10006FF43F /* Debug */, + E47AD87C2A698C10006FF43F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; - rootObject = 58B511D31A9E6C8500147676 /* Project object */; + rootObject = E47AD8692A698C10006FF43F /* Project object */; } diff --git a/ios/RNCSegmentedControl/RNCSegmentedControl.h b/ios/RNCSegmentedControl/RNCSegmentedControl.h new file mode 100644 index 00000000..8e17aaf5 --- /dev/null +++ b/ios/RNCSegmentedControl/RNCSegmentedControl.h @@ -0,0 +1,16 @@ +#ifdef RCT_NEW_ARCH_ENABLED +#import +#import + +#ifndef NativeComponentExampleComponentView_h +#define NativeComponentExampleComponentView_h + +NS_ASSUME_NONNULL_BEGIN + +@interface RNCSegmentedControl : RCTViewComponentView +@end + +NS_ASSUME_NONNULL_END + +#endif /* NativeComponentExampleComponentView_h */ +#endif /* RCT_NEW_ARCH_ENABLED */ diff --git a/ios/RNCSegmentedControl/RNCSegmentedControl.mm b/ios/RNCSegmentedControl/RNCSegmentedControl.mm new file mode 100644 index 00000000..b49f441b --- /dev/null +++ b/ios/RNCSegmentedControl/RNCSegmentedControl.mm @@ -0,0 +1,194 @@ +// This guard prevent the code from being compiled in the old architecture +#ifdef RCT_NEW_ARCH_ENABLED +#import "RNCSegmentedControl.h" +//#import "RNCSegmentedControlImpl.h" +#import "RNCSegmentedControlImpl.h" + +#import + +#import +#import +#import +#import + +#import "RCTFabricComponentsPlugins.h" + +using namespace facebook::react; + +@interface RNCSegmentedControl () + +@end + +@implementation RNCSegmentedControl { + RNCSegmentedControlImpl * _view; +} + ++ (ComponentDescriptorProvider)componentDescriptorProvider +{ + return concreteComponentDescriptorProvider(); +} + +- (instancetype)initWithFrame:(CGRect)frame +{ +if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + + _view = [[RNCSegmentedControlImpl alloc] init]; + + __weak __typeof(self) weakSelf = self; + _view.onChangeFabric = ^(NSString *value, NSInteger index) { + [weakSelf onChange:value selectedIndex:index]; + }; + + self.contentView = _view; +} + +return self; +} + +- (void)onChange:(NSString *) value selectedIndex:(NSInteger) index +{ + if(!_eventEmitter) { + return; + } + + RNCSegmentedControlEventEmitter::OnChange event = { value: std::string([value UTF8String]), + selectedSegmentIndex: (int) index }; + + std::dynamic_pointer_cast(_eventEmitter)->onChange(event); +} + +- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps +{ + const auto &oldViewProps = *std::static_pointer_cast(_props); + const auto &newViewProps = *std::static_pointer_cast(props); + + NSMutableArray *oldValues = [[NSMutableArray alloc] init]; + auto oldValuesIt = oldViewProps.values.begin(); + + while (oldValuesIt != oldViewProps.values.end()) { + if (oldValuesIt->type==1) { + [oldValues addObject: RCTNSStringFromString(oldValuesIt->stringValue)]; + } + else if(oldValuesIt->type==2) { + [oldValues addObject: [self imageResolvedAssetSourceToDictionary:oldValuesIt->imgValue]]; + } + oldValuesIt++; + } + + NSMutableArray *newValues = [[NSMutableArray alloc] init]; + auto newValuesIt = newViewProps.values.begin(); + + while (newValuesIt != newViewProps.values.end()) { + if (newValuesIt->type==1) { + [newValues addObject: RCTNSStringFromString(newValuesIt->stringValue)]; + } + else if(newValuesIt->type==2) { + [newValues addObject: [self imageResolvedAssetSourceToDictionary:newValuesIt->imgValue]]; + } + newValuesIt++; + } + if(![newValues isEqualToArray:oldValues]){ + [_view setValues:newValues]; + } + if (oldViewProps.selectedIndex != newViewProps.selectedIndex) { + _view.selectedIndex = newViewProps.selectedIndex; + } + if (oldViewProps.tintColor != newViewProps.tintColor) { + UIColor *tintColor = RCTUIColorFromSharedColor(newViewProps.tintColor); + _view.tintColor = tintColor; + } + if (oldViewProps.backgroundColor != newViewProps.backgroundColor) { + UIColor *backgroundColor = RCTUIColorFromSharedColor(newViewProps.backgroundColor); + _view.backgroundColor = backgroundColor; + } + if (oldViewProps.momentary != newViewProps.momentary) { + _view.momentary = newViewProps.momentary; + } + + if (oldViewProps.enabled != newViewProps.enabled) { + _view.enabled = newViewProps.enabled; + } + + if (oldViewProps.appearance != newViewProps.appearance) { + _view.appearance = RCTNSStringFromString(newViewProps.appearance); + } + +#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \ + __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0 + if (@available(iOS 13.0, *)) { + if (oldViewProps.fontStyle.color!=newViewProps.fontStyle.color || + oldViewProps.fontStyle.fontSize!=newViewProps.fontStyle.fontSize || + oldViewProps.fontStyle.fontFamily!=newViewProps.fontStyle.fontFamily) { + + UIColor *color = RCTUIColorFromSharedColor(newViewProps.fontStyle.color); + NSInteger fontSize = newViewProps.fontStyle.fontSize; // default 13.0 + UIFont *font = [UIFont systemFontOfSize:fontSize]; + NSString *fontName = RCTNSStringFromStringNilIfEmpty(newViewProps.fontStyle.fontFamily); + if (fontName) { + UIFont *tempFont = [UIFont fontWithName:fontName + size:fontSize]; + if (tempFont != nil) { + font = tempFont; + } + } + + NSDictionary *attributes = [NSDictionary + dictionaryWithObjectsAndKeys:font, NSFontAttributeName, color, + NSForegroundColorAttributeName, nil]; + [_view setTitleTextAttributes:attributes forState:UIControlStateNormal]; + } + } +#endif + +#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \ + __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0 + if (@available(iOS 13.0, *)) { + if (oldViewProps.activeFontStyle.color!=newViewProps.activeFontStyle.color || + oldViewProps.activeFontStyle.fontSize!=newViewProps.activeFontStyle.fontSize || + oldViewProps.activeFontStyle.fontFamily!=newViewProps.activeFontStyle.fontFamily) { + + UIColor *color = RCTUIColorFromSharedColor(newViewProps.activeFontStyle.color); + NSInteger fontSize = newViewProps.activeFontStyle.fontSize; // default 13.0 + UIFont *font = [UIFont boldSystemFontOfSize:fontSize]; + NSString *fontName = RCTNSStringFromStringNilIfEmpty(newViewProps.activeFontStyle.fontFamily); + if (fontName) { + UIFont *tempFont = [UIFont fontWithName:fontName + size:fontSize]; + if (tempFont != nil) { + font = tempFont; + } + } + + NSDictionary *attributes = [NSDictionary + dictionaryWithObjectsAndKeys:font, NSFontAttributeName, color, + NSForegroundColorAttributeName, nil]; + [_view setTitleTextAttributes:attributes forState:UIControlStateSelected]; + } + } +#endif + + [super updateProps:props oldProps:oldProps]; +} + +Class RNCSegmentedControlCls(void) +{ + return RNCSegmentedControl.class; +} + +- imageResolvedAssetSourceToDictionary:(facebook::react::RNCSegmentedControlValuesImgValueStruct)rawObject +{ + // it's important to have a NSMutableDictionary for the Impl to detect the right case (img vs text) + NSMutableDictionary *ret = [NSMutableDictionary new]; + + [ret setObject:[NSNumber numberWithInt: rawObject.height] forKey:@"height"]; + [ret setObject:[NSNumber numberWithInt: rawObject.width] forKey:@"width"]; + [ret setObject:[NSNumber numberWithFloat: rawObject.scale] forKey:@"scale"]; + [ret setObject:RCTNSStringFromString(rawObject.uri) forKey:@"uri"]; + + return ret; +} + +@end +#endif diff --git a/ios/RNCSegmentedControl.h b/ios/RNCSegmentedControl/RNCSegmentedControlImpl.h similarity index 58% rename from ios/RNCSegmentedControl.h rename to ios/RNCSegmentedControl/RNCSegmentedControlImpl.h index af81a54a..c4e20709 100644 --- a/ios/RNCSegmentedControl.h +++ b/ios/RNCSegmentedControl/RNCSegmentedControlImpl.h @@ -8,8 +8,17 @@ #import #import -@interface RNCSegmentedControl : UISegmentedControl +typedef void(^OnChangeCallback)(NSString *value, NSInteger index); + +@interface RNCSegmentedControlImpl : UISegmentedControl + +@property(nonatomic) NSArray * values; @property(nonatomic, assign) NSInteger selectedIndex; + +@property NSString * appearance; + @property(nonatomic, copy) RCTBubblingEventBlock onChange; +@property (nonatomic, copy) OnChangeCallback onChangeFabric; + @end diff --git a/ios/RNCSegmentedControl.m b/ios/RNCSegmentedControl/RNCSegmentedControlImpl.m similarity index 82% rename from ios/RNCSegmentedControl.m rename to ios/RNCSegmentedControl/RNCSegmentedControlImpl.m index 285abbdc..371d6fb1 100644 --- a/ios/RNCSegmentedControl.m +++ b/ios/RNCSegmentedControl/RNCSegmentedControlImpl.m @@ -5,13 +5,13 @@ * LICENSE file in the root directory of this source tree. */ -#import "RNCSegmentedControl.h" +#import "RNCSegmentedControlImpl.h" #import #import #import -@implementation RNCSegmentedControl +@implementation RNCSegmentedControlImpl - (instancetype)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { @@ -37,10 +37,12 @@ - (void)setValues:(NSArray *)values { animated:NO]; } } + [[UILabel appearanceWhenContainedIn:[UISegmentedControl class], nil] setNumberOfLines:0]; super.selectedSegmentIndex = _selectedIndex; } - (void)setSelectedIndex:(NSInteger)selectedIndex { + NSLog(@"IMPL set selectedIndex to %ld",selectedIndex); _selectedIndex = selectedIndex; super.selectedSegmentIndex = selectedIndex; } @@ -76,12 +78,16 @@ - (void)setTintColor:(UIColor *)tintColor { - (void)didChange { _selectedIndex = self.selectedSegmentIndex; if (_onChange) { - NSString *segmentTitle = [self titleForSegmentAtIndex:_selectedIndex]; + NSString *segmentTitle = [self titleForSegmentAtIndex:_selectedIndex]; _onChange(@{ - @"value" : (segmentTitle) ? segmentTitle : [self imageForSegmentAtIndex:_selectedIndex], - @"selectedSegmentIndex" : @(_selectedIndex) + @"value" : (segmentTitle) ? segmentTitle : [self imageForSegmentAtIndex:_selectedIndex], + @"selectedSegmentIndex" : @(_selectedIndex) }); } + if(_onChangeFabric){ + NSString *segmentTitle = [self titleForSegmentAtIndex:_selectedIndex]; + _onChangeFabric((segmentTitle) ? segmentTitle : @"RCTImage",_selectedIndex); + } } - (void)setAppearance:(NSString *)appearanceString { diff --git a/ios/RNCSegmentedControlManager.h b/ios/RNCSegmentedControl/RNCSegmentedControlManager.h similarity index 100% rename from ios/RNCSegmentedControlManager.h rename to ios/RNCSegmentedControl/RNCSegmentedControlManager.h diff --git a/ios/RNCSegmentedControlManager.m b/ios/RNCSegmentedControl/RNCSegmentedControlManager.mm similarity index 95% rename from ios/RNCSegmentedControlManager.m rename to ios/RNCSegmentedControl/RNCSegmentedControlManager.mm index 6a277958..dfdfd3cc 100644 --- a/ios/RNCSegmentedControlManager.m +++ b/ios/RNCSegmentedControl/RNCSegmentedControlManager.mm @@ -7,16 +7,16 @@ #import "RNCSegmentedControlManager.h" -#import "RNCSegmentedControl.h" +#import "RNCSegmentedControlImpl.h" #import #import @implementation RNCSegmentedControlManager -RCT_EXPORT_MODULE() +RCT_EXPORT_MODULE(RNCSegmentedControl) - (UIView *)view { - return [RNCSegmentedControl new]; + return [RNCSegmentedControlImpl new]; } RCT_EXPORT_VIEW_PROPERTY(values, NSArray) @@ -28,7 +28,7 @@ - (UIView *)view { RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock) RCT_EXPORT_VIEW_PROPERTY(appearance, NSString) -RCT_CUSTOM_VIEW_PROPERTY(fontStyle, NSObject, RNCSegmentedControl) { +RCT_CUSTOM_VIEW_PROPERTY(fontStyle, NSObject, RNCSegmentedControlImpl) { #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \ __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0 if (@available(iOS 13.0, *)) { @@ -55,7 +55,7 @@ - (UIView *)view { #endif } -RCT_CUSTOM_VIEW_PROPERTY(activeFontStyle, NSObject, RNCSegmentedControl) { +RCT_CUSTOM_VIEW_PROPERTY(activeFontStyle, NSObject, RNCSegmentedControlImpl) { #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \ __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0 if (@available(iOS 13.0, *)) { diff --git a/js/RNCSegmentedControlNativeComponent.js b/js/RNCSegmentedControlNativeComponent.js index 908b5491..3a233841 100644 --- a/js/RNCSegmentedControlNativeComponent.js +++ b/js/RNCSegmentedControlNativeComponent.js @@ -9,11 +9,16 @@ 'use strict'; import {requireNativeComponent} from 'react-native'; -import type {HostComponent} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes'; -import type {SegmentedControlProps} from './types'; +// import type {HostComponent} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes'; +// import type {SegmentedControlProps} from './types'; -type NativeSegmentedControlIOS = HostComponent; +// type NativeSegmentedControlIOS = HostComponent; -module.exports = ((requireNativeComponent( - 'RNCSegmentedControl', -): any): NativeSegmentedControlIOS); +const isFabricEnabled = global.nativeFabricUIManager != null; + +// const RNCSegmentedControl: NativeSegmentedControlIOS = isFabricEnabled +const RNCSegmentedControl = isFabricEnabled + ? require('../codegen/SegmentedControlNativeComponent').default + : requireNativeComponent('RNCSegmentedControl'); + +module.exports = RNCSegmentedControl; diff --git a/js/SegmentedControl.ios.js b/js/SegmentedControl.ios.js index 909eba08..76bcd95f 100644 --- a/js/SegmentedControl.ios.js +++ b/js/SegmentedControl.ios.js @@ -21,6 +21,8 @@ type Props = $ReadOnly<{| forwardedRef: ?React.Ref, |}>; +const isFabricEnabled = global.nativeFabricUIManager != null; + /** * Use `SegmentedControlIOS` to render a UISegmentedControl iOS. * @@ -86,9 +88,16 @@ class SegmentedControlIOS extends React.Component { } : undefined } - values={values.map((val) => - typeof val === 'string' ? val : Image.resolveAssetSource(val), - )} + values={values.map((val) => { + var ret = isFabricEnabled + ? typeof val === 'string' + ? {type: 1, stringValue: val} + : {type: 2, imgValue: Image.resolveAssetSource(val)} + : typeof val === 'string' + ? val + : Image.resolveAssetSource(val); + return ret; + })} {...props} ref={forwardedRef} style={[styles.segmentedControl, this.props.style]} diff --git a/package.json b/package.json index 531532ad..083243f1 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "index.d.ts", "ios", "js", + "codegen", "react-native-segmented-control.podspec" ], "scripts": { @@ -78,5 +79,10 @@ "homepage": "https://github.com/react-native-segmented-control/segmented-control#readme", "publishConfig": { "access": "public" + }, + "codegenConfig": { + "name": "SegmentedControl", + "type": "components", + "jsSrcsDir": "./codegen" } } diff --git a/react-native-segmented-control.podspec b/react-native-segmented-control.podspec index 41d70614..c4222672 100644 --- a/react-native-segmented-control.podspec +++ b/react-native-segmented-control.podspec @@ -2,6 +2,8 @@ require 'json' package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) +folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' + Pod::Spec.new do |s| s.name = "react-native-segmented-control" s.version = package['version'] @@ -13,7 +15,23 @@ Pod::Spec.new do |s| s.platform = :ios, "9.0" s.source = { :git => "https://github.com/react-native-segmented-control/segmented-control.git", :tag => "#{s.version}" } - s.source_files = "ios/**/*.{h,m}" + s.source_files = "ios/**/*.{h,m,mm}" s.dependency 'React-Core' + + if ENV["RCT_NEW_ARCH_ENABLED"] == "1" + s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" + s.pod_target_xcconfig = { + "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"", + "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1", + "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" + } + + s.dependency "React-Codegen" + s.dependency "React-RCTFabric" + s.dependency "RCT-Folly" + s.dependency "RCTRequired" + s.dependency "RCTTypeSafety" + s.dependency "ReactCommon/turbomodule/core" + end end