diff --git a/packages/react-native/Package.swift b/packages/react-native/Package.swift index 6280f48ab08c..bbcb11c7957f 100644 --- a/packages/react-native/Package.swift +++ b/packages/react-native/Package.swift @@ -433,6 +433,7 @@ let reactFabricComponents = RNTarget( "components/view/platform/android", "components/view/platform/windows", "components/view/platform/macos", + "components/switch/iosswitch/react/renderer/components/switch/MacOSSwitchShadowNode.mm", "components/textinput/platform/android", "components/text/platform/android", "components/textinput/platform/macos", @@ -445,7 +446,7 @@ let reactFabricComponents = RNTarget( "conponents/rncore", // this was the old folder where RN Core Components were generated. If you ran codegen in the past, you might have some files in it that might make the build fail. ], dependencies: [.reactNativeDependencies, .reactCore, .reactJsiExecutor, .reactTurboModuleCore, .jsi, .logger, .reactDebug, .reactFeatureFlags, .reactUtils, .reactRuntimeScheduler, .reactCxxReact, .yoga, .reactRendererDebug, .reactGraphics, .reactFabric, .reactTurboModuleBridging], - sources: ["components/inputaccessory", "components/modal", "components/safeareaview", "components/text", "components/text/platform/cxx", "components/textinput", "components/textinput/platform/ios/", "components/unimplementedview", "components/virtualview", "components/virtualviewexperimental", "textlayoutmanager", "textlayoutmanager/platform/ios"] + sources: ["components/inputaccessory", "components/modal", "components/safeareaview", "components/text", "components/text/platform/cxx", "components/textinput", "components/textinput/platform/ios/", "components/unimplementedview", "components/virtualview", "components/virtualviewexperimental", "textlayoutmanager", "textlayoutmanager/platform/ios", "components/switch/iosswitch"] ) /// React-FabricImage.podspec diff --git a/packages/react-native/React/Base/RCTUtils.h b/packages/react-native/React/Base/RCTUtils.h index edc96044edd4..a6b4ea0d0c02 100644 --- a/packages/react-native/React/Base/RCTUtils.h +++ b/packages/react-native/React/Base/RCTUtils.h @@ -53,6 +53,7 @@ RCT_EXTERN CGFloat RCTScreenScale(void); RCT_EXTERN CGFloat RCTFontSizeMultiplier(void); RCT_EXTERN CGSize RCTScreenSize(void); RCT_EXTERN CGSize RCTViewportSize(void); +RCT_EXTERN CGSize RCTSwitchSize(void); // Round float coordinates to nearest whole screen pixel (not point) RCT_EXTERN CGFloat RCTRoundPixelValue(CGFloat value); diff --git a/packages/react-native/React/Base/RCTUtils.mm b/packages/react-native/React/Base/RCTUtils.mm index 44189018e01b..82712cb3f9ec 100644 --- a/packages/react-native/React/Base/RCTUtils.mm +++ b/packages/react-native/React/Base/RCTUtils.mm @@ -410,6 +410,16 @@ CGSize RCTViewportSize(void) return window ? window.bounds.size : RCTScreenSize(); } +CGSize RCTSwitchSize(void) +{ + static CGSize rctSwitchSize; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + rctSwitchSize = [UISwitch new].intrinsicContentSize; + }); + return rctSwitchSize; +} + CGFloat RCTRoundPixelValue(CGFloat value) { CGFloat scale = RCTScreenScale(); diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm index 552dd5def91a..ba836bf5fd44 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm @@ -9,10 +9,10 @@ #import -#import #import #import #import +#import #import "RCTFabricComponentsPlugins.h" diff --git a/packages/react-native/React/React-RCTFabric.podspec b/packages/react-native/React/React-RCTFabric.podspec index f18e190c43e0..83000572e5ba 100644 --- a/packages/react-native/React/React-RCTFabric.podspec +++ b/packages/react-native/React/React-RCTFabric.podspec @@ -75,6 +75,7 @@ Pod::Spec.new do |s| "react/renderer/components/scrollview/platform/cxx", "react/renderer/components/text/platform/cxx", "react/renderer/components/textinput/platform/ios", + "react/renderer/components/switch/iosswitch", ]); add_dependency(s, "React-graphics", :additional_framework_paths => ["react/renderer/graphics/platform/ios"]) diff --git a/packages/react-native/ReactCommon/React-FabricComponents.podspec b/packages/react-native/ReactCommon/React-FabricComponents.podspec index a2a6944da86b..2f0bbab875b1 100644 --- a/packages/react-native/ReactCommon/React-FabricComponents.podspec +++ b/packages/react-native/ReactCommon/React-FabricComponents.podspec @@ -127,6 +127,14 @@ Pod::Spec.new do |s| sss.header_dir = "react/renderer/components/iostextinput" end + ss.subspec "switch" do |sss| + sss.source_files = podspec_sources( + ["react/renderer/components/switch/iosswitch/**/*.{m,mm,cpp,h}"], + ["react/renderer/components/switch/iosswitch/**/*.h"]) + sss.exclude_files = "react/renderer/components/switch/iosswitch/**/MacOS*.{m,mm,cpp,h}" + sss.header_dir = "react/renderer/components/switch/" + end + ss.subspec "textinput" do |sss| sss.source_files = podspec_sources("react/renderer/components/textinput/*.{m,mm,cpp,h}", "react/renderer/components/textinput/**/*.h") sss.header_dir = "react/renderer/components/textinput" diff --git a/packages/react-native/ReactCommon/react/renderer/components/switch/iosswitch/react/renderer/components/switch/AppleSwitchComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/components/switch/iosswitch/react/renderer/components/switch/AppleSwitchComponentDescriptor.h new file mode 100644 index 000000000000..de4cef29aaa3 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/components/switch/iosswitch/react/renderer/components/switch/AppleSwitchComponentDescriptor.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include "AppleSwitchShadowNode.h" + +#include + +namespace facebook::react { + +/* + * Descriptor for component. + */ +class SwitchComponentDescriptor final + : public ConcreteComponentDescriptor { + public: + SwitchComponentDescriptor(const ComponentDescriptorParameters& parameters) + : ConcreteComponentDescriptor(parameters) {} + + void adopt(ShadowNode& shadowNode) const override { + ConcreteComponentDescriptor::adopt(shadowNode); + } +}; + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/switch/iosswitch/react/renderer/components/switch/AppleSwitchShadowNode.h b/packages/react-native/ReactCommon/react/renderer/components/switch/iosswitch/react/renderer/components/switch/AppleSwitchShadowNode.h new file mode 100644 index 000000000000..2cffdf139f5d --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/components/switch/iosswitch/react/renderer/components/switch/AppleSwitchShadowNode.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include + +namespace facebook::react { + +extern const char AppleSwitchComponentName[]; + +/* + * `ShadowNode` for component. + */ +class SwitchShadowNode final : public ConcreteViewShadowNode< + AppleSwitchComponentName, + SwitchProps, + SwitchEventEmitter> { + public: + using ConcreteViewShadowNode::ConcreteViewShadowNode; + + static ShadowNodeTraits BaseTraits() { + auto traits = ConcreteViewShadowNode::BaseTraits(); + traits.set(ShadowNodeTraits::Trait::LeafYogaNode); + traits.set(ShadowNodeTraits::Trait::MeasurableYogaNode); + return traits; + } + +#pragma mark - LayoutableShadowNode + + Size measureContent( + const LayoutContext& layoutContext, + const LayoutConstraints& layoutConstraints) const override; +}; + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/switch/iosswitch/react/renderer/components/switch/IOSSwitchShadowNode.mm b/packages/react-native/ReactCommon/react/renderer/components/switch/iosswitch/react/renderer/components/switch/IOSSwitchShadowNode.mm new file mode 100644 index 000000000000..b38b0b0509c8 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/components/switch/iosswitch/react/renderer/components/switch/IOSSwitchShadowNode.mm @@ -0,0 +1,26 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import +#include "AppleSwitchShadowNode.h" + +namespace facebook::react { + +extern const char AppleSwitchComponentName[] = "Switch"; + +#pragma mark - LayoutableShadowNode + +Size SwitchShadowNode::measureContent( + const LayoutContext & /*layoutContext*/, + const LayoutConstraints & /*layoutConstraints*/) const +{ + CGSize uiSwitchSize = RCTSwitchSize(); + return {.width = uiSwitchSize.width, .height = uiSwitchSize.height}; +} + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/switch/iosswitch/react/renderer/components/switch/MacOSSwitchShadowNode.mm b/packages/react-native/ReactCommon/react/renderer/components/switch/iosswitch/react/renderer/components/switch/MacOSSwitchShadowNode.mm new file mode 100644 index 000000000000..cd62f626ba68 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/components/switch/iosswitch/react/renderer/components/switch/MacOSSwitchShadowNode.mm @@ -0,0 +1,32 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#include "AppleSwitchShadowNode.h" + +namespace facebook::react { + +extern const char AppleSwitchComponentName[] = "Switch"; + +#pragma mark - LayoutableShadowNode + +Size SwitchShadowNode::measureContent( + const LayoutContext & /*layoutContext*/, + const LayoutConstraints & /*layoutConstraints*/) const +{ + static CGSize nsSwitchSize = CGSizeZero; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + dispatch_sync(dispatch_get_main_queue(), ^{ + nsSwitchSize = [NSSwitch new].intrinsicContentSize; + }); + }); + + return {.width = nsSwitchSize.width, .height = nsSwitchSize.height}; +} + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm index 62585c6129dd..f5e53529e420 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm @@ -366,6 +366,7 @@ - (void)_start RCTScreenSize(); RCTScreenScale(); + RCTSwitchSize(); std::lock_guard lock(*mutex); *isReady = true;